2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A/*
2N/A *
2N/A * Start of crcmodel.c
2N/A *
2N/A *
2N/A * Author : Ross Williams (ross@guest.adelaide.edu.au.).
2N/A * Date : 3 June 1993.
2N/A * Status : Public domain.
2N/A *
2N/A * Description : This is the implementation (.c) file for the reference
2N/A * implementation of the Rocksoft^tm Model CRC Algorithm. For more
2N/A * information on the Rocksoft^tm Model CRC Algorithm, see the document
2N/A * titled "A Painless Guide to CRC Error Detection Algorithms" by Ross
2N/A * Williams (ross@guest.adelaide.edu.au.). This document is likely to be in
2N/A * "ftp.adelaide.edu.au/pub/rocksoft".
2N/A *
2N/A * Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia.
2N/A *
2N/A *
2N/A *
2N/A * Implementation Notes
2N/A * --------------------
2N/A * To avoid inconsistencies, the specification of each function is not echoed
2N/A * here. See the header file for a description of these functions.
2N/A * This package is light on checking because I want to keep it short and
2N/A * simple and portable (i.e. it would be too messy to distribute my entire
2N/A * C culture (e.g. assertions package) with this package.
2N/A *
2N/A *
2N/A */
2N/A
2N/A#include "crcmodel.h"
2N/A
2N/A/* The following definitions make the code more readable. */
2N/A
2N/A#define BITMASK(X) (1L << (X))
2N/A#define MASK32 0xFFFFFFFFL
2N/A#define LOCAL static
2N/A
2N/ALOCAL uint32_t reflect P_((uint32_t v, int b));
2N/ALOCAL uint32_t
2N/Areflect(v, b)
2N/A/* Returns the value v with the bottom b [0,32] bits reflected. */
2N/A/* Example: reflect(0x3e23L,3) == 0x3e26 */
2N/Auint32_t v;
2N/Aint b;
2N/A{
2N/A int i;
2N/A uint32_t t = v;
2N/A for (i = 0; i < b; i++) {
2N/A if (t & 1L)
2N/A v |= BITMASK((b-1)-i);
2N/A else
2N/A v &= ~BITMASK((b-1)-i);
2N/A t >>= 1;
2N/A }
2N/A return (v);
2N/A}
2N/A
2N/ALOCAL uint32_t widmask P_((p_cm_t));
2N/ALOCAL uint32_t
2N/Awidmask(p_cm)
2N/A/* Returns a longword whose value is (2^p_cm->cm_width)-1. */
2N/A/* The trick is to do this portably (e.g. without doing <<32). */
2N/Ap_cm_t p_cm;
2N/A{
2N/A return ((((1L<<(p_cm->cm_width-1))-1L)<<1)|1L);
2N/A}
2N/A
2N/Avoid
2N/Acm_ini(p_cm)
2N/Ap_cm_t p_cm;
2N/A{
2N/A p_cm->cm_reg = p_cm->cm_init;
2N/A}
2N/A
2N/Avoid
2N/Acm_nxt(p_cm, ch)
2N/Ap_cm_t p_cm;
2N/Aint ch;
2N/A{
2N/A int i;
2N/A uint32_t uch = (uint32_t)ch;
2N/A uint32_t topbit = BITMASK(p_cm->cm_width-1);
2N/A
2N/A if (p_cm->cm_refin)
2N/A uch = reflect(uch, 8);
2N/A
2N/A p_cm->cm_reg ^= (uch << (p_cm->cm_width-8));
2N/A for (i = 0; i < 8; i++) {
2N/A if (p_cm->cm_reg & topbit)
2N/A p_cm->cm_reg = (p_cm->cm_reg << 1) ^ p_cm->cm_poly;
2N/A else
2N/A p_cm->cm_reg <<= 1;
2N/A
2N/A p_cm->cm_reg &= widmask(p_cm);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Acm_blk(p_cm, blk_adr, blk_len)
2N/Ap_cm_t p_cm;
2N/Ap_ubyte_ blk_adr;
2N/Auint32_t blk_len;
2N/A{
2N/A while (blk_len--)
2N/A cm_nxt(p_cm, *blk_adr++);
2N/A}
2N/A
2N/Auint32_t
2N/Acm_crc(p_cm)
2N/Ap_cm_t p_cm;
2N/A{
2N/A if (p_cm->cm_refot)
2N/A return (p_cm->cm_xorot ^ reflect(p_cm->cm_reg, p_cm->cm_width));
2N/A else
2N/A return (p_cm->cm_xorot ^ p_cm->cm_reg);
2N/A}
2N/A
2N/Auint32_t
2N/Acm_tab(p_cm, index)
2N/Ap_cm_t p_cm;
2N/Aint index;
2N/A{
2N/A int i;
2N/A uint32_t r;
2N/A uint32_t topbit = BITMASK(p_cm->cm_width-1);
2N/A uint32_t inbyte = (uint32_t)index;
2N/A
2N/A if (p_cm->cm_refin)
2N/A inbyte = reflect(inbyte, 8);
2N/A
2N/A r = inbyte << (p_cm->cm_width-8);
2N/A for (i = 0; i < 8; i++)
2N/A if (r & topbit)
2N/A r = (r << 1) ^ p_cm->cm_poly;
2N/A else
2N/A r <<= 1;
2N/A
2N/A if (p_cm->cm_refin)
2N/A r = reflect(r, p_cm->cm_width);
2N/A
2N/A return (r & widmask(p_cm));
2N/A}