1/* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License as 4 * published by the Free Software Foundation; either version 2 of 5 * the License, or (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 15 * MA 02111-1307 USA 16 */ 17/* 18 Copyright 2001, ASUSTeK Inc. 19 All Rights Reserved. 20 21 This is UNPUBLISHED PROPRIETARY SOURCE CODE of ASUSTeK Inc.; 22 the contents of this file may not be disclosed to third parties, copied or 23 duplicated in any form, in whole or in part, without the prior written 24 permission of ASUSTeK Inc. 25*/ 26/* 27 * Misc useful OS-independent routines. 28 * 29 * Copyright(c) 2001 ASUSTeK Inc. 30 */ 31 32#include <osl.h> 33#include <nvram/bcmutils.h> 34 35#define _U 0x01 /* upper */ 36#define _L 0x02 /* lower */ 37#define _D 0x04 /* digit */ 38#define _C 0x08 /* cntrl */ 39#define _P 0x10 /* punct */ 40#define _S 0x20 /* white space (space/lf/tab) */ 41#define _X 0x40 /* hex digit */ 42#define _SP 0x80 /* hard space (0x20) */ 43 44static unsigned char _ctype[] = { 45 _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ 46 _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ 47 _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ 48 _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ 49 _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ 50 _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ 51 _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ 52 _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ 53 _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ 54 _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ 55 _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ 56 _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ 57 _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ 58 _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ 59 _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ 60 _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ 61 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ 62 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ 63 _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ 64 _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ 65 _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ 66 _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ 67 _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ 68 _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L /* 240-255 */ 69}; 70 71#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) 72 73#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) 74#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) 75#define iscntrl(c) ((__ismask(c)&(_C)) != 0) 76#define isdigit(c) ((__ismask(c)&(_D)) != 0) 77#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) 78#define islower(c) ((__ismask(c)&(_L)) != 0) 79#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) 80#define ispunct(c) ((__ismask(c)&(_P)) != 0) 81#define isspace(c) ((__ismask(c)&(_S)) != 0) 82#define isupper(c) ((__ismask(c)&(_U)) != 0) 83#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) 84 85static uchar 86bcm_toupper(uchar c) 87{ 88 if (islower(c)) 89 c -= 'a'-'A'; 90 return (c); 91} 92 93ulong 94bcm_strtoul(char *cp, char **endp, uint base) 95{ 96 ulong result, value; 97 98 /* The real strtoul supports a base of 0, but we don't */ 99 ASSERT(base); 100 101 result = 0; 102 103 while (isxdigit(*cp) && 104 (value = isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) { 105 result = result*base + value; 106 cp++; 107 } 108 if (endp) 109 *endp = (char *)cp; 110 111 return (result); 112} 113 114uint 115bcm_atoi(char *s) 116{ 117 uint n; 118 119 n = 0; 120 121 while (isdigit(*s)) 122 n = (n * 10) + *s++ - '0'; 123 return (n); 124} 125 126void 127deadbeef(char *p, uint len) 128{ 129 static uchar meat[] = { 0xde, 0xad, 0xbe, 0xef }; 130 131 while (len-- > 0) { 132 *p = meat[((uint)p) & 3]; 133 p++; 134 } 135} 136 137uchar* 138bcm_ether_ntoa(char *ea, char *buf) 139{ 140 sprintf(buf,"%x:%x:%x:%x:%x:%x", 141 ea[0]&0xff, ea[1]&0xff, ea[2]&0xff, ea[3]&0xff, ea[4]&0xff, ea[5]&0xff); 142 return (buf); 143} 144 145/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ 146void 147bcm_ether_atoe(char *p, char *ea) 148{ 149 int i; 150 151 for (i = 0; i < 6; i++) { 152 ea[i] = (char) bcm_strtoul(p, &p, 16); 153 if (*p == '\0') /* just bail on error */ 154 break; 155 p++; 156 } 157} 158 159int 160bcm_isprint(uchar c) 161{ 162 return (isprint(c)); 163} 164 165/* 166 * Traverse a string of 1-byte tag/1-byte length/variable-length value 167 * triples, returning a pointer to the substring whose first element 168 * matches tag 169 */ 170uint8 * 171bcm_parse_tlvs(uint8 *buf, int buflen, uint key) 172{ 173 uint8 *cp; 174 int totlen; 175 176 cp = buf; 177 totlen = buflen; 178 179 /* find tagged parameter */ 180 while (totlen > 0) { 181 uint tag, len; 182 183 tag = *cp; 184 185 if (tag == key) 186 return (cp); 187 188 len = *(cp + 1); 189 cp += (len + 2); 190 totlen -= (len + 2); 191 } 192 193 return NULL; 194} 195 196#define pktq_next(i) ((i+1) & (MAXQLEN-1)) 197#define pktq_prev(i) ((i-1) & (MAXQLEN-1)) 198 199void 200pktqinit(struct pktq *q) 201{ 202 q->head = q->tail = 0; 203 bzero((char*)q->p, sizeof (q->p)); 204} 205 206void 207pktenq(struct pktq *q, void *p) 208{ 209 ASSERT(p); 210 ASSERT(!pktq_full(q)); 211 212 ASSERT(q->p[q->tail] == NULL); 213 q->p[q->tail] = p; 214 q->tail = pktq_next(q->tail); 215} 216 217void* 218pktdeq(struct pktq *q) 219{ 220 void *p; 221 222 if (q->head == q->tail) 223 return (NULL); 224 225 p = q->p[q->head]; 226 ASSERT(p); 227 228 q->p[q->head] = NULL; 229 q->head = pktq_next(q->head); 230 231 return (p); 232} 233 234/******************************************************************************* 235 * crc8 236 * 237 * Computes a crc8 over the input data using the polynomial: 238 * 239 * x^8 + x^7 +x^6 + x^4 + x^2 + 1 240 * 241 * The caller provides the initial value (either CRC8_INIT_VALUE 242 * or the previous returned value) to allow for processing of 243 * discontiguous blocks of data. When generating the CRC the 244 * caller is responsible for complementing the final return value 245 * and inserting it into the byte stream. When checking, a final 246 * return value of CRC8_GOOD_VALUE indicates a valid CRC. 247 * 248 * Reference: Dallas Semiconductor Application Note 27 249 * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", 250 * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., 251 * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt 252 * 253 ******************************************************************************/ 254 255static uint8 crc8_table[256] = { 256 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, 257 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, 258 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, 259 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, 260 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, 261 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, 262 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, 263 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, 264 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, 265 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, 266 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, 267 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, 268 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, 269 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, 270 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, 271 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, 272 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, 273 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, 274 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, 275 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, 276 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, 277 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, 278 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, 279 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, 280 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, 281 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, 282 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, 283 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, 284 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, 285 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, 286 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, 287 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F 288}; 289 290#define CRC_INNER_LOOP(n, c, x) \ 291 (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] 292 293uint8 294crc8( 295 uint8 *pdata, /* pointer to array of data to process */ 296 uint nbytes, /* number of input data bytes to process */ 297 uint8 crc /* either CRC8_INIT_VALUE or previous return value */ 298) 299{ 300 /* hard code the crc loop instead of using CRC_INNER_LOOP macro 301 * to avoid the undefined and unnecessary (uint8 >> 8) operation. */ 302 while (nbytes-- > 0) 303 crc = crc8_table[(crc ^ *pdata++) & 0xff]; 304 305 return crc; 306} 307 308/******************************************************************************* 309 * crc16 310 * 311 * Computes a crc16 over the input data using the polynomial: 312 * 313 * x^16 + x^12 +x^5 + 1 314 * 315 * The caller provides the initial value (either CRC16_INIT_VALUE 316 * or the previous returned value) to allow for processing of 317 * discontiguous blocks of data. When generating the CRC the 318 * caller is responsible for complementing the final return value 319 * and inserting it into the byte stream. When checking, a final 320 * return value of CRC16_GOOD_VALUE indicates a valid CRC. 321 * 322 * Reference: Dallas Semiconductor Application Note 27 323 * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", 324 * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., 325 * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt 326 * 327 ******************************************************************************/ 328 329static uint16 crc16_table[256] = { 330 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 331 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, 332 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, 333 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, 334 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, 335 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, 336 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, 337 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, 338 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, 339 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, 340 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, 341 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, 342 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, 343 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, 344 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, 345 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, 346 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, 347 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, 348 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, 349 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, 350 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, 351 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, 352 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, 353 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, 354 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, 355 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, 356 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, 357 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, 358 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, 359 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, 360 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, 361 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 362}; 363 364uint16 365crc16( 366 uint8 *pdata, /* pointer to array of data to process */ 367 uint nbytes, /* number of input data bytes to process */ 368 uint16 crc /* either CRC16_INIT_VALUE or previous return value */ 369) 370{ 371 while (nbytes-- > 0) 372 CRC_INNER_LOOP(16, crc, *pdata++); 373 return crc; 374} 375 376static uint32 crc32_table[256] = { 377 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 378 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 379 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 380 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 381 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 382 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 383 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 384 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 385 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 386 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 387 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 388 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 389 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 390 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 391 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 392 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 393 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 394 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 395 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 396 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 397 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 398 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 399 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 400 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 401 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 402 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 403 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 404 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 405 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 406 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 407 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 408 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 409 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 410 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 411 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 412 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 413 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 414 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 415 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 416 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 417 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 418 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 419 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 420 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 421 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 422 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 423 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 424 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 425 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 426 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 427 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 428 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 429 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 430 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 431 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 432 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 433 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 434 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 435 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 436 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 437 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 438 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 439 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 440 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 441}; 442 443uint32 444crc32( 445 uint8 *pdata, /* pointer to array of data to process */ 446 uint nbytes, /* number of input data bytes to process */ 447 uint32 crc /* either CRC32_INIT_VALUE or previous return value */ 448) 449{ 450 uint8 *pend; 451#ifdef __mips__ 452 uint8 tmp[4]; 453 ulong *tptr = (ulong *)tmp; 454 455 /* in case the beginning of the buffer isn't aligned */ 456 pend = (uint8 *)((uint)(pdata + 3) & 0xfffffffc); 457 nbytes -= (pend - pdata); 458 while (pdata < pend) 459 CRC_INNER_LOOP(32, crc, *pdata++); 460 461 /* handle bulk of data as 32-bit words */ 462 pend = pdata + (nbytes & 0xfffffffc); 463 while (pdata < pend) { 464 *tptr = *((ulong *)pdata)++; 465 CRC_INNER_LOOP(32, crc, tmp[0]); 466 CRC_INNER_LOOP(32, crc, tmp[1]); 467 CRC_INNER_LOOP(32, crc, tmp[2]); 468 CRC_INNER_LOOP(32, crc, tmp[3]); 469 } 470 471 /* 1-3 bytes at end of buffer */ 472 pend = pdata + (nbytes & 0x03); 473 while (pdata < pend) 474 CRC_INNER_LOOP(32, crc, *pdata++); 475#else 476 pend = pdata + nbytes; 477 while (pdata < pend) 478 CRC_INNER_LOOP(32, crc, *pdata++); 479#endif 480 481 return crc; 482} 483 484 485#ifdef BCMDBG 486#define CLEN 1499 487#define CBUFSIZ (CLEN+4) 488#define CNBUFS 5 489 490void testcrc32(void) 491{ 492 uint j,k,l; 493 uint8 *buf; 494 uint len[CNBUFS]; 495 uint32 crcr; 496 uint32 crc32tv[CNBUFS] = 497 {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110}; 498 499 ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL); 500 501 /* step through all possible alignments */ 502 for (l=0;l<=4;l++) { 503 for (j=0; j<CNBUFS; j++) { 504 len[j] = CLEN; 505 for (k=0; k<len[j]; k++) 506 *(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff; 507 } 508 509 for (j=0; j<CNBUFS; j++) { 510 crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE); 511 ASSERT(crcr == crc32tv[j]); 512 } 513 } 514 515 MFREE(buf, CBUFSIZ*CNBUFS); 516 return; 517} 518#endif 519