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