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