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