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