net: wifi: rockchip: update broadcom drivers for kernel4.4
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rkwifi / bcmdhd / bcmutils.c
1 /*
2  * Driver O/S-independent utility routines
3  *
4  * Copyright (C) 1999-2016, Broadcom Corporation
5  * 
6  *      Unless you and Broadcom execute a separate written software license
7  * agreement governing use of this software, this software is licensed to you
8  * under the terms of the GNU General Public License version 2 (the "GPL"),
9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10  * following added to such license:
11  * 
12  *      As a special exception, the copyright holders of this software give you
13  * permission to link this software with independent modules, and to copy and
14  * distribute the resulting executable under terms of your choice, provided that
15  * you also meet, for each linked independent module, the terms and conditions of
16  * the license of that module.  An independent module is a module which is not
17  * derived from this software.  The special exception does not apply to any
18  * modifications of the software.
19  * 
20  *      Notwithstanding the above, under no circumstances may you combine this
21  * software in any way with any other Broadcom software provided under a license
22  * other than the GPL, without Broadcom's express prior written consent.
23  *
24  *
25  * <<Broadcom-WL-IPTag/Open:>>
26  *
27  * $Id: bcmutils.c 591286 2015-10-07 11:59:26Z $
28  */
29
30 #include <bcm_cfg.h>
31 #include <typedefs.h>
32 #include <bcmdefs.h>
33 #include <stdarg.h>
34 #ifdef BCMDRIVER
35
36 #include <osl.h>
37 #include <bcmutils.h>
38
39 #else /* !BCMDRIVER */
40
41 #include <stdio.h>
42 #include <string.h>
43 #include <bcmutils.h>
44
45 #if defined(BCMEXTSUP)
46 #include <bcm_osl.h>
47 #endif
48
49 #ifndef ASSERT
50 #define ASSERT(exp)
51 #endif
52
53 #endif /* !BCMDRIVER */
54
55 #include <bcmendian.h>
56 #include <bcmdevs.h>
57 #include <proto/ethernet.h>
58 #include <proto/vlan.h>
59 #include <proto/bcmip.h>
60 #include <proto/802.1d.h>
61 #include <proto/802.11.h>
62
63
64 void *_bcmutils_dummy_fn = NULL;
65
66
67
68
69 #ifdef BCMDRIVER
70
71
72
73 /* copy a pkt buffer chain into a buffer */
74 uint
75 pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf)
76 {
77         uint n, ret = 0;
78
79         if (len < 0)
80                 len = 4096;     /* "infinite" */
81
82         /* skip 'offset' bytes */
83         for (; p && offset; p = PKTNEXT(osh, p)) {
84                 if (offset < (uint)PKTLEN(osh, p))
85                         break;
86                 offset -= PKTLEN(osh, p);
87         }
88
89         if (!p)
90                 return 0;
91
92         /* copy the data */
93         for (; p && len; p = PKTNEXT(osh, p)) {
94                 n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
95                 bcopy(PKTDATA(osh, p) + offset, buf, n);
96                 buf += n;
97                 len -= n;
98                 ret += n;
99                 offset = 0;
100         }
101
102         return ret;
103 }
104
105 /* copy a buffer into a pkt buffer chain */
106 uint
107 pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf)
108 {
109         uint n, ret = 0;
110
111
112         /* skip 'offset' bytes */
113         for (; p && offset; p = PKTNEXT(osh, p)) {
114                 if (offset < (uint)PKTLEN(osh, p))
115                         break;
116                 offset -= PKTLEN(osh, p);
117         }
118
119         if (!p)
120                 return 0;
121
122         /* copy the data */
123         for (; p && len; p = PKTNEXT(osh, p)) {
124                 n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
125                 bcopy(buf, PKTDATA(osh, p) + offset, n);
126                 buf += n;
127                 len -= n;
128                 ret += n;
129                 offset = 0;
130         }
131
132         return ret;
133 }
134
135
136
137 /* return total length of buffer chain */
138 uint BCMFASTPATH
139 pkttotlen(osl_t *osh, void *p)
140 {
141         uint total;
142         int len;
143
144         total = 0;
145         for (; p; p = PKTNEXT(osh, p)) {
146                 len = PKTLEN(osh, p);
147                 total += len;
148 #ifdef BCMLFRAG
149                 if (BCMLFRAG_ENAB()) {
150                         if (PKTISFRAG(osh, p)) {
151                                 total += PKTFRAGTOTLEN(osh, p);
152                         }
153                 }
154 #endif
155         }
156
157         return (total);
158 }
159
160 /* return the last buffer of chained pkt */
161 void *
162 pktlast(osl_t *osh, void *p)
163 {
164         for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p))
165                 ;
166
167         return (p);
168 }
169
170 /* count segments of a chained packet */
171 uint BCMFASTPATH
172 pktsegcnt(osl_t *osh, void *p)
173 {
174         uint cnt;
175
176         for (cnt = 0; p; p = PKTNEXT(osh, p)) {
177                 cnt++;
178 #ifdef BCMLFRAG
179                 if (BCMLFRAG_ENAB()) {
180                         if (PKTISFRAG(osh, p)) {
181                                 cnt += PKTFRAGTOTNUM(osh, p);
182                         }
183                 }
184 #endif
185         }
186
187         return cnt;
188 }
189
190
191 /* count segments of a chained packet */
192 uint BCMFASTPATH
193 pktsegcnt_war(osl_t *osh, void *p)
194 {
195         uint cnt;
196         uint8 *pktdata;
197         uint len, remain, align64;
198
199         for (cnt = 0; p; p = PKTNEXT(osh, p)) {
200                 cnt++;
201                 len = PKTLEN(osh, p);
202                 if (len > 128) {
203                         pktdata = (uint8 *)PKTDATA(osh, p);     /* starting address of data */
204                         /* Check for page boundary straddle (2048B) */
205                         if (((uintptr)pktdata & ~0x7ff) != ((uintptr)(pktdata+len) & ~0x7ff))
206                                 cnt++;
207
208                         align64 = (uint)((uintptr)pktdata & 0x3f);      /* aligned to 64B */
209                         align64 = (64 - align64) & 0x3f;
210                         len -= align64;         /* bytes from aligned 64B to end */
211                         /* if aligned to 128B, check for MOD 128 between 1 to 4B */
212                         remain = len % 128;
213                         if (remain > 0 && remain <= 4)
214                                 cnt++;          /* add extra seg */
215                 }
216         }
217
218         return cnt;
219 }
220
221 uint8 * BCMFASTPATH
222 pktdataoffset(osl_t *osh, void *p,  uint offset)
223 {
224         uint total = pkttotlen(osh, p);
225         uint pkt_off = 0, len = 0;
226         uint8 *pdata = (uint8 *) PKTDATA(osh, p);
227
228         if (offset > total)
229                 return NULL;
230
231         for (; p; p = PKTNEXT(osh, p)) {
232                 pdata = (uint8 *) PKTDATA(osh, p);
233                 pkt_off = offset - len;
234                 len += PKTLEN(osh, p);
235                 if (len > offset)
236                         break;
237         }
238         return (uint8*) (pdata+pkt_off);
239 }
240
241
242 /* given a offset in pdata, find the pkt seg hdr */
243 void *
244 pktoffset(osl_t *osh, void *p,  uint offset)
245 {
246         uint total = pkttotlen(osh, p);
247         uint len = 0;
248
249         if (offset > total)
250                 return NULL;
251
252         for (; p; p = PKTNEXT(osh, p)) {
253                 len += PKTLEN(osh, p);
254                 if (len > offset)
255                         break;
256         }
257         return p;
258 }
259
260 #endif /* BCMDRIVER */
261
262 #if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
263 const unsigned char bcm_ctype[] = {
264
265         _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,                        /* 0-7 */
266         _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C,
267         _BCM_C, /* 8-15 */
268         _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,                        /* 16-23 */
269         _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,                        /* 24-31 */
270         _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,                /* 32-39 */
271         _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,                        /* 40-47 */
272         _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,                        /* 48-55 */
273         _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,                        /* 56-63 */
274         _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X,
275         _BCM_U|_BCM_X, _BCM_U, /* 64-71 */
276         _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,                        /* 72-79 */
277         _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,                        /* 80-87 */
278         _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,                        /* 88-95 */
279         _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X,
280         _BCM_L|_BCM_X, _BCM_L, /* 96-103 */
281         _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */
282         _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */
283         _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */
284         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         /* 128-143 */
285         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,         /* 144-159 */
286         _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
287         _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */
288         _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
289         _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */
290         _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,
291         _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */
292         _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U,
293         _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */
294         _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,
295         _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */
296         _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L,
297         _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */
298 };
299
300 ulong
301 bcm_strtoul(const char *cp, char **endp, uint base)
302 {
303         ulong result, last_result = 0, value;
304         bool minus;
305
306         minus = FALSE;
307
308         while (bcm_isspace(*cp))
309                 cp++;
310
311         if (cp[0] == '+')
312                 cp++;
313         else if (cp[0] == '-') {
314                 minus = TRUE;
315                 cp++;
316         }
317
318         if (base == 0) {
319                 if (cp[0] == '0') {
320                         if ((cp[1] == 'x') || (cp[1] == 'X')) {
321                                 base = 16;
322                                 cp = &cp[2];
323                         } else {
324                                 base = 8;
325                                 cp = &cp[1];
326                         }
327                 } else
328                         base = 10;
329         } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
330                 cp = &cp[2];
331         }
332
333         result = 0;
334
335         while (bcm_isxdigit(*cp) &&
336                (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) {
337                 result = result*base + value;
338                 /* Detected overflow */
339                 if (result < last_result && !minus)
340                         return (ulong)-1;
341                 last_result = result;
342                 cp++;
343         }
344
345         if (minus)
346                 result = (ulong)(-(long)result);
347
348         if (endp)
349                 *endp = DISCARD_QUAL(cp, char);
350
351         return (result);
352 }
353
354 int
355 bcm_atoi(const char *s)
356 {
357         return (int)bcm_strtoul(s, NULL, 10);
358 }
359
360 /* return pointer to location of substring 'needle' in 'haystack' */
361 char *
362 bcmstrstr(const char *haystack, const char *needle)
363 {
364         int len, nlen;
365         int i;
366
367         if ((haystack == NULL) || (needle == NULL))
368                 return DISCARD_QUAL(haystack, char);
369
370         nlen = (int)strlen(needle);
371         len = (int)strlen(haystack) - nlen + 1;
372
373         for (i = 0; i < len; i++)
374                 if (memcmp(needle, &haystack[i], nlen) == 0)
375                         return DISCARD_QUAL(&haystack[i], char);
376         return (NULL);
377 }
378
379 char *
380 bcmstrnstr(const char *s, uint s_len, const char *substr, uint substr_len)
381 {
382         for (; s_len >= substr_len; s++, s_len--)
383                 if (strncmp(s, substr, substr_len) == 0)
384                         return DISCARD_QUAL(s, char);
385
386         return NULL;
387 }
388
389 char *
390 bcmstrcat(char *dest, const char *src)
391 {
392         char *p;
393
394         p = dest + strlen(dest);
395
396         while ((*p++ = *src++) != '\0')
397                 ;
398
399         return (dest);
400 }
401
402 char *
403 bcmstrncat(char *dest, const char *src, uint size)
404 {
405         char *endp;
406         char *p;
407
408         p = dest + strlen(dest);
409         endp = p + size;
410
411         while (p != endp && (*p++ = *src++) != '\0')
412                 ;
413
414         return (dest);
415 }
416
417
418 /****************************************************************************
419 * Function:   bcmstrtok
420 *
421 * Purpose:
422 *  Tokenizes a string. This function is conceptually similiar to ANSI C strtok(),
423 *  but allows strToken() to be used by different strings or callers at the same
424 *  time. Each call modifies '*string' by substituting a NULL character for the
425 *  first delimiter that is encountered, and updates 'string' to point to the char
426 *  after the delimiter. Leading delimiters are skipped.
427 *
428 * Parameters:
429 *  string      (mod) Ptr to string ptr, updated by token.
430 *  delimiters  (in)  Set of delimiter characters.
431 *  tokdelim    (out) Character that delimits the returned token. (May
432 *                    be set to NULL if token delimiter is not required).
433 *
434 * Returns:  Pointer to the next token found. NULL when no more tokens are found.
435 *****************************************************************************
436 */
437 char *
438 bcmstrtok(char **string, const char *delimiters, char *tokdelim)
439 {
440         unsigned char *str;
441         unsigned long map[8];
442         int count;
443         char *nextoken;
444
445         if (tokdelim != NULL) {
446                 /* Prime the token delimiter */
447                 *tokdelim = '\0';
448         }
449
450         /* Clear control map */
451         for (count = 0; count < 8; count++) {
452                 map[count] = 0;
453         }
454
455         /* Set bits in delimiter table */
456         do {
457                 map[*delimiters >> 5] |= (1 << (*delimiters & 31));
458         }
459         while (*delimiters++);
460
461         str = (unsigned char*)*string;
462
463         /* Find beginning of token (skip over leading delimiters). Note that
464          * there is no token iff this loop sets str to point to the terminal
465          * null (*str == '\0')
466          */
467         while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) {
468                 str++;
469         }
470
471         nextoken = (char*)str;
472
473         /* Find the end of the token. If it is not the end of the string,
474          * put a null there.
475          */
476         for (; *str; str++) {
477                 if (map[*str >> 5] & (1 << (*str & 31))) {
478                         if (tokdelim != NULL) {
479                                 *tokdelim = *str;
480                         }
481
482                         *str++ = '\0';
483                         break;
484                 }
485         }
486
487         *string = (char*)str;
488
489         /* Determine if a token has been found. */
490         if (nextoken == (char *) str) {
491                 return NULL;
492         }
493         else {
494                 return nextoken;
495         }
496 }
497
498
499 #define xToLower(C) \
500         ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C)
501
502
503 /****************************************************************************
504 * Function:   bcmstricmp
505 *
506 * Purpose:    Compare to strings case insensitively.
507 *
508 * Parameters: s1 (in) First string to compare.
509 *             s2 (in) Second string to compare.
510 *
511 * Returns:    Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
512 *             t1 > t2, when ignoring case sensitivity.
513 *****************************************************************************
514 */
515 int
516 bcmstricmp(const char *s1, const char *s2)
517 {
518         char dc, sc;
519
520         while (*s2 && *s1) {
521                 dc = xToLower(*s1);
522                 sc = xToLower(*s2);
523                 if (dc < sc) return -1;
524                 if (dc > sc) return 1;
525                 s1++;
526                 s2++;
527         }
528
529         if (*s1 && !*s2) return 1;
530         if (!*s1 && *s2) return -1;
531         return 0;
532 }
533
534
535 /****************************************************************************
536 * Function:   bcmstrnicmp
537 *
538 * Purpose:    Compare to strings case insensitively, upto a max of 'cnt'
539 *             characters.
540 *
541 * Parameters: s1  (in) First string to compare.
542 *             s2  (in) Second string to compare.
543 *             cnt (in) Max characters to compare.
544 *
545 * Returns:    Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
546 *             t1 > t2, when ignoring case sensitivity.
547 *****************************************************************************
548 */
549 int
550 bcmstrnicmp(const char* s1, const char* s2, int cnt)
551 {
552         char dc, sc;
553
554         while (*s2 && *s1 && cnt) {
555                 dc = xToLower(*s1);
556                 sc = xToLower(*s2);
557                 if (dc < sc) return -1;
558                 if (dc > sc) return 1;
559                 s1++;
560                 s2++;
561                 cnt--;
562         }
563
564         if (!cnt) return 0;
565         if (*s1 && !*s2) return 1;
566         if (!*s1 && *s2) return -1;
567         return 0;
568 }
569
570 /* parse a xx:xx:xx:xx:xx:xx format ethernet address */
571 int
572 bcm_ether_atoe(const char *p, struct ether_addr *ea)
573 {
574         int i = 0;
575         char *ep;
576
577         for (;;) {
578                 ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16);
579                 p = ep;
580                 if (!*p++ || i == 6)
581                         break;
582         }
583
584         return (i == 6);
585 }
586
587 int
588 bcm_atoipv4(const char *p, struct ipv4_addr *ip)
589 {
590
591         int i = 0;
592         char *c;
593         for (;;) {
594                 ip->addr[i++] = (uint8)bcm_strtoul(p, &c, 0);
595                 if (*c++ != '.' || i == IPV4_ADDR_LEN)
596                         break;
597                 p = c;
598         }
599         return (i == IPV4_ADDR_LEN);
600 }
601 #endif  /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
602
603
604 #if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER)
605 /* registry routine buffer preparation utility functions:
606  * parameter order is like strncpy, but returns count
607  * of bytes copied. Minimum bytes copied is null char(1)/wchar(2)
608  */
609 ulong
610 wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen)
611 {
612         ulong copyct = 1;
613         ushort i;
614
615         if (abuflen == 0)
616                 return 0;
617
618         /* wbuflen is in bytes */
619         wbuflen /= sizeof(ushort);
620
621         for (i = 0; i < wbuflen; ++i) {
622                 if (--abuflen == 0)
623                         break;
624                 *abuf++ = (char) *wbuf++;
625                 ++copyct;
626         }
627         *abuf = '\0';
628
629         return copyct;
630 }
631 #endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */
632
633 char *
634 bcm_ether_ntoa(const struct ether_addr *ea, char *buf)
635 {
636         static const char hex[] =
637           {
638                   '0', '1', '2', '3', '4', '5', '6', '7',
639                   '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
640           };
641         const uint8 *octet = ea->octet;
642         char *p = buf;
643         int i;
644
645         for (i = 0; i < 6; i++, octet++) {
646                 *p++ = hex[(*octet >> 4) & 0xf];
647                 *p++ = hex[*octet & 0xf];
648                 *p++ = ':';
649         }
650
651         *(p-1) = '\0';
652
653         return (buf);
654 }
655
656 char *
657 bcm_ip_ntoa(struct ipv4_addr *ia, char *buf)
658 {
659         snprintf(buf, 16, "%d.%d.%d.%d",
660                  ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]);
661         return (buf);
662 }
663
664 char *
665 bcm_ipv6_ntoa(void *ipv6, char *buf)
666 {
667         /* Implementing RFC 5952 Sections 4 + 5 */
668         /* Not thoroughly tested */
669         uint16 tmp[8];
670         uint16 *a = &tmp[0];
671         char *p = buf;
672         int i, i_max = -1, cnt = 0, cnt_max = 1;
673         uint8 *a4 = NULL;
674         memcpy((uint8 *)&tmp[0], (uint8 *)ipv6, IPV6_ADDR_LEN);
675
676         for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
677                 if (a[i]) {
678                         if (cnt > cnt_max) {
679                                 cnt_max = cnt;
680                                 i_max = i - cnt;
681                         }
682                         cnt = 0;
683                 } else
684                         cnt++;
685         }
686         if (cnt > cnt_max) {
687                 cnt_max = cnt;
688                 i_max = i - cnt;
689         }
690         if (i_max == 0 &&
691                 /* IPv4-translated: ::ffff:0:a.b.c.d */
692                 ((cnt_max == 4 && a[4] == 0xffff && a[5] == 0) ||
693                 /* IPv4-mapped: ::ffff:a.b.c.d */
694                 (cnt_max == 5 && a[5] == 0xffff)))
695                 a4 = (uint8*) (a + 6);
696
697         for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
698                 if ((uint8*) (a + i) == a4) {
699                         snprintf(p, 16, ":%u.%u.%u.%u", a4[0], a4[1], a4[2], a4[3]);
700                         break;
701                 } else if (i == i_max) {
702                         *p++ = ':';
703                         i += cnt_max - 1;
704                         p[0] = ':';
705                         p[1] = '\0';
706                 } else {
707                         if (i)
708                                 *p++ = ':';
709                         p += snprintf(p, 8, "%x", ntoh16(a[i]));
710                 }
711         }
712
713         return buf;
714 }
715 #ifdef BCMDRIVER
716
717 void
718 bcm_mdelay(uint ms)
719 {
720         uint i;
721
722         for (i = 0; i < ms; i++) {
723                 OSL_DELAY(1000);
724         }
725 }
726
727
728
729
730
731 #if defined(DHD_DEBUG)
732 /* pretty hex print a pkt buffer chain */
733 void
734 prpkt(const char *msg, osl_t *osh, void *p0)
735 {
736         void *p;
737
738         if (msg && (msg[0] != '\0'))
739                 printf("%s:\n", msg);
740
741         for (p = p0; p; p = PKTNEXT(osh, p))
742                 prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p));
743 }
744 #endif  
745
746 /* Takes an Ethernet frame and sets out-of-bound PKTPRIO.
747  * Also updates the inplace vlan tag if requested.
748  * For debugging, it returns an indication of what it did.
749  */
750 uint BCMFASTPATH
751 pktsetprio(void *pkt, bool update_vtag)
752 {
753         struct ether_header *eh;
754         struct ethervlan_header *evh;
755         uint8 *pktdata;
756         int priority = 0;
757         int rc = 0;
758
759         pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
760         ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
761
762         eh = (struct ether_header *) pktdata;
763
764         if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) {
765                 uint16 vlan_tag;
766                 int vlan_prio, dscp_prio = 0;
767
768                 evh = (struct ethervlan_header *)eh;
769
770                 vlan_tag = ntoh16(evh->vlan_tag);
771                 vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
772
773                 if ((evh->ether_type == hton16(ETHER_TYPE_IP)) ||
774                         (evh->ether_type == hton16(ETHER_TYPE_IPV6))) {
775                         uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
776                         uint8 tos_tc = IP_TOS46(ip_body);
777                         dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
778                 }
779
780                 /* DSCP priority gets precedence over 802.1P (vlan tag) */
781                 if (dscp_prio != 0) {
782                         priority = dscp_prio;
783                         rc |= PKTPRIO_VDSCP;
784                 } else {
785                         priority = vlan_prio;
786                         rc |= PKTPRIO_VLAN;
787                 }
788                 /*
789                  * If the DSCP priority is not the same as the VLAN priority,
790                  * then overwrite the priority field in the vlan tag, with the
791                  * DSCP priority value. This is required for Linux APs because
792                  * the VLAN driver on Linux, overwrites the skb->priority field
793                  * with the priority value in the vlan tag
794                  */
795                 if (update_vtag && (priority != vlan_prio)) {
796                         vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
797                         vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT;
798                         evh->vlan_tag = hton16(vlan_tag);
799                         rc |= PKTPRIO_UPD;
800                 }
801 #ifdef DHD_LOSSLESS_ROAMING
802         } else if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
803                 priority = PRIO_8021D_NC;
804                 rc = PKTPRIO_DSCP;
805 #endif /* DHD_LOSSLESS_ROAMING */
806         } else if ((eh->ether_type == hton16(ETHER_TYPE_IP)) ||
807                 (eh->ether_type == hton16(ETHER_TYPE_IPV6))) {
808                 uint8 *ip_body = pktdata + sizeof(struct ether_header);
809                 uint8 tos_tc = IP_TOS46(ip_body);
810                 uint8 dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT;
811                 switch (dscp) {
812                 case DSCP_EF:
813                         priority = PRIO_8021D_VO;
814                         break;
815                 case DSCP_AF31:
816                 case DSCP_AF32:
817                 case DSCP_AF33:
818                         priority = PRIO_8021D_CL;
819                         break;
820                 case DSCP_AF21:
821                 case DSCP_AF22:
822                 case DSCP_AF23:
823                 case DSCP_AF11:
824                 case DSCP_AF12:
825                 case DSCP_AF13:
826                         priority = PRIO_8021D_EE;
827                         break;
828                 default:
829                         priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
830                         break;
831                 }
832
833                 rc |= PKTPRIO_DSCP;
834         }
835
836         ASSERT(priority >= 0 && priority <= MAXPRIO);
837         PKTSETPRIO(pkt, priority);
838         return (rc | priority);
839 }
840
841 /* lookup user priority for specified DSCP */
842 static uint8
843 dscp2up(uint8 *up_table, uint8 dscp)
844 {
845         uint8 user_priority = 255;
846
847         /* lookup up from table if parameters valid */
848         if (up_table != NULL && dscp < UP_TABLE_MAX) {
849                 user_priority = up_table[dscp];
850         }
851
852         /* 255 is unused value so return up from dscp */
853         if (user_priority == 255) {
854                 user_priority = dscp >> (IPV4_TOS_PREC_SHIFT - IPV4_TOS_DSCP_SHIFT);
855         }
856
857         return user_priority;
858 }
859
860 /* set user priority by QoS Map Set table (UP table), table size is UP_TABLE_MAX */
861 uint BCMFASTPATH
862 pktsetprio_qms(void *pkt, uint8* up_table, bool update_vtag)
863 {
864         if (up_table) {
865                 uint8 *pktdata;
866                 uint pktlen;
867                 uint8 dscp;
868                 uint user_priority = 0;
869                 uint rc = 0;
870
871                 pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
872                 pktlen = PKTLEN(OSH_NULL, pkt);
873
874                 if (pktgetdscp(pktdata, pktlen, &dscp)) {
875                         rc = PKTPRIO_DSCP;
876                         user_priority = dscp2up(up_table, dscp);
877                         PKTSETPRIO(pkt, user_priority);
878                 }
879
880                 return (rc | user_priority);
881         } else {
882                 return pktsetprio(pkt, update_vtag);
883         }
884 }
885
886 /* Returns TRUE and DSCP if IP header found, FALSE otherwise.
887  */
888 bool BCMFASTPATH
889 pktgetdscp(uint8 *pktdata, uint pktlen, uint8 *dscp)
890 {
891         struct ether_header *eh;
892         struct ethervlan_header *evh;
893         uint8 *ip_body;
894         bool rc = FALSE;
895
896         /* minimum length is ether header and IP header */
897         if (pktlen < sizeof(struct ether_header) + IPV4_MIN_HEADER_LEN)
898                 return FALSE;
899
900         eh = (struct ether_header *) pktdata;
901
902         if (eh->ether_type == HTON16(ETHER_TYPE_IP)) {
903                 ip_body = pktdata + sizeof(struct ether_header);
904                 *dscp = IP_DSCP46(ip_body);
905                 rc = TRUE;
906         }
907         else if (eh->ether_type == HTON16(ETHER_TYPE_8021Q)) {
908                 evh = (struct ethervlan_header *)eh;
909
910                 /* minimum length is ethervlan header and IP header */
911                 if (pktlen >= sizeof(struct ethervlan_header) + IPV4_MIN_HEADER_LEN &&
912                         evh->ether_type == HTON16(ETHER_TYPE_IP)) {
913                         ip_body = pktdata + sizeof(struct ethervlan_header);
914                         *dscp = IP_DSCP46(ip_body);
915                         rc = TRUE;
916                 }
917         }
918
919         return rc;
920 }
921
922 /* Add to adjust the 802.1x priority */
923 void
924 pktset8021xprio(void *pkt, int prio)
925 {
926         struct ether_header *eh;
927         uint8 *pktdata;
928         if(prio == PKTPRIO(pkt))
929                 return;
930         pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
931         ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
932         eh = (struct ether_header *) pktdata;
933         if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
934                 ASSERT(prio >= 0 && prio <= MAXPRIO);
935                 PKTSETPRIO(pkt, prio);
936         }
937 }
938
939 /* The 0.5KB string table is not removed by compiler even though it's unused */
940
941 static char bcm_undeferrstr[32];
942 static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE;
943
944 /* Convert the error codes into related error strings  */
945 const char *
946 bcmerrorstr(int bcmerror)
947 {
948         /* check if someone added a bcmerror code but forgot to add errorstring */
949         ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1));
950
951         if (bcmerror > 0 || bcmerror < BCME_LAST) {
952                 snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror);
953                 return bcm_undeferrstr;
954         }
955
956         ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN);
957
958         return bcmerrorstrtable[-bcmerror];
959 }
960
961
962
963 /* iovar table lookup */
964 /* could mandate sorted tables and do a binary search */
965 const bcm_iovar_t*
966 bcm_iovar_lookup(const bcm_iovar_t *table, const char *name)
967 {
968         const bcm_iovar_t *vi;
969         const char *lookup_name;
970
971         /* skip any ':' delimited option prefixes */
972         lookup_name = strrchr(name, ':');
973         if (lookup_name != NULL)
974                 lookup_name++;
975         else
976                 lookup_name = name;
977
978         ASSERT(table != NULL);
979
980         for (vi = table; vi->name; vi++) {
981                 if (!strcmp(vi->name, lookup_name))
982                         return vi;
983         }
984         /* ran to end of table */
985
986         return NULL; /* var name not found */
987 }
988
989 int
990 bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
991 {
992         int bcmerror = 0;
993
994         /* length check on io buf */
995         switch (vi->type) {
996         case IOVT_BOOL:
997         case IOVT_INT8:
998         case IOVT_INT16:
999         case IOVT_INT32:
1000         case IOVT_UINT8:
1001         case IOVT_UINT16:
1002         case IOVT_UINT32:
1003                 /* all integers are int32 sized args at the ioctl interface */
1004                 if (len < (int)sizeof(int)) {
1005                         bcmerror = BCME_BUFTOOSHORT;
1006                 }
1007                 break;
1008
1009         case IOVT_BUFFER:
1010                 /* buffer must meet minimum length requirement */
1011                 if (len < vi->minlen) {
1012                         bcmerror = BCME_BUFTOOSHORT;
1013                 }
1014                 break;
1015
1016         case IOVT_VOID:
1017                 if (!set) {
1018                         /* Cannot return nil... */
1019                         bcmerror = BCME_UNSUPPORTED;
1020                 } else if (len) {
1021                         /* Set is an action w/o parameters */
1022                         bcmerror = BCME_BUFTOOLONG;
1023                 }
1024                 break;
1025
1026         default:
1027                 /* unknown type for length check in iovar info */
1028                 ASSERT(0);
1029                 bcmerror = BCME_UNSUPPORTED;
1030         }
1031
1032         return bcmerror;
1033 }
1034
1035 #endif  /* BCMDRIVER */
1036
1037 #ifdef BCM_OBJECT_TRACE
1038
1039 #define BCM_OBJECT_MERGE_SAME_OBJ       0
1040
1041 /* some place may add / remove the object to trace list for Linux: */
1042 /* add:    osl_alloc_skb dev_alloc_skb skb_realloc_headroom dhd_start_xmit */
1043 /* remove: osl_pktfree dev_kfree_skb netif_rx */
1044
1045 #define BCM_OBJDBG_COUNT          (1024 * 100)
1046 static spinlock_t dbgobj_lock;
1047 #define BCM_OBJDBG_LOCK_INIT()    spin_lock_init(&dbgobj_lock)
1048 #define BCM_OBJDBG_LOCK_DESTROY()
1049 #define BCM_OBJDBG_LOCK           spin_lock_irqsave
1050 #define BCM_OBJDBG_UNLOCK         spin_unlock_irqrestore
1051
1052 #define BCM_OBJDBG_ADDTOHEAD      0
1053 #define BCM_OBJDBG_ADDTOTAIL      1
1054
1055 #define BCM_OBJDBG_CALLER_LEN     32
1056 struct bcm_dbgobj {
1057         struct bcm_dbgobj *prior;
1058         struct bcm_dbgobj *next;
1059         uint32 flag;
1060         void   *obj;
1061         uint32 obj_sn;
1062         uint32 obj_state;
1063         uint32 line;
1064         char   caller[BCM_OBJDBG_CALLER_LEN];
1065 };
1066
1067 static struct bcm_dbgobj *dbgobj_freehead = NULL;
1068 static struct bcm_dbgobj *dbgobj_freetail = NULL;
1069 static struct bcm_dbgobj *dbgobj_objhead = NULL;
1070 static struct bcm_dbgobj *dbgobj_objtail = NULL;
1071
1072 static uint32 dbgobj_sn = 0;
1073 static int dbgobj_count = 0;
1074 static struct bcm_dbgobj bcm_dbg_objs[BCM_OBJDBG_COUNT];
1075
1076 void
1077 bcm_object_trace_init(void)
1078 {
1079         int i = 0;
1080         BCM_OBJDBG_LOCK_INIT();
1081         memset(&bcm_dbg_objs, 0x00, sizeof(struct bcm_dbgobj) * BCM_OBJDBG_COUNT);
1082         dbgobj_freehead = &bcm_dbg_objs[0];
1083         dbgobj_freetail = &bcm_dbg_objs[BCM_OBJDBG_COUNT - 1];
1084
1085         for (i = 0; i < BCM_OBJDBG_COUNT; ++i) {
1086                 bcm_dbg_objs[i].next = (i == (BCM_OBJDBG_COUNT - 1)) ?
1087                         dbgobj_freehead : &bcm_dbg_objs[i + 1];
1088                 bcm_dbg_objs[i].prior = (i == 0) ?
1089                         dbgobj_freetail : &bcm_dbg_objs[i - 1];
1090         }
1091 }
1092
1093 void
1094 bcm_object_trace_deinit(void)
1095 {
1096         if (dbgobj_objhead || dbgobj_objtail) {
1097                 printf("%s: not all objects are released\n", __FUNCTION__);
1098                 ASSERT(0);
1099         }
1100         BCM_OBJDBG_LOCK_DESTROY();
1101 }
1102
1103 static void
1104 bcm_object_rm_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
1105         struct bcm_dbgobj *dbgobj)
1106 {
1107         if ((dbgobj == *head) && (dbgobj == *tail)) {
1108                 *head = NULL;
1109                 *tail = NULL;
1110         } else if (dbgobj == *head) {
1111                 *head = (*head)->next;
1112         } else if (dbgobj == *tail) {
1113                 *tail = (*tail)->prior;
1114         }
1115         dbgobj->next->prior = dbgobj->prior;
1116         dbgobj->prior->next = dbgobj->next;
1117 }
1118
1119 static void
1120 bcm_object_add_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
1121         struct bcm_dbgobj *dbgobj, int addtotail)
1122 {
1123         if (!(*head) && !(*tail)) {
1124                 *head = dbgobj;
1125                 *tail = dbgobj;
1126                 dbgobj->next = dbgobj;
1127                 dbgobj->prior = dbgobj;
1128         } else if ((*head) && (*tail)) {
1129                 (*tail)->next = dbgobj;
1130                 (*head)->prior = dbgobj;
1131                 dbgobj->next = *head;
1132                 dbgobj->prior = *tail;
1133                 if (addtotail == BCM_OBJDBG_ADDTOTAIL)
1134                         *tail = dbgobj;
1135                 else
1136                         *head = dbgobj;
1137         } else {
1138                 ASSERT(0); /* can't be this case */
1139         }
1140 }
1141
1142 static INLINE void
1143 bcm_object_movetoend(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
1144         struct bcm_dbgobj *dbgobj, int movetotail)
1145 {
1146         if ((*head) && (*tail)) {
1147                 if (movetotail == BCM_OBJDBG_ADDTOTAIL) {
1148                         if (dbgobj != (*tail)) {
1149                                 bcm_object_rm_list(head, tail, dbgobj);
1150                                 bcm_object_add_list(head, tail, dbgobj, movetotail);
1151                         }
1152                 } else {
1153                         if (dbgobj != (*head)) {
1154                                 bcm_object_rm_list(head, tail, dbgobj);
1155                                 bcm_object_add_list(head, tail, dbgobj, movetotail);
1156                         }
1157                 }
1158         } else {
1159                 ASSERT(0); /* can't be this case */
1160         }
1161 }
1162
1163 void
1164 bcm_object_trace_opr(void *obj, uint32 opt, const char *caller, int line)
1165 {
1166         struct bcm_dbgobj *dbgobj;
1167         unsigned long flags;
1168
1169         BCM_REFERENCE(flags);
1170         BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
1171
1172         if (opt == BCM_OBJDBG_ADD_PKT ||
1173                 opt == BCM_OBJDBG_ADD) {
1174                 dbgobj = dbgobj_objtail;
1175                 while (dbgobj) {
1176                         if (dbgobj->obj == obj) {
1177                                 printf("%s: obj %p allocated from %s(%d),"
1178                                         " allocate again from %s(%d)\n",
1179                                         __FUNCTION__, dbgobj->obj,
1180                                         dbgobj->caller, dbgobj->line,
1181                                         caller, line);
1182                                 ASSERT(0);
1183                                 goto EXIT;
1184                         }
1185                         dbgobj = dbgobj->prior;
1186                         if (dbgobj == dbgobj_objtail)
1187                                 break;
1188                 }
1189
1190 #if BCM_OBJECT_MERGE_SAME_OBJ
1191                 dbgobj = dbgobj_freetail;
1192                 while (dbgobj) {
1193                         if (dbgobj->obj == obj) {
1194                                 goto FREED_ENTRY_FOUND;
1195                         }
1196                         dbgobj = dbgobj->prior;
1197                         if (dbgobj == dbgobj_freetail)
1198                                 break;
1199                 }
1200 #endif /* BCM_OBJECT_MERGE_SAME_OBJ */
1201
1202                 dbgobj = dbgobj_freehead;
1203 #if BCM_OBJECT_MERGE_SAME_OBJ
1204 FREED_ENTRY_FOUND:
1205 #endif /* BCM_OBJECT_MERGE_SAME_OBJ */
1206                 if (!dbgobj) {
1207                         printf("%s: already got %d objects ?????????????????????\n",
1208                                 __FUNCTION__, BCM_OBJDBG_COUNT);
1209                         ASSERT(0);
1210                         goto EXIT;
1211                 }
1212
1213                 bcm_object_rm_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj);
1214                 dbgobj->obj = obj;
1215                 strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN);
1216                 dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0';
1217                 dbgobj->line = line;
1218                 dbgobj->flag = 0;
1219                 if (opt == BCM_OBJDBG_ADD_PKT) {
1220                         dbgobj->obj_sn = dbgobj_sn++;
1221                         dbgobj->obj_state = 0;
1222                         /* first 4 bytes is pkt sn */
1223                         if (((unsigned long)PKTTAG(obj)) & 0x3)
1224                                 printf("pkt tag address not aligned by 4: %p\n", PKTTAG(obj));
1225                         *(uint32*)PKTTAG(obj) = dbgobj->obj_sn;
1226                 }
1227                 bcm_object_add_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj,
1228                         BCM_OBJDBG_ADDTOTAIL);
1229
1230                 dbgobj_count++;
1231
1232         } else if (opt == BCM_OBJDBG_REMOVE) {
1233                 dbgobj = dbgobj_objtail;
1234                 while (dbgobj) {
1235                         if (dbgobj->obj == obj) {
1236                                 if (dbgobj->flag) {
1237                                         printf("%s: rm flagged obj %p flag 0x%08x from %s(%d)\n",
1238                                                 __FUNCTION__, obj, dbgobj->flag, caller, line);
1239                                 }
1240                                 bcm_object_rm_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj);
1241                                 memset(dbgobj->caller, 0x00, BCM_OBJDBG_CALLER_LEN);
1242                                 strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN);
1243                                 dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0';
1244                                 dbgobj->line = line;
1245                                 bcm_object_add_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj,
1246                                         BCM_OBJDBG_ADDTOTAIL);
1247                                 dbgobj_count--;
1248                                 goto EXIT;
1249                         }
1250                         dbgobj = dbgobj->prior;
1251                         if (dbgobj == dbgobj_objtail)
1252                                 break;
1253                 }
1254
1255                 dbgobj = dbgobj_freetail;
1256                 while (dbgobj && dbgobj->obj) {
1257                         if (dbgobj->obj == obj) {
1258                                 printf("%s: obj %p already freed from from %s(%d),"
1259                                         " try free again from %s(%d)\n",
1260                                         __FUNCTION__, obj,
1261                                         dbgobj->caller, dbgobj->line,
1262                                         caller, line);
1263                                 //ASSERT(0); /* release same obj more than one time? */
1264                                 goto EXIT;
1265                         }
1266                         dbgobj = dbgobj->prior;
1267                         if (dbgobj == dbgobj_freetail)
1268                                 break;
1269                 }
1270
1271                 printf("%s: ################### release none-existing obj %p from %s(%d)\n",
1272                         __FUNCTION__, obj, caller, line);
1273                 //ASSERT(0); /* release same obj more than one time? */
1274
1275         }
1276
1277 EXIT:
1278         BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
1279         return;
1280 }
1281
1282 void
1283 bcm_object_trace_upd(void *obj, void *obj_new)
1284 {
1285         struct bcm_dbgobj *dbgobj;
1286         unsigned long flags;
1287
1288         BCM_REFERENCE(flags);
1289         BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
1290
1291         dbgobj = dbgobj_objtail;
1292         while (dbgobj) {
1293                 if (dbgobj->obj == obj) {
1294                         dbgobj->obj = obj_new;
1295                         if (dbgobj != dbgobj_objtail) {
1296                                 bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
1297                                         dbgobj, BCM_OBJDBG_ADDTOTAIL);
1298                         }
1299                         goto EXIT;
1300                 }
1301                 dbgobj = dbgobj->prior;
1302                 if (dbgobj == dbgobj_objtail)
1303                         break;
1304         }
1305
1306 EXIT:
1307         BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
1308         return;
1309 }
1310
1311 void
1312 bcm_object_trace_chk(void *obj, uint32 chksn, uint32 sn,
1313         const char *caller, int line)
1314 {
1315         struct bcm_dbgobj *dbgobj;
1316         unsigned long flags;
1317
1318         BCM_REFERENCE(flags);
1319         BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
1320
1321         dbgobj = dbgobj_objtail;
1322         while (dbgobj) {
1323                 if ((dbgobj->obj == obj) &&
1324                         ((!chksn) || (dbgobj->obj_sn == sn))) {
1325                         if (dbgobj != dbgobj_objtail) {
1326                                 bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
1327                                         dbgobj, BCM_OBJDBG_ADDTOTAIL);
1328                         }
1329                         goto EXIT;
1330                 }
1331                 dbgobj = dbgobj->prior;
1332                 if (dbgobj == dbgobj_objtail)
1333                         break;
1334         }
1335
1336         dbgobj = dbgobj_freetail;
1337         while (dbgobj) {
1338                 if ((dbgobj->obj == obj) &&
1339                         ((!chksn) || (dbgobj->obj_sn == sn))) {
1340                         printf("%s: (%s:%d) obj %p (sn %d state %d) was freed from %s(%d)\n",
1341                                 __FUNCTION__, caller, line,
1342                                 dbgobj->obj, dbgobj->obj_sn, dbgobj->obj_state,
1343                                 dbgobj->caller, dbgobj->line);
1344                         goto EXIT;
1345                 }
1346                 else if (dbgobj->obj == NULL) {
1347                         break;
1348                 }
1349                 dbgobj = dbgobj->prior;
1350                 if (dbgobj == dbgobj_freetail)
1351                         break;
1352         }
1353
1354         printf("%s: obj %p not found, check from %s(%d), chksn %s, sn %d\n",
1355                 __FUNCTION__, obj, caller, line, chksn ? "yes" : "no", sn);
1356         dbgobj = dbgobj_objtail;
1357         while (dbgobj) {
1358                 printf("%s: (%s:%d) obj %p sn %d was allocated from %s(%d)\n",
1359                                 __FUNCTION__, caller, line,
1360                                 dbgobj->obj, dbgobj->obj_sn, dbgobj->caller, dbgobj->line);
1361                 dbgobj = dbgobj->prior;
1362                 if (dbgobj == dbgobj_objtail)
1363                         break;
1364         }
1365
1366 EXIT:
1367         BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
1368         return;
1369 }
1370
1371 void
1372 bcm_object_feature_set(void *obj, uint32 type, uint32 value)
1373 {
1374         struct bcm_dbgobj *dbgobj;
1375         unsigned long flags;
1376
1377         BCM_REFERENCE(flags);
1378         BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
1379
1380         dbgobj = dbgobj_objtail;
1381         while (dbgobj) {
1382                 if (dbgobj->obj == obj) {
1383                         if (type == BCM_OBJECT_FEATURE_FLAG) {
1384                                 if (value & BCM_OBJECT_FEATURE_CLEAR)
1385                                         dbgobj->flag &= ~(value);
1386                                 else
1387                                         dbgobj->flag |= (value);
1388                         } else if (type == BCM_OBJECT_FEATURE_PKT_STATE) {
1389                                 dbgobj->obj_state = value;
1390                         }
1391                         if (dbgobj != dbgobj_objtail) {
1392                                 bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
1393                                         dbgobj, BCM_OBJDBG_ADDTOTAIL);
1394                         }
1395                         goto EXIT;
1396                 }
1397                 dbgobj = dbgobj->prior;
1398                 if (dbgobj == dbgobj_objtail)
1399                         break;
1400         }
1401
1402         printf("%s: obj %p not found in active list\n", __FUNCTION__, obj);
1403         ASSERT(0);
1404
1405 EXIT:
1406         BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
1407         return;
1408 }
1409
1410 int
1411 bcm_object_feature_get(void *obj, uint32 type, uint32 value)
1412 {
1413         int rtn = 0;
1414         struct bcm_dbgobj *dbgobj;
1415         unsigned long flags;
1416
1417         BCM_REFERENCE(flags);
1418         BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
1419
1420         dbgobj = dbgobj_objtail;
1421         while (dbgobj) {
1422                 if (dbgobj->obj == obj) {
1423                         if (type == BCM_OBJECT_FEATURE_FLAG) {
1424                                 rtn = (dbgobj->flag & value) & (~BCM_OBJECT_FEATURE_CLEAR);
1425                         }
1426                         if (dbgobj != dbgobj_objtail) {
1427                                 bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
1428                                         dbgobj, BCM_OBJDBG_ADDTOTAIL);
1429                         }
1430                         goto EXIT;
1431                 }
1432                 dbgobj = dbgobj->prior;
1433                 if (dbgobj == dbgobj_objtail)
1434                         break;
1435         }
1436
1437         printf("%s: obj %p not found in active list\n", __FUNCTION__, obj);
1438         ASSERT(0);
1439
1440 EXIT:
1441         BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
1442         return rtn;
1443 }
1444
1445 #endif /* BCM_OBJECT_TRACE */
1446
1447 uint8 *
1448 bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst)
1449 {
1450         uint8 *new_dst = dst;
1451         bcm_tlv_t *dst_tlv = (bcm_tlv_t *)dst;
1452
1453         /* dst buffer should always be valid */
1454         ASSERT(dst);
1455
1456         /* data len must be within valid range */
1457         ASSERT((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE));
1458
1459         /* source data buffer pointer should be valid, unless datalen is 0
1460          * meaning no data with this TLV
1461          */
1462         ASSERT((data != NULL) || (datalen == 0));
1463
1464         /* only do work if the inputs are valid
1465          * - must have a dst to write to AND
1466          * - datalen must be within range AND
1467          * - the source data pointer must be non-NULL if datalen is non-zero
1468          * (this last condition detects datalen > 0 with a NULL data pointer)
1469          */
1470         if ((dst != NULL) &&
1471             ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) &&
1472             ((data != NULL) || (datalen == 0))) {
1473
1474                 /* write type, len fields */
1475                 dst_tlv->id = (uint8)type;
1476                 dst_tlv->len = (uint8)datalen;
1477
1478                 /* if data is present, copy to the output buffer and update
1479                  * pointer to output buffer
1480                  */
1481                 if (datalen > 0) {
1482
1483                         memcpy(dst_tlv->data, data, datalen);
1484                 }
1485
1486                 /* update the output destination poitner to point past
1487                  * the TLV written
1488                  */
1489                 new_dst = dst + BCM_TLV_HDR_SIZE + datalen;
1490         }
1491
1492         return (new_dst);
1493 }
1494
1495 uint8 *
1496 bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst, int dst_maxlen)
1497 {
1498         uint8 *new_dst = dst;
1499
1500         if ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) {
1501
1502                 /* if len + tlv hdr len is more than destlen, don't do anything
1503                  * just return the buffer untouched
1504                  */
1505                 if ((int)(datalen + BCM_TLV_HDR_SIZE) <= dst_maxlen) {
1506
1507                         new_dst = bcm_write_tlv(type, data, datalen, dst);
1508                 }
1509         }
1510
1511         return (new_dst);
1512 }
1513
1514 uint8 *
1515 bcm_copy_tlv(const void *src, uint8 *dst)
1516 {
1517         uint8 *new_dst = dst;
1518         const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src;
1519         uint totlen;
1520
1521         ASSERT(dst && src);
1522         if (dst && src) {
1523
1524                 totlen = BCM_TLV_HDR_SIZE + src_tlv->len;
1525                 memcpy(dst, src_tlv, totlen);
1526                 new_dst = dst + totlen;
1527         }
1528
1529         return (new_dst);
1530 }
1531
1532
1533 uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen)
1534 {
1535         uint8 *new_dst = dst;
1536         const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src;
1537
1538         ASSERT(src);
1539         if (src) {
1540                 if (bcm_valid_tlv(src_tlv, dst_maxlen)) {
1541                         new_dst = bcm_copy_tlv(src, dst);
1542                 }
1543         }
1544
1545         return (new_dst);
1546 }
1547
1548
1549 #if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
1550 /*******************************************************************************
1551  * crc8
1552  *
1553  * Computes a crc8 over the input data using the polynomial:
1554  *
1555  *       x^8 + x^7 +x^6 + x^4 + x^2 + 1
1556  *
1557  * The caller provides the initial value (either CRC8_INIT_VALUE
1558  * or the previous returned value) to allow for processing of
1559  * discontiguous blocks of data.  When generating the CRC the
1560  * caller is responsible for complementing the final return value
1561  * and inserting it into the byte stream.  When checking, a final
1562  * return value of CRC8_GOOD_VALUE indicates a valid CRC.
1563  *
1564  * Reference: Dallas Semiconductor Application Note 27
1565  *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
1566  *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
1567  *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
1568  *
1569  * ****************************************************************************
1570  */
1571
1572 static const uint8 crc8_table[256] = {
1573     0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
1574     0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
1575     0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
1576     0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
1577     0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
1578     0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
1579     0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
1580     0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
1581     0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
1582     0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
1583     0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
1584     0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
1585     0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
1586     0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
1587     0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
1588     0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
1589     0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
1590     0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
1591     0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
1592     0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
1593     0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
1594     0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
1595     0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
1596     0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
1597     0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
1598     0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
1599     0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
1600     0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
1601     0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
1602     0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
1603     0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
1604     0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
1605 };
1606
1607 #define CRC_INNER_LOOP(n, c, x) \
1608         (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
1609
1610 uint8
1611 hndcrc8(
1612         uint8 *pdata,   /* pointer to array of data to process */
1613         uint  nbytes,   /* number of input data bytes to process */
1614         uint8 crc       /* either CRC8_INIT_VALUE or previous return value */
1615 )
1616 {
1617         /* hard code the crc loop instead of using CRC_INNER_LOOP macro
1618          * to avoid the undefined and unnecessary (uint8 >> 8) operation.
1619          */
1620         while (nbytes-- > 0)
1621                 crc = crc8_table[(crc ^ *pdata++) & 0xff];
1622
1623         return crc;
1624 }
1625
1626 /*******************************************************************************
1627  * crc16
1628  *
1629  * Computes a crc16 over the input data using the polynomial:
1630  *
1631  *       x^16 + x^12 +x^5 + 1
1632  *
1633  * The caller provides the initial value (either CRC16_INIT_VALUE
1634  * or the previous returned value) to allow for processing of
1635  * discontiguous blocks of data.  When generating the CRC the
1636  * caller is responsible for complementing the final return value
1637  * and inserting it into the byte stream.  When checking, a final
1638  * return value of CRC16_GOOD_VALUE indicates a valid CRC.
1639  *
1640  * Reference: Dallas Semiconductor Application Note 27
1641  *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
1642  *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
1643  *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
1644  *
1645  * ****************************************************************************
1646  */
1647
1648 static const uint16 crc16_table[256] = {
1649     0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
1650     0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
1651     0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
1652     0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
1653     0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
1654     0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
1655     0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
1656     0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
1657     0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
1658     0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
1659     0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
1660     0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
1661     0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
1662     0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
1663     0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
1664     0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
1665     0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
1666     0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
1667     0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
1668     0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
1669     0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
1670     0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
1671     0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
1672     0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
1673     0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
1674     0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
1675     0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
1676     0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
1677     0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
1678     0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
1679     0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
1680     0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
1681 };
1682
1683 uint16
1684 hndcrc16(
1685     uint8 *pdata,  /* pointer to array of data to process */
1686     uint nbytes, /* number of input data bytes to process */
1687     uint16 crc     /* either CRC16_INIT_VALUE or previous return value */
1688 )
1689 {
1690         while (nbytes-- > 0)
1691                 CRC_INNER_LOOP(16, crc, *pdata++);
1692         return crc;
1693 }
1694
1695 static const uint32 crc32_table[256] = {
1696     0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
1697     0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
1698     0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
1699     0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
1700     0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
1701     0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
1702     0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
1703     0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
1704     0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
1705     0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
1706     0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
1707     0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
1708     0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
1709     0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
1710     0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
1711     0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
1712     0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
1713     0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
1714     0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
1715     0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
1716     0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
1717     0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
1718     0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
1719     0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
1720     0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
1721     0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
1722     0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
1723     0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
1724     0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
1725     0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
1726     0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
1727     0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
1728     0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
1729     0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
1730     0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
1731     0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
1732     0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
1733     0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
1734     0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
1735     0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
1736     0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
1737     0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
1738     0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
1739     0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
1740     0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
1741     0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
1742     0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
1743     0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
1744     0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
1745     0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
1746     0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
1747     0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
1748     0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
1749     0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
1750     0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
1751     0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
1752     0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
1753     0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
1754     0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
1755     0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
1756     0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
1757     0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
1758     0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
1759     0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
1760 };
1761
1762 /*
1763  * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if
1764  * accumulating over multiple pieces.
1765  */
1766 uint32
1767 hndcrc32(uint8 *pdata, uint nbytes, uint32 crc)
1768 {
1769         uint8 *pend;
1770         pend = pdata + nbytes;
1771         while (pdata < pend)
1772                 CRC_INNER_LOOP(32, crc, *pdata++);
1773
1774         return crc;
1775 }
1776
1777 #ifdef notdef
1778 #define CLEN    1499    /*  CRC Length */
1779 #define CBUFSIZ         (CLEN+4)
1780 #define CNBUFS          5 /* # of bufs */
1781
1782 void
1783 testcrc32(void)
1784 {
1785         uint j, k, l;
1786         uint8 *buf;
1787         uint len[CNBUFS];
1788         uint32 crcr;
1789         uint32 crc32tv[CNBUFS] =
1790                 {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110};
1791
1792         ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL);
1793
1794         /* step through all possible alignments */
1795         for (l = 0; l <= 4; l++) {
1796                 for (j = 0; j < CNBUFS; j++) {
1797                         len[j] = CLEN;
1798                         for (k = 0; k < len[j]; k++)
1799                                 *(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff;
1800                 }
1801
1802                 for (j = 0; j < CNBUFS; j++) {
1803                         crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE);
1804                         ASSERT(crcr == crc32tv[j]);
1805                 }
1806         }
1807
1808         MFREE(buf, CBUFSIZ*CNBUFS);
1809         return;
1810 }
1811 #endif /* notdef */
1812
1813 /*
1814  * Advance from the current 1-byte tag/1-byte length/variable-length value
1815  * triple, to the next, returning a pointer to the next.
1816  * If the current or next TLV is invalid (does not fit in given buffer length),
1817  * NULL is returned.
1818  * *buflen is not modified if the TLV elt parameter is invalid, or is decremented
1819  * by the TLV parameter's length if it is valid.
1820  */
1821 bcm_tlv_t *
1822 bcm_next_tlv(bcm_tlv_t *elt, int *buflen)
1823 {
1824         int len;
1825
1826         /* validate current elt */
1827         if (!bcm_valid_tlv(elt, *buflen)) {
1828                 return NULL;
1829         }
1830
1831         /* advance to next elt */
1832         len = elt->len;
1833         elt = (bcm_tlv_t*)(elt->data + len);
1834         *buflen -= (TLV_HDR_LEN + len);
1835
1836         /* validate next elt */
1837         if (!bcm_valid_tlv(elt, *buflen)) {
1838                 return NULL;
1839         }
1840
1841         return elt;
1842 }
1843
1844 /*
1845  * Traverse a string of 1-byte tag/1-byte length/variable-length value
1846  * triples, returning a pointer to the substring whose first element
1847  * matches tag
1848  */
1849 bcm_tlv_t *
1850 bcm_parse_tlvs(void *buf, int buflen, uint key)
1851 {
1852         bcm_tlv_t *elt;
1853         int totlen;
1854
1855         if ((elt = (bcm_tlv_t*)buf) == NULL) {
1856                 return NULL;
1857         }
1858         totlen = buflen;
1859
1860         /* find tagged parameter */
1861         while (totlen >= TLV_HDR_LEN) {
1862                 int len = elt->len;
1863
1864                 /* validate remaining totlen */
1865                 if ((elt->id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
1866
1867                         return (elt);
1868                 }
1869
1870                 elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
1871                 totlen -= (len + TLV_HDR_LEN);
1872         }
1873
1874         return NULL;
1875 }
1876
1877 /*
1878  * Traverse a string of 1-byte tag/1-byte length/variable-length value
1879  * triples, returning a pointer to the substring whose first element
1880  * matches tag
1881  * return NULL if not found or length field < min_varlen
1882  */
1883 bcm_tlv_t *
1884 bcm_parse_tlvs_min_bodylen(void *buf, int buflen, uint key, int min_bodylen)
1885 {
1886         bcm_tlv_t * ret = bcm_parse_tlvs(buf, buflen, key);
1887         if (ret == NULL || ret->len < min_bodylen) {
1888                 return NULL;
1889         }
1890         return ret;
1891 }
1892
1893 /*
1894  * Traverse a string of 1-byte tag/1-byte length/variable-length value
1895  * triples, returning a pointer to the substring whose first element
1896  * matches tag.  Stop parsing when we see an element whose ID is greater
1897  * than the target key.
1898  */
1899 bcm_tlv_t *
1900 bcm_parse_ordered_tlvs(void *buf, int buflen, uint key)
1901 {
1902         bcm_tlv_t *elt;
1903         int totlen;
1904
1905         elt = (bcm_tlv_t*)buf;
1906         totlen = buflen;
1907
1908         /* find tagged parameter */
1909         while (totlen >= TLV_HDR_LEN) {
1910                 uint id = elt->id;
1911                 int len = elt->len;
1912
1913                 /* Punt if we start seeing IDs > than target key */
1914                 if (id > key) {
1915                         return (NULL);
1916                 }
1917
1918                 /* validate remaining totlen */
1919                 if ((id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
1920                         return (elt);
1921                 }
1922
1923                 elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
1924                 totlen -= (len + TLV_HDR_LEN);
1925         }
1926         return NULL;
1927 }
1928 #endif  /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
1929
1930 #if defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \
1931         defined(DHD_DEBUG)
1932 int
1933 bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 flags, char* buf, int len)
1934 {
1935         int i, slen = 0;
1936         uint32 bit, mask;
1937         const char *name;
1938         mask = bd->mask;
1939         if (len < 2 || !buf)
1940                 return 0;
1941
1942         buf[0] = '\0';
1943
1944         for (i = 0;  (name = bd->bitfield[i].name) != NULL; i++) {
1945                 bit = bd->bitfield[i].bit;
1946                 if ((flags & mask) == bit) {
1947                         if (len > (int)strlen(name)) {
1948                                 slen = strlen(name);
1949                                 strncpy(buf, name, slen+1);
1950                         }
1951                         break;
1952                 }
1953         }
1954         return slen;
1955 }
1956
1957 int
1958 bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len)
1959 {
1960         int i;
1961         char* p = buf;
1962         char hexstr[16];
1963         int slen = 0, nlen = 0;
1964         uint32 bit;
1965         const char* name;
1966
1967         if (len < 2 || !buf)
1968                 return 0;
1969
1970         buf[0] = '\0';
1971
1972         for (i = 0; flags != 0; i++) {
1973                 bit = bd[i].bit;
1974                 name = bd[i].name;
1975                 if (bit == 0 && flags != 0) {
1976                         /* print any unnamed bits */
1977                         snprintf(hexstr, 16, "0x%X", flags);
1978                         name = hexstr;
1979                         flags = 0;      /* exit loop */
1980                 } else if ((flags & bit) == 0)
1981                         continue;
1982                 flags &= ~bit;
1983                 nlen = strlen(name);
1984                 slen += nlen;
1985                 /* count btwn flag space */
1986                 if (flags != 0)
1987                         slen += 1;
1988                 /* need NULL char as well */
1989                 if (len <= slen)
1990                         break;
1991                 /* copy NULL char but don't count it */
1992                 strncpy(p, name, nlen + 1);
1993                 p += nlen;
1994                 /* copy btwn flag space and NULL char */
1995                 if (flags != 0)
1996                         p += snprintf(p, 2, " ");
1997         }
1998
1999         /* indicate the str was too short */
2000         if (flags != 0) {
2001                 p += snprintf(p, 2, ">");
2002         }
2003
2004         return (int)(p - buf);
2005 }
2006 #endif 
2007
2008 /* print bytes formatted as hex to a string. return the resulting string length */
2009 int
2010 bcm_format_hex(char *str, const void *bytes, int len)
2011 {
2012         int i;
2013         char *p = str;
2014         const uint8 *src = (const uint8*)bytes;
2015
2016         for (i = 0; i < len; i++) {
2017                 p += snprintf(p, 3, "%02X", *src);
2018                 src++;
2019         }
2020         return (int)(p - str);
2021 }
2022
2023 /* pretty hex print a contiguous buffer */
2024 void
2025 prhex(const char *msg, uchar *buf, uint nbytes)
2026 {
2027         char line[128], *p;
2028         int len = sizeof(line);
2029         int nchar;
2030         uint i;
2031
2032         if (msg && (msg[0] != '\0'))
2033                 printf("%s:\n", msg);
2034
2035         p = line;
2036         for (i = 0; i < nbytes; i++) {
2037                 if (i % 16 == 0) {
2038                         nchar = snprintf(p, len, "  %04x: ", i);        /* line prefix */
2039                         p += nchar;
2040                         len -= nchar;
2041                 }
2042                 if (len > 0) {
2043                         nchar = snprintf(p, len, "%02x ", buf[i]);
2044                         p += nchar;
2045                         len -= nchar;
2046                 }
2047
2048                 if (i % 16 == 15) {
2049                         printf("%s\n", line);           /* flush line */
2050                         p = line;
2051                         len = sizeof(line);
2052                 }
2053         }
2054
2055         /* flush last partial line */
2056         if (p != line)
2057                 printf("%s\n", line);
2058 }
2059
2060 static const char *crypto_algo_names[] = {
2061         "NONE",
2062         "WEP1",
2063         "TKIP",
2064         "WEP128",
2065         "AES_CCM",
2066         "AES_OCB_MSDU",
2067         "AES_OCB_MPDU",
2068         "NALG",
2069         "UNDEF",
2070         "UNDEF",
2071         "UNDEF",
2072         "UNDEF"
2073         "PMK",
2074         "BIP",
2075         "AES_GCM",
2076         "AES_CCM256",
2077         "AES_GCM256",
2078         "BIP_CMAC256",
2079         "BIP_GMAC",
2080         "BIP_GMAC256",
2081         "UNDEF"
2082 };
2083
2084 const char *
2085 bcm_crypto_algo_name(uint algo)
2086 {
2087         return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR";
2088 }
2089
2090
2091 char *
2092 bcm_chipname(uint chipid, char *buf, uint len)
2093 {
2094         const char *fmt;
2095
2096         fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
2097         snprintf(buf, len, fmt, chipid);
2098         return buf;
2099 }
2100
2101 /* Produce a human-readable string for boardrev */
2102 char *
2103 bcm_brev_str(uint32 brev, char *buf)
2104 {
2105         if (brev < 0x100)
2106                 snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf);
2107         else
2108                 snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff);
2109
2110         return (buf);
2111 }
2112
2113 #define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */
2114
2115 /* dump large strings to console */
2116 void
2117 printbig(char *buf)
2118 {
2119         uint len, max_len;
2120         char c;
2121
2122         len = (uint)strlen(buf);
2123
2124         max_len = BUFSIZE_TODUMP_ATONCE;
2125
2126         while (len > max_len) {
2127                 c = buf[max_len];
2128                 buf[max_len] = '\0';
2129                 printf("%s", buf);
2130                 buf[max_len] = c;
2131
2132                 buf += max_len;
2133                 len -= max_len;
2134         }
2135         /* print the remaining string */
2136         printf("%s\n", buf);
2137         return;
2138 }
2139
2140 /* routine to dump fields in a fileddesc structure */
2141 uint
2142 bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array,
2143         char *buf, uint32 bufsize)
2144 {
2145         uint  filled_len;
2146         int len;
2147         struct fielddesc *cur_ptr;
2148
2149         filled_len = 0;
2150         cur_ptr = fielddesc_array;
2151
2152         while (bufsize > 1) {
2153                 if (cur_ptr->nameandfmt == NULL)
2154                         break;
2155                 len = snprintf(buf, bufsize, cur_ptr->nameandfmt,
2156                                read_rtn(arg0, arg1, cur_ptr->offset));
2157                 /* check for snprintf overflow or error */
2158                 if (len < 0 || (uint32)len >= bufsize)
2159                         len = bufsize - 1;
2160                 buf += len;
2161                 bufsize -= len;
2162                 filled_len += len;
2163                 cur_ptr++;
2164         }
2165         return filled_len;
2166 }
2167
2168 uint
2169 bcm_mkiovar(const char *name, char *data, uint datalen, char *buf, uint buflen)
2170 {
2171         uint len;
2172
2173         len = (uint)strlen(name) + 1;
2174
2175         if ((len + datalen) > buflen)
2176                 return 0;
2177
2178         strncpy(buf, name, buflen);
2179
2180         /* append data onto the end of the name string */
2181         memcpy(&buf[len], data, datalen);
2182         len += datalen;
2183
2184         return len;
2185 }
2186
2187 /* Quarter dBm units to mW
2188  * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
2189  * Table is offset so the last entry is largest mW value that fits in
2190  * a uint16.
2191  */
2192
2193 #define QDBM_OFFSET 153         /* Offset for first entry */
2194 #define QDBM_TABLE_LEN 40       /* Table size */
2195
2196 /* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
2197  * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
2198  */
2199 #define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
2200
2201 /* Largest mW value that will round down to the last table entry,
2202  * QDBM_OFFSET + QDBM_TABLE_LEN-1.
2203  * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
2204  */
2205 #define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
2206
2207 static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
2208 /* qdBm:        +0      +1      +2      +3      +4      +5      +6      +7 */
2209 /* 153: */      6683,   7079,   7499,   7943,   8414,   8913,   9441,   10000,
2210 /* 161: */      10593,  11220,  11885,  12589,  13335,  14125,  14962,  15849,
2211 /* 169: */      16788,  17783,  18836,  19953,  21135,  22387,  23714,  25119,
2212 /* 177: */      26607,  28184,  29854,  31623,  33497,  35481,  37584,  39811,
2213 /* 185: */      42170,  44668,  47315,  50119,  53088,  56234,  59566,  63096
2214 };
2215
2216 uint16
2217 bcm_qdbm_to_mw(uint8 qdbm)
2218 {
2219         uint factor = 1;
2220         int idx = qdbm - QDBM_OFFSET;
2221
2222         if (idx >= QDBM_TABLE_LEN) {
2223                 /* clamp to max uint16 mW value */
2224                 return 0xFFFF;
2225         }
2226
2227         /* scale the qdBm index up to the range of the table 0-40
2228          * where an offset of 40 qdBm equals a factor of 10 mW.
2229          */
2230         while (idx < 0) {
2231                 idx += 40;
2232                 factor *= 10;
2233         }
2234
2235         /* return the mW value scaled down to the correct factor of 10,
2236          * adding in factor/2 to get proper rounding.
2237          */
2238         return ((nqdBm_to_mW_map[idx] + factor/2) / factor);
2239 }
2240
2241 uint8
2242 bcm_mw_to_qdbm(uint16 mw)
2243 {
2244         uint8 qdbm;
2245         int offset;
2246         uint mw_uint = mw;
2247         uint boundary;
2248
2249         /* handle boundary case */
2250         if (mw_uint <= 1)
2251                 return 0;
2252
2253         offset = QDBM_OFFSET;
2254
2255         /* move mw into the range of the table */
2256         while (mw_uint < QDBM_TABLE_LOW_BOUND) {
2257                 mw_uint *= 10;
2258                 offset -= 40;
2259         }
2260
2261         for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) {
2262                 boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] -
2263                                                     nqdBm_to_mW_map[qdbm])/2;
2264                 if (mw_uint < boundary) break;
2265         }
2266
2267         qdbm += (uint8)offset;
2268
2269         return (qdbm);
2270 }
2271
2272
2273 uint
2274 bcm_bitcount(uint8 *bitmap, uint length)
2275 {
2276         uint bitcount = 0, i;
2277         uint8 tmp;
2278         for (i = 0; i < length; i++) {
2279                 tmp = bitmap[i];
2280                 while (tmp) {
2281                         bitcount++;
2282                         tmp &= (tmp - 1);
2283                 }
2284         }
2285         return bitcount;
2286 }
2287
2288 #if defined(BCMDRIVER) || defined(WL_UNITTEST)
2289
2290 /* triggers bcm_bprintf to print to kernel log */
2291 bool bcm_bprintf_bypass = FALSE;
2292
2293 /* Initialization of bcmstrbuf structure */
2294 void
2295 bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
2296 {
2297         b->origsize = b->size = size;
2298         b->origbuf = b->buf = buf;
2299 }
2300
2301 /* Buffer sprintf wrapper to guard against buffer overflow */
2302 int
2303 bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
2304 {
2305         va_list ap;
2306         int r;
2307
2308         va_start(ap, fmt);
2309
2310         r = vsnprintf(b->buf, b->size, fmt, ap);
2311         if (bcm_bprintf_bypass == TRUE) {
2312                 printf(b->buf);
2313                 goto exit;
2314         }
2315
2316         /* Non Ansi C99 compliant returns -1,
2317          * Ansi compliant return r >= b->size,
2318          * bcmstdlib returns 0, handle all
2319          */
2320         /* r == 0 is also the case when strlen(fmt) is zero.
2321          * typically the case when "" is passed as argument.
2322          */
2323         if ((r == -1) || (r >= (int)b->size)) {
2324                 b->size = 0;
2325         } else {
2326                 b->size -= r;
2327                 b->buf += r;
2328         }
2329
2330 exit:
2331         va_end(ap);
2332
2333         return r;
2334 }
2335
2336 void
2337 bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, const uint8 *buf, int len)
2338 {
2339         int i;
2340
2341         if (msg != NULL && msg[0] != '\0')
2342                 bcm_bprintf(b, "%s", msg);
2343         for (i = 0; i < len; i ++)
2344                 bcm_bprintf(b, "%02X", buf[i]);
2345         if (newline)
2346                 bcm_bprintf(b, "\n");
2347 }
2348
2349 void
2350 bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount)
2351 {
2352         int i;
2353
2354         for (i = 0; i < num_bytes; i++) {
2355                 num[i] += amount;
2356                 if (num[i] >= amount)
2357                         break;
2358                 amount = 1;
2359         }
2360 }
2361
2362 int
2363 bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes)
2364 {
2365         int i;
2366
2367         for (i = nbytes - 1; i >= 0; i--) {
2368                 if (arg1[i] != arg2[i])
2369                         return (arg1[i] - arg2[i]);
2370         }
2371         return 0;
2372 }
2373
2374 void
2375 bcm_print_bytes(const char *name, const uchar *data, int len)
2376 {
2377         int i;
2378         int per_line = 0;
2379
2380         printf("%s: %d \n", name ? name : "", len);
2381         for (i = 0; i < len; i++) {
2382                 printf("%02x ", *data++);
2383                 per_line++;
2384                 if (per_line == 16) {
2385                         per_line = 0;
2386                         printf("\n");
2387                 }
2388         }
2389         printf("\n");
2390 }
2391
2392 /* Look for vendor-specific IE with specified OUI and optional type */
2393 bcm_tlv_t *
2394 bcm_find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type, int type_len)
2395 {
2396         bcm_tlv_t *ie;
2397         uint8 ie_len;
2398
2399         ie = (bcm_tlv_t*)tlvs;
2400
2401         /* make sure we are looking at a valid IE */
2402         if (ie == NULL || !bcm_valid_tlv(ie, tlvs_len)) {
2403                 return NULL;
2404         }
2405
2406         /* Walk through the IEs looking for an OUI match */
2407         do {
2408                 ie_len = ie->len;
2409                 if ((ie->id == DOT11_MNG_PROPR_ID) &&
2410                     (ie_len >= (DOT11_OUI_LEN + type_len)) &&
2411                     !bcmp(ie->data, voui, DOT11_OUI_LEN))
2412                 {
2413                         /* compare optional type */
2414                         if (type_len == 0 ||
2415                             !bcmp(&ie->data[DOT11_OUI_LEN], type, type_len)) {
2416                                 return (ie);            /* a match */
2417                         }
2418                 }
2419         } while ((ie = bcm_next_tlv(ie, &tlvs_len)) != NULL);
2420
2421         return NULL;
2422 }
2423
2424 #if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \
2425         defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
2426 #define SSID_FMT_BUF_LEN        ((4 * DOT11_MAX_SSID_LEN) + 1)
2427
2428 int
2429 bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len)
2430 {
2431         uint i, c;
2432         char *p = buf;
2433         char *endp = buf + SSID_FMT_BUF_LEN;
2434
2435         if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN;
2436
2437         for (i = 0; i < ssid_len; i++) {
2438                 c = (uint)ssid[i];
2439                 if (c == '\\') {
2440                         *p++ = '\\';
2441                         *p++ = '\\';
2442                 } else if (bcm_isprint((uchar)c)) {
2443                         *p++ = (char)c;
2444                 } else {
2445                         p += snprintf(p, (endp - p), "\\x%02X", c);
2446                 }
2447         }
2448         *p = '\0';
2449         ASSERT(p < endp);
2450
2451         return (int)(p - buf);
2452 }
2453 #endif 
2454
2455 #endif /* BCMDRIVER || WL_UNITTEST */
2456
2457 /*
2458  * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file and ending in a NUL.
2459  * also accepts nvram files which are already in the format of <var1>=<value>\0\<var2>=<value2>\0
2460  * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs.
2461  * Shortens buffer as needed and pads with NULs.  End of buffer is marked by two NULs.
2462 */
2463
2464 unsigned int
2465 process_nvram_vars(char *varbuf, unsigned int len)
2466 {
2467         char *dp;
2468         bool findNewline;
2469         int column;
2470         unsigned int buf_len, n;
2471         unsigned int pad = 0;
2472
2473         dp = varbuf;
2474
2475         findNewline = FALSE;
2476         column = 0;
2477
2478         // terence 20130914: print out NVRAM version
2479         if (varbuf[0] == '#') {
2480                 printf("NVRAM version: ");
2481                 for (n=1; n<len; n++) {
2482                         if (varbuf[n] == '\n')
2483                                 break;
2484                         printk("%c", varbuf[n]);
2485                 }
2486                 printk("\n");
2487         }
2488
2489         for (n = 0; n < len; n++) {
2490                 if (varbuf[n] == '\r')
2491                         continue;
2492                 if (findNewline && varbuf[n] != '\n')
2493                         continue;
2494                 findNewline = FALSE;
2495                 if (varbuf[n] == '#') {
2496                         findNewline = TRUE;
2497                         continue;
2498                 }
2499                 if (varbuf[n] == '\n') {
2500                         if (column == 0)
2501                                 continue;
2502                         *dp++ = 0;
2503                         column = 0;
2504                         continue;
2505                 }
2506                 *dp++ = varbuf[n];
2507                 column++;
2508         }
2509         buf_len = (unsigned int)(dp - varbuf);
2510         if (buf_len % 4) {
2511                 pad = 4 - buf_len % 4;
2512                 if (pad && (buf_len + pad <= len)) {
2513                         buf_len += pad;
2514                 }
2515         }
2516
2517         while (dp < varbuf + n)
2518                 *dp++ = 0;
2519
2520         return buf_len;
2521 }
2522
2523 /* calculate a * b + c */
2524 void
2525 bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c)
2526 {
2527 #define FORMALIZE(var) {cc += (var & 0x80000000) ? 1 : 0; var &= 0x7fffffff;}
2528         uint32 r1, r0;
2529         uint32 a1, a0, b1, b0, t, cc = 0;
2530
2531         a1 = a >> 16;
2532         a0 = a & 0xffff;
2533         b1 = b >> 16;
2534         b0 = b & 0xffff;
2535
2536         r0 = a0 * b0;
2537         FORMALIZE(r0);
2538
2539         t = (a1 * b0) << 16;
2540         FORMALIZE(t);
2541
2542         r0 += t;
2543         FORMALIZE(r0);
2544
2545         t = (a0 * b1) << 16;
2546         FORMALIZE(t);
2547
2548         r0 += t;
2549         FORMALIZE(r0);
2550
2551         FORMALIZE(c);
2552
2553         r0 += c;
2554         FORMALIZE(r0);
2555
2556         r0 |= (cc % 2) ? 0x80000000 : 0;
2557         r1 = a1 * b1 + ((a1 * b0) >> 16) + ((b1 * a0) >> 16) + (cc / 2);
2558
2559         *r_high = r1;
2560         *r_low = r0;
2561 }
2562
2563 /* calculate a / b */
2564 void
2565 bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
2566 {
2567         uint32 a1 = a_high, a0 = a_low, r0 = 0;
2568
2569         if (b < 2)
2570                 return;
2571
2572         while (a1 != 0) {
2573                 r0 += (0xffffffff / b) * a1;
2574                 bcm_uint64_multiple_add(&a1, &a0, ((0xffffffff % b) + 1) % b, a1, a0);
2575         }
2576
2577         r0 += a0 / b;
2578         *r = r0;
2579 }
2580
2581 #ifndef setbit /* As in the header file */
2582 #ifdef BCMUTILS_BIT_MACROS_USE_FUNCS
2583 /* Set bit in byte array. */
2584 void
2585 setbit(void *array, uint bit)
2586 {
2587         ((uint8 *)array)[bit / NBBY] |= 1 << (bit % NBBY);
2588 }
2589
2590 /* Clear bit in byte array. */
2591 void
2592 clrbit(void *array, uint bit)
2593 {
2594         ((uint8 *)array)[bit / NBBY] &= ~(1 << (bit % NBBY));
2595 }
2596
2597 /* Test if bit is set in byte array. */
2598 bool
2599 isset(const void *array, uint bit)
2600 {
2601         return (((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY)));
2602 }
2603
2604 /* Test if bit is clear in byte array. */
2605 bool
2606 isclr(const void *array, uint bit)
2607 {
2608         return ((((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))) == 0);
2609 }
2610 #endif /* BCMUTILS_BIT_MACROS_USE_FUNCS */
2611 #endif /* setbit */
2612
2613 void
2614 set_bitrange(void *array, uint start, uint end, uint maxbit)
2615 {
2616         uint startbyte = start/NBBY;
2617         uint endbyte = end/NBBY;
2618         uint i, startbytelastbit, endbytestartbit;
2619
2620         if (end >= start) {
2621                 if (endbyte - startbyte > 1)
2622                 {
2623                         startbytelastbit = (startbyte+1)*NBBY - 1;
2624                         endbytestartbit = endbyte*NBBY;
2625                         for (i = startbyte+1; i < endbyte; i++)
2626                                 ((uint8 *)array)[i] = 0xFF;
2627                         for (i = start; i <= startbytelastbit; i++)
2628                                 setbit(array, i);
2629                         for (i = endbytestartbit; i <= end; i++)
2630                                 setbit(array, i);
2631                 } else {
2632                         for (i = start; i <= end; i++)
2633                                 setbit(array, i);
2634                 }
2635         }
2636         else {
2637                 set_bitrange(array, start, maxbit, maxbit);
2638                 set_bitrange(array, 0, end, maxbit);
2639         }
2640 }
2641
2642 void
2643 bcm_bitprint32(const uint32 u32arg)
2644 {
2645         int i;
2646         for (i = NBITS(uint32) - 1; i >= 0; i--) {
2647                 isbitset(u32arg, i) ? printf("1") : printf("0");
2648                 if ((i % NBBY) == 0) printf(" ");
2649         }
2650         printf("\n");
2651 }
2652
2653 /* calculate checksum for ip header, tcp / udp header / data */
2654 uint16
2655 bcm_ip_cksum(uint8 *buf, uint32 len, uint32 sum)
2656 {
2657         while (len > 1) {
2658                 sum += (buf[0] << 8) | buf[1];
2659                 buf += 2;
2660                 len -= 2;
2661         }
2662
2663         if (len > 0) {
2664                 sum += (*buf) << 8;
2665         }
2666
2667         while (sum >> 16) {
2668                 sum = (sum & 0xffff) + (sum >> 16);
2669         }
2670
2671         return ((uint16)~sum);
2672 }
2673 #if defined(BCMDRIVER) && !defined(_CFEZ_)
2674 /*
2675  * Hierarchical Multiword bitmap based small id allocator.
2676  *
2677  * Multilevel hierarchy bitmap. (maximum 2 levels)
2678  * First hierarchy uses a multiword bitmap to identify 32bit words in the
2679  * second hierarchy that have at least a single bit set. Each bit in a word of
2680  * the second hierarchy represents a unique ID that may be allocated.
2681  *
2682  * BCM_MWBMAP_ITEMS_MAX: Maximum number of IDs managed.
2683  * BCM_MWBMAP_BITS_WORD: Number of bits in a bitmap word word
2684  * BCM_MWBMAP_WORDS_MAX: Maximum number of bitmap words needed for free IDs.
2685  * BCM_MWBMAP_WDMAP_MAX: Maximum number of bitmap wordss identifying first non
2686  *                       non-zero bitmap word carrying at least one free ID.
2687  * BCM_MWBMAP_SHIFT_OP:  Used in MOD, DIV and MUL operations.
2688  * BCM_MWBMAP_INVALID_IDX: Value ~0U is treated as an invalid ID
2689  *
2690  * Design Notes:
2691  * BCM_MWBMAP_USE_CNTSETBITS trades CPU for memory. A runtime count of how many
2692  * bits are computed each time on allocation and deallocation, requiring 4
2693  * array indexed access and 3 arithmetic operations. When not defined, a runtime
2694  * count of set bits state is maintained. Upto 32 Bytes per 1024 IDs is needed.
2695  * In a 4K max ID allocator, up to 128Bytes are hence used per instantiation.
2696  * In a memory limited system e.g. dongle builds, a CPU for memory tradeoff may
2697  * be used by defining BCM_MWBMAP_USE_CNTSETBITS.
2698  *
2699  * Note: wd_bitmap[] is statically declared and is not ROM friendly ... array
2700  * size is fixed. No intention to support larger than 4K indice allocation. ID
2701  * allocators for ranges smaller than 4K will have a wastage of only 12Bytes
2702  * with savings in not having to use an indirect access, had it been dynamically
2703  * allocated.
2704  */
2705 #define BCM_MWBMAP_ITEMS_MAX    (64 * 1024)  /* May increase to 64K */
2706
2707 #define BCM_MWBMAP_BITS_WORD    (NBITS(uint32))
2708 #define BCM_MWBMAP_WORDS_MAX    (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD)
2709 #define BCM_MWBMAP_WDMAP_MAX    (BCM_MWBMAP_WORDS_MAX / BCM_MWBMAP_BITS_WORD)
2710 #define BCM_MWBMAP_SHIFT_OP     (5)
2711 #define BCM_MWBMAP_MODOP(ix)    ((ix) & (BCM_MWBMAP_BITS_WORD - 1))
2712 #define BCM_MWBMAP_DIVOP(ix)    ((ix) >> BCM_MWBMAP_SHIFT_OP)
2713 #define BCM_MWBMAP_MULOP(ix)    ((ix) << BCM_MWBMAP_SHIFT_OP)
2714
2715 /* Redefine PTR() and/or HDL() conversion to invoke audit for debugging */
2716 #define BCM_MWBMAP_PTR(hdl)             ((struct bcm_mwbmap *)(hdl))
2717 #define BCM_MWBMAP_HDL(ptr)             ((void *)(ptr))
2718
2719 #if defined(BCM_MWBMAP_DEBUG)
2720 #define BCM_MWBMAP_AUDIT(mwb) \
2721         do { \
2722                 ASSERT((mwb != NULL) && \
2723                        (((struct bcm_mwbmap *)(mwb))->magic == (void *)(mwb))); \
2724                 bcm_mwbmap_audit(mwb); \
2725         } while (0)
2726 #define MWBMAP_ASSERT(exp)              ASSERT(exp)
2727 #define MWBMAP_DBG(x)           printf x
2728 #else   /* !BCM_MWBMAP_DEBUG */
2729 #define BCM_MWBMAP_AUDIT(mwb)   do {} while (0)
2730 #define MWBMAP_ASSERT(exp)              do {} while (0)
2731 #define MWBMAP_DBG(x)
2732 #endif  /* !BCM_MWBMAP_DEBUG */
2733
2734
2735 typedef struct bcm_mwbmap {     /* Hierarchical multiword bitmap allocator    */
2736         uint16 wmaps;               /* Total number of words in free wd bitmap    */
2737         uint16 imaps;               /* Total number of words in free id bitmap    */
2738         int32  ifree;               /* Count of free indices. Used only in audits */
2739         uint16 total;               /* Total indices managed by multiword bitmap  */
2740
2741         void * magic;               /* Audit handle parameter from user           */
2742
2743         uint32 wd_bitmap[BCM_MWBMAP_WDMAP_MAX]; /* 1st level bitmap of            */
2744 #if !defined(BCM_MWBMAP_USE_CNTSETBITS)
2745         int8   wd_count[BCM_MWBMAP_WORDS_MAX];  /* free id running count, 1st lvl */
2746 #endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
2747
2748         uint32 id_bitmap[0];        /* Second level bitmap                        */
2749 } bcm_mwbmap_t;
2750
2751 /* Incarnate a hierarchical multiword bitmap based small index allocator. */
2752 struct bcm_mwbmap *
2753 bcm_mwbmap_init(osl_t *osh, uint32 items_max)
2754 {
2755         struct bcm_mwbmap * mwbmap_p;
2756         uint32 wordix, size, words, extra;
2757
2758         /* Implementation Constraint: Uses 32bit word bitmap */
2759         MWBMAP_ASSERT(BCM_MWBMAP_BITS_WORD == 32U);
2760         MWBMAP_ASSERT(BCM_MWBMAP_SHIFT_OP == 5U);
2761         MWBMAP_ASSERT(ISPOWEROF2(BCM_MWBMAP_ITEMS_MAX));
2762         MWBMAP_ASSERT((BCM_MWBMAP_ITEMS_MAX % BCM_MWBMAP_BITS_WORD) == 0U);
2763
2764         ASSERT(items_max <= BCM_MWBMAP_ITEMS_MAX);
2765
2766         /* Determine the number of words needed in the multiword bitmap */
2767         extra = BCM_MWBMAP_MODOP(items_max);
2768         words = BCM_MWBMAP_DIVOP(items_max) + ((extra != 0U) ? 1U : 0U);
2769
2770         /* Allocate runtime state of multiword bitmap */
2771         /* Note: wd_count[] or wd_bitmap[] are not dynamically allocated */
2772         size = sizeof(bcm_mwbmap_t) + (sizeof(uint32) * words);
2773         mwbmap_p = (bcm_mwbmap_t *)MALLOC(osh, size);
2774         if (mwbmap_p == (bcm_mwbmap_t *)NULL) {
2775                 ASSERT(0);
2776                 goto error1;
2777         }
2778         memset(mwbmap_p, 0, size);
2779
2780         /* Initialize runtime multiword bitmap state */
2781         mwbmap_p->imaps = (uint16)words;
2782         mwbmap_p->ifree = (int32)items_max;
2783         mwbmap_p->total = (uint16)items_max;
2784
2785         /* Setup magic, for use in audit of handle */
2786         mwbmap_p->magic = BCM_MWBMAP_HDL(mwbmap_p);
2787
2788         /* Setup the second level bitmap of free indices */
2789         /* Mark all indices as available */
2790         for (wordix = 0U; wordix < mwbmap_p->imaps; wordix++) {
2791                 mwbmap_p->id_bitmap[wordix] = (uint32)(~0U);
2792 #if !defined(BCM_MWBMAP_USE_CNTSETBITS)
2793                 mwbmap_p->wd_count[wordix] = BCM_MWBMAP_BITS_WORD;
2794 #endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
2795         }
2796
2797         /* Ensure that extra indices are tagged as un-available */
2798         if (extra) { /* fixup the free ids in last bitmap and wd_count */
2799                 uint32 * bmap_p = &mwbmap_p->id_bitmap[mwbmap_p->imaps - 1];
2800                 *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
2801 #if !defined(BCM_MWBMAP_USE_CNTSETBITS)
2802                 mwbmap_p->wd_count[mwbmap_p->imaps - 1] = (int8)extra; /* fixup count */
2803 #endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
2804         }
2805
2806         /* Setup the first level bitmap hierarchy */
2807         extra = BCM_MWBMAP_MODOP(mwbmap_p->imaps);
2808         words = BCM_MWBMAP_DIVOP(mwbmap_p->imaps) + ((extra != 0U) ? 1U : 0U);
2809
2810         mwbmap_p->wmaps = (uint16)words;
2811
2812         for (wordix = 0U; wordix < mwbmap_p->wmaps; wordix++)
2813                 mwbmap_p->wd_bitmap[wordix] = (uint32)(~0U);
2814         if (extra) {
2815                 uint32 * bmap_p = &mwbmap_p->wd_bitmap[mwbmap_p->wmaps - 1];
2816                 *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
2817         }
2818
2819         return mwbmap_p;
2820
2821 error1:
2822         return BCM_MWBMAP_INVALID_HDL;
2823 }
2824
2825 /* Release resources used by multiword bitmap based small index allocator. */
2826 void
2827 bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl)
2828 {
2829         bcm_mwbmap_t * mwbmap_p;
2830
2831         BCM_MWBMAP_AUDIT(mwbmap_hdl);
2832         mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
2833
2834         MFREE(osh, mwbmap_p, sizeof(struct bcm_mwbmap)
2835                              + (sizeof(uint32) * mwbmap_p->imaps));
2836         return;
2837 }
2838
2839 /* Allocate a unique small index using a multiword bitmap index allocator.    */
2840 uint32 BCMFASTPATH
2841 bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl)
2842 {
2843         bcm_mwbmap_t * mwbmap_p;
2844         uint32 wordix, bitmap;
2845
2846         BCM_MWBMAP_AUDIT(mwbmap_hdl);
2847         mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
2848
2849         /* Start with the first hierarchy */
2850         for (wordix = 0; wordix < mwbmap_p->wmaps; ++wordix) {
2851
2852                 bitmap = mwbmap_p->wd_bitmap[wordix]; /* get the word bitmap */
2853
2854                 if (bitmap != 0U) {
2855
2856                         uint32 count, bitix, *bitmap_p;
2857
2858                         bitmap_p = &mwbmap_p->wd_bitmap[wordix];
2859
2860                         /* clear all except trailing 1 */
2861                         bitmap   = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
2862                         MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
2863                                       bcm_count_leading_zeros(bitmap));
2864                         bitix    = (BCM_MWBMAP_BITS_WORD - 1)
2865                                  - bcm_count_leading_zeros(bitmap); /* use asm clz */
2866                         wordix   = BCM_MWBMAP_MULOP(wordix) + bitix;
2867
2868                         /* Clear bit if wd count is 0, without conditional branch */
2869 #if defined(BCM_MWBMAP_USE_CNTSETBITS)
2870                         count = bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1;
2871 #else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
2872                         mwbmap_p->wd_count[wordix]--;
2873                         count = mwbmap_p->wd_count[wordix];
2874                         MWBMAP_ASSERT(count ==
2875                                       (bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1));
2876 #endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
2877                         MWBMAP_ASSERT(count >= 0);
2878
2879                         /* clear wd_bitmap bit if id_map count is 0 */
2880                         bitmap = (count == 0) << bitix;
2881
2882                         MWBMAP_DBG((
2883                             "Lvl1: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
2884                             bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, count));
2885
2886                         *bitmap_p ^= bitmap;
2887
2888                         /* Use bitix in the second hierarchy */
2889                         bitmap_p = &mwbmap_p->id_bitmap[wordix];
2890
2891                         bitmap = mwbmap_p->id_bitmap[wordix]; /* get the id bitmap */
2892                         MWBMAP_ASSERT(bitmap != 0U);
2893
2894                         /* clear all except trailing 1 */
2895                         bitmap   = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
2896                         MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
2897                                       bcm_count_leading_zeros(bitmap));
2898                         bitix    = BCM_MWBMAP_MULOP(wordix)
2899                                  + (BCM_MWBMAP_BITS_WORD - 1)
2900                                  - bcm_count_leading_zeros(bitmap); /* use asm clz */
2901
2902                         mwbmap_p->ifree--; /* decrement system wide free count */
2903                         MWBMAP_ASSERT(mwbmap_p->ifree >= 0);
2904
2905                         MWBMAP_DBG((
2906                             "Lvl2: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x ifree %d",
2907                             bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
2908                             mwbmap_p->ifree));
2909
2910                         *bitmap_p ^= bitmap; /* mark as allocated = 1b0 */
2911
2912                         return bitix;
2913                 }
2914         }
2915
2916         ASSERT(mwbmap_p->ifree == 0);
2917
2918         return BCM_MWBMAP_INVALID_IDX;
2919 }
2920
2921 /* Force an index at a specified position to be in use */
2922 void
2923 bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
2924 {
2925         bcm_mwbmap_t * mwbmap_p;
2926         uint32 count, wordix, bitmap, *bitmap_p;
2927
2928         BCM_MWBMAP_AUDIT(mwbmap_hdl);
2929         mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
2930
2931         ASSERT(bitix < mwbmap_p->total);
2932
2933         /* Start with second hierarchy */
2934         wordix   = BCM_MWBMAP_DIVOP(bitix);
2935         bitmap   = (uint32)(1U << BCM_MWBMAP_MODOP(bitix));
2936         bitmap_p = &mwbmap_p->id_bitmap[wordix];
2937
2938         ASSERT((*bitmap_p & bitmap) == bitmap);
2939
2940         mwbmap_p->ifree--; /* update free count */
2941         ASSERT(mwbmap_p->ifree >= 0);
2942
2943         MWBMAP_DBG(("Lvl2: bitix<%u> wordix<%u>: %08x ^ %08x = %08x ifree %d",
2944                    bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
2945                    mwbmap_p->ifree));
2946
2947         *bitmap_p ^= bitmap; /* mark as in use */
2948
2949         /* Update first hierarchy */
2950         bitix    = wordix;
2951
2952         wordix   = BCM_MWBMAP_DIVOP(bitix);
2953         bitmap_p = &mwbmap_p->wd_bitmap[wordix];
2954
2955 #if defined(BCM_MWBMAP_USE_CNTSETBITS)
2956         count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
2957 #else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
2958         mwbmap_p->wd_count[bitix]--;
2959         count = mwbmap_p->wd_count[bitix];
2960         MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
2961 #endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
2962         MWBMAP_ASSERT(count >= 0);
2963
2964         bitmap   = (count == 0) << BCM_MWBMAP_MODOP(bitix);
2965
2966         MWBMAP_DBG(("Lvl1: bitix<%02lu> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
2967                    BCM_MWBMAP_MODOP(bitix), wordix, *bitmap_p, bitmap,
2968                    (*bitmap_p) ^ bitmap, count));
2969
2970         *bitmap_p ^= bitmap; /* mark as in use */
2971
2972         return;
2973 }
2974
2975 /* Free a previously allocated index back into the multiword bitmap allocator */
2976 void BCMFASTPATH
2977 bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
2978 {
2979         bcm_mwbmap_t * mwbmap_p;
2980         uint32 wordix, bitmap, *bitmap_p;
2981
2982         BCM_MWBMAP_AUDIT(mwbmap_hdl);
2983         mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
2984
2985         ASSERT(bitix < mwbmap_p->total);
2986
2987         /* Start with second level hierarchy */
2988         wordix   = BCM_MWBMAP_DIVOP(bitix);
2989         bitmap   = (1U << BCM_MWBMAP_MODOP(bitix));
2990         bitmap_p = &mwbmap_p->id_bitmap[wordix];
2991
2992         ASSERT((*bitmap_p & bitmap) == 0U);     /* ASSERT not a double free */
2993
2994         mwbmap_p->ifree++; /* update free count */
2995         ASSERT(mwbmap_p->ifree <= mwbmap_p->total);
2996
2997         MWBMAP_DBG(("Lvl2: bitix<%02u> wordix<%02u>: %08x | %08x = %08x ifree %d",
2998                    bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap,
2999                    mwbmap_p->ifree));
3000
3001         *bitmap_p |= bitmap; /* mark as available */
3002
3003         /* Now update first level hierarchy */
3004
3005         bitix    = wordix;
3006
3007         wordix   = BCM_MWBMAP_DIVOP(bitix); /* first level's word index */
3008         bitmap   = (1U << BCM_MWBMAP_MODOP(bitix));
3009         bitmap_p = &mwbmap_p->wd_bitmap[wordix];
3010
3011 #if !defined(BCM_MWBMAP_USE_CNTSETBITS)
3012         mwbmap_p->wd_count[bitix]++;
3013 #endif
3014
3015 #if defined(BCM_MWBMAP_DEBUG)
3016         {
3017                 uint32 count;
3018 #if defined(BCM_MWBMAP_USE_CNTSETBITS)
3019                 count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
3020 #else  /*  ! BCM_MWBMAP_USE_CNTSETBITS */
3021                 count = mwbmap_p->wd_count[bitix];
3022                 MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
3023 #endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
3024
3025                 MWBMAP_ASSERT(count <= BCM_MWBMAP_BITS_WORD);
3026
3027                 MWBMAP_DBG(("Lvl1: bitix<%02u> wordix<%02u>: %08x | %08x = %08x wfree %d",
3028                             bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, count));
3029         }
3030 #endif /* BCM_MWBMAP_DEBUG */
3031
3032         *bitmap_p |= bitmap;
3033
3034         return;
3035 }
3036
3037 /* Fetch the toal number of free indices in the multiword bitmap allocator */
3038 uint32
3039 bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl)
3040 {
3041         bcm_mwbmap_t * mwbmap_p;
3042
3043         BCM_MWBMAP_AUDIT(mwbmap_hdl);
3044         mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
3045
3046         ASSERT(mwbmap_p->ifree >= 0);
3047
3048         return mwbmap_p->ifree;
3049 }
3050
3051 /* Determine whether an index is inuse or free */
3052 bool
3053 bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
3054 {
3055         bcm_mwbmap_t * mwbmap_p;
3056         uint32 wordix, bitmap;
3057
3058         BCM_MWBMAP_AUDIT(mwbmap_hdl);
3059         mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
3060
3061         ASSERT(bitix < mwbmap_p->total);
3062
3063         wordix   = BCM_MWBMAP_DIVOP(bitix);
3064         bitmap   = (1U << BCM_MWBMAP_MODOP(bitix));
3065
3066         return ((mwbmap_p->id_bitmap[wordix] & bitmap) != 0U);
3067 }
3068
3069 /* Debug dump a multiword bitmap allocator */
3070 void
3071 bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl)
3072 {
3073         uint32 ix, count;
3074         bcm_mwbmap_t * mwbmap_p;
3075
3076         BCM_MWBMAP_AUDIT(mwbmap_hdl);
3077         mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
3078
3079         printf("mwbmap_p %p wmaps %u imaps %u ifree %d total %u\n", mwbmap_p,
3080                mwbmap_p->wmaps, mwbmap_p->imaps, mwbmap_p->ifree, mwbmap_p->total);
3081         for (ix = 0U; ix < mwbmap_p->wmaps; ix++) {
3082                 printf("\tWDMAP:%2u. 0x%08x\t", ix, mwbmap_p->wd_bitmap[ix]);
3083                 bcm_bitprint32(mwbmap_p->wd_bitmap[ix]);
3084                 printf("\n");
3085         }
3086         for (ix = 0U; ix < mwbmap_p->imaps; ix++) {
3087 #if defined(BCM_MWBMAP_USE_CNTSETBITS)
3088                 count = bcm_cntsetbits(mwbmap_p->id_bitmap[ix]);
3089 #else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
3090                 count = mwbmap_p->wd_count[ix];
3091                 MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[ix]));
3092 #endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
3093                 printf("\tIDMAP:%2u. 0x%08x %02u\t", ix, mwbmap_p->id_bitmap[ix], count);
3094                 bcm_bitprint32(mwbmap_p->id_bitmap[ix]);
3095                 printf("\n");
3096         }
3097
3098         return;
3099 }
3100
3101 /* Audit a hierarchical multiword bitmap */
3102 void
3103 bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl)
3104 {
3105         bcm_mwbmap_t * mwbmap_p;
3106         uint32 count, free_cnt = 0U, wordix, idmap_ix, bitix, *bitmap_p;
3107
3108         mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
3109
3110         for (wordix = 0U; wordix < mwbmap_p->wmaps; ++wordix) {
3111
3112                 bitmap_p = &mwbmap_p->wd_bitmap[wordix];
3113
3114                 for (bitix = 0U; bitix < BCM_MWBMAP_BITS_WORD; bitix++) {
3115                         if ((*bitmap_p) & (1 << bitix)) {
3116                                 idmap_ix = BCM_MWBMAP_MULOP(wordix) + bitix;
3117 #if defined(BCM_MWBMAP_USE_CNTSETBITS)
3118                                 count = bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]);
3119 #else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
3120                                 count = mwbmap_p->wd_count[idmap_ix];
3121                                 ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]));
3122 #endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
3123                                 ASSERT(count != 0U);
3124                                 free_cnt += count;
3125                         }
3126                 }
3127         }
3128
3129         ASSERT((int)free_cnt == mwbmap_p->ifree);
3130 }
3131 /* END : Multiword bitmap based 64bit to Unique 32bit Id allocator. */
3132
3133 /* Simple 16bit Id allocator using a stack implementation. */
3134 typedef struct id16_map {
3135         uint32  failures;  /* count of failures */
3136         void    *dbg;      /* debug placeholder */
3137         uint16  total;     /* total number of ids managed by allocator */
3138         uint16  start;     /* start value of 16bit ids to be managed */
3139         int     stack_idx; /* index into stack of available ids */
3140         uint16  stack[0];  /* stack of 16 bit ids */
3141 } id16_map_t;
3142
3143 #define ID16_MAP_SZ(items)      (sizeof(id16_map_t) + \
3144                                      (sizeof(uint16) * (items)))
3145
3146 #if defined(BCM_DBG)
3147
3148 /* Uncomment BCM_DBG_ID16 to debug double free */
3149 /* #define BCM_DBG_ID16 */
3150
3151 typedef struct id16_map_dbg {
3152         uint16  total;
3153         bool    avail[0];
3154 } id16_map_dbg_t;
3155 #define ID16_MAP_DBG_SZ(items)  (sizeof(id16_map_dbg_t) + \
3156                                      (sizeof(bool) * (items)))
3157 #define ID16_MAP_MSG(x)         print x
3158 #else
3159 #define ID16_MAP_MSG(x)
3160 #endif /* BCM_DBG */
3161
3162 void * /* Construct an id16 allocator: [start_val16 .. start_val16+total_ids) */
3163 id16_map_init(osl_t *osh, uint16 total_ids, uint16 start_val16)
3164 {
3165         uint16 idx, val16;
3166         id16_map_t * id16_map;
3167
3168         ASSERT(total_ids > 0);
3169
3170         /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
3171          * with random values.
3172          */
3173         ASSERT((start_val16 == ID16_UNDEFINED) ||
3174                (start_val16 + total_ids) < ID16_INVALID);
3175
3176         id16_map = (id16_map_t *) MALLOC(osh, ID16_MAP_SZ(total_ids));
3177         if (id16_map == NULL) {
3178                 return NULL;
3179         }
3180
3181         id16_map->total = total_ids;
3182         id16_map->start = start_val16;
3183         id16_map->failures = 0;
3184         id16_map->dbg = NULL;
3185
3186         /*
3187          * Populate stack with 16bit id values, commencing with start_val16.
3188          * if start_val16 is ID16_UNDEFINED, then do not populate the id16 map.
3189          */
3190         id16_map->stack_idx = -1;
3191
3192         if (id16_map->start != ID16_UNDEFINED) {
3193                 val16 = start_val16;
3194
3195                 for (idx = 0; idx < total_ids; idx++, val16++) {
3196                         id16_map->stack_idx = idx;
3197                         id16_map->stack[id16_map->stack_idx] = val16;
3198                 }
3199         }
3200
3201 #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3202         if (id16_map->start != ID16_UNDEFINED) {
3203                 id16_map->dbg = MALLOC(osh, ID16_MAP_DBG_SZ(total_ids));
3204
3205                 if (id16_map->dbg) {
3206                         id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
3207
3208                         id16_map_dbg->total = total_ids;
3209                         for (idx = 0; idx < total_ids; idx++) {
3210                                 id16_map_dbg->avail[idx] = TRUE;
3211                         }
3212                 }
3213         }
3214 #endif /* BCM_DBG && BCM_DBG_ID16 */
3215
3216         return (void *)id16_map;
3217 }
3218
3219 void * /* Destruct an id16 allocator instance */
3220 id16_map_fini(osl_t *osh, void * id16_map_hndl)
3221 {
3222         uint16 total_ids;
3223         id16_map_t * id16_map;
3224
3225         if (id16_map_hndl == NULL)
3226                 return NULL;
3227
3228         id16_map = (id16_map_t *)id16_map_hndl;
3229
3230         total_ids = id16_map->total;
3231         ASSERT(total_ids > 0);
3232
3233 #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3234         if (id16_map->dbg) {
3235                 MFREE(osh, id16_map->dbg, ID16_MAP_DBG_SZ(total_ids));
3236                 id16_map->dbg = NULL;
3237         }
3238 #endif /* BCM_DBG && BCM_DBG_ID16 */
3239
3240         id16_map->total = 0;
3241         MFREE(osh, id16_map, ID16_MAP_SZ(total_ids));
3242
3243         return NULL;
3244 }
3245
3246 void
3247 id16_map_clear(void * id16_map_hndl, uint16 total_ids, uint16 start_val16)
3248 {
3249         uint16 idx, val16;
3250         id16_map_t * id16_map;
3251
3252         ASSERT(total_ids > 0);
3253         /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
3254          * with random values.
3255          */
3256         ASSERT((start_val16 == ID16_UNDEFINED) ||
3257                (start_val16 + total_ids) < ID16_INVALID);
3258
3259         id16_map = (id16_map_t *)id16_map_hndl;
3260         if (id16_map == NULL) {
3261                 return;
3262         }
3263
3264         id16_map->total = total_ids;
3265         id16_map->start = start_val16;
3266         id16_map->failures = 0;
3267
3268         /* Populate stack with 16bit id values, commencing with start_val16 */
3269         id16_map->stack_idx = -1;
3270
3271         if (id16_map->start != ID16_UNDEFINED) {
3272                 val16 = start_val16;
3273
3274                 for (idx = 0; idx < total_ids; idx++, val16++) {
3275                         id16_map->stack_idx = idx;
3276                         id16_map->stack[id16_map->stack_idx] = val16;
3277                 }
3278         }
3279
3280 #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3281         if (id16_map->start != ID16_UNDEFINED) {
3282                 if (id16_map->dbg) {
3283                         id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
3284
3285                         id16_map_dbg->total = total_ids;
3286                         for (idx = 0; idx < total_ids; idx++) {
3287                                 id16_map_dbg->avail[idx] = TRUE;
3288                         }
3289                 }
3290         }
3291 #endif /* BCM_DBG && BCM_DBG_ID16 */
3292 }
3293
3294 uint16 BCMFASTPATH /* Allocate a unique 16bit id */
3295 id16_map_alloc(void * id16_map_hndl)
3296 {
3297         uint16 val16;
3298         id16_map_t * id16_map;
3299
3300         ASSERT(id16_map_hndl != NULL);
3301
3302         id16_map = (id16_map_t *)id16_map_hndl;
3303
3304         ASSERT(id16_map->total > 0);
3305
3306         if (id16_map->stack_idx < 0) {
3307                 id16_map->failures++;
3308                 return ID16_INVALID;
3309         }
3310
3311         val16 = id16_map->stack[id16_map->stack_idx];
3312         id16_map->stack_idx--;
3313
3314 #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3315         ASSERT((id16_map->start == ID16_UNDEFINED) ||
3316                (val16 < (id16_map->start + id16_map->total)));
3317
3318         if (id16_map->dbg) { /* Validate val16 */
3319                 id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
3320
3321                 ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == TRUE);
3322                 id16_map_dbg->avail[val16 - id16_map->start] = FALSE;
3323         }
3324 #endif /* BCM_DBG && BCM_DBG_ID16 */
3325
3326         return val16;
3327 }
3328
3329
3330 void BCMFASTPATH /* Free a 16bit id value into the id16 allocator */
3331 id16_map_free(void * id16_map_hndl, uint16 val16)
3332 {
3333         id16_map_t * id16_map;
3334
3335         ASSERT(id16_map_hndl != NULL);
3336
3337         id16_map = (id16_map_t *)id16_map_hndl;
3338
3339 #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3340         ASSERT((id16_map->start == ID16_UNDEFINED) ||
3341                (val16 < (id16_map->start + id16_map->total)));
3342
3343         if (id16_map->dbg) { /* Validate val16 */
3344                 id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
3345
3346                 ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == FALSE);
3347                 id16_map_dbg->avail[val16 - id16_map->start] = TRUE;
3348         }
3349 #endif /* BCM_DBG && BCM_DBG_ID16 */
3350
3351         id16_map->stack_idx++;
3352         id16_map->stack[id16_map->stack_idx] = val16;
3353 }
3354
3355 uint32 /* Returns number of failures to allocate an unique id16 */
3356 id16_map_failures(void * id16_map_hndl)
3357 {
3358         ASSERT(id16_map_hndl != NULL);
3359         return ((id16_map_t *)id16_map_hndl)->failures;
3360 }
3361
3362 bool
3363 id16_map_audit(void * id16_map_hndl)
3364 {
3365         int idx;
3366         int insane = 0;
3367         id16_map_t * id16_map;
3368
3369         ASSERT(id16_map_hndl != NULL);
3370
3371         id16_map = (id16_map_t *)id16_map_hndl;
3372
3373         ASSERT(id16_map->stack_idx >= -1);
3374         ASSERT(id16_map->stack_idx < (int)id16_map->total);
3375
3376         if (id16_map->start == ID16_UNDEFINED)
3377                 goto done;
3378
3379         for (idx = 0; idx <= id16_map->stack_idx; idx++) {
3380                 ASSERT(id16_map->stack[idx] >= id16_map->start);
3381                 ASSERT(id16_map->stack[idx] < (id16_map->start + id16_map->total));
3382
3383 #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3384                 if (id16_map->dbg) {
3385                         uint16 val16 = id16_map->stack[idx];
3386                         if (((id16_map_dbg_t *)(id16_map->dbg))->avail[val16] != TRUE) {
3387                                 insane |= 1;
3388                                 ID16_MAP_MSG(("id16_map<%p>: stack_idx %u invalid val16 %u\n",
3389                                         id16_map_hndl, idx, val16));
3390                         }
3391                 }
3392 #endif /* BCM_DBG && BCM_DBG_ID16 */
3393         }
3394
3395 #if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3396         if (id16_map->dbg) {
3397                 uint16 avail = 0; /* Audit available ids counts */
3398                 for (idx = 0; idx < id16_map_dbg->total; idx++) {
3399                         if (((id16_map_dbg_t *)(id16_map->dbg))->avail[idx16] == TRUE)
3400                                 avail++;
3401                 }
3402                 if (avail && (avail != (id16_map->stack_idx + 1))) {
3403                         insane |= 1;
3404                         ID16_MAP_MSG(("id16_map<%p>: avail %u stack_idx %u\n",
3405                                 id16_map_hndl, avail, id16_map->stack_idx));
3406                 }
3407         }
3408 #endif /* BCM_DBG && BCM_DBG_ID16 */
3409
3410 done:
3411         /* invoke any other system audits */
3412         return (!!insane);
3413 }
3414 /* END: Simple id16 allocator */
3415
3416
3417 #endif 
3418
3419 /* calculate a >> b; and returns only lower 32 bits */
3420 void
3421 bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
3422 {
3423         uint32 a1 = a_high, a0 = a_low, r0 = 0;
3424
3425         if (b == 0) {
3426                 r0 = a_low;
3427                 *r = r0;
3428                 return;
3429         }
3430
3431         if (b < 32) {
3432                 a0 = a0 >> b;
3433                 a1 = a1 & ((1 << b) - 1);
3434                 a1 = a1 << (32 - b);
3435                 r0 = a0 | a1;
3436                 *r = r0;
3437                 return;
3438         } else {
3439                 r0 = a1 >> (b - 32);
3440                 *r = r0;
3441                 return;
3442         }
3443
3444 }
3445
3446 /* calculate a + b where a is a 64 bit number and b is a 32 bit number */
3447 void
3448 bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset)
3449 {
3450         uint32 r1_lo = *r_lo;
3451         (*r_lo) += offset;
3452         if (*r_lo < r1_lo)
3453                 (*r_hi) ++;
3454 }
3455
3456 /* calculate a - b where a is a 64 bit number and b is a 32 bit number */
3457 void
3458 bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset)
3459 {
3460         uint32 r1_lo = *r_lo;
3461         (*r_lo) -= offset;
3462         if (*r_lo > r1_lo)
3463                 (*r_hi) --;
3464 }
3465
3466 #ifdef DEBUG_COUNTER
3467 #if (OSL_SYSUPTIME_SUPPORT == TRUE)
3468 void counter_printlog(counter_tbl_t *ctr_tbl)
3469 {
3470         uint32 now;
3471
3472         if (!ctr_tbl->enabled)
3473                 return;
3474
3475         now = OSL_SYSUPTIME();
3476
3477         if (now - ctr_tbl->prev_log_print > ctr_tbl->log_print_interval) {
3478                 uint8 i = 0;
3479                 printf("counter_print(%s %d):", ctr_tbl->name, now - ctr_tbl->prev_log_print);
3480
3481                 for (i = 0; i < ctr_tbl->needed_cnt; i++) {
3482                         printf(" %u", ctr_tbl->cnt[i]);
3483                 }
3484                 printf("\n");
3485
3486                 ctr_tbl->prev_log_print = now;
3487                 bzero(ctr_tbl->cnt, CNTR_TBL_MAX * sizeof(uint));
3488         }
3489 }
3490 #else
3491 /* OSL_SYSUPTIME is not supported so no way to get time */
3492 #define counter_printlog(a) do {} while (0)
3493 #endif /* OSL_SYSUPTIME_SUPPORT == TRUE */
3494 #endif /* DEBUG_COUNTER */
3495
3496 #if defined(BCMDRIVER) && !defined(_CFEZ_)
3497 void
3498 dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size)
3499 {
3500         uint32 mem_size;
3501         mem_size = sizeof(dll_pool_t) + (elems_max * elem_size);
3502         if (pool)
3503                 MFREE(osh, pool, mem_size);
3504 }
3505 dll_pool_t *
3506 dll_pool_init(void * osh, uint16 elems_max, uint16 elem_size)
3507 {
3508         uint32 mem_size, i;
3509         dll_pool_t * dll_pool_p;
3510         dll_t * elem_p;
3511
3512         ASSERT(elem_size > sizeof(dll_t));
3513
3514         mem_size = sizeof(dll_pool_t) + (elems_max * elem_size);
3515
3516         if ((dll_pool_p = (dll_pool_t *)MALLOCZ(osh, mem_size)) == NULL) {
3517                 printf("dll_pool_init: elems_max<%u> elem_size<%u> malloc failure\n",
3518                         elems_max, elem_size);
3519                 ASSERT(0);
3520                 return dll_pool_p;
3521         }
3522
3523         dll_init(&dll_pool_p->free_list);
3524         dll_pool_p->elems_max = elems_max;
3525         dll_pool_p->elem_size = elem_size;
3526
3527         elem_p = dll_pool_p->elements;
3528         for (i = 0; i < elems_max; i++) {
3529                 dll_append(&dll_pool_p->free_list, elem_p);
3530                 elem_p = (dll_t *)((uintptr)elem_p + elem_size);
3531         }
3532
3533         dll_pool_p->free_count = elems_max;
3534
3535         return dll_pool_p;
3536 }
3537
3538
3539 void *
3540 dll_pool_alloc(dll_pool_t * dll_pool_p)
3541 {
3542         dll_t * elem_p;
3543
3544         if (dll_pool_p->free_count == 0) {
3545                 ASSERT(dll_empty(&dll_pool_p->free_list));
3546                 return NULL;
3547         }
3548
3549         elem_p = dll_head_p(&dll_pool_p->free_list);
3550         dll_delete(elem_p);
3551         dll_pool_p->free_count -= 1;
3552
3553         return (void *)elem_p;
3554 }
3555
3556 void
3557 dll_pool_free(dll_pool_t * dll_pool_p, void * elem_p)
3558 {
3559         dll_t * node_p = (dll_t *)elem_p;
3560         dll_prepend(&dll_pool_p->free_list, node_p);
3561         dll_pool_p->free_count += 1;
3562 }
3563
3564
3565 void
3566 dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p)
3567 {
3568         dll_t * node_p = (dll_t *)elem_p;
3569         dll_append(&dll_pool_p->free_list, node_p);
3570         dll_pool_p->free_count += 1;
3571 }
3572
3573 #endif