xref: /illumos-gate/usr/src/cmd/picl/plugins/sun4u/lib/fruaccess/crcmodel.c (revision 55fea89dcaa64928bed4327112404dcb3e07b79f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  *
22  * Copyright 2000 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  *
28  *                             Start of crcmodel.c
29  *
30  *
31  * Author : Ross Williams (ross@guest.adelaide.edu.au.).
32  * Date   : 3 June 1993.
33  * Status : Public domain.
34  *
35  * Description : This is the implementation (.c) file for the reference
36  * implementation of the Rocksoft^tm Model CRC Algorithm. For more
37  * information on the Rocksoft^tm Model CRC Algorithm, see the document
38  * titled "A Painless Guide to CRC Error Detection Algorithms" by Ross
39  * Williams (ross@guest.adelaide.edu.au.). This document is likely to be in
40  * "ftp.adelaide.edu.au/pub/rocksoft".
41  *
42  * Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia.
43  *
44  *
45  *
46  * Implementation Notes
47  * --------------------
48  * To avoid inconsistencies, the specification of each function is not echoed
49  * here. See the header file for a description of these functions.
50  * This package is light on checking because I want to keep it short and
51  * simple and portable (i.e. it would be too messy to distribute my entire
52  * C culture (e.g. assertions package) with this package.
53  *
54  *
55  */
56 
57 #include "crcmodel.h"
58 
59 /* The following definitions make the code more readable. */
60 
61 #define	BITMASK(X) (1L << (X))
62 #define	MASK32 0xFFFFFFFFL
63 #define	LOCAL static
64 
65 LOCAL uint32_t reflect P_((uint32_t v, int b));
66 LOCAL uint32_t
67 reflect(v, b)
68 /* Returns the value v with the bottom b [0,32] bits reflected. */
69 /* Example: reflect(0x3e23L,3) == 0x3e26 */
70 uint32_t v;
71 int   b;
72 {
73 	int i;
74 	uint32_t t = v;
75 	for (i = 0; i < b; i++) {
76 		if (t & 1L)
77 			v |=  BITMASK((b-1)-i);
78 		else
79 			v &= ~BITMASK((b-1)-i);
80 		t >>= 1;
81 	}
82 	return (v);
83 }
84 
85 LOCAL uint32_t widmask P_((p_cm_t));
86 LOCAL uint32_t
87 widmask(p_cm)
88 /* Returns a longword whose value is (2^p_cm->cm_width)-1. */
89 /* The trick is to do this portably (e.g. without doing <<32). */
90 p_cm_t p_cm;
91 {
92 	return ((((1L<<(p_cm->cm_width-1))-1L)<<1)|1L);
93 }
94 
95 void
96 cm_ini(p_cm)
97 p_cm_t p_cm;
98 {
99 	p_cm->cm_reg = p_cm->cm_init;
100 }
101 
102 void
103 cm_nxt(p_cm, ch)
104 p_cm_t p_cm;
105 int    ch;
106 {
107 	int i;
108 	uint32_t uch = (uint32_t)ch;
109 	uint32_t topbit = BITMASK(p_cm->cm_width-1);
110 
111 	if (p_cm->cm_refin)
112 		uch = reflect(uch, 8);
113 
114 	p_cm->cm_reg ^= (uch << (p_cm->cm_width-8));
115 	for (i = 0; i < 8; i++) {
116 		if (p_cm->cm_reg & topbit)
117 			p_cm->cm_reg = (p_cm->cm_reg << 1) ^ p_cm->cm_poly;
118 		else
119 			p_cm->cm_reg <<= 1;
120 
121 		p_cm->cm_reg &= widmask(p_cm);
122 	}
123 }
124 
125 void
126 cm_blk(p_cm, blk_adr, blk_len)
127 p_cm_t   p_cm;
128 p_ubyte_ blk_adr;
129 uint32_t    blk_len;
130 {
131 	while (blk_len--)
132 		cm_nxt(p_cm, *blk_adr++);
133 }
134 
135 uint32_t
136 cm_crc(p_cm)
137 p_cm_t p_cm;
138 {
139 	if (p_cm->cm_refot)
140 		return (p_cm->cm_xorot ^ reflect(p_cm->cm_reg, p_cm->cm_width));
141 	else
142 		return (p_cm->cm_xorot ^ p_cm->cm_reg);
143 }
144 
145 uint32_t
146 cm_tab(p_cm, index)
147 p_cm_t p_cm;
148 int    index;
149 {
150 	int   i;
151 	uint32_t r;
152 	uint32_t topbit = BITMASK(p_cm->cm_width-1);
153 	uint32_t inbyte = (uint32_t)index;
154 
155 	if (p_cm->cm_refin)
156 		inbyte = reflect(inbyte, 8);
157 
158 	r = inbyte << (p_cm->cm_width-8);
159 	for (i = 0; i < 8; i++)
160 		if (r & topbit)
161 			r = (r << 1) ^ p_cm->cm_poly;
162 		else
163 			r <<= 1;
164 
165 	if (p_cm->cm_refin)
166 		r = reflect(r, p_cm->cm_width);
167 
168 	return (r & widmask(p_cm));
169 }
170