crcmodel.c revision 11015:0a0751599d31
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
66LOCAL uint32_t reflect P_((uint32_t v, int b));
67LOCAL uint32_t
68reflect(v, b)
69/* Returns the value v with the bottom b [0,32] bits reflected. */
70/* Example: reflect(0x3e23L,3) == 0x3e26 */
71uint32_t v;
72int   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
86LOCAL uint32_t widmask P_((p_cm_t));
87LOCAL uint32_t
88widmask(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). */
91p_cm_t p_cm;
92{
93	return ((((1L<<(p_cm->cm_width-1))-1L)<<1)|1L);
94}
95
96void
97cm_ini(p_cm)
98p_cm_t p_cm;
99{
100	p_cm->cm_reg = p_cm->cm_init;
101}
102
103void
104cm_nxt(p_cm, ch)
105p_cm_t p_cm;
106int    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
126void
127cm_blk(p_cm, blk_adr, blk_len)
128p_cm_t   p_cm;
129p_ubyte_ blk_adr;
130uint32_t    blk_len;
131{
132	while (blk_len--)
133		cm_nxt(p_cm, *blk_adr++);
134}
135
136uint32_t
137cm_crc(p_cm)
138p_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
146uint32_t
147cm_tab(p_cm, index)
148p_cm_t p_cm;
149int    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