]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/brcm80211/brcmfmac/bcmutils.c
Staging: brcm80211: remove STATIC definition
[net-next-2.6.git] / drivers / staging / brcm80211 / brcmfmac / 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 <typedefs.h>
18 #include <bcmdefs.h>
19 #include <stdarg.h>
20 #include <bcmutils.h>
21 #ifdef BCMDRIVER
22 #include <osl.h>
23 #include <siutils.h>
24 #else
25 #include <stdio.h>
26 #include <string.h>
27 /* This case for external supplicant use */
28 #if defined(BCMEXTSUP)
29 #include <bcm_osl.h>
30 #endif
31
32 #endif                          /* BCMDRIVER */
33 #include <bcmendian.h>
34 #include <bcmdevs.h>
35 #include <bcmnvram.h>
36 #include <proto/ethernet.h>
37 #include <proto/vlan.h>
38 #include <proto/bcmip.h>
39 #include <proto/802.1d.h>
40 #include <proto/802.11.h>
41
42 #ifdef BCMDRIVER
43
44 /* copy a pkt buffer chain into a buffer */
45 uint pktcopy(osl_t *osh, void *p, uint offset, int len, unsigned char * buf)
46 {
47         uint n, ret = 0;
48
49         if (len < 0)
50                 len = 4096;     /* "infinite" */
51
52         /* skip 'offset' bytes */
53         for (; p && offset; p = PKTNEXT(p)) {
54                 if (offset < (uint) PKTLEN(p))
55                         break;
56                 offset -= PKTLEN(p);
57         }
58
59         if (!p)
60                 return 0;
61
62         /* copy the data */
63         for (; p && len; p = PKTNEXT(p)) {
64                 n = MIN((uint) PKTLEN(p) - offset, (uint) len);
65                 bcopy(PKTDATA(p) + offset, buf, n);
66                 buf += n;
67                 len -= n;
68                 ret += n;
69                 offset = 0;
70         }
71
72         return ret;
73 }
74
75 /* copy a buffer into a pkt buffer chain */
76 uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, unsigned char *buf)
77 {
78         uint n, ret = 0;
79
80         /* skip 'offset' bytes */
81         for (; p && offset; p = PKTNEXT(p)) {
82                 if (offset < (uint) PKTLEN(p))
83                         break;
84                 offset -= PKTLEN(p);
85         }
86
87         if (!p)
88                 return 0;
89
90         /* copy the data */
91         for (; p && len; p = PKTNEXT(p)) {
92                 n = MIN((uint) PKTLEN(p) - offset, (uint) len);
93                 bcopy(buf, PKTDATA(p) + offset, n);
94                 buf += n;
95                 len -= n;
96                 ret += n;
97                 offset = 0;
98         }
99
100         return ret;
101 }
102
103 /* return total length of buffer chain */
104 uint pkttotlen(osl_t *osh, void *p)
105 {
106         uint total;
107
108         total = 0;
109         for (; p; p = PKTNEXT(p))
110                 total += PKTLEN(p);
111         return total;
112 }
113
114 /* return the last buffer of chained pkt */
115 void *pktlast(osl_t *osh, void *p)
116 {
117         for (; PKTNEXT(p); p = PKTNEXT(p))
118                 ;
119
120         return p;
121 }
122
123 /* count segments of a chained packet */
124 uint pktsegcnt(osl_t *osh, void *p)
125 {
126         uint cnt;
127
128         for (cnt = 0; p; p = PKTNEXT(p))
129                 cnt++;
130
131         return cnt;
132 }
133
134 /*
135  * osl multiple-precedence packet queue
136  * hi_prec is always >= the number of the highest non-empty precedence
137  */
138 void *pktq_penq(struct pktq *pq, int prec, void *p)
139 {
140         struct pktq_prec *q;
141
142         ASSERT(prec >= 0 && prec < pq->num_prec);
143         ASSERT(PKTLINK(p) == NULL);     /* queueing chains not allowed */
144
145         ASSERT(!pktq_full(pq));
146         ASSERT(!pktq_pfull(pq, prec));
147
148         q = &pq->q[prec];
149
150         if (q->head)
151                 PKTSETLINK(q->tail, p);
152         else
153                 q->head = p;
154
155         q->tail = p;
156         q->len++;
157
158         pq->len++;
159
160         if (pq->hi_prec < prec)
161                 pq->hi_prec = (u8) prec;
162
163         return p;
164 }
165
166 void *pktq_penq_head(struct pktq *pq, int prec, void *p)
167 {
168         struct pktq_prec *q;
169
170         ASSERT(prec >= 0 && prec < pq->num_prec);
171         ASSERT(PKTLINK(p) == NULL);     /* queueing chains not allowed */
172
173         ASSERT(!pktq_full(pq));
174         ASSERT(!pktq_pfull(pq, prec));
175
176         q = &pq->q[prec];
177
178         if (q->head == NULL)
179                 q->tail = p;
180
181         PKTSETLINK(p, q->head);
182         q->head = p;
183         q->len++;
184
185         pq->len++;
186
187         if (pq->hi_prec < prec)
188                 pq->hi_prec = (u8) prec;
189
190         return p;
191 }
192
193 void *pktq_pdeq(struct pktq *pq, int prec)
194 {
195         struct pktq_prec *q;
196         void *p;
197
198         ASSERT(prec >= 0 && prec < pq->num_prec);
199
200         q = &pq->q[prec];
201
202         p = q->head;
203         if (p == NULL)
204                 return NULL;
205
206         q->head = PKTLINK(p);
207         if (q->head == NULL)
208                 q->tail = NULL;
209
210         q->len--;
211
212         pq->len--;
213
214         PKTSETLINK(p, NULL);
215
216         return p;
217 }
218
219 void *pktq_pdeq_tail(struct pktq *pq, int prec)
220 {
221         struct pktq_prec *q;
222         void *p, *prev;
223
224         ASSERT(prec >= 0 && prec < pq->num_prec);
225
226         q = &pq->q[prec];
227
228         p = q->head;
229         if (p == NULL)
230                 return NULL;
231
232         for (prev = NULL; p != q->tail; p = PKTLINK(p))
233                 prev = p;
234
235         if (prev)
236                 PKTSETLINK(prev, NULL);
237         else
238                 q->head = NULL;
239
240         q->tail = prev;
241         q->len--;
242
243         pq->len--;
244
245         return p;
246 }
247
248 void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir)
249 {
250         struct pktq_prec *q;
251         void *p;
252
253         q = &pq->q[prec];
254         p = q->head;
255         while (p) {
256                 q->head = PKTLINK(p);
257                 PKTSETLINK(p, NULL);
258                 PKTFREE(osh, p, dir);
259                 q->len--;
260                 pq->len--;
261                 p = q->head;
262         }
263         ASSERT(q->len == 0);
264         q->tail = NULL;
265 }
266
267 bool pktq_pdel(struct pktq *pq, void *pktbuf, int prec)
268 {
269         struct pktq_prec *q;
270         void *p;
271
272         ASSERT(prec >= 0 && prec < pq->num_prec);
273
274         if (!pktbuf)
275                 return FALSE;
276
277         q = &pq->q[prec];
278
279         if (q->head == pktbuf) {
280                 q->head = PKTLINK(pktbuf);
281                 if (q->head == NULL)
282                         q->tail = NULL;
283         } else {
284                 for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p))
285                         ;
286                 if (p == NULL)
287                         return FALSE;
288
289                 PKTSETLINK(p, PKTLINK(pktbuf));
290                 if (q->tail == pktbuf)
291                         q->tail = p;
292         }
293
294         q->len--;
295         pq->len--;
296         PKTSETLINK(pktbuf, NULL);
297         return TRUE;
298 }
299
300 void pktq_init(struct pktq *pq, int num_prec, int max_len)
301 {
302         int prec;
303
304         ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC);
305
306         /* pq is variable size; only zero out what's requested */
307         bzero(pq,
308               OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
309
310         pq->num_prec = (uint16) num_prec;
311
312         pq->max = (uint16) max_len;
313
314         for (prec = 0; prec < num_prec; prec++)
315                 pq->q[prec].max = pq->max;
316 }
317
318 void *pktq_deq(struct pktq *pq, int *prec_out)
319 {
320         struct pktq_prec *q;
321         void *p;
322         int prec;
323
324         if (pq->len == 0)
325                 return NULL;
326
327         while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
328                 pq->hi_prec--;
329
330         q = &pq->q[prec];
331
332         p = q->head;
333         if (p == NULL)
334                 return NULL;
335
336         q->head = PKTLINK(p);
337         if (q->head == NULL)
338                 q->tail = NULL;
339
340         q->len--;
341
342         pq->len--;
343
344         if (prec_out)
345                 *prec_out = prec;
346
347         PKTSETLINK(p, NULL);
348
349         return p;
350 }
351
352 void *pktq_deq_tail(struct pktq *pq, int *prec_out)
353 {
354         struct pktq_prec *q;
355         void *p, *prev;
356         int prec;
357
358         if (pq->len == 0)
359                 return NULL;
360
361         for (prec = 0; prec < pq->hi_prec; prec++)
362                 if (pq->q[prec].head)
363                         break;
364
365         q = &pq->q[prec];
366
367         p = q->head;
368         if (p == NULL)
369                 return NULL;
370
371         for (prev = NULL; p != q->tail; p = PKTLINK(p))
372                 prev = p;
373
374         if (prev)
375                 PKTSETLINK(prev, NULL);
376         else
377                 q->head = NULL;
378
379         q->tail = prev;
380         q->len--;
381
382         pq->len--;
383
384         if (prec_out)
385                 *prec_out = prec;
386
387         PKTSETLINK(p, NULL);
388
389         return p;
390 }
391
392 void *pktq_peek(struct pktq *pq, int *prec_out)
393 {
394         int prec;
395
396         if (pq->len == 0)
397                 return NULL;
398
399         while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
400                 pq->hi_prec--;
401
402         if (prec_out)
403                 *prec_out = prec;
404
405         return pq->q[prec].head;
406 }
407
408 void *pktq_peek_tail(struct pktq *pq, int *prec_out)
409 {
410         int prec;
411
412         if (pq->len == 0)
413                 return NULL;
414
415         for (prec = 0; prec < pq->hi_prec; prec++)
416                 if (pq->q[prec].head)
417                         break;
418
419         if (prec_out)
420                 *prec_out = prec;
421
422         return pq->q[prec].tail;
423 }
424
425 void pktq_flush(osl_t *osh, struct pktq *pq, bool dir)
426 {
427         int prec;
428         for (prec = 0; prec < pq->num_prec; prec++)
429                 pktq_pflush(osh, pq, prec, dir);
430         ASSERT(pq->len == 0);
431 }
432
433 /* Return sum of lengths of a specific set of precedences */
434 int pktq_mlen(struct pktq *pq, uint prec_bmp)
435 {
436         int prec, len;
437
438         len = 0;
439
440         for (prec = 0; prec <= pq->hi_prec; prec++)
441                 if (prec_bmp & (1 << prec))
442                         len += pq->q[prec].len;
443
444         return len;
445 }
446
447 /* Priority dequeue from a specific set of precedences */
448 void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out)
449 {
450         struct pktq_prec *q;
451         void *p;
452         int prec;
453
454         if (pq->len == 0)
455                 return NULL;
456
457         while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
458                 pq->hi_prec--;
459
460         while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
461                 if (prec-- == 0)
462                         return NULL;
463
464         q = &pq->q[prec];
465
466         p = q->head;
467         if (p == NULL)
468                 return NULL;
469
470         q->head = PKTLINK(p);
471         if (q->head == NULL)
472                 q->tail = NULL;
473
474         q->len--;
475
476         if (prec_out)
477                 *prec_out = prec;
478
479         pq->len--;
480
481         PKTSETLINK(p, NULL);
482
483         return p;
484 }
485 #endif                          /* BCMDRIVER */
486
487 const unsigned char bcm_ctype[] = {
488         _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C,
489         _BCM_C, _BCM_C | _BCM_S, _BCM_C | _BCM_S, _BCM_C | _BCM_S,
490         _BCM_C | _BCM_S, _BCM_C | _BCM_S, _BCM_C,
491         _BCM_C,                 /* 8-15 */
492         _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C,
493         _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C,
494         _BCM_S | _BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
495         _BCM_P,
496         _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
497         _BCM_D, _BCM_D, _BCM_D, _BCM_D, _BCM_D, _BCM_D, _BCM_D, _BCM_D,
498         _BCM_D, _BCM_D, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
499         _BCM_P, _BCM_U | _BCM_X, _BCM_U | _BCM_X, _BCM_U | _BCM_X,
500         _BCM_U | _BCM_X, _BCM_U | _BCM_X,
501         _BCM_U | _BCM_X, _BCM_U,
502         _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,
503         _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,
504         _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
505         _BCM_P, _BCM_L | _BCM_X, _BCM_L | _BCM_X, _BCM_L | _BCM_X,
506         _BCM_L | _BCM_X, _BCM_L | _BCM_X,
507         _BCM_L | _BCM_X, _BCM_L,
508         _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,
509         _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,
510         _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_C,
511         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */
512         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */
513         _BCM_S | _BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
514         _BCM_P, _BCM_P, _BCM_P,
515         _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */
516         _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
517         _BCM_P, _BCM_P,
518         _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */
519         _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,
520         _BCM_U, _BCM_U,
521         _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */
522         _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U,
523         _BCM_U, _BCM_U,
524         _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */
525         _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,
526         _BCM_L, _BCM_L,
527         _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */
528         _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L,
529         _BCM_L, _BCM_L,
530         _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L  /* 240-255 */
531 };
532
533 unsigned long bcm_strtoul(char *cp, char **endp, uint base)
534 {
535         unsigned long result, last_result = 0, value;
536         bool minus;
537
538         minus = FALSE;
539
540         while (bcm_isspace(*cp))
541                 cp++;
542
543         if (cp[0] == '+')
544                 cp++;
545         else if (cp[0] == '-') {
546                 minus = TRUE;
547                 cp++;
548         }
549
550         if (base == 0) {
551                 if (cp[0] == '0') {
552                         if ((cp[1] == 'x') || (cp[1] == 'X')) {
553                                 base = 16;
554                                 cp = &cp[2];
555                         } else {
556                                 base = 8;
557                                 cp = &cp[1];
558                         }
559                 } else
560                         base = 10;
561         } else if (base == 16 && (cp[0] == '0')
562                    && ((cp[1] == 'x') || (cp[1] == 'X'))) {
563                 cp = &cp[2];
564         }
565
566         result = 0;
567
568         while (bcm_isxdigit(*cp) &&
569                (value =
570                 bcm_isdigit(*cp) ? *cp - '0' : bcm_toupper(*cp) - 'A' + 10) <
571                base) {
572                 result = result * base + value;
573                 /* Detected overflow */
574                 if (result < last_result && !minus)
575                         return (unsigned long)-1;
576                 last_result = result;
577                 cp++;
578         }
579
580         if (minus)
581                 result = (unsigned long) (-(long)result);
582
583         if (endp)
584                 *endp = (char *)cp;
585
586         return result;
587 }
588
589 int bcm_atoi(char *s)
590 {
591         return (int)bcm_strtoul(s, NULL, 10);
592 }
593
594 /* return pointer to location of substring 'needle' in 'haystack' */
595 char *bcmstrstr(char *haystack, char *needle)
596 {
597         int len, nlen;
598         int i;
599
600         if ((haystack == NULL) || (needle == NULL))
601                 return haystack;
602
603         nlen = strlen(needle);
604         len = strlen(haystack) - nlen + 1;
605
606         for (i = 0; i < len; i++)
607                 if (memcmp(needle, &haystack[i], nlen) == 0)
608                         return &haystack[i];
609         return NULL;
610 }
611
612 char *bcmstrcat(char *dest, const char *src)
613 {
614         char *p;
615
616         p = dest + strlen(dest);
617
618         while ((*p++ = *src++) != '\0')
619                 ;
620
621         return dest;
622 }
623
624 char *bcmstrncat(char *dest, const char *src, uint size)
625 {
626         char *endp;
627         char *p;
628
629         p = dest + strlen(dest);
630         endp = p + size;
631
632         while (p != endp && (*p++ = *src++) != '\0')
633                 ;
634
635         return dest;
636 }
637
638 /****************************************************************************
639 * Function:   bcmstrtok
640 *
641 * Purpose:
642 *  Tokenizes a string. This function is conceptually similiar
643 *  to ANSI C strtok(),
644 *  but allows strToken() to be used by different strings or callers at the same
645 *  time. Each call modifies '*string' by substituting a NULL character for the
646 *  first delimiter that is encountered, and updates 'string' to point to
647 *  the char
648 *  after the delimiter. Leading delimiters are skipped.
649 *
650 * Parameters:
651 *  string      (mod) Ptr to string ptr, updated by token.
652 *  delimiters  (in)  Set of delimiter characters.
653 *  tokdelim    (out) Character that delimits the returned token. (May
654 *                    be set to NULL if token delimiter is not required).
655 *
656 * Returns:  Pointer to the next token found. NULL when no more tokens are found.
657 *****************************************************************************
658 */
659 char *bcmstrtok(char **string, const char *delimiters, char *tokdelim)
660 {
661         unsigned char *str;
662         unsigned long map[8];
663         int count;
664         char *nextoken;
665
666         if (tokdelim != NULL) {
667                 /* Prime the token delimiter */
668                 *tokdelim = '\0';
669         }
670
671         /* Clear control map */
672         for (count = 0; count < 8; count++)
673                 map[count] = 0;
674
675         /* Set bits in delimiter table */
676         do {
677                 map[*delimiters >> 5] |= (1 << (*delimiters & 31));
678         }
679         while (*delimiters++)
680                 ;
681
682         str = (unsigned char *)*string;
683
684         /* Find beginning of token (skip over leading delimiters). Note that
685          * there is no token iff this loop sets str to point to the terminal
686          * null (*str == '\0')
687          */
688         while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' '))
689                 str++;
690
691         nextoken = (char *)str;
692
693         /* Find the end of the token. If it is not the end of the string,
694          * put a null there.
695          */
696         for (; *str; str++) {
697                 if (map[*str >> 5] & (1 << (*str & 31))) {
698                         if (tokdelim != NULL)
699                                 *tokdelim = *str;
700
701                         *str++ = '\0';
702                         break;
703                 }
704         }
705
706         *string = (char *)str;
707
708         /* Determine if a token has been found. */
709         if (nextoken == (char *)str)
710                 return NULL;
711         else
712                 return nextoken;
713 }
714
715 #define xToLower(C) \
716         ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C)
717
718 /****************************************************************************
719 * Function:   bcmstricmp
720 *
721 * Purpose:    Compare to strings case insensitively.
722 *
723 * Parameters: s1 (in) First string to compare.
724 *             s2 (in) Second string to compare.
725 *
726 * Returns:    Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
727 *             t1 > t2, when ignoring case sensitivity.
728 *****************************************************************************
729 */
730 int bcmstricmp(const char *s1, const char *s2)
731 {
732         char dc, sc;
733
734         while (*s2 && *s1) {
735                 dc = xToLower(*s1);
736                 sc = xToLower(*s2);
737                 if (dc < sc)
738                         return -1;
739                 if (dc > sc)
740                         return 1;
741                 s1++;
742                 s2++;
743         }
744
745         if (*s1 && !*s2)
746                 return 1;
747         if (!*s1 && *s2)
748                 return -1;
749         return 0;
750 }
751
752 /****************************************************************************
753 * Function:   bcmstrnicmp
754 *
755 * Purpose:    Compare to strings case insensitively, upto a max of 'cnt'
756 *             characters.
757 *
758 * Parameters: s1  (in) First string to compare.
759 *             s2  (in) Second string to compare.
760 *             cnt (in) Max characters to compare.
761 *
762 * Returns:    Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
763 *             t1 > t2, when ignoring case sensitivity.
764 *****************************************************************************
765 */
766 int bcmstrnicmp(const char *s1, const char *s2, int cnt)
767 {
768         char dc, sc;
769
770         while (*s2 && *s1 && cnt) {
771                 dc = xToLower(*s1);
772                 sc = xToLower(*s2);
773                 if (dc < sc)
774                         return -1;
775                 if (dc > sc)
776                         return 1;
777                 s1++;
778                 s2++;
779                 cnt--;
780         }
781
782         if (!cnt)
783                 return 0;
784         if (*s1 && !*s2)
785                 return 1;
786         if (!*s1 && *s2)
787                 return -1;
788         return 0;
789 }
790
791 /* parse a xx:xx:xx:xx:xx:xx format ethernet address */
792 int bcm_ether_atoe(char *p, struct ether_addr *ea)
793 {
794         int i = 0;
795
796         for (;;) {
797                 ea->octet[i++] = (char)bcm_strtoul(p, &p, 16);
798                 if (!*p++ || i == 6)
799                         break;
800         }
801
802         return i == 6;
803 }
804
805 #if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER)
806 /* registry routine buffer preparation utility functions:
807  * parameter order is like strncpy, but returns count
808  * of bytes copied. Minimum bytes copied is null char(1)/wchar(2)
809  */
810 unsigned long wchar2ascii(char *abuf, unsigned short * wbuf, unsigned short wbuflen, unsigned long abuflen)
811 {
812         unsigned long copyct = 1;
813         unsigned short i;
814
815         if (abuflen == 0)
816                 return 0;
817
818         /* wbuflen is in bytes */
819         wbuflen /= sizeof(unsigned short);
820
821         for (i = 0; i < wbuflen; ++i) {
822                 if (--abuflen == 0)
823                         break;
824                 *abuf++ = (char)*wbuf++;
825                 ++copyct;
826         }
827         *abuf = '\0';
828
829         return copyct;
830 }
831 #endif  /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */
832
833 char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf)
834 {
835         static const char template[] = "%02x:%02x:%02x:%02x:%02x:%02x";
836         snprintf(buf, 18, template,
837                  ea->octet[0] & 0xff, ea->octet[1] & 0xff, ea->octet[2] & 0xff,
838                  ea->octet[3] & 0xff, ea->octet[4] & 0xff, ea->octet[5] & 0xff);
839         return buf;
840 }
841
842 char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf)
843 {
844         snprintf(buf, 16, "%d.%d.%d.%d",
845                  ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]);
846         return buf;
847 }
848
849 #ifdef BCMDRIVER
850
851 void bcm_mdelay(uint ms)
852 {
853         uint i;
854
855         for (i = 0; i < ms; i++)
856                 OSL_DELAY(1000);
857 }
858
859 #if defined(DHD_DEBUG)
860 /* pretty hex print a pkt buffer chain */
861 void prpkt(const char *msg, osl_t *osh, void *p0)
862 {
863         void *p;
864
865         if (msg && (msg[0] != '\0'))
866                 printf("%s:\n", msg);
867
868         for (p = p0; p; p = PKTNEXT(p))
869                 prhex(NULL, PKTDATA(p), PKTLEN(p));
870 }
871 #endif
872
873 /* Takes an Ethernet frame and sets out-of-bound PKTPRIO.
874  * Also updates the inplace vlan tag if requested.
875  * For debugging, it returns an indication of what it did.
876  */
877 uint pktsetprio(void *pkt, bool update_vtag)
878 {
879         struct ether_header *eh;
880         struct ethervlan_header *evh;
881         u8 *pktdata;
882         int priority = 0;
883         int rc = 0;
884
885         pktdata = (u8 *) PKTDATA(pkt);
886         ASSERT(ISALIGNED((uintptr) pktdata, sizeof(uint16)));
887
888         eh = (struct ether_header *)pktdata;
889
890         if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) {
891                 uint16 vlan_tag;
892                 int vlan_prio, dscp_prio = 0;
893
894                 evh = (struct ethervlan_header *)eh;
895
896                 vlan_tag = ntoh16(evh->vlan_tag);
897                 vlan_prio = (int)(vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
898
899                 if (ntoh16(evh->ether_type) == ETHER_TYPE_IP) {
900                         u8 *ip_body =
901                             pktdata + sizeof(struct ethervlan_header);
902                         u8 tos_tc = IP_TOS(ip_body);
903                         dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
904                 }
905
906                 /* DSCP priority gets precedence over 802.1P (vlan tag) */
907                 if (dscp_prio != 0) {
908                         priority = dscp_prio;
909                         rc |= PKTPRIO_VDSCP;
910                 } else {
911                         priority = vlan_prio;
912                         rc |= PKTPRIO_VLAN;
913                 }
914                 /*
915                  * If the DSCP priority is not the same as the VLAN priority,
916                  * then overwrite the priority field in the vlan tag, with the
917                  * DSCP priority value. This is required for Linux APs because
918                  * the VLAN driver on Linux, overwrites the skb->priority field
919                  * with the priority value in the vlan tag
920                  */
921                 if (update_vtag && (priority != vlan_prio)) {
922                         vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
923                         vlan_tag |= (uint16) priority << VLAN_PRI_SHIFT;
924                         evh->vlan_tag = hton16(vlan_tag);
925                         rc |= PKTPRIO_UPD;
926                 }
927         } else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) {
928                 u8 *ip_body = pktdata + sizeof(struct ether_header);
929                 u8 tos_tc = IP_TOS(ip_body);
930                 priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
931                 rc |= PKTPRIO_DSCP;
932         }
933
934         ASSERT(priority >= 0 && priority <= MAXPRIO);
935         PKTSETPRIO(pkt, priority);
936         return rc | priority;
937 }
938
939 static char bcm_undeferrstr[BCME_STRLEN];
940
941 static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE;
942
943 /* Convert the error codes into related error strings  */
944 const char *bcmerrorstr(int bcmerror)
945 {
946         /* check if someone added a bcmerror code but
947                  forgot to add errorstring */
948         ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1));
949
950         if (bcmerror > 0 || bcmerror < BCME_LAST) {
951                 snprintf(bcm_undeferrstr, BCME_STRLEN, "Undefined error %d",
952                          bcmerror);
953                 return bcm_undeferrstr;
954         }
955
956         ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN);
957
958         return bcmerrorstrtable[-bcmerror];
959 }
960
961 /* iovar table lookup */
962 const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name)
963 {
964         const bcm_iovar_t *vi;
965         const char *lookup_name;
966
967         /* skip any ':' delimited option prefixes */
968         lookup_name = strrchr(name, ':');
969         if (lookup_name != NULL)
970                 lookup_name++;
971         else
972                 lookup_name = name;
973
974         ASSERT(table != NULL);
975
976         for (vi = table; vi->name; vi++) {
977                 if (!strcmp(vi->name, lookup_name))
978                         return vi;
979         }
980         /* ran to end of table */
981
982         return NULL;            /* var name not found */
983 }
984
985 int bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
986 {
987         int bcmerror = 0;
988
989         /* length check on io buf */
990         switch (vi->type) {
991         case IOVT_BOOL:
992         case IOVT_INT8:
993         case IOVT_INT16:
994         case IOVT_INT32:
995         case IOVT_UINT8:
996         case IOVT_UINT16:
997         case IOVT_UINT32:
998                 /* all integers are int32 sized args at the ioctl interface */
999                 if (len < (int)sizeof(int))
1000                         bcmerror = BCME_BUFTOOSHORT;
1001                 break;
1002
1003         case IOVT_BUFFER:
1004                 /* buffer must meet minimum length requirement */
1005                 if (len < vi->minlen)
1006                         bcmerror = BCME_BUFTOOSHORT;
1007                 break;
1008
1009         case IOVT_VOID:
1010                 if (!set) {
1011                         /* Cannot return nil... */
1012                         bcmerror = BCME_UNSUPPORTED;
1013                 } else if (len) {
1014                         /* Set is an action w/o parameters */
1015                         bcmerror = BCME_BUFTOOLONG;
1016                 }
1017                 break;
1018
1019         default:
1020                 /* unknown type for length check in iovar info */
1021                 ASSERT(0);
1022                 bcmerror = BCME_UNSUPPORTED;
1023         }
1024
1025         return bcmerror;
1026 }
1027
1028 #endif                          /* BCMDRIVER */
1029
1030 /****************************************************************************
1031  * crc8
1032  *
1033  * Computes a crc8 over the input data using the polynomial:
1034  *
1035  *       x^8 + x^7 +x^6 + x^4 + x^2 + 1
1036  *
1037  * The caller provides the initial value (either CRC8_INIT_VALUE
1038  * or the previous returned value) to allow for processing of
1039  * discontiguous blocks of data.  When generating the CRC the
1040  * caller is responsible for complementing the final return value
1041  * and inserting it into the byte stream.  When checking, a final
1042  * return value of CRC8_GOOD_VALUE indicates a valid CRC.
1043  *
1044  * Reference: Dallas Semiconductor Application Note 27
1045  *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
1046  *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
1047  *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
1048  *
1049  * ****************************************************************************
1050  */
1051
1052 static const u8 crc8_table[256] = {
1053         0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
1054         0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
1055         0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
1056         0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
1057         0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
1058         0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
1059         0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
1060         0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
1061         0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
1062         0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
1063         0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
1064         0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
1065         0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
1066         0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
1067         0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
1068         0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
1069         0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
1070         0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
1071         0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
1072         0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
1073         0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
1074         0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
1075         0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
1076         0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
1077         0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
1078         0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
1079         0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
1080         0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
1081         0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
1082         0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
1083         0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
1084         0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
1085 };
1086
1087 #define CRC_INNER_LOOP(n, c, x) \
1088         (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
1089
1090 u8 hndcrc8(u8 *pdata,   /* pointer to array of data to process */
1091               uint nbytes,      /* number of input data bytes to process */
1092               u8 crc            /* either CRC8_INIT_VALUE or previous
1093                                          return value */
1094     )
1095 {
1096         /* hard code the crc loop instead of using CRC_INNER_LOOP macro
1097          * to avoid the undefined and unnecessary (u8 >> 8) operation.
1098         */
1099         while (nbytes-- > 0)
1100                 crc = crc8_table[(crc ^ *pdata++) & 0xff];
1101
1102         return crc;
1103 }
1104
1105 /*****************************************************************************
1106  * crc16
1107  *
1108  * Computes a crc16 over the input data using the polynomial:
1109  *
1110  *       x^16 + x^12 +x^5 + 1
1111  *
1112  * The caller provides the initial value (either CRC16_INIT_VALUE
1113  * or the previous returned value) to allow for processing of
1114  * discontiguous blocks of data.  When generating the CRC the
1115  * caller is responsible for complementing the final return value
1116  * and inserting it into the byte stream.  When checking, a final
1117  * return value of CRC16_GOOD_VALUE indicates a valid CRC.
1118  *
1119  * Reference: Dallas Semiconductor Application Note 27
1120  *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
1121  *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
1122  *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
1123  *
1124  * ****************************************************************************
1125  */
1126
1127 static const uint16 crc16_table[256] = {
1128         0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
1129         0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
1130         0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
1131         0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
1132         0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
1133         0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
1134         0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
1135         0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
1136         0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
1137         0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
1138         0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
1139         0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
1140         0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
1141         0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
1142         0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
1143         0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
1144         0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
1145         0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
1146         0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
1147         0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
1148         0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
1149         0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
1150         0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
1151         0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
1152         0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
1153         0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
1154         0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
1155         0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
1156         0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
1157         0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
1158         0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
1159         0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
1160 };
1161
1162 uint16 hndcrc16(u8 *pdata,      /* pointer to array of data to process */
1163                 uint nbytes,    /* number of input data bytes to process */
1164                 uint16 crc      /* either CRC16_INIT_VALUE or previous
1165                                  return value */
1166 )
1167 {
1168         while (nbytes-- > 0)
1169                 CRC_INNER_LOOP(16, crc, *pdata++);
1170         return crc;
1171 }
1172
1173 static const uint32 crc32_table[256] = {
1174         0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
1175         0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
1176         0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
1177         0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
1178         0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
1179         0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
1180         0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
1181         0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
1182         0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
1183         0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
1184         0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
1185         0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
1186         0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
1187         0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
1188         0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
1189         0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
1190         0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
1191         0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
1192         0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
1193         0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
1194         0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
1195         0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
1196         0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
1197         0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
1198         0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
1199         0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
1200         0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
1201         0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
1202         0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
1203         0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
1204         0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
1205         0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
1206         0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
1207         0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
1208         0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
1209         0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
1210         0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
1211         0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
1212         0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
1213         0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
1214         0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
1215         0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
1216         0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
1217         0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
1218         0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
1219         0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
1220         0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
1221         0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
1222         0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
1223         0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
1224         0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
1225         0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
1226         0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
1227         0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
1228         0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
1229         0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
1230         0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
1231         0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
1232         0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
1233         0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
1234         0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
1235         0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
1236         0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
1237         0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
1238 };
1239
1240 uint32 hndcrc32(u8 *pdata,      /* pointer to array of data to process */
1241                 uint nbytes,    /* number of input data bytes to process */
1242                 uint32 crc      /* either CRC32_INIT_VALUE or previous
1243                                          return value */
1244 )
1245 {
1246         u8 *pend;
1247 #ifdef __mips__
1248         u8 tmp[4];
1249         unsigned long *tptr = (unsigned long *) tmp;
1250
1251         /* in case the beginning of the buffer isn't aligned */
1252         pend = (u8 *) ((uint) (pdata + 3) & 0xfffffffc);
1253         nbytes -= (pend - pdata);
1254         while (pdata < pend)
1255                 CRC_INNER_LOOP(32, crc, *pdata++);
1256
1257         /* handle bulk of data as 32-bit words */
1258         pend = pdata + (nbytes & 0xfffffffc);
1259         while (pdata < pend) {
1260                 *tptr = *(unsigned long *) pdata;
1261                 pdata += sizeof(unsigned long *);
1262                 CRC_INNER_LOOP(32, crc, tmp[0]);
1263                 CRC_INNER_LOOP(32, crc, tmp[1]);
1264                 CRC_INNER_LOOP(32, crc, tmp[2]);
1265                 CRC_INNER_LOOP(32, crc, tmp[3]);
1266         }
1267
1268         /* 1-3 bytes at end of buffer */
1269         pend = pdata + (nbytes & 0x03);
1270         while (pdata < pend)
1271                 CRC_INNER_LOOP(32, crc, *pdata++);
1272 #else
1273         pend = pdata + nbytes;
1274         while (pdata < pend)
1275                 CRC_INNER_LOOP(32, crc, *pdata++);
1276 #endif                          /* __mips__ */
1277
1278         return crc;
1279 }
1280
1281 #ifdef notdef
1282 #define CLEN    1499 /*  CRC Length */
1283 #define CBUFSIZ         (CLEN+4)
1284 #define CNBUFS          5       /* # of bufs */
1285
1286 void testcrc32(void)
1287 {
1288         uint j, k, l;
1289         u8 *buf;
1290         uint len[CNBUFS];
1291         uint32 crcr;
1292         uint32 crc32tv[CNBUFS] = {
1293                 0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110};
1294
1295         ASSERT((buf = MALLOC(CBUFSIZ * CNBUFS)) != NULL);
1296
1297         /* step through all possible alignments */
1298         for (l = 0; l <= 4; l++) {
1299                 for (j = 0; j < CNBUFS; j++) {
1300                         len[j] = CLEN;
1301                         for (k = 0; k < len[j]; k++)
1302                                 *(buf + j * CBUFSIZ + (k + l)) = (j + k) & 0xff;
1303                 }
1304
1305                 for (j = 0; j < CNBUFS; j++) {
1306                         crcr =
1307                             crc32(buf + j * CBUFSIZ + l, len[j],
1308                                   CRC32_INIT_VALUE);
1309                         ASSERT(crcr == crc32tv[j]);
1310                 }
1311         }
1312
1313         MFREE(buf, CBUFSIZ * CNBUFS);
1314         return;
1315 }
1316 #endif                          /* notdef */
1317
1318 /*
1319  * Advance from the current 1-byte tag/1-byte length/variable-length value
1320  * triple, to the next, returning a pointer to the next.
1321  * If the current or next TLV is invalid (does not fit in given buffer length),
1322  * NULL is returned.
1323  * *buflen is not modified if the TLV elt parameter is invalid,
1324  * or is decremented
1325  * by the TLV parameter's length if it is valid.
1326  */
1327 bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen)
1328 {
1329         int len;
1330
1331         /* validate current elt */
1332         if (!bcm_valid_tlv(elt, *buflen))
1333                 return NULL;
1334
1335         /* advance to next elt */
1336         len = elt->len;
1337         elt = (bcm_tlv_t *) (elt->data + len);
1338         *buflen -= (2 + len);
1339
1340         /* validate next elt */
1341         if (!bcm_valid_tlv(elt, *buflen))
1342                 return NULL;
1343
1344         return elt;
1345 }
1346
1347 /*
1348  * Traverse a string of 1-byte tag/1-byte length/variable-length value
1349  * triples, returning a pointer to the substring whose first element
1350  * matches tag
1351  */
1352 bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key)
1353 {
1354         bcm_tlv_t *elt;
1355         int totlen;
1356
1357         elt = (bcm_tlv_t *) buf;
1358         totlen = buflen;
1359
1360         /* find tagged parameter */
1361         while (totlen >= 2) {
1362                 int len = elt->len;
1363
1364                 /* validate remaining totlen */
1365                 if ((elt->id == key) && (totlen >= (len + 2)))
1366                         return elt;
1367
1368                 elt = (bcm_tlv_t *) ((u8 *) elt + (len + 2));
1369                 totlen -= (len + 2);
1370         }
1371
1372         return NULL;
1373 }
1374
1375 /*
1376  * Traverse a string of 1-byte tag/1-byte length/variable-length value
1377  * triples, returning a pointer to the substring whose first element
1378  * matches tag.  Stop parsing when we see an element whose ID is greater
1379  * than the target key.
1380  */
1381 bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key)
1382 {
1383         bcm_tlv_t *elt;
1384         int totlen;
1385
1386         elt = (bcm_tlv_t *) buf;
1387         totlen = buflen;
1388
1389         /* find tagged parameter */
1390         while (totlen >= 2) {
1391                 uint id = elt->id;
1392                 int len = elt->len;
1393
1394                 /* Punt if we start seeing IDs > than target key */
1395                 if (id > key)
1396                         return NULL;
1397
1398                 /* validate remaining totlen */
1399                 if ((id == key) && (totlen >= (len + 2)))
1400                         return elt;
1401
1402                 elt = (bcm_tlv_t *) ((u8 *) elt + (len + 2));
1403                 totlen -= (len + 2);
1404         }
1405         return NULL;
1406 }
1407
1408 #if defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \
1409         defined(DHD_DEBUG)
1410 int
1411 bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char *buf, int len)
1412 {
1413         int i;
1414         char *p = buf;
1415         char hexstr[16];
1416         int slen = 0;
1417         uint32 bit;
1418         const char *name;
1419
1420         if (len < 2 || !buf)
1421                 return 0;
1422
1423         buf[0] = '\0';
1424         len -= 1;
1425
1426         for (i = 0; flags != 0; i++) {
1427                 bit = bd[i].bit;
1428                 name = bd[i].name;
1429                 if (bit == 0 && flags) {
1430                         /* print any unnamed bits */
1431                         sprintf(hexstr, "0x%X", flags);
1432                         name = hexstr;
1433                         flags = 0;      /* exit loop */
1434                 } else if ((flags & bit) == 0)
1435                         continue;
1436                 slen += strlen(name);
1437                 if (len < slen)
1438                         break;
1439                 if (p != buf)
1440                         p += sprintf(p, " ");   /* btwn flag space */
1441                 strcat(p, name);
1442                 p += strlen(name);
1443                 flags &= ~bit;
1444                 len -= slen;
1445                 slen = 1;       /* account for btwn flag space */
1446         }
1447
1448         /* indicate the str was too short */
1449         if (flags != 0) {
1450                 if (len == 0)
1451                         p--;    /* overwrite last char */
1452                 p += sprintf(p, ">");
1453         }
1454
1455         return (int)(p - buf);
1456 }
1457
1458 /*
1459 * print bytes formatted as hex to a string. return the resulting
1460 * string length
1461 */
1462 int bcm_format_hex(char *str, const void *bytes, int len)
1463 {
1464         int i;
1465         char *p = str;
1466         const u8 *src = (const u8 *)bytes;
1467
1468         for (i = 0; i < len; i++) {
1469                 p += sprintf(p, "%02X", *src);
1470                 src++;
1471         }
1472         return (int)(p - str);
1473 }
1474
1475 /* pretty hex print a contiguous buffer */
1476 void prhex(const char *msg, unsigned char *buf, uint nbytes)
1477 {
1478         char line[128], *p;
1479         uint i;
1480
1481         if (msg && (msg[0] != '\0'))
1482                 printf("%s:\n", msg);
1483
1484         p = line;
1485         for (i = 0; i < nbytes; i++) {
1486                 if (i % 16 == 0)
1487                         p += sprintf(p, "  %04d: ", i); /* line prefix */
1488
1489                 p += sprintf(p, "%02x ", buf[i]);
1490                 if (i % 16 == 15) {
1491                         printf("%s\n", line);   /* flush line */
1492                         p = line;
1493                 }
1494         }
1495
1496         /* flush last partial line */
1497         if (p != line)
1498                 printf("%s\n", line);
1499 }
1500 #endif          /* defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) */
1501
1502 /* Produce a human-readable string for boardrev */
1503 char *bcm_brev_str(uint32 brev, char *buf)
1504 {
1505         if (brev < 0x100)
1506                 snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf);
1507         else
1508                 snprintf(buf, 8, "%c%03x",
1509                          ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff);
1510
1511         return buf;
1512 }
1513
1514 #define BUFSIZE_TODUMP_ATONCE 512       /* Buffer size */
1515
1516 /* dump large strings to console */
1517 void printbig(char *buf)
1518 {
1519         uint len, max_len;
1520         char c;
1521
1522         len = strlen(buf);
1523
1524         max_len = BUFSIZE_TODUMP_ATONCE;
1525
1526         while (len > max_len) {
1527                 c = buf[max_len];
1528                 buf[max_len] = '\0';
1529                 printf("%s", buf);
1530                 buf[max_len] = c;
1531
1532                 buf += max_len;
1533                 len -= max_len;
1534         }
1535         /* print the remaining string */
1536         printf("%s\n", buf);
1537         return;
1538 }
1539
1540 /* routine to dump fields in a fileddesc structure */
1541 uint
1542 bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1,
1543               struct fielddesc *fielddesc_array, char *buf, uint32 bufsize)
1544 {
1545         uint filled_len;
1546         int len;
1547         struct fielddesc *cur_ptr;
1548
1549         filled_len = 0;
1550         cur_ptr = fielddesc_array;
1551
1552         while (bufsize > 1) {
1553                 if (cur_ptr->nameandfmt == NULL)
1554                         break;
1555                 len = snprintf(buf, bufsize, cur_ptr->nameandfmt,
1556                                read_rtn(arg0, arg1, cur_ptr->offset));
1557                 /* check for snprintf overflow or error */
1558                 if (len < 0 || (uint32) len >= bufsize)
1559                         len = bufsize - 1;
1560                 buf += len;
1561                 bufsize -= len;
1562                 filled_len += len;
1563                 cur_ptr++;
1564         }
1565         return filled_len;
1566 }
1567
1568 uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
1569 {
1570         uint len;
1571
1572         len = strlen(name) + 1;
1573
1574         if ((len + datalen) > buflen)
1575                 return 0;
1576
1577         strncpy(buf, name, buflen);
1578
1579         /* append data onto the end of the name string */
1580         memcpy(&buf[len], data, datalen);
1581         len += datalen;
1582
1583         return len;
1584 }
1585
1586 /* Quarter dBm units to mW
1587  * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
1588  * Table is offset so the last entry is largest mW value that fits in
1589  * a uint16.
1590  */
1591
1592 #define QDBM_OFFSET 153         /* Offset for first entry */
1593 #define QDBM_TABLE_LEN 40       /* Table size */
1594
1595 /* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
1596  * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
1597  */
1598 #define QDBM_TABLE_LOW_BOUND 6493       /* Low bound */
1599
1600 /* Largest mW value that will round down to the last table entry,
1601  * QDBM_OFFSET + QDBM_TABLE_LEN-1.
1602  * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
1603  * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
1604  */
1605 #define QDBM_TABLE_HIGH_BOUND 64938     /* High bound */
1606
1607 static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
1608 /* qdBm:        +0      +1      +2      +3      +4      +5      +6      +7 */
1609 /* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
1610 /* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
1611 /* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
1612 /* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
1613 /* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
1614 };
1615
1616 uint16 bcm_qdbm_to_mw(u8 qdbm)
1617 {
1618         uint factor = 1;
1619         int idx = qdbm - QDBM_OFFSET;
1620
1621         if (idx >= QDBM_TABLE_LEN) {
1622                 /* clamp to max uint16 mW value */
1623                 return 0xFFFF;
1624         }
1625
1626         /* scale the qdBm index up to the range of the table 0-40
1627          * where an offset of 40 qdBm equals a factor of 10 mW.
1628          */
1629         while (idx < 0) {
1630                 idx += 40;
1631                 factor *= 10;
1632         }
1633
1634         /* return the mW value scaled down to the correct factor of 10,
1635          * adding in factor/2 to get proper rounding.
1636          */
1637         return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
1638 }
1639
1640 u8 bcm_mw_to_qdbm(uint16 mw)
1641 {
1642         u8 qdbm;
1643         int offset;
1644         uint mw_uint = mw;
1645         uint boundary;
1646
1647         /* handle boundary case */
1648         if (mw_uint <= 1)
1649                 return 0;
1650
1651         offset = QDBM_OFFSET;
1652
1653         /* move mw into the range of the table */
1654         while (mw_uint < QDBM_TABLE_LOW_BOUND) {
1655                 mw_uint *= 10;
1656                 offset -= 40;
1657         }
1658
1659         for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
1660                 boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
1661                                                     nqdBm_to_mW_map[qdbm]) / 2;
1662                 if (mw_uint < boundary)
1663                         break;
1664         }
1665
1666         qdbm += (u8) offset;
1667
1668         return qdbm;
1669 }
1670
1671 uint bcm_bitcount(u8 *bitmap, uint length)
1672 {
1673         uint bitcount = 0, i;
1674         u8 tmp;
1675         for (i = 0; i < length; i++) {
1676                 tmp = bitmap[i];
1677                 while (tmp) {
1678                         bitcount++;
1679                         tmp &= (tmp - 1);
1680                 }
1681         }
1682         return bitcount;
1683 }
1684
1685 #ifdef BCMDRIVER
1686
1687 /* Initialization of bcmstrbuf structure */
1688 void bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
1689 {
1690         b->origsize = b->size = size;
1691         b->origbuf = b->buf = buf;
1692 }
1693
1694 /* Buffer sprintf wrapper to guard against buffer overflow */
1695 int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
1696 {
1697         va_list ap;
1698         int r;
1699
1700         va_start(ap, fmt);
1701         r = vsnprintf(b->buf, b->size, fmt, ap);
1702
1703         /* Non Ansi C99 compliant returns -1,
1704          * Ansi compliant return r >= b->size,
1705          * bcmstdlib returns 0, handle all
1706          */
1707         if ((r == -1) || (r >= (int)b->size) || (r == 0)) {
1708                 b->size = 0;
1709         } else {
1710                 b->size -= r;
1711                 b->buf += r;
1712         }
1713
1714         va_end(ap);
1715
1716         return r;
1717 }
1718
1719 void bcm_inc_bytes(unsigned char *num, int num_bytes, u8 amount)
1720 {
1721         int i;
1722
1723         for (i = 0; i < num_bytes; i++) {
1724                 num[i] += amount;
1725                 if (num[i] >= amount)
1726                         break;
1727                 amount = 1;
1728         }
1729 }
1730
1731 int bcm_cmp_bytes(unsigned char *arg1, unsigned char *arg2, u8 nbytes)
1732 {
1733         int i;
1734
1735         for (i = nbytes - 1; i >= 0; i--) {
1736                 if (arg1[i] != arg2[i])
1737                         return arg1[i] - arg2[i];
1738         }
1739         return 0;
1740 }
1741
1742 void bcm_print_bytes(char *name, const unsigned char *data, int len)
1743 {
1744         int i;
1745         int per_line = 0;
1746
1747         printf("%s: %d \n", name ? name : "", len);
1748         for (i = 0; i < len; i++) {
1749                 printf("%02x ", *data++);
1750                 per_line++;
1751                 if (per_line == 16) {
1752                         per_line = 0;
1753                         printf("\n");
1754                 }
1755         }
1756         printf("\n");
1757 }
1758
1759 int getintvar(char *vars, const char *name)
1760 {
1761         return 0;
1762 }
1763
1764 char *bcm_chipname(uint chipid, char *buf, uint len)
1765 {
1766         const char *fmt;
1767
1768         fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
1769         snprintf(buf, len, fmt, chipid);
1770         return buf;
1771 }
1772
1773 char *getvar(char *vars, const char *name)
1774 {
1775         return NULL;
1776 }
1777
1778 /*
1779  * buffer length needed for wlc_format_ssid
1780  * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
1781  */
1782
1783 #if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \
1784         defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
1785 int bcm_format_ssid(char *buf, const unsigned char ssid[], uint ssid_len)
1786 {
1787         uint i, c;
1788         char *p = buf;
1789         char *endp = buf + SSID_FMT_BUF_LEN;
1790
1791         if (ssid_len > DOT11_MAX_SSID_LEN)
1792                 ssid_len = DOT11_MAX_SSID_LEN;
1793
1794         for (i = 0; i < ssid_len; i++) {
1795                 c = (uint) ssid[i];
1796                 if (c == '\\') {
1797                         *p++ = '\\';
1798                         *p++ = '\\';
1799                 } else if (bcm_isprint((unsigned char) c)) {
1800                         *p++ = (char)c;
1801                 } else {
1802                         p += snprintf(p, (endp - p), "\\x%02X", c);
1803                 }
1804         }
1805         *p = '\0';
1806         ASSERT(p < endp);
1807
1808         return (int)(p - buf);
1809 }
1810 #endif  /* defined(WLTINYDUMP) ||
1811          defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) */
1812
1813 #endif                          /* BCMDRIVER */