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