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