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