2 * Misc useful OS-independent routines.
4 * Copyright 2004, Broadcom Corporation
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
17 #include <bcmendian.h>
20 unsigned char bcm_ctype
[] = {
21 _BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
, /* 0-7 */
22 _BCM_C
,_BCM_C
|_BCM_S
,_BCM_C
|_BCM_S
,_BCM_C
|_BCM_S
,_BCM_C
|_BCM_S
,_BCM_C
|_BCM_S
,_BCM_C
,_BCM_C
, /* 8-15 */
23 _BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
, /* 16-23 */
24 _BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
,_BCM_C
, /* 24-31 */
25 _BCM_S
|_BCM_SP
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
, /* 32-39 */
26 _BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
, /* 40-47 */
27 _BCM_D
,_BCM_D
,_BCM_D
,_BCM_D
,_BCM_D
,_BCM_D
,_BCM_D
,_BCM_D
, /* 48-55 */
28 _BCM_D
,_BCM_D
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
, /* 56-63 */
29 _BCM_P
,_BCM_U
|_BCM_X
,_BCM_U
|_BCM_X
,_BCM_U
|_BCM_X
,_BCM_U
|_BCM_X
,_BCM_U
|_BCM_X
,_BCM_U
|_BCM_X
,_BCM_U
, /* 64-71 */
30 _BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
, /* 72-79 */
31 _BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
, /* 80-87 */
32 _BCM_U
,_BCM_U
,_BCM_U
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
, /* 88-95 */
33 _BCM_P
,_BCM_L
|_BCM_X
,_BCM_L
|_BCM_X
,_BCM_L
|_BCM_X
,_BCM_L
|_BCM_X
,_BCM_L
|_BCM_X
,_BCM_L
|_BCM_X
,_BCM_L
, /* 96-103 */
34 _BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
, /* 104-111 */
35 _BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
, /* 112-119 */
36 _BCM_L
,_BCM_L
,_BCM_L
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_C
, /* 120-127 */
37 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
38 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
39 _BCM_S
|_BCM_SP
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
, /* 160-175 */
40 _BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
,_BCM_P
, /* 176-191 */
41 _BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
, /* 192-207 */
42 _BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_P
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_U
,_BCM_L
, /* 208-223 */
43 _BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
, /* 224-239 */
44 _BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_P
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
,_BCM_L
/* 240-255 */
56 bcm_strtoul(char *cp
, char **endp
, uint base
)
63 while (bcm_isspace(*cp
))
68 else if (cp
[0] == '-') {
75 if ((cp
[1] == 'x') || (cp
[1] == 'X')) {
84 } else if (base
== 16 && (cp
[0] == '0') && ((cp
[1] == 'x') || (cp
[1] == 'X'))) {
90 while (bcm_isxdigit(*cp
) &&
91 (value
= bcm_isdigit(*cp
) ? *cp
-'0' : bcm_toupper(*cp
)-'A'+10) < base
) {
92 result
= result
*base
+ value
;
97 result
= (ulong
)(result
* -1);
112 while (bcm_isdigit(*s
))
113 n
= (n
* 10) + *s
++ - '0';
118 deadbeef(char *p
, uint len
)
120 static uchar meat
[] = { 0xde, 0xad, 0xbe, 0xef };
123 *p
= meat
[((uint
)p
) & 3];
128 /* pretty hex print a contiguous buffer */
130 prhex(char *msg
, uchar
*buf
, uint nbytes
)
136 if (msg
&& (msg
[0] != '\0'))
140 for (i
= 0; i
< nbytes
; i
++) {
142 p
+= sprintf(p
, "%04d: ", i
); /* line prefix */
144 p
+= sprintf(p
, "%02x ", buf
[i
]);
146 printf("%s\n", line
); /* flush line */
151 /* flush last partial line */
153 printf("%s\n", line
);
156 /* pretty hex print a pkt buffer chain */
158 prpkt(char *msg
, void *drv
, void *p0
)
162 if (msg
&& (msg
[0] != '\0'))
165 for (p
= p0
; p
; p
= PKTNEXT(drv
, p
))
166 prhex(NULL
, PKTDATA(drv
, p
), PKTLEN(drv
, p
));
169 /* copy a pkt buffer chain into a buffer */
171 pktcopy(void *drv
, void *p
, uint offset
, int len
, uchar
*buf
)
176 len
= 4096; /* "infinite" */
178 /* skip 'offset' bytes */
179 for (; p
&& offset
; p
= PKTNEXT(drv
, p
)) {
180 if (offset
< (uint
)PKTLEN(drv
, p
))
182 offset
-= PKTLEN(drv
, p
);
189 for (; p
&& len
; p
= PKTNEXT(drv
, p
)) {
190 n
= MIN((uint
)PKTLEN(drv
, p
) - offset
, (uint
)len
);
191 bcopy(PKTDATA(drv
, p
) + offset
, buf
, n
);
201 /* return total length of buffer chain */
203 pkttotlen(void *drv
, void *p
)
208 for (; p
; p
= PKTNEXT(drv
, p
))
209 total
+= PKTLEN(drv
, p
);
215 bcm_ether_ntoa(char *ea
, char *buf
)
217 sprintf(buf
,"%02x:%02x:%02x:%02x:%02x:%02x",
218 (uchar
)ea
[0]&0xff, (uchar
)ea
[1]&0xff, (uchar
)ea
[2]&0xff,
219 (uchar
)ea
[3]&0xff, (uchar
)ea
[4]&0xff, (uchar
)ea
[5]&0xff);
223 /* parse a xx:xx:xx:xx:xx:xx format ethernet address */
225 bcm_ether_atoe(char *p
, char *ea
)
230 ea
[i
++] = (char) bcm_strtoul(p
, &p
, 16);
239 * Advance from the current 1-byte tag/1-byte length/variable-length value
240 * triple, to the next, returning a pointer to the next.
243 bcm_next_tlv(bcm_tlv_t
*elt
, int *buflen
)
247 /* validate current elt */
254 /* validate remaining buflen */
255 if (*buflen
>= (2 + len
+ 2)) {
256 elt
= (bcm_tlv_t
*)(elt
->data
+ len
);
257 *buflen
-= (2 + len
);
266 * Traverse a string of 1-byte tag/1-byte length/variable-length value
267 * triples, returning a pointer to the substring whose first element
268 * matches tag. Stop parsing when we see an element whose ID is greater
269 * than the target key.
272 bcm_parse_ordered_tlvs(void *buf
, int buflen
, uint key
)
277 elt
= (bcm_tlv_t
*)buf
;
280 /* find tagged parameter */
281 while (totlen
>= 2) {
285 /* Punt if we start seeing IDs > than target key */
289 /* validate remaining totlen */
290 if ((id
== key
) && (totlen
>= (len
+ 2)))
293 elt
= (bcm_tlv_t
*)((uint8
*)elt
+ (len
+ 2));
301 * Traverse a string of 1-byte tag/1-byte length/variable-length value
302 * triples, returning a pointer to the substring whose first element
306 bcm_parse_tlvs(void *buf
, int buflen
, uint key
)
311 elt
= (bcm_tlv_t
*)buf
;
314 /* find tagged parameter */
315 while (totlen
>= 2) {
318 /* validate remaining totlen */
319 if ((elt
->id
== key
) && (totlen
>= (len
+ 2)))
322 elt
= (bcm_tlv_t
*)((uint8
*)elt
+ (len
+ 2));
330 pktq_init(struct pktq
*q
, uint maxlen
, bool priority
)
332 q
->head
= q
->tail
= NULL
;
333 q
->priority
= priority
;
339 pktenq(struct pktq
*q
, void *p
, bool lifo
)
344 if (q
->len
>= q
->maxlen
)
347 /* Queueing chains not allowed */
348 ASSERT(PKTLINK(p
) == NULL
);
351 if (q
->tail
== NULL
) {
352 ASSERT(q
->head
== NULL
);
353 q
->head
= q
->tail
= p
;
356 /* Insert at head or tail */
357 else if (q
->priority
== FALSE
) {
358 /* Insert at head (LIFO) */
360 PKTSETLINK(p
, q
->head
);
363 /* Insert at tail (FIFO) */
365 ASSERT(PKTLINK(q
->tail
) == NULL
);
366 PKTSETLINK(q
->tail
, p
);
372 /* Insert by priority */
376 /* Shortcut to insertion at tail */
377 if (PKTPRIO(p
) < PKTPRIO(q
->tail
) ||
378 (!lifo
&& PKTPRIO(p
) <= PKTPRIO(q
->tail
))) {
382 /* Insert at head or in the middle */
388 for (; next
; prev
= next
, next
= PKTLINK(next
)) {
389 /* Priority queue invariant */
390 ASSERT(!prev
|| PKTPRIO(prev
) >= PKTPRIO(next
));
391 /* Insert at head of string of packets of same priority (LIFO) */
393 if (PKTPRIO(p
) >= PKTPRIO(next
))
396 /* Insert at tail of string of packets of same priority (FIFO) */
398 if (PKTPRIO(p
) > PKTPRIO(next
))
404 ASSERT(PKTLINK(q
->tail
) == NULL
);
405 PKTSETLINK(q
->tail
, p
);
409 /* Insert in the middle */
416 PKTSETLINK(p
, q
->head
);
421 /* List invariants after insertion */
423 ASSERT(PKTLINK(q
->tail
) == NULL
);
430 pktdeq(struct pktq
*q
)
436 q
->head
= PKTLINK(p
);
443 ASSERT(q
->tail
== NULL
);
449 /*******************************************************************************
452 * Computes a crc8 over the input data using the polynomial:
454 * x^8 + x^7 +x^6 + x^4 + x^2 + 1
456 * The caller provides the initial value (either CRC8_INIT_VALUE
457 * or the previous returned value) to allow for processing of
458 * discontiguous blocks of data. When generating the CRC the
459 * caller is responsible for complementing the final return value
460 * and inserting it into the byte stream. When checking, a final
461 * return value of CRC8_GOOD_VALUE indicates a valid CRC.
463 * Reference: Dallas Semiconductor Application Note 27
464 * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
465 * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
466 * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
468 ******************************************************************************/
470 static uint8 crc8_table
[256] = {
471 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
472 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
473 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
474 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
475 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
476 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
477 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
478 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
479 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
480 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
481 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
482 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
483 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
484 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
485 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
486 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
487 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
488 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
489 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
490 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
491 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
492 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
493 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
494 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
495 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
496 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
497 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
498 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
499 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
500 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
501 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
502 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
506 * Search the name=value vars for a specific one and return its value.
507 * Returns NULL if not found.
510 getvar(char *vars
, char *name
)
517 /* first look in vars[] */
518 for (s
= vars
; s
&& *s
; ) {
519 if ((bcmp(s
, name
, len
) == 0) && (s
[len
] == '='))
526 /* then query nvram */
527 return (nvram_get(name
));
531 * Search the vars for a specific one and return its value as
532 * an integer. Returns 0 if not found.
535 getintvar(char *vars
, char *name
)
539 if ((val
= getvar(vars
, name
)) == NULL
)
542 return (bcm_strtoul(val
, NULL
, 0));
545 /* return pointer to location of substring 'needle' in 'haystack' */
547 bcmstrstr(char *haystack
, char *needle
)
552 if ((haystack
== NULL
) || (needle
== NULL
))
555 nlen
= strlen(needle
);
556 len
= strlen(haystack
) - nlen
+ 1;
558 for (i
= 0; i
< len
; i
++)
559 if (bcmp(needle
, &haystack
[i
], nlen
) == 0)
560 return (&haystack
[i
]);
569 for (i
= 0; i
< ms
; i
++) {
574 #define CRC_INNER_LOOP(n, c, x) \
575 (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
579 uint8
*pdata
, /* pointer to array of data to process */
580 uint nbytes
, /* number of input data bytes to process */
581 uint8 crc
/* either CRC8_INIT_VALUE or previous return value */
584 /* hard code the crc loop instead of using CRC_INNER_LOOP macro
585 * to avoid the undefined and unnecessary (uint8 >> 8) operation. */
587 crc
= crc8_table
[(crc
^ *pdata
++) & 0xff];
592 /*******************************************************************************
595 * Computes a crc16 over the input data using the polynomial:
597 * x^16 + x^12 +x^5 + 1
599 * The caller provides the initial value (either CRC16_INIT_VALUE
600 * or the previous returned value) to allow for processing of
601 * discontiguous blocks of data. When generating the CRC the
602 * caller is responsible for complementing the final return value
603 * and inserting it into the byte stream. When checking, a final
604 * return value of CRC16_GOOD_VALUE indicates a valid CRC.
606 * Reference: Dallas Semiconductor Application Note 27
607 * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
608 * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
609 * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
611 ******************************************************************************/
613 static uint16 crc16_table
[256] = {
614 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
615 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
616 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
617 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
618 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
619 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
620 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
621 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
622 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
623 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
624 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
625 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
626 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
627 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
628 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
629 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
630 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
631 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
632 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
633 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
634 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
635 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
636 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
637 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
638 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
639 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
640 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
641 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
642 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
643 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
644 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
645 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
650 uint8
*pdata
, /* pointer to array of data to process */
651 uint nbytes
, /* number of input data bytes to process */
652 uint16 crc
/* either CRC16_INIT_VALUE or previous return value */
656 CRC_INNER_LOOP(16, crc
, *pdata
++);
660 static uint32 crc32_table
[256] = {
661 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
662 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
663 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
664 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
665 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
666 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
667 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
668 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
669 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
670 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
671 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
672 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
673 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
674 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
675 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
676 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
677 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
678 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
679 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
680 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
681 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
682 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
683 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
684 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
685 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
686 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
687 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
688 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
689 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
690 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
691 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
692 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
693 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
694 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
695 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
696 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
697 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
698 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
699 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
700 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
701 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
702 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
703 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
704 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
705 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
706 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
707 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
708 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
709 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
710 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
711 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
712 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
713 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
714 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
715 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
716 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
717 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
718 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
719 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
720 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
721 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
722 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
723 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
724 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
729 uint8
*pdata
, /* pointer to array of data to process */
730 uint nbytes
, /* number of input data bytes to process */
731 uint32 crc
/* either CRC32_INIT_VALUE or previous return value */
737 ulong
*tptr
= (ulong
*)tmp
;
739 /* in case the beginning of the buffer isn't aligned */
740 pend
= (uint8
*)((uint
)(pdata
+ 3) & 0xfffffffc);
741 nbytes
-= (pend
- pdata
);
743 CRC_INNER_LOOP(32, crc
, *pdata
++);
745 /* handle bulk of data as 32-bit words */
746 pend
= pdata
+ (nbytes
& 0xfffffffc);
747 while (pdata
< pend
) {
748 *tptr
= *((ulong
*)pdata
)++;
749 CRC_INNER_LOOP(32, crc
, tmp
[0]);
750 CRC_INNER_LOOP(32, crc
, tmp
[1]);
751 CRC_INNER_LOOP(32, crc
, tmp
[2]);
752 CRC_INNER_LOOP(32, crc
, tmp
[3]);
755 /* 1-3 bytes at end of buffer */
756 pend
= pdata
+ (nbytes
& 0x03);
758 CRC_INNER_LOOP(32, crc
, *pdata
++);
760 pend
= pdata
+ nbytes
;
762 CRC_INNER_LOOP(32, crc
, *pdata
++);
770 #define CBUFSIZ (CLEN+4)
779 uint32 crc32tv
[CNBUFS
] =
780 {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110};
782 ASSERT((buf
= MALLOC(CBUFSIZ
*CNBUFS
)) != NULL
);
784 /* step through all possible alignments */
786 for (j
=0; j
<CNBUFS
; j
++) {
788 for (k
=0; k
<len
[j
]; k
++)
789 *(buf
+ j
*CBUFSIZ
+ (k
+l
)) = (j
+k
) & 0xff;
792 for (j
=0; j
<CNBUFS
; j
++) {
793 crcr
= crc32(buf
+ j
*CBUFSIZ
+ l
, len
[j
], CRC32_INIT_VALUE
);
794 ASSERT(crcr
== crc32tv
[j
]);
798 MFREE(buf
, CBUFSIZ
*CNBUFS
);
This page took 0.097158 seconds and 5 git commands to generate.