staging: brcm80211: bcmp => memcmp
[pandora-kernel.git] / drivers / staging / brcm80211 / util / bcmutils.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <linux/ctype.h>
18 #include <linux/kernel.h>
19 #include <linux/string.h>
20 #include <bcmdefs.h>
21 #include <stdarg.h>
22 #include <linux/module.h>
23 #include <linux/pci.h>
24 #include <linux/netdevice.h>
25 #include <osl.h>
26 #include <bcmutils.h>
27 #include <siutils.h>
28 #include <bcmnvram.h>
29 #include <bcmendian.h>
30 #include <bcmdevs.h>
31 #include <proto/ethernet.h>
32 #include <proto/802.1d.h>
33 #include <proto/802.11.h>
34
35 /* copy a buffer into a pkt buffer chain */
36 uint pktfrombuf(struct osl_info *osh, struct sk_buff *p, uint offset, int len,
37                 unsigned char *buf)
38 {
39         uint n, ret = 0;
40
41         /* skip 'offset' bytes */
42         for (; p && offset; p = p->next) {
43                 if (offset < (uint) (p->len))
44                         break;
45                 offset -= p->len;
46         }
47
48         if (!p)
49                 return 0;
50
51         /* copy the data */
52         for (; p && len; p = p->next) {
53                 n = min((uint) (p->len) - offset, (uint) len);
54                 bcopy(buf, p->data + offset, n);
55                 buf += n;
56                 len -= n;
57                 ret += n;
58                 offset = 0;
59         }
60
61         return ret;
62 }
63 /* return total length of buffer chain */
64 uint BCMFASTPATH pkttotlen(struct osl_info *osh, struct sk_buff *p)
65 {
66         uint total;
67
68         total = 0;
69         for (; p; p = p->next)
70                 total += p->len;
71         return total;
72 }
73
74 /*
75  * osl multiple-precedence packet queue
76  * hi_prec is always >= the number of the highest non-empty precedence
77  */
78 struct sk_buff *BCMFASTPATH pktq_penq(struct pktq *pq, int prec,
79                                       struct sk_buff *p)
80 {
81         struct pktq_prec *q;
82
83         ASSERT(prec >= 0 && prec < pq->num_prec);
84         ASSERT(p->prev == NULL);        /* queueing chains not allowed */
85
86         ASSERT(!pktq_full(pq));
87         ASSERT(!pktq_pfull(pq, prec));
88
89         q = &pq->q[prec];
90
91         if (q->head)
92                 q->tail->prev = p;
93         else
94                 q->head = p;
95
96         q->tail = p;
97         q->len++;
98
99         pq->len++;
100
101         if (pq->hi_prec < prec)
102                 pq->hi_prec = (u8) prec;
103
104         return p;
105 }
106
107 struct sk_buff *BCMFASTPATH pktq_penq_head(struct pktq *pq, int prec,
108                                            struct sk_buff *p)
109 {
110         struct pktq_prec *q;
111
112         ASSERT(prec >= 0 && prec < pq->num_prec);
113         ASSERT(p->prev == NULL);        /* queueing chains not allowed */
114
115         ASSERT(!pktq_full(pq));
116         ASSERT(!pktq_pfull(pq, prec));
117
118         q = &pq->q[prec];
119
120         if (q->head == NULL)
121                 q->tail = p;
122
123         p->prev = q->head;
124         q->head = p;
125         q->len++;
126
127         pq->len++;
128
129         if (pq->hi_prec < prec)
130                 pq->hi_prec = (u8) prec;
131
132         return p;
133 }
134
135 struct sk_buff *BCMFASTPATH pktq_pdeq(struct pktq *pq, int prec)
136 {
137         struct pktq_prec *q;
138         struct sk_buff *p;
139
140         ASSERT(prec >= 0 && prec < pq->num_prec);
141
142         q = &pq->q[prec];
143
144         p = q->head;
145         if (p == NULL)
146                 return NULL;
147
148         q->head = p->prev;
149         if (q->head == NULL)
150                 q->tail = NULL;
151
152         q->len--;
153
154         pq->len--;
155
156         p->prev = NULL;
157
158         return p;
159 }
160
161 struct sk_buff *BCMFASTPATH pktq_pdeq_tail(struct pktq *pq, int prec)
162 {
163         struct pktq_prec *q;
164         struct sk_buff *p, *prev;
165
166         ASSERT(prec >= 0 && prec < pq->num_prec);
167
168         q = &pq->q[prec];
169
170         p = q->head;
171         if (p == NULL)
172                 return NULL;
173
174         for (prev = NULL; p != q->tail; p = p->prev)
175                 prev = p;
176
177         if (prev)
178                 prev->prev = NULL;
179         else
180                 q->head = NULL;
181
182         q->tail = prev;
183         q->len--;
184
185         pq->len--;
186
187         return p;
188 }
189
190 #ifdef BRCM_FULLMAC
191 void pktq_pflush(struct osl_info *osh, struct pktq *pq, int prec, bool dir)
192 {
193         struct pktq_prec *q;
194         struct sk_buff *p;
195
196         q = &pq->q[prec];
197         p = q->head;
198         while (p) {
199                 q->head = p->prev;
200                 p->prev = NULL;
201                 PKTFREE(osh, p, dir);
202                 q->len--;
203                 pq->len--;
204                 p = q->head;
205         }
206         ASSERT(q->len == 0);
207         q->tail = NULL;
208 }
209
210 void pktq_flush(struct osl_info *osh, struct pktq *pq, bool dir)
211 {
212         int prec;
213         for (prec = 0; prec < pq->num_prec; prec++)
214                 pktq_pflush(osh, pq, prec, dir);
215         ASSERT(pq->len == 0);
216 }
217 #else /* !BRCM_FULLMAC */
218 void
219 pktq_pflush(struct osl_info *osh, struct pktq *pq, int prec, bool dir,
220             ifpkt_cb_t fn, int arg)
221 {
222         struct pktq_prec *q;
223         struct sk_buff *p, *prev = NULL;
224
225         q = &pq->q[prec];
226         p = q->head;
227         while (p) {
228                 if (fn == NULL || (*fn) (p, arg)) {
229                         bool head = (p == q->head);
230                         if (head)
231                                 q->head = p->prev;
232                         else
233                                 prev->prev = p->prev;
234                         p->prev = NULL;
235                         PKTFREE(osh, p, dir);
236                         q->len--;
237                         pq->len--;
238                         p = (head ? q->head : prev->prev);
239                 } else {
240                         prev = p;
241                         p = p->prev;
242                 }
243         }
244
245         if (q->head == NULL) {
246                 ASSERT(q->len == 0);
247                 q->tail = NULL;
248         }
249 }
250
251 void pktq_flush(struct osl_info *osh, struct pktq *pq, bool dir,
252                 ifpkt_cb_t fn, int arg)
253 {
254         int prec;
255         for (prec = 0; prec < pq->num_prec; prec++)
256                 pktq_pflush(osh, pq, prec, dir, fn, arg);
257         if (fn == NULL)
258                 ASSERT(pq->len == 0);
259 }
260 #endif /* BRCM_FULLMAC */
261
262 void pktq_init(struct pktq *pq, int num_prec, int max_len)
263 {
264         int prec;
265
266         ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC);
267
268         /* pq is variable size; only zero out what's requested */
269         memset(pq, 0,
270               offsetof(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
271
272         pq->num_prec = (u16) num_prec;
273
274         pq->max = (u16) max_len;
275
276         for (prec = 0; prec < num_prec; prec++)
277                 pq->q[prec].max = pq->max;
278 }
279
280 struct sk_buff *pktq_peek_tail(struct pktq *pq, int *prec_out)
281 {
282         int prec;
283
284         if (pq->len == 0)
285                 return NULL;
286
287         for (prec = 0; prec < pq->hi_prec; prec++)
288                 if (pq->q[prec].head)
289                         break;
290
291         if (prec_out)
292                 *prec_out = prec;
293
294         return pq->q[prec].tail;
295 }
296
297 /* Return sum of lengths of a specific set of precedences */
298 int pktq_mlen(struct pktq *pq, uint prec_bmp)
299 {
300         int prec, len;
301
302         len = 0;
303
304         for (prec = 0; prec <= pq->hi_prec; prec++)
305                 if (prec_bmp & (1 << prec))
306                         len += pq->q[prec].len;
307
308         return len;
309 }
310 /* Priority dequeue from a specific set of precedences */
311 struct sk_buff *BCMFASTPATH pktq_mdeq(struct pktq *pq, uint prec_bmp,
312                                       int *prec_out)
313 {
314         struct pktq_prec *q;
315         struct sk_buff *p;
316         int prec;
317
318         if (pq->len == 0)
319                 return NULL;
320
321         while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
322                 pq->hi_prec--;
323
324         while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
325                 if (prec-- == 0)
326                         return NULL;
327
328         q = &pq->q[prec];
329
330         p = q->head;
331         if (p == NULL)
332                 return NULL;
333
334         q->head = p->prev;
335         if (q->head == NULL)
336                 q->tail = NULL;
337
338         q->len--;
339
340         if (prec_out)
341                 *prec_out = prec;
342
343         pq->len--;
344
345         p->prev = NULL;
346
347         return p;
348 }
349
350 /* parse a xx:xx:xx:xx:xx:xx format ethernet address */
351 int bcm_ether_atoe(char *p, struct ether_addr *ea)
352 {
353         int i = 0;
354
355         for (;;) {
356                 ea->octet[i++] = (char)simple_strtoul(p, &p, 16);
357                 if (!*p++ || i == 6)
358                         break;
359         }
360
361         return i == 6;
362 }
363
364 /*
365  * Search the name=value vars for a specific one and return its value.
366  * Returns NULL if not found.
367  */
368 char *getvar(char *vars, const char *name)
369 {
370         char *s;
371         int len;
372
373         if (!name)
374                 return NULL;
375
376         len = strlen(name);
377         if (len == 0)
378                 return NULL;
379
380         /* first look in vars[] */
381         for (s = vars; s && *s;) {
382                 if ((memcmp(s, name, len) == 0) && (s[len] == '='))
383                         return &s[len + 1];
384
385                 while (*s++)
386                         ;
387         }
388 #ifdef BRCM_FULLMAC
389         return NULL;
390 #else
391         /* then query nvram */
392         return nvram_get(name);
393 #endif
394 }
395
396 /*
397  * Search the vars for a specific one and return its value as
398  * an integer. Returns 0 if not found.
399  */
400 int getintvar(char *vars, const char *name)
401 {
402         char *val;
403
404         val = getvar(vars, name);
405         if (val == NULL)
406                 return 0;
407
408         return simple_strtoul(val, NULL, 0);
409 }
410
411 #if defined(BCMDBG)
412 /* pretty hex print a pkt buffer chain */
413 void prpkt(const char *msg, struct osl_info *osh, struct sk_buff *p0)
414 {
415         struct sk_buff *p;
416
417         if (msg && (msg[0] != '\0'))
418                 printf("%s:\n", msg);
419
420         for (p = p0; p; p = p->next)
421                 prhex(NULL, p->data, p->len);
422 }
423 #endif                          /* defined(BCMDBG) */
424
425 static char bcm_undeferrstr[BCME_STRLEN];
426
427 static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE;
428
429 /* Convert the error codes into related error strings  */
430 const char *bcmerrorstr(int bcmerror)
431 {
432         /* check if someone added a bcmerror code but
433                  forgot to add errorstring */
434         ASSERT(ABS(BCME_LAST) == (ARRAY_SIZE(bcmerrorstrtable) - 1));
435
436         if (bcmerror > 0 || bcmerror < BCME_LAST) {
437                 snprintf(bcm_undeferrstr, BCME_STRLEN, "Undefined error %d",
438                          bcmerror);
439                 return bcm_undeferrstr;
440         }
441
442         ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN);
443
444         return bcmerrorstrtable[-bcmerror];
445 }
446
447 /* iovar table lookup */
448 const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name)
449 {
450         const bcm_iovar_t *vi;
451         const char *lookup_name;
452
453         /* skip any ':' delimited option prefixes */
454         lookup_name = strrchr(name, ':');
455         if (lookup_name != NULL)
456                 lookup_name++;
457         else
458                 lookup_name = name;
459
460         ASSERT(table != NULL);
461
462         for (vi = table; vi->name; vi++) {
463                 if (!strcmp(vi->name, lookup_name))
464                         return vi;
465         }
466         /* ran to end of table */
467
468         return NULL;            /* var name not found */
469 }
470
471 int bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
472 {
473         int bcmerror = 0;
474
475         /* length check on io buf */
476         switch (vi->type) {
477         case IOVT_BOOL:
478         case IOVT_INT8:
479         case IOVT_INT16:
480         case IOVT_INT32:
481         case IOVT_UINT8:
482         case IOVT_UINT16:
483         case IOVT_UINT32:
484                 /* all integers are s32 sized args at the ioctl interface */
485                 if (len < (int)sizeof(int)) {
486                         bcmerror = BCME_BUFTOOSHORT;
487                 }
488                 break;
489
490         case IOVT_BUFFER:
491                 /* buffer must meet minimum length requirement */
492                 if (len < vi->minlen) {
493                         bcmerror = BCME_BUFTOOSHORT;
494                 }
495                 break;
496
497         case IOVT_VOID:
498                 if (!set) {
499                         /* Cannot return nil... */
500                         bcmerror = BCME_UNSUPPORTED;
501                 } else if (len) {
502                         /* Set is an action w/o parameters */
503                         bcmerror = BCME_BUFTOOLONG;
504                 }
505                 break;
506
507         default:
508                 /* unknown type for length check in iovar info */
509                 ASSERT(0);
510                 bcmerror = BCME_UNSUPPORTED;
511         }
512
513         return bcmerror;
514 }
515
516 /*******************************************************************************
517  * crc8
518  *
519  * Computes a crc8 over the input data using the polynomial:
520  *
521  *       x^8 + x^7 +x^6 + x^4 + x^2 + 1
522  *
523  * The caller provides the initial value (either CRC8_INIT_VALUE
524  * or the previous returned value) to allow for processing of
525  * discontiguous blocks of data.  When generating the CRC the
526  * caller is responsible for complementing the final return value
527  * and inserting it into the byte stream.  When checking, a final
528  * return value of CRC8_GOOD_VALUE indicates a valid CRC.
529  *
530  * Reference: Dallas Semiconductor Application Note 27
531  *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
532  *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
533  *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
534  *
535  * ****************************************************************************
536  */
537
538 static const u8 crc8_table[256] = {
539         0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
540         0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
541         0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
542         0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
543         0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
544         0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
545         0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
546         0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
547         0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
548         0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
549         0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
550         0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
551         0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
552         0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
553         0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
554         0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
555         0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
556         0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
557         0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
558         0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
559         0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
560         0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
561         0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
562         0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
563         0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
564         0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
565         0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
566         0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
567         0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
568         0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
569         0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
570         0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
571 };
572
573 #define CRC_INNER_LOOP(n, c, x) \
574         ((c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff])
575
576 u8 hndcrc8(u8 *pdata,   /* pointer to array of data to process */
577                          uint nbytes,   /* number of input data bytes to process */
578                          u8 crc /* either CRC8_INIT_VALUE or previous return value */
579     ) {
580         /* hard code the crc loop instead of using CRC_INNER_LOOP macro
581          * to avoid the undefined and unnecessary (u8 >> 8) operation.
582          */
583         while (nbytes-- > 0)
584                 crc = crc8_table[(crc ^ *pdata++) & 0xff];
585
586         return crc;
587 }
588
589 /*******************************************************************************
590  * crc16
591  *
592  * Computes a crc16 over the input data using the polynomial:
593  *
594  *       x^16 + x^12 +x^5 + 1
595  *
596  * The caller provides the initial value (either CRC16_INIT_VALUE
597  * or the previous returned value) to allow for processing of
598  * discontiguous blocks of data.  When generating the CRC the
599  * caller is responsible for complementing the final return value
600  * and inserting it into the byte stream.  When checking, a final
601  * return value of CRC16_GOOD_VALUE indicates a valid CRC.
602  *
603  * Reference: Dallas Semiconductor Application Note 27
604  *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
605  *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
606  *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
607  *
608  * ****************************************************************************
609  */
610
611 static const u16 crc16_table[256] = {
612         0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
613         0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
614         0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
615         0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
616         0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
617         0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
618         0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
619         0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
620         0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
621         0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
622         0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
623         0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
624         0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
625         0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
626         0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
627         0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
628         0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
629         0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
630         0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
631         0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
632         0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
633         0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
634         0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
635         0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
636         0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
637         0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
638         0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
639         0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
640         0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
641         0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
642         0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
643         0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
644 };
645
646 u16 hndcrc16(u8 *pdata, /* pointer to array of data to process */
647         uint nbytes,    /* number of input data bytes to process */
648         u16 crc /* either CRC16_INIT_VALUE or previous return value */
649     ) {
650         while (nbytes-- > 0)
651                 CRC_INNER_LOOP(16, crc, *pdata++);
652         return crc;
653 }
654
655 static const u32 crc32_table[256] = {
656         0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
657         0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
658         0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
659         0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
660         0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
661         0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
662         0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
663         0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
664         0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
665         0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
666         0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
667         0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
668         0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
669         0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
670         0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
671         0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
672         0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
673         0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
674         0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
675         0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
676         0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
677         0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
678         0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
679         0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
680         0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
681         0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
682         0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
683         0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
684         0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
685         0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
686         0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
687         0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
688         0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
689         0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
690         0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
691         0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
692         0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
693         0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
694         0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
695         0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
696         0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
697         0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
698         0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
699         0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
700         0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
701         0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
702         0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
703         0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
704         0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
705         0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
706         0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
707         0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
708         0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
709         0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
710         0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
711         0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
712         0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
713         0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
714         0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
715         0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
716         0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
717         0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
718         0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
719         0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
720 };
721
722 u32 hndcrc32(u8 *pdata, /* pointer to array of data to process */
723                 uint nbytes,    /* number of input data bytes to process */
724                 u32 crc /* either CRC32_INIT_VALUE or previous
725                                          return value */
726 )
727 {
728         u8 *pend;
729 #ifdef __mips__
730         u8 tmp[4];
731         unsigned long *tptr = (unsigned long *) tmp;
732
733         /* in case the beginning of the buffer isn't aligned */
734         pend = (u8 *) ((uint) (pdata + 3) & 0xfffffffc);
735         nbytes -= (pend - pdata);
736         while (pdata < pend)
737                 CRC_INNER_LOOP(32, crc, *pdata++);
738
739         /* handle bulk of data as 32-bit words */
740         pend = pdata + (nbytes & 0xfffffffc);
741         while (pdata < pend) {
742                 *tptr = *(unsigned long *) pdata;
743                 pdata += sizeof(unsigned long *);
744                 CRC_INNER_LOOP(32, crc, tmp[0]);
745                 CRC_INNER_LOOP(32, crc, tmp[1]);
746                 CRC_INNER_LOOP(32, crc, tmp[2]);
747                 CRC_INNER_LOOP(32, crc, tmp[3]);
748         }
749
750         /* 1-3 bytes at end of buffer */
751         pend = pdata + (nbytes & 0x03);
752         while (pdata < pend)
753                 CRC_INNER_LOOP(32, crc, *pdata++);
754 #else
755         pend = pdata + nbytes;
756         while (pdata < pend)
757                 CRC_INNER_LOOP(32, crc, *pdata++);
758 #endif                          /* __mips__ */
759
760         return crc;
761 }
762 /*
763  * Traverse a string of 1-byte tag/1-byte length/variable-length value
764  * triples, returning a pointer to the substring whose first element
765  * matches tag
766  */
767 bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key)
768 {
769         bcm_tlv_t *elt;
770         int totlen;
771
772         elt = (bcm_tlv_t *) buf;
773         totlen = buflen;
774
775         /* find tagged parameter */
776         while (totlen >= 2) {
777                 int len = elt->len;
778
779                 /* validate remaining totlen */
780                 if ((elt->id == key) && (totlen >= (len + 2)))
781                         return elt;
782
783                 elt = (bcm_tlv_t *) ((u8 *) elt + (len + 2));
784                 totlen -= (len + 2);
785         }
786
787         return NULL;
788 }
789
790
791 #if defined(BCMDBG)
792 int
793 bcm_format_flags(const bcm_bit_desc_t *bd, u32 flags, char *buf, int len)
794 {
795         int i;
796         char *p = buf;
797         char hexstr[16];
798         int slen = 0, nlen = 0;
799         u32 bit;
800         const char *name;
801
802         if (len < 2 || !buf)
803                 return 0;
804
805         buf[0] = '\0';
806
807         for (i = 0; flags != 0; i++) {
808                 bit = bd[i].bit;
809                 name = bd[i].name;
810                 if (bit == 0 && flags != 0) {
811                         /* print any unnamed bits */
812                         snprintf(hexstr, 16, "0x%X", flags);
813                         name = hexstr;
814                         flags = 0;      /* exit loop */
815                 } else if ((flags & bit) == 0)
816                         continue;
817                 flags &= ~bit;
818                 nlen = strlen(name);
819                 slen += nlen;
820                 /* count btwn flag space */
821                 if (flags != 0)
822                         slen += 1;
823                 /* need NULL char as well */
824                 if (len <= slen)
825                         break;
826                 /* copy NULL char but don't count it */
827                 strncpy(p, name, nlen + 1);
828                 p += nlen;
829                 /* copy btwn flag space and NULL char */
830                 if (flags != 0)
831                         p += snprintf(p, 2, " ");
832                 len -= slen;
833         }
834
835         /* indicate the str was too short */
836         if (flags != 0) {
837                 if (len < 2)
838                         p -= 2 - len;   /* overwrite last char */
839                 p += snprintf(p, 2, ">");
840         }
841
842         return (int)(p - buf);
843 }
844
845 /* print bytes formatted as hex to a string. return the resulting string length */
846 int bcm_format_hex(char *str, const void *bytes, int len)
847 {
848         int i;
849         char *p = str;
850         const u8 *src = (const u8 *)bytes;
851
852         for (i = 0; i < len; i++) {
853                 p += snprintf(p, 3, "%02X", *src);
854                 src++;
855         }
856         return (int)(p - str);
857 }
858 #endif                          /* defined(BCMDBG) */
859
860 /* pretty hex print a contiguous buffer */
861 void prhex(const char *msg, unsigned char *buf, uint nbytes)
862 {
863         char line[128], *p;
864         int len = sizeof(line);
865         int nchar;
866         uint i;
867
868         if (msg && (msg[0] != '\0'))
869                 printf("%s:\n", msg);
870
871         p = line;
872         for (i = 0; i < nbytes; i++) {
873                 if (i % 16 == 0) {
874                         nchar = snprintf(p, len, "  %04d: ", i);        /* line prefix */
875                         p += nchar;
876                         len -= nchar;
877                 }
878                 if (len > 0) {
879                         nchar = snprintf(p, len, "%02x ", buf[i]);
880                         p += nchar;
881                         len -= nchar;
882                 }
883
884                 if (i % 16 == 15) {
885                         printf("%s\n", line);   /* flush line */
886                         p = line;
887                         len = sizeof(line);
888                 }
889         }
890
891         /* flush last partial line */
892         if (p != line)
893                 printf("%s\n", line);
894 }
895
896 char *bcm_chipname(uint chipid, char *buf, uint len)
897 {
898         const char *fmt;
899
900         fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
901         snprintf(buf, len, fmt, chipid);
902         return buf;
903 }
904
905 uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
906 {
907         uint len;
908
909         len = strlen(name) + 1;
910
911         if ((len + datalen) > buflen)
912                 return 0;
913
914         strncpy(buf, name, buflen);
915
916         /* append data onto the end of the name string */
917         memcpy(&buf[len], data, datalen);
918         len += datalen;
919
920         return len;
921 }
922
923 /* Quarter dBm units to mW
924  * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
925  * Table is offset so the last entry is largest mW value that fits in
926  * a u16.
927  */
928
929 #define QDBM_OFFSET 153         /* Offset for first entry */
930 #define QDBM_TABLE_LEN 40       /* Table size */
931
932 /* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
933  * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
934  */
935 #define QDBM_TABLE_LOW_BOUND 6493       /* Low bound */
936
937 /* Largest mW value that will round down to the last table entry,
938  * QDBM_OFFSET + QDBM_TABLE_LEN-1.
939  * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
940  * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
941  */
942 #define QDBM_TABLE_HIGH_BOUND 64938     /* High bound */
943
944 static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
945 /* qdBm:        +0      +1      +2      +3      +4      +5      +6      +7 */
946 /* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
947 /* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
948 /* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
949 /* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
950 /* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
951 };
952
953 u16 bcm_qdbm_to_mw(u8 qdbm)
954 {
955         uint factor = 1;
956         int idx = qdbm - QDBM_OFFSET;
957
958         if (idx >= QDBM_TABLE_LEN) {
959                 /* clamp to max u16 mW value */
960                 return 0xFFFF;
961         }
962
963         /* scale the qdBm index up to the range of the table 0-40
964          * where an offset of 40 qdBm equals a factor of 10 mW.
965          */
966         while (idx < 0) {
967                 idx += 40;
968                 factor *= 10;
969         }
970
971         /* return the mW value scaled down to the correct factor of 10,
972          * adding in factor/2 to get proper rounding.
973          */
974         return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
975 }
976 u8 bcm_mw_to_qdbm(u16 mw)
977 {
978         u8 qdbm;
979         int offset;
980         uint mw_uint = mw;
981         uint boundary;
982
983         /* handle boundary case */
984         if (mw_uint <= 1)
985                 return 0;
986
987         offset = QDBM_OFFSET;
988
989         /* move mw into the range of the table */
990         while (mw_uint < QDBM_TABLE_LOW_BOUND) {
991                 mw_uint *= 10;
992                 offset -= 40;
993         }
994
995         for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
996                 boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
997                                                     nqdBm_to_mW_map[qdbm]) / 2;
998                 if (mw_uint < boundary)
999                         break;
1000         }
1001
1002         qdbm += (u8) offset;
1003
1004         return qdbm;
1005 }
1006 uint bcm_bitcount(u8 *bitmap, uint length)
1007 {
1008         uint bitcount = 0, i;
1009         u8 tmp;
1010         for (i = 0; i < length; i++) {
1011                 tmp = bitmap[i];
1012                 while (tmp) {
1013                         bitcount++;
1014                         tmp &= (tmp - 1);
1015                 }
1016         }
1017         return bitcount;
1018 }
1019 /* Initialization of bcmstrbuf structure */
1020 void bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
1021 {
1022         b->origsize = b->size = size;
1023         b->origbuf = b->buf = buf;
1024 }
1025
1026 /* Buffer sprintf wrapper to guard against buffer overflow */
1027 int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
1028 {
1029         va_list ap;
1030         int r;
1031
1032         va_start(ap, fmt);
1033         r = vsnprintf(b->buf, b->size, fmt, ap);
1034
1035         /* Non Ansi C99 compliant returns -1,
1036          * Ansi compliant return r >= b->size,
1037          * bcmstdlib returns 0, handle all
1038          */
1039         if ((r == -1) || (r >= (int)b->size) || (r == 0)) {
1040                 b->size = 0;
1041         } else {
1042                 b->size -= r;
1043                 b->buf += r;
1044         }
1045
1046         va_end(ap);
1047
1048         return r;
1049 }
1050