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