staging: brcm80211: fix "ERROR: do not use assignment in if condition"
[deliverable/linux.git] / drivers / staging / brcm80211 / util / bcmsrom.c
CommitLineData
a9533e7e
HP
1/*
2 * Copyright (c) 2010 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <typedefs.h>
18#include <bcmdefs.h>
19#include <osl.h>
20#include <stdarg.h>
21#include <bcmutils.h>
22#include <hndsoc.h>
23#include <sbchipc.h>
24#include <bcmdevs.h>
25#include <bcmendian.h>
26#include <pcicfg.h>
27#include <siutils.h>
28#include <bcmsrom.h>
29#include <bcmsrom_tbl.h>
30#ifdef BCMSDIO
31#include <bcmsdh.h>
32#include <sdio.h>
33#endif
34
35#include <bcmnvram.h>
36#include <bcmotp.h>
37
38#if defined(BCMSDIO)
39#include <sbsdio.h>
40#include <sbhnddma.h>
41#include <sbsdpcmdev.h>
42#endif
43
44#include <proto/ethernet.h> /* for sprom content groking */
45
46#define BS_ERROR(args)
47
48#define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \
49 (((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \
50 ((uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \
51 ((uint8 *)curmap + PCI_BAR0_SPROM_OFFSET))
52
53#if defined(BCMDBG)
54#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
55#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
56#endif
57
58typedef struct varbuf {
59 char *base; /* pointer to buffer base */
60 char *buf; /* pointer to current position */
61 unsigned int size; /* current (residual) size in bytes */
62} varbuf_t;
63extern char *_vars;
64extern uint _varsz;
65
66#define SROM_CIS_SINGLE 1
67
7cc4a4c0
JC
68static int initvars_srom_si(si_t *sih, osl_t *osh, void *curmap, char **vars,
69 uint *count);
70static void _initvars_srom_pci(uint8 sromrev, uint16 *srom, uint off,
71 varbuf_t *b);
72static int initvars_srom_pci(si_t *sih, void *curmap, char **vars,
73 uint *count);
74static int initvars_flash_si(si_t *sih, char **vars, uint *count);
a9533e7e 75#ifdef BCMSDIO
7cc4a4c0
JC
76static int initvars_cis_sdio(osl_t *osh, char **vars, uint *count);
77static int sprom_cmd_sdio(osl_t *osh, uint8 cmd);
78static int sprom_read_sdio(osl_t *osh, uint16 addr, uint16 *data);
a9533e7e 79#endif /* BCMSDIO */
7cc4a4c0
JC
80static int sprom_read_pci(osl_t *osh, si_t *sih, uint16 *sprom, uint wordoff,
81 uint16 *buf, uint nwords, bool check_crc);
a9533e7e 82#if defined(BCMNVRAMR)
7cc4a4c0 83static int otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz);
a9533e7e 84#endif
7cc4a4c0 85static uint16 srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, uint32 cmd,
a9533e7e
HP
86 uint wordoff, uint16 data);
87
7cc4a4c0
JC
88static int initvars_table(osl_t *osh, char *start, char *end, char **vars,
89 uint *count);
90static int initvars_flash(si_t *sih, osl_t *osh, char **vp, uint len);
a9533e7e
HP
91
92/* Initialization of varbuf structure */
a2627bc0
JC
93static void BCMATTACHFN(varbuf_init) (varbuf_t *b, char *buf, uint size)
94{
a9533e7e
HP
95 b->size = size;
96 b->base = b->buf = buf;
97}
98
99/* append a null terminated var=value string */
a2627bc0
JC
100static int BCMATTACHFN(varbuf_append) (varbuf_t *b, const char *fmt, ...)
101{
a9533e7e
HP
102 va_list ap;
103 int r;
104 size_t len;
105 char *s;
106
107 if (b->size < 2)
108 return 0;
109
110 va_start(ap, fmt);
111 r = vsnprintf(b->buf, b->size, fmt, ap);
112 va_end(ap);
113
114 /* C99 snprintf behavior returns r >= size on overflow,
115 * others return -1 on overflow.
116 * All return -1 on format error.
117 * We need to leave room for 2 null terminations, one for the current var
118 * string, and one for final null of the var table. So check that the
119 * strlen written, r, leaves room for 2 chars.
120 */
121 if ((r == -1) || (r > (int)(b->size - 2))) {
122 b->size = 0;
123 return 0;
124 }
125
126 /* Remove any earlier occurrence of the same variable */
ca8c1e59
JC
127 s = strchr(b->buf, '=');
128 if (s != NULL) {
a9533e7e
HP
129 len = (size_t) (s - b->buf);
130 for (s = b->base; s < b->buf;) {
131 if ((bcmp(s, b->buf, len) == 0) && s[len] == '=') {
132 len = strlen(s) + 1;
133 memmove(s, (s + len),
134 ((b->buf + r + 1) - (s + len)));
135 b->buf -= len;
136 b->size += (unsigned int)len;
137 break;
138 }
139
140 while (*s++) ;
141 }
142 }
143
144 /* skip over this string's null termination */
145 r++;
146 b->size -= r;
147 b->buf += r;
148
149 return r;
150}
151
152/*
153 * Initialize local vars from the right source for this platform.
154 * Return 0 on success, nonzero on error.
155 */
156int
7cc4a4c0
JC
157BCMATTACHFN(srom_var_init) (si_t *sih, uint bustype, void *curmap, osl_t *osh,
158 char **vars, uint *count) {
a9533e7e
HP
159 uint len;
160
161 len = 0;
162
163 ASSERT(bustype == BUSTYPE(bustype));
164 if (vars == NULL || count == NULL)
90ea2296 165 return 0;
a9533e7e
HP
166
167 *vars = NULL;
168 *count = 0;
169
170 switch (BUSTYPE(bustype)) {
171 case SI_BUS:
172 case JTAG_BUS:
173 return initvars_srom_si(sih, osh, curmap, vars, count);
174
175 case PCI_BUS:
176 ASSERT(curmap != NULL);
177 if (curmap == NULL)
90ea2296 178 return -1;
a9533e7e
HP
179
180 return initvars_srom_pci(sih, curmap, vars, count);
181
182#ifdef BCMSDIO
183 case SDIO_BUS:
184 return initvars_cis_sdio(osh, vars, count);
185#endif /* BCMSDIO */
186
187 default:
188 ASSERT(0);
189 }
90ea2296 190 return -1;
a9533e7e
HP
191}
192
193/* support only 16-bit word read from srom */
194int
7cc4a4c0
JC
195srom_read(si_t *sih, uint bustype, void *curmap, osl_t *osh,
196 uint byteoff, uint nbytes, uint16 *buf, bool check_crc)
a9533e7e
HP
197{
198 uint off, nw;
199#ifdef BCMSDIO
200 uint i;
201#endif /* BCMSDIO */
202
203 ASSERT(bustype == BUSTYPE(bustype));
204
205 /* check input - 16-bit access only */
206 if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > SROM_MAX)
207 return 1;
208
209 off = byteoff / 2;
210 nw = nbytes / 2;
211
212 if (BUSTYPE(bustype) == PCI_BUS) {
213 if (!curmap)
214 return 1;
215
216 if (si_is_sprom_available(sih)) {
217 uint16 *srom;
218
219 srom = (uint16 *) SROM_OFFSET(sih);
220 if (srom == NULL)
221 return 1;
222
223 if (sprom_read_pci
224 (osh, sih, srom, off, buf, nw, check_crc))
225 return 1;
226 }
227#if defined(BCMNVRAMR)
228 else {
229 if (otp_read_pci(osh, sih, buf, SROM_MAX))
230 return 1;
231 }
232#endif
233#ifdef BCMSDIO
234 } else if (BUSTYPE(bustype) == SDIO_BUS) {
235 off = byteoff / 2;
236 nw = nbytes / 2;
237 for (i = 0; i < nw; i++) {
238 if (sprom_read_sdio
239 (osh, (uint16) (off + i), (uint16 *) (buf + i)))
240 return 1;
241 }
242#endif /* BCMSDIO */
243 } else if (BUSTYPE(bustype) == SI_BUS) {
244 return 1;
245 } else {
246 return 1;
247 }
248
249 return 0;
250}
251
252static const char BCMATTACHDATA(vstr_manf)[] = "manf=%s";
253static const char BCMATTACHDATA(vstr_productname)[] = "productname=%s";
254static const char BCMATTACHDATA(vstr_manfid)[] = "manfid=0x%x";
255static const char BCMATTACHDATA(vstr_prodid)[] = "prodid=0x%x";
256#ifdef BCMSDIO
257static const char BCMATTACHDATA(vstr_sdmaxspeed)[] = "sdmaxspeed=%d";
258static const char BCMATTACHDATA(vstr_sdmaxblk)[][13] =
259{
260"sdmaxblk0=%d", "sdmaxblk1=%d", "sdmaxblk2=%d"};
261#endif
262static const char BCMATTACHDATA(vstr_regwindowsz)[] = "regwindowsz=%d";
263static const char BCMATTACHDATA(vstr_sromrev)[] = "sromrev=%d";
264static const char BCMATTACHDATA(vstr_chiprev)[] = "chiprev=%d";
265static const char BCMATTACHDATA(vstr_subvendid)[] = "subvendid=0x%x";
266static const char BCMATTACHDATA(vstr_subdevid)[] = "subdevid=0x%x";
267static const char BCMATTACHDATA(vstr_boardrev)[] = "boardrev=0x%x";
268static const char BCMATTACHDATA(vstr_aa2g)[] = "aa2g=0x%x";
269static const char BCMATTACHDATA(vstr_aa5g)[] = "aa5g=0x%x";
270static const char BCMATTACHDATA(vstr_ag)[] = "ag%d=0x%x";
271static const char BCMATTACHDATA(vstr_cc)[] = "cc=%d";
272static const char BCMATTACHDATA(vstr_opo)[] = "opo=%d";
273static const char BCMATTACHDATA(vstr_pa0b)[][9] =
274{
275"pa0b0=%d", "pa0b1=%d", "pa0b2=%d"};
276
277static const char BCMATTACHDATA(vstr_pa0itssit)[] = "pa0itssit=%d";
278static const char BCMATTACHDATA(vstr_pa0maxpwr)[] = "pa0maxpwr=%d";
279static const char BCMATTACHDATA(vstr_pa1b)[][9] =
280{
281"pa1b0=%d", "pa1b1=%d", "pa1b2=%d"};
282
283static const char BCMATTACHDATA(vstr_pa1lob)[][11] =
284{
285"pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d"};
286
287static const char BCMATTACHDATA(vstr_pa1hib)[][11] =
288{
289"pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d"};
290
291static const char BCMATTACHDATA(vstr_pa1itssit)[] = "pa1itssit=%d";
292static const char BCMATTACHDATA(vstr_pa1maxpwr)[] = "pa1maxpwr=%d";
293static const char BCMATTACHDATA(vstr_pa1lomaxpwr)[] = "pa1lomaxpwr=%d";
294static const char BCMATTACHDATA(vstr_pa1himaxpwr)[] = "pa1himaxpwr=%d";
295static const char BCMATTACHDATA(vstr_oem)[] =
296 "oem=%02x%02x%02x%02x%02x%02x%02x%02x";
297static const char BCMATTACHDATA(vstr_boardflags)[] = "boardflags=0x%x";
298static const char BCMATTACHDATA(vstr_boardflags2)[] = "boardflags2=0x%x";
299static const char BCMATTACHDATA(vstr_ledbh)[] = "ledbh%d=0x%x";
300static const char BCMATTACHDATA(vstr_noccode)[] = "ccode=0x0";
301static const char BCMATTACHDATA(vstr_ccode)[] = "ccode=%c%c";
302static const char BCMATTACHDATA(vstr_cctl)[] = "cctl=0x%x";
303static const char BCMATTACHDATA(vstr_cckpo)[] = "cckpo=0x%x";
304static const char BCMATTACHDATA(vstr_ofdmpo)[] = "ofdmpo=0x%x";
305static const char BCMATTACHDATA(vstr_rdlid)[] = "rdlid=0x%x";
306static const char BCMATTACHDATA(vstr_rdlrndis)[] = "rdlrndis=%d";
307static const char BCMATTACHDATA(vstr_rdlrwu)[] = "rdlrwu=%d";
308static const char BCMATTACHDATA(vstr_usbfs)[] = "usbfs=%d";
309static const char BCMATTACHDATA(vstr_wpsgpio)[] = "wpsgpio=%d";
310static const char BCMATTACHDATA(vstr_wpsled)[] = "wpsled=%d";
311static const char BCMATTACHDATA(vstr_rdlsn)[] = "rdlsn=%d";
312static const char BCMATTACHDATA(vstr_rssismf2g)[] = "rssismf2g=%d";
313static const char BCMATTACHDATA(vstr_rssismc2g)[] = "rssismc2g=%d";
314static const char BCMATTACHDATA(vstr_rssisav2g)[] = "rssisav2g=%d";
315static const char BCMATTACHDATA(vstr_bxa2g)[] = "bxa2g=%d";
316static const char BCMATTACHDATA(vstr_rssismf5g)[] = "rssismf5g=%d";
317static const char BCMATTACHDATA(vstr_rssismc5g)[] = "rssismc5g=%d";
318static const char BCMATTACHDATA(vstr_rssisav5g)[] = "rssisav5g=%d";
319static const char BCMATTACHDATA(vstr_bxa5g)[] = "bxa5g=%d";
320static const char BCMATTACHDATA(vstr_tri2g)[] = "tri2g=%d";
321static const char BCMATTACHDATA(vstr_tri5gl)[] = "tri5gl=%d";
322static const char BCMATTACHDATA(vstr_tri5g)[] = "tri5g=%d";
323static const char BCMATTACHDATA(vstr_tri5gh)[] = "tri5gh=%d";
324static const char BCMATTACHDATA(vstr_rxpo2g)[] = "rxpo2g=%d";
325static const char BCMATTACHDATA(vstr_rxpo5g)[] = "rxpo5g=%d";
326static const char BCMATTACHDATA(vstr_boardtype)[] = "boardtype=0x%x";
327static const char BCMATTACHDATA(vstr_leddc)[] = "leddc=0x%04x";
328static const char BCMATTACHDATA(vstr_vendid)[] = "vendid=0x%x";
329static const char BCMATTACHDATA(vstr_devid)[] = "devid=0x%x";
330static const char BCMATTACHDATA(vstr_xtalfreq)[] = "xtalfreq=%d";
331static const char BCMATTACHDATA(vstr_txchain)[] = "txchain=0x%x";
332static const char BCMATTACHDATA(vstr_rxchain)[] = "rxchain=0x%x";
333static const char BCMATTACHDATA(vstr_antswitch)[] = "antswitch=0x%x";
334static const char BCMATTACHDATA(vstr_regrev)[] = "regrev=0x%x";
335static const char BCMATTACHDATA(vstr_antswctl2g)[] = "antswctl2g=0x%x";
336static const char BCMATTACHDATA(vstr_triso2g)[] = "triso2g=0x%x";
337static const char BCMATTACHDATA(vstr_pdetrange2g)[] = "pdetrange2g=0x%x";
338static const char BCMATTACHDATA(vstr_extpagain2g)[] = "extpagain2g=0x%x";
339static const char BCMATTACHDATA(vstr_tssipos2g)[] = "tssipos2g=0x%x";
340static const char BCMATTACHDATA(vstr_antswctl5g)[] = "antswctl5g=0x%x";
341static const char BCMATTACHDATA(vstr_triso5g)[] = "triso5g=0x%x";
342static const char BCMATTACHDATA(vstr_pdetrange5g)[] = "pdetrange5g=0x%x";
343static const char BCMATTACHDATA(vstr_extpagain5g)[] = "extpagain5g=0x%x";
344static const char BCMATTACHDATA(vstr_tssipos5g)[] = "tssipos5g=0x%x";
345static const char BCMATTACHDATA(vstr_maxp2ga0)[] = "maxp2ga0=0x%x";
346static const char BCMATTACHDATA(vstr_itt2ga0)[] = "itt2ga0=0x%x";
347static const char BCMATTACHDATA(vstr_pa)[] = "pa%dgw%da%d=0x%x";
348static const char BCMATTACHDATA(vstr_pahl)[] = "pa%dg%cw%da%d=0x%x";
349static const char BCMATTACHDATA(vstr_maxp5ga0)[] = "maxp5ga0=0x%x";
350static const char BCMATTACHDATA(vstr_itt5ga0)[] = "itt5ga0=0x%x";
351static const char BCMATTACHDATA(vstr_maxp5gha0)[] = "maxp5gha0=0x%x";
352static const char BCMATTACHDATA(vstr_maxp5gla0)[] = "maxp5gla0=0x%x";
353static const char BCMATTACHDATA(vstr_maxp2ga1)[] = "maxp2ga1=0x%x";
354static const char BCMATTACHDATA(vstr_itt2ga1)[] = "itt2ga1=0x%x";
355static const char BCMATTACHDATA(vstr_maxp5ga1)[] = "maxp5ga1=0x%x";
356static const char BCMATTACHDATA(vstr_itt5ga1)[] = "itt5ga1=0x%x";
357static const char BCMATTACHDATA(vstr_maxp5gha1)[] = "maxp5gha1=0x%x";
358static const char BCMATTACHDATA(vstr_maxp5gla1)[] = "maxp5gla1=0x%x";
359static const char BCMATTACHDATA(vstr_cck2gpo)[] = "cck2gpo=0x%x";
360static const char BCMATTACHDATA(vstr_ofdm2gpo)[] = "ofdm2gpo=0x%x";
361static const char BCMATTACHDATA(vstr_ofdm5gpo)[] = "ofdm5gpo=0x%x";
362static const char BCMATTACHDATA(vstr_ofdm5glpo)[] = "ofdm5glpo=0x%x";
363static const char BCMATTACHDATA(vstr_ofdm5ghpo)[] = "ofdm5ghpo=0x%x";
364static const char BCMATTACHDATA(vstr_cddpo)[] = "cddpo=0x%x";
365static const char BCMATTACHDATA(vstr_stbcpo)[] = "stbcpo=0x%x";
366static const char BCMATTACHDATA(vstr_bw40po)[] = "bw40po=0x%x";
367static const char BCMATTACHDATA(vstr_bwduppo)[] = "bwduppo=0x%x";
368static const char BCMATTACHDATA(vstr_mcspo)[] = "mcs%dgpo%d=0x%x";
369static const char BCMATTACHDATA(vstr_mcspohl)[] = "mcs%dg%cpo%d=0x%x";
370static const char BCMATTACHDATA(vstr_custom)[] = "customvar%d=0x%x";
371static const char BCMATTACHDATA(vstr_cckdigfilttype)[] = "cckdigfilttype=%d";
372static const char BCMATTACHDATA(vstr_boardnum)[] = "boardnum=%d";
373static const char BCMATTACHDATA(vstr_macaddr)[] = "macaddr=%s";
374static const char BCMATTACHDATA(vstr_usbepnum)[] = "usbepnum=0x%x";
375static const char BCMATTACHDATA(vstr_end)[] = "END\0";
376
377uint8 patch_pair = 0;
378
379/* For dongle HW, accept partial calibration parameters */
380#define BCMDONGLECASE(n)
381
382int
7cc4a4c0
JC
383BCMATTACHFN(srom_parsecis) (osl_t *osh, uint8 *pcis[], uint ciscnt,
384 char **vars, uint *count)
a9533e7e
HP
385{
386 char eabuf[32];
387 char *base;
388 varbuf_t b;
389 uint8 *cis, tup, tlen, sromrev = 1;
390 int i, j;
391 bool ag_init = FALSE;
392 uint32 w32;
393 uint funcid;
394 uint cisnum;
395 int32 boardnum;
396 int err;
397 bool standard_cis;
398
399 ASSERT(vars != NULL);
400 ASSERT(count != NULL);
401
402 boardnum = -1;
403
404 base = MALLOC(osh, MAXSZ_NVRAM_VARS);
405 ASSERT(base != NULL);
406 if (!base)
407 return -2;
408
409 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
410 bzero(base, MAXSZ_NVRAM_VARS);
411 eabuf[0] = '\0';
412 for (cisnum = 0; cisnum < ciscnt; cisnum++) {
413 cis = *pcis++;
414 i = 0;
415 funcid = 0;
416 standard_cis = TRUE;
417 do {
418 if (standard_cis) {
419 tup = cis[i++];
420 if (tup == CISTPL_NULL || tup == CISTPL_END)
421 tlen = 0;
422 else
423 tlen = cis[i++];
424 } else {
425 if (cis[i] == CISTPL_NULL
426 || cis[i] == CISTPL_END) {
427 tlen = 0;
428 tup = cis[i];
429 } else {
430 tlen = cis[i];
431 tup = CISTPL_BRCM_HNBU;
432 }
433 ++i;
434 }
435 if ((i + tlen) >= CIS_SIZE)
436 break;
437
438 switch (tup) {
439 case CISTPL_VERS_1:
440 /* assume the strings are good if the version field checks out */
441 if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) {
442 varbuf_append(&b, vstr_manf,
443 &cis[i + 2]);
444 varbuf_append(&b, vstr_productname,
445 &cis[i + 3 +
446 strlen((char *)
447 &cis[i +
448 2])]);
449 break;
450 }
451
452 case CISTPL_MANFID:
453 varbuf_append(&b, vstr_manfid,
454 (cis[i + 1] << 8) + cis[i]);
455 varbuf_append(&b, vstr_prodid,
456 (cis[i + 3] << 8) + cis[i + 2]);
457 break;
458
459 case CISTPL_FUNCID:
460 funcid = cis[i];
461 break;
462
463 case CISTPL_FUNCE:
464 switch (funcid) {
465 case CISTPL_FID_SDIO:
466#ifdef BCMSDIO
467 if (cis[i] == 0) {
468 uint8 spd = cis[i + 3];
469 static int base[] = {
470 -1, 10, 12, 13, 15, 20,
471 25, 30,
472 35, 40, 45, 50, 55, 60,
473 70, 80
474 };
475 static int mult[] = {
476 10, 100, 1000, 10000,
477 -1, -1, -1, -1
478 };
479 ASSERT((mult[spd & 0x7] != -1)
480 &&
481 (base
482 [(spd >> 3) & 0x0f]));
483 varbuf_append(&b,
484 vstr_sdmaxblk[0],
485 (cis[i + 2] << 8)
486 + cis[i + 1]);
487 varbuf_append(&b,
488 vstr_sdmaxspeed,
489 (mult[spd & 0x7] *
490 base[(spd >> 3) &
491 0x0f]));
492 } else if (cis[i] == 1) {
493 varbuf_append(&b,
494 vstr_sdmaxblk
495 [cisnum],
496 (cis[i + 13] << 8)
497 | cis[i + 12]);
498 }
499#endif /* BCMSDIO */
500 funcid = 0;
501 break;
502 default:
503 /* set macaddr if HNBU_MACADDR not seen yet */
504 if (eabuf[0] == '\0'
505 && cis[i] == LAN_NID
506 && !(ETHER_ISNULLADDR(&cis[i + 2]))
507 && !(ETHER_ISMULTI(&cis[i + 2]))) {
508 ASSERT(cis[i + 1] ==
509 ETHER_ADDR_LEN);
510 bcm_ether_ntoa((struct
511 ether_addr *)
512 &cis[i + 2],
513 eabuf);
514
515 /* set boardnum if HNBU_BOARDNUM not seen yet */
516 if (boardnum == -1)
517 boardnum =
518 (cis[i + 6] << 8) +
519 cis[i + 7];
520 }
521 break;
522 }
523 break;
524
525 case CISTPL_CFTABLE:
526 varbuf_append(&b, vstr_regwindowsz,
527 (cis[i + 7] << 8) | cis[i + 6]);
528 break;
529
530 case CISTPL_BRCM_HNBU:
531 switch (cis[i]) {
532 case HNBU_SROMREV:
533 sromrev = cis[i + 1];
534 varbuf_append(&b, vstr_sromrev,
535 sromrev);
536 break;
537
538 case HNBU_XTALFREQ:
539 varbuf_append(&b, vstr_xtalfreq,
540 (cis[i + 4] << 24) |
541 (cis[i + 3] << 16) |
542 (cis[i + 2] << 8) |
543 cis[i + 1]);
544 break;
545
546 case HNBU_CHIPID:
547 varbuf_append(&b, vstr_vendid,
548 (cis[i + 2] << 8) +
549 cis[i + 1]);
550 varbuf_append(&b, vstr_devid,
551 (cis[i + 4] << 8) +
552 cis[i + 3]);
553 if (tlen >= 7) {
554 varbuf_append(&b, vstr_chiprev,
555 (cis[i + 6] << 8)
556 + cis[i + 5]);
557 }
558 if (tlen >= 9) {
559 varbuf_append(&b,
560 vstr_subvendid,
561 (cis[i + 8] << 8)
562 + cis[i + 7]);
563 }
564 if (tlen >= 11) {
565 varbuf_append(&b, vstr_subdevid,
566 (cis[i + 10] << 8)
567 + cis[i + 9]);
568 /* subdevid doubles for boardtype */
569 varbuf_append(&b,
570 vstr_boardtype,
571 (cis[i + 10] << 8)
572 + cis[i + 9]);
573 }
574 break;
575
576 case HNBU_BOARDNUM:
577 boardnum =
578 (cis[i + 2] << 8) + cis[i + 1];
579 break;
580
581 case HNBU_PATCH:
582 {
583 char vstr_paddr[16];
584 char vstr_pdata[16];
585
586 /* retrieve the patch pairs
587 * from tlen/6; where 6 is
588 * sizeof(patch addr(2)) +
589 * sizeof(patch data(4)).
590 */
591 patch_pair = tlen / 6;
592
593 for (j = 0; j < patch_pair; j++) {
594 snprintf(vstr_paddr,
595 sizeof
596 (vstr_paddr),
597 "pa%d=0x%%x",
598 j);
599 snprintf(vstr_pdata,
600 sizeof
601 (vstr_pdata),
602 "pd%d=0x%%x",
603 j);
604
605 varbuf_append(&b,
606 vstr_paddr,
607 (cis
608 [i +
609 (j *
610 6) +
611 2] << 8)
612 | cis[i +
613 (j *
614 6)
615 +
616 1]);
617
618 varbuf_append(&b,
619 vstr_pdata,
620 (cis
621 [i +
622 (j *
623 6) +
624 6] <<
625 24) |
626 (cis
627 [i +
628 (j *
629 6) +
630 5] <<
631 16) |
632 (cis
633 [i +
634 (j *
635 6) +
636 4] << 8)
637 | cis[i +
638 (j *
639 6)
640 +
641 3]);
642 }
643 }
644 break;
645
646 case HNBU_BOARDREV:
647 if (tlen == 2)
648 varbuf_append(&b, vstr_boardrev,
649 cis[i + 1]);
650 else
651 varbuf_append(&b, vstr_boardrev,
652 (cis[i + 2] << 8)
653 + cis[i + 1]);
654 break;
655
656 case HNBU_BOARDFLAGS:
657 w32 = (cis[i + 2] << 8) + cis[i + 1];
658 if (tlen >= 5)
659 w32 |=
660 ((cis[i + 4] << 24) +
661 (cis[i + 3] << 16));
662 varbuf_append(&b, vstr_boardflags, w32);
663
664 if (tlen >= 7) {
665 w32 =
666 (cis[i + 6] << 8) + cis[i +
667 5];
668 if (tlen >= 9)
669 w32 |=
670 ((cis[i + 8] << 24)
671 +
672 (cis[i + 7] <<
673 16));
674 varbuf_append(&b,
675 vstr_boardflags2,
676 w32);
677 }
678 break;
679
680 case HNBU_USBFS:
681 varbuf_append(&b, vstr_usbfs,
682 cis[i + 1]);
683 break;
684
685 case HNBU_BOARDTYPE:
686 varbuf_append(&b, vstr_boardtype,
687 (cis[i + 2] << 8) +
688 cis[i + 1]);
689 break;
690
691 case HNBU_HNBUCIS:
692 /*
693 * what follows is a nonstandard HNBU CIS
694 * that lacks CISTPL_BRCM_HNBU tags
695 *
696 * skip 0xff (end of standard CIS)
697 * after this tuple
698 */
699 tlen++;
700 standard_cis = FALSE;
701 break;
702
703 case HNBU_USBEPNUM:
704 varbuf_append(&b, vstr_usbepnum,
705 (cis[i + 2] << 8) | cis[i
706 +
707 1]);
708 break;
709
710 case HNBU_AA:
711 varbuf_append(&b, vstr_aa2g,
712 cis[i + 1]);
713 if (tlen >= 3)
714 varbuf_append(&b, vstr_aa5g,
715 cis[i + 2]);
716 break;
717
718 case HNBU_AG:
719 varbuf_append(&b, vstr_ag, 0,
720 cis[i + 1]);
721 if (tlen >= 3)
722 varbuf_append(&b, vstr_ag, 1,
723 cis[i + 2]);
724 if (tlen >= 4)
725 varbuf_append(&b, vstr_ag, 2,
726 cis[i + 3]);
727 if (tlen >= 5)
728 varbuf_append(&b, vstr_ag, 3,
729 cis[i + 4]);
730 ag_init = TRUE;
731 break;
732
733 case HNBU_ANT5G:
734 varbuf_append(&b, vstr_aa5g,
735 cis[i + 1]);
736 varbuf_append(&b, vstr_ag, 1,
737 cis[i + 2]);
738 break;
739
740 case HNBU_CC:
741 ASSERT(sromrev == 1);
742 varbuf_append(&b, vstr_cc, cis[i + 1]);
743 break;
744
745 case HNBU_PAPARMS:
746 switch (tlen) {
747 case 2:
748 ASSERT(sromrev == 1);
749 varbuf_append(&b,
750 vstr_pa0maxpwr,
751 cis[i + 1]);
752 break;
753 case 10:
754 ASSERT(sromrev >= 2);
755 varbuf_append(&b, vstr_opo,
756 cis[i + 9]);
757 /* FALLTHROUGH */
758 case 9:
759 varbuf_append(&b,
760 vstr_pa0maxpwr,
761 cis[i + 8]);
762 /* FALLTHROUGH */
763 BCMDONGLECASE(8)
764 varbuf_append(&b,
765 vstr_pa0itssit,
766 cis[i + 7]);
767 /* FALLTHROUGH */
768 BCMDONGLECASE(7)
769 for (j = 0; j < 3; j++) {
770 varbuf_append(&b,
771 vstr_pa0b
772 [j],
773 (cis
774 [i +
775 (j *
776 2) +
777 2] << 8)
778 + cis[i +
779 (j *
780 2)
781 +
782 1]);
783 }
784 break;
785 default:
786 ASSERT((tlen == 2)
787 || (tlen == 9)
788 || (tlen == 10));
789 break;
790 }
791 break;
792
793 case HNBU_PAPARMS5G:
794 ASSERT((sromrev == 2)
795 || (sromrev == 3));
796 switch (tlen) {
797 case 23:
798 varbuf_append(&b,
799 vstr_pa1himaxpwr,
800 cis[i + 22]);
801 varbuf_append(&b,
802 vstr_pa1lomaxpwr,
803 cis[i + 21]);
804 varbuf_append(&b,
805 vstr_pa1maxpwr,
806 cis[i + 20]);
807 /* FALLTHROUGH */
808 case 20:
809 varbuf_append(&b,
810 vstr_pa1itssit,
811 cis[i + 19]);
812 /* FALLTHROUGH */
813 case 19:
814 for (j = 0; j < 3; j++) {
815 varbuf_append(&b,
816 vstr_pa1b
817 [j],
818 (cis
819 [i +
820 (j *
821 2) +
822 2] << 8)
823 + cis[i +
824 (j *
825 2)
826 +
827 1]);
828 }
829 for (j = 3; j < 6; j++) {
830 varbuf_append(&b,
831 vstr_pa1lob
832 [j - 3],
833 (cis
834 [i +
835 (j *
836 2) +
837 2] << 8)
838 + cis[i +
839 (j *
840 2)
841 +
842 1]);
843 }
844 for (j = 6; j < 9; j++) {
845 varbuf_append(&b,
846 vstr_pa1hib
847 [j - 6],
848 (cis
849 [i +
850 (j *
851 2) +
852 2] << 8)
853 + cis[i +
854 (j *
855 2)
856 +
857 1]);
858 }
859 break;
860 default:
861 ASSERT((tlen == 19) ||
862 (tlen == 20)
863 || (tlen == 23));
864 break;
865 }
866 break;
867
868 case HNBU_OEM:
869 ASSERT(sromrev == 1);
870 varbuf_append(&b, vstr_oem,
871 cis[i + 1], cis[i + 2],
872 cis[i + 3], cis[i + 4],
873 cis[i + 5], cis[i + 6],
874 cis[i + 7], cis[i + 8]);
875 break;
876
877 case HNBU_LEDS:
878 for (j = 1; j <= 4; j++) {
879 if (cis[i + j] != 0xff) {
880 varbuf_append(&b,
881 vstr_ledbh,
882 j - 1,
883 cis[i +
884 j]);
885 }
886 }
887 break;
888
889 case HNBU_CCODE:
890 ASSERT(sromrev > 1);
891 if ((cis[i + 1] == 0)
892 || (cis[i + 2] == 0))
893 varbuf_append(&b, vstr_noccode);
894 else
895 varbuf_append(&b, vstr_ccode,
896 cis[i + 1],
897 cis[i + 2]);
898 varbuf_append(&b, vstr_cctl,
899 cis[i + 3]);
900 break;
901
902 case HNBU_CCKPO:
903 ASSERT(sromrev > 2);
904 varbuf_append(&b, vstr_cckpo,
905 (cis[i + 2] << 8) | cis[i
906 +
907 1]);
908 break;
909
910 case HNBU_OFDMPO:
911 ASSERT(sromrev > 2);
912 varbuf_append(&b, vstr_ofdmpo,
913 (cis[i + 4] << 24) |
914 (cis[i + 3] << 16) |
915 (cis[i + 2] << 8) |
916 cis[i + 1]);
917 break;
918
919 case HNBU_WPS:
920 varbuf_append(&b, vstr_wpsgpio,
921 cis[i + 1]);
922 if (tlen >= 3)
923 varbuf_append(&b, vstr_wpsled,
924 cis[i + 2]);
925 break;
926
927 case HNBU_RSSISMBXA2G:
928 ASSERT(sromrev == 3);
929 varbuf_append(&b, vstr_rssismf2g,
930 cis[i + 1] & 0xf);
931 varbuf_append(&b, vstr_rssismc2g,
932 (cis[i + 1] >> 4) & 0xf);
933 varbuf_append(&b, vstr_rssisav2g,
934 cis[i + 2] & 0x7);
935 varbuf_append(&b, vstr_bxa2g,
936 (cis[i + 2] >> 3) & 0x3);
937 break;
938
939 case HNBU_RSSISMBXA5G:
940 ASSERT(sromrev == 3);
941 varbuf_append(&b, vstr_rssismf5g,
942 cis[i + 1] & 0xf);
943 varbuf_append(&b, vstr_rssismc5g,
944 (cis[i + 1] >> 4) & 0xf);
945 varbuf_append(&b, vstr_rssisav5g,
946 cis[i + 2] & 0x7);
947 varbuf_append(&b, vstr_bxa5g,
948 (cis[i + 2] >> 3) & 0x3);
949 break;
950
951 case HNBU_TRI2G:
952 ASSERT(sromrev == 3);
953 varbuf_append(&b, vstr_tri2g,
954 cis[i + 1]);
955 break;
956
957 case HNBU_TRI5G:
958 ASSERT(sromrev == 3);
959 varbuf_append(&b, vstr_tri5gl,
960 cis[i + 1]);
961 varbuf_append(&b, vstr_tri5g,
962 cis[i + 2]);
963 varbuf_append(&b, vstr_tri5gh,
964 cis[i + 3]);
965 break;
966
967 case HNBU_RXPO2G:
968 ASSERT(sromrev == 3);
969 varbuf_append(&b, vstr_rxpo2g,
970 cis[i + 1]);
971 break;
972
973 case HNBU_RXPO5G:
974 ASSERT(sromrev == 3);
975 varbuf_append(&b, vstr_rxpo5g,
976 cis[i + 1]);
977 break;
978
979 case HNBU_MACADDR:
980 if (!(ETHER_ISNULLADDR(&cis[i + 1])) &&
981 !(ETHER_ISMULTI(&cis[i + 1]))) {
982 bcm_ether_ntoa((struct
983 ether_addr *)
984 &cis[i + 1],
985 eabuf);
986
987 /* set boardnum if HNBU_BOARDNUM not seen yet */
988 if (boardnum == -1)
989 boardnum =
990 (cis[i + 5] << 8) +
991 cis[i + 6];
992 }
993 break;
994
995 case HNBU_LEDDC:
996 /* CIS leddc only has 16bits, convert it to 32bits */
997 w32 = ((cis[i + 2] << 24) | /* oncount */
998 (cis[i + 1] << 8)); /* offcount */
999 varbuf_append(&b, vstr_leddc, w32);
1000 break;
1001
1002 case HNBU_CHAINSWITCH:
1003 varbuf_append(&b, vstr_txchain,
1004 cis[i + 1]);
1005 varbuf_append(&b, vstr_rxchain,
1006 cis[i + 2]);
1007 varbuf_append(&b, vstr_antswitch,
1008 (cis[i + 4] << 8) +
1009 cis[i + 3]);
1010 break;
1011
1012 case HNBU_REGREV:
1013 varbuf_append(&b, vstr_regrev,
1014 cis[i + 1]);
1015 break;
1016
1017 case HNBU_FEM:{
1018 uint16 fem =
1019 (cis[i + 2] << 8) + cis[i +
1020 1];
1021 varbuf_append(&b,
1022 vstr_antswctl2g,
1023 (fem &
1024 SROM8_FEM_ANTSWLUT_MASK)
1025 >>
1026 SROM8_FEM_ANTSWLUT_SHIFT);
1027 varbuf_append(&b, vstr_triso2g,
1028 (fem &
1029 SROM8_FEM_TR_ISO_MASK)
1030 >>
1031 SROM8_FEM_TR_ISO_SHIFT);
1032 varbuf_append(&b,
1033 vstr_pdetrange2g,
1034 (fem &
1035 SROM8_FEM_PDET_RANGE_MASK)
1036 >>
1037 SROM8_FEM_PDET_RANGE_SHIFT);
1038 varbuf_append(&b,
1039 vstr_extpagain2g,
1040 (fem &
1041 SROM8_FEM_EXTPA_GAIN_MASK)
1042 >>
1043 SROM8_FEM_EXTPA_GAIN_SHIFT);
1044 varbuf_append(&b,
1045 vstr_tssipos2g,
1046 (fem &
1047 SROM8_FEM_TSSIPOS_MASK)
1048 >>
1049 SROM8_FEM_TSSIPOS_SHIFT);
1050 if (tlen < 5)
1051 break;
1052
1053 fem =
1054 (cis[i + 4] << 8) + cis[i +
1055 3];
1056 varbuf_append(&b,
1057 vstr_antswctl5g,
1058 (fem &
1059 SROM8_FEM_ANTSWLUT_MASK)
1060 >>
1061 SROM8_FEM_ANTSWLUT_SHIFT);
1062 varbuf_append(&b, vstr_triso5g,
1063 (fem &
1064 SROM8_FEM_TR_ISO_MASK)
1065 >>
1066 SROM8_FEM_TR_ISO_SHIFT);
1067 varbuf_append(&b,
1068 vstr_pdetrange5g,
1069 (fem &
1070 SROM8_FEM_PDET_RANGE_MASK)
1071 >>
1072 SROM8_FEM_PDET_RANGE_SHIFT);
1073 varbuf_append(&b,
1074 vstr_extpagain5g,
1075 (fem &
1076 SROM8_FEM_EXTPA_GAIN_MASK)
1077 >>
1078 SROM8_FEM_EXTPA_GAIN_SHIFT);
1079 varbuf_append(&b,
1080 vstr_tssipos5g,
1081 (fem &
1082 SROM8_FEM_TSSIPOS_MASK)
1083 >>
1084 SROM8_FEM_TSSIPOS_SHIFT);
1085 break;
1086 }
1087
1088 case HNBU_PAPARMS_C0:
1089 varbuf_append(&b, vstr_maxp2ga0,
1090 cis[i + 1]);
1091 varbuf_append(&b, vstr_itt2ga0,
1092 cis[i + 2]);
1093 varbuf_append(&b, vstr_pa, 2, 0, 0,
1094 (cis[i + 4] << 8) +
1095 cis[i + 3]);
1096 varbuf_append(&b, vstr_pa, 2, 1, 0,
1097 (cis[i + 6] << 8) +
1098 cis[i + 5]);
1099 varbuf_append(&b, vstr_pa, 2, 2, 0,
1100 (cis[i + 8] << 8) +
1101 cis[i + 7]);
1102 if (tlen < 31)
1103 break;
1104
1105 varbuf_append(&b, vstr_maxp5ga0,
1106 cis[i + 9]);
1107 varbuf_append(&b, vstr_itt5ga0,
1108 cis[i + 10]);
1109 varbuf_append(&b, vstr_maxp5gha0,
1110 cis[i + 11]);
1111 varbuf_append(&b, vstr_maxp5gla0,
1112 cis[i + 12]);
1113 varbuf_append(&b, vstr_pa, 5, 0, 0,
1114 (cis[i + 14] << 8) +
1115 cis[i + 13]);
1116 varbuf_append(&b, vstr_pa, 5, 1, 0,
1117 (cis[i + 16] << 8) +
1118 cis[i + 15]);
1119 varbuf_append(&b, vstr_pa, 5, 2, 0,
1120 (cis[i + 18] << 8) +
1121 cis[i + 17]);
1122 varbuf_append(&b, vstr_pahl, 5, 'l', 0,
1123 0,
1124 (cis[i + 20] << 8) +
1125 cis[i + 19]);
1126 varbuf_append(&b, vstr_pahl, 5, 'l', 1,
1127 0,
1128 (cis[i + 22] << 8) +
1129 cis[i + 21]);
1130 varbuf_append(&b, vstr_pahl, 5, 'l', 2,
1131 0,
1132 (cis[i + 24] << 8) +
1133 cis[i + 23]);
1134 varbuf_append(&b, vstr_pahl, 5, 'h', 0,
1135 0,
1136 (cis[i + 26] << 8) +
1137 cis[i + 25]);
1138 varbuf_append(&b, vstr_pahl, 5, 'h', 1,
1139 0,
1140 (cis[i + 28] << 8) +
1141 cis[i + 27]);
1142 varbuf_append(&b, vstr_pahl, 5, 'h', 2,
1143 0,
1144 (cis[i + 30] << 8) +
1145 cis[i + 29]);
1146 break;
1147
1148 case HNBU_PAPARMS_C1:
1149 varbuf_append(&b, vstr_maxp2ga1,
1150 cis[i + 1]);
1151 varbuf_append(&b, vstr_itt2ga1,
1152 cis[i + 2]);
1153 varbuf_append(&b, vstr_pa, 2, 0, 1,
1154 (cis[i + 4] << 8) +
1155 cis[i + 3]);
1156 varbuf_append(&b, vstr_pa, 2, 1, 1,
1157 (cis[i + 6] << 8) +
1158 cis[i + 5]);
1159 varbuf_append(&b, vstr_pa, 2, 2, 1,
1160 (cis[i + 8] << 8) +
1161 cis[i + 7]);
1162 if (tlen < 31)
1163 break;
1164
1165 varbuf_append(&b, vstr_maxp5ga1,
1166 cis[i + 9]);
1167 varbuf_append(&b, vstr_itt5ga1,
1168 cis[i + 10]);
1169 varbuf_append(&b, vstr_maxp5gha1,
1170 cis[i + 11]);
1171 varbuf_append(&b, vstr_maxp5gla1,
1172 cis[i + 12]);
1173 varbuf_append(&b, vstr_pa, 5, 0, 1,
1174 (cis[i + 14] << 8) +
1175 cis[i + 13]);
1176 varbuf_append(&b, vstr_pa, 5, 1, 1,
1177 (cis[i + 16] << 8) +
1178 cis[i + 15]);
1179 varbuf_append(&b, vstr_pa, 5, 2, 1,
1180 (cis[i + 18] << 8) +
1181 cis[i + 17]);
1182 varbuf_append(&b, vstr_pahl, 5, 'l', 0,
1183 1,
1184 (cis[i + 20] << 8) +
1185 cis[i + 19]);
1186 varbuf_append(&b, vstr_pahl, 5, 'l', 1,
1187 1,
1188 (cis[i + 22] << 8) +
1189 cis[i + 21]);
1190 varbuf_append(&b, vstr_pahl, 5, 'l', 2,
1191 1,
1192 (cis[i + 24] << 8) +
1193 cis[i + 23]);
1194 varbuf_append(&b, vstr_pahl, 5, 'h', 0,
1195 1,
1196 (cis[i + 26] << 8) +
1197 cis[i + 25]);
1198 varbuf_append(&b, vstr_pahl, 5, 'h', 1,
1199 1,
1200 (cis[i + 28] << 8) +
1201 cis[i + 27]);
1202 varbuf_append(&b, vstr_pahl, 5, 'h', 2,
1203 1,
1204 (cis[i + 30] << 8) +
1205 cis[i + 29]);
1206 break;
1207
1208 case HNBU_PO_CCKOFDM:
1209 varbuf_append(&b, vstr_cck2gpo,
1210 (cis[i + 2] << 8) +
1211 cis[i + 1]);
1212 varbuf_append(&b, vstr_ofdm2gpo,
1213 (cis[i + 6] << 24) +
1214 (cis[i + 5] << 16) +
1215 (cis[i + 4] << 8) +
1216 cis[i + 3]);
1217 if (tlen < 19)
1218 break;
1219
1220 varbuf_append(&b, vstr_ofdm5gpo,
1221 (cis[i + 10] << 24) +
1222 (cis[i + 9] << 16) +
1223 (cis[i + 8] << 8) +
1224 cis[i + 7]);
1225 varbuf_append(&b, vstr_ofdm5glpo,
1226 (cis[i + 14] << 24) +
1227 (cis[i + 13] << 16) +
1228 (cis[i + 12] << 8) +
1229 cis[i + 11]);
1230 varbuf_append(&b, vstr_ofdm5ghpo,
1231 (cis[i + 18] << 24) +
1232 (cis[i + 17] << 16) +
1233 (cis[i + 16] << 8) +
1234 cis[i + 15]);
1235 break;
1236
1237 case HNBU_PO_MCS2G:
1238 for (j = 0; j <= (tlen / 2); j++) {
1239 varbuf_append(&b, vstr_mcspo, 2,
1240 j,
1241 (cis
1242 [i + 2 +
1243 2 * j] << 8) +
1244 cis[i + 1 +
1245 2 * j]);
1246 }
1247 break;
1248
1249 case HNBU_PO_MCS5GM:
1250 for (j = 0; j <= (tlen / 2); j++) {
1251 varbuf_append(&b, vstr_mcspo, 5,
1252 j,
1253 (cis
1254 [i + 2 +
1255 2 * j] << 8) +
1256 cis[i + 1 +
1257 2 * j]);
1258 }
1259 break;
1260
1261 case HNBU_PO_MCS5GLH:
1262 for (j = 0; j <= (tlen / 4); j++) {
1263 varbuf_append(&b, vstr_mcspohl,
1264 5, 'l', j,
1265 (cis
1266 [i + 2 +
1267 2 * j] << 8) +
1268 cis[i + 1 +
1269 2 * j]);
1270 }
1271
1272 for (j = 0; j <= (tlen / 4); j++) {
1273 varbuf_append(&b, vstr_mcspohl,
1274 5, 'h', j,
1275 (cis
1276 [i +
1277 ((tlen / 2) +
1278 2) +
1279 2 * j] << 8) +
1280 cis[i +
1281 ((tlen / 2) +
1282 1) + 2 * j]);
1283 }
1284
1285 break;
1286
1287 case HNBU_PO_CDD:
1288 varbuf_append(&b, vstr_cddpo,
1289 (cis[i + 2] << 8) +
1290 cis[i + 1]);
1291 break;
1292
1293 case HNBU_PO_STBC:
1294 varbuf_append(&b, vstr_stbcpo,
1295 (cis[i + 2] << 8) +
1296 cis[i + 1]);
1297 break;
1298
1299 case HNBU_PO_40M:
1300 varbuf_append(&b, vstr_bw40po,
1301 (cis[i + 2] << 8) +
1302 cis[i + 1]);
1303 break;
1304
1305 case HNBU_PO_40MDUP:
1306 varbuf_append(&b, vstr_bwduppo,
1307 (cis[i + 2] << 8) +
1308 cis[i + 1]);
1309 break;
1310
1311 case HNBU_OFDMPO5G:
1312 varbuf_append(&b, vstr_ofdm5gpo,
1313 (cis[i + 4] << 24) +
1314 (cis[i + 3] << 16) +
1315 (cis[i + 2] << 8) +
1316 cis[i + 1]);
1317 varbuf_append(&b, vstr_ofdm5glpo,
1318 (cis[i + 8] << 24) +
1319 (cis[i + 7] << 16) +
1320 (cis[i + 6] << 8) +
1321 cis[i + 5]);
1322 varbuf_append(&b, vstr_ofdm5ghpo,
1323 (cis[i + 12] << 24) +
1324 (cis[i + 11] << 16) +
1325 (cis[i + 10] << 8) +
1326 cis[i + 9]);
1327 break;
1328
1329 case HNBU_CUSTOM1:
1330 varbuf_append(&b, vstr_custom, 1,
1331 ((cis[i + 4] << 24) +
1332 (cis[i + 3] << 16) +
1333 (cis[i + 2] << 8) +
1334 cis[i + 1]));
1335 break;
1336
1337#if defined(BCMSDIO)
1338 case HNBU_SROM3SWRGN:
1339 if (tlen >= 73) {
1340 uint16 srom[35];
1341 uint8 srev = cis[i + 1 + 70];
1342 ASSERT(srev == 3);
1343 /* make tuple value 16-bit aligned and parse it */
1344 bcopy(&cis[i + 1], srom,
1345 sizeof(srom));
1346 _initvars_srom_pci(srev, srom,
1347 SROM3_SWRGN_OFF,
1348 &b);
1349 /* 2.4G antenna gain is included in SROM */
1350 ag_init = TRUE;
1351 /* Ethernet MAC address is included in SROM */
1352 eabuf[0] = 0;
1353 boardnum = -1;
1354 }
1355 /* create extra variables */
1356 if (tlen >= 75)
1357 varbuf_append(&b, vstr_vendid,
1358 (cis[i + 1 + 73]
1359 << 8) + cis[i +
1360 1 +
1361 72]);
1362 if (tlen >= 77)
1363 varbuf_append(&b, vstr_devid,
1364 (cis[i + 1 + 75]
1365 << 8) + cis[i +
1366 1 +
1367 74]);
1368 if (tlen >= 79)
1369 varbuf_append(&b, vstr_xtalfreq,
1370 (cis[i + 1 + 77]
1371 << 8) + cis[i +
1372 1 +
1373 76]);
1374 break;
1375#endif /* defined(BCMSDIO) */
1376
1377 case HNBU_CCKFILTTYPE:
1378 varbuf_append(&b, vstr_cckdigfilttype,
1379 (cis[i + 1]));
1380 break;
1381 }
1382
1383 break;
1384 }
1385 i += tlen;
1386 } while (tup != CISTPL_END);
1387 }
1388
1389 if (boardnum != -1) {
1390 varbuf_append(&b, vstr_boardnum, boardnum);
1391 }
1392
1393 if (eabuf[0]) {
1394 varbuf_append(&b, vstr_macaddr, eabuf);
1395 }
1396
1397 /* if there is no antenna gain field, set default */
1398 if (getvar(NULL, "ag0") == NULL && ag_init == FALSE) {
1399 varbuf_append(&b, vstr_ag, 0, 0xff);
1400 }
1401
1402 /* final nullbyte terminator */
1403 ASSERT(b.size >= 1);
1404 *b.buf++ = '\0';
1405
1406 ASSERT(b.buf - base <= MAXSZ_NVRAM_VARS);
1407 err = initvars_table(osh, base, b.buf, vars, count);
1408
1409 MFREE(osh, base, MAXSZ_NVRAM_VARS);
1410 return err;
1411}
1412
1413/* In chips with chipcommon rev 32 and later, the srom is in chipcommon,
1414 * not in the bus cores.
1415 */
1416static uint16
7cc4a4c0 1417srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, uint32 cmd, uint wordoff,
a9533e7e
HP
1418 uint16 data)
1419{
1420 chipcregs_t *cc = (chipcregs_t *) ccregs;
1421 uint wait_cnt = 1000;
1422
1423 if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
1424 W_REG(osh, &cc->sromaddress, wordoff * 2);
1425 if (cmd == SRC_OP_WRITE)
1426 W_REG(osh, &cc->sromdata, data);
1427 }
1428
1429 W_REG(osh, &cc->sromcontrol, SRC_START | cmd);
1430
1431 while (wait_cnt--) {
1432 if ((R_REG(osh, &cc->sromcontrol) & SRC_BUSY) == 0)
1433 break;
1434 }
1435
1436 if (!wait_cnt) {
1437 BS_ERROR(("%s: Command 0x%x timed out\n", __func__, cmd));
1438 return 0xffff;
1439 }
1440 if (cmd == SRC_OP_READ)
1441 return (uint16) R_REG(osh, &cc->sromdata);
1442 else
1443 return 0xffff;
1444}
1445
1446/*
1447 * Read in and validate sprom.
1448 * Return 0 on success, nonzero on error.
1449 */
1450static int
7cc4a4c0
JC
1451sprom_read_pci(osl_t *osh, si_t *sih, uint16 *sprom, uint wordoff,
1452 uint16 *buf, uint nwords, bool check_crc)
a9533e7e
HP
1453{
1454 int err = 0;
1455 uint i;
1456 void *ccregs = NULL;
1457
1458 /* read the sprom */
1459 for (i = 0; i < nwords; i++) {
1460
1461 if (sih->ccrev > 31 && ISSIM_ENAB(sih)) {
1462 /* use indirect since direct is too slow on QT */
1463 if ((sih->cccaps & CC_CAP_SROM) == 0)
1464 return 1;
1465
1466 ccregs = (void *)((uint8 *) sprom - CC_SROM_OTP);
1467 buf[i] =
1468 srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ,
1469 wordoff + i, 0);
1470
1471 } else {
1472 if (ISSIM_ENAB(sih))
1473 buf[i] = R_REG(osh, &sprom[wordoff + i]);
1474
1475 buf[i] = R_REG(osh, &sprom[wordoff + i]);
1476 }
1477
1478 }
1479
1480 /* bypass crc checking for simulation to allow srom hack */
1481 if (ISSIM_ENAB(sih))
1482 return err;
1483
1484 if (check_crc) {
1485
1486 if (buf[0] == 0xffff) {
1487 /* The hardware thinks that an srom that starts with 0xffff
1488 * is blank, regardless of the rest of the content, so declare
1489 * it bad.
1490 */
1491 BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n",
1492 __func__, buf[0]));
1493 return 1;
1494 }
1495
1496 /* fixup the endianness so crc8 will pass */
1497 htol16_buf(buf, nwords * 2);
1498 if (hndcrc8((uint8 *) buf, nwords * 2, CRC8_INIT_VALUE) !=
1499 CRC8_GOOD_VALUE) {
1500 /* DBG only pci always read srom4 first, then srom8/9 */
1501 /* BS_ERROR(("%s: bad crc\n", __func__)); */
1502 err = 1;
1503 }
1504 /* now correct the endianness of the byte array */
1505 ltoh16_buf(buf, nwords * 2);
1506 }
1507 return err;
1508}
1509
1510#if defined(BCMNVRAMR)
7cc4a4c0 1511static int otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz)
a9533e7e
HP
1512{
1513 uint8 *otp;
1514 uint sz = OTP_SZ_MAX / 2; /* size in words */
1515 int err = 0;
1516
1517 ASSERT(bufsz <= OTP_SZ_MAX);
1518
ca8c1e59
JC
1519 otp = MALLOC(osh, OTP_SZ_MAX);
1520 if (otp == NULL) {
a9533e7e
HP
1521 return BCME_ERROR;
1522 }
1523
1524 bzero(otp, OTP_SZ_MAX);
1525
1526 err = otp_read_region(sih, OTP_HW_RGN, (uint16 *) otp, &sz);
1527
1528 bcopy(otp, buf, bufsz);
1529
1530 if (otp)
1531 MFREE(osh, otp, OTP_SZ_MAX);
1532
1533 /* Check CRC */
1534 if (buf[0] == 0xffff) {
1535 /* The hardware thinks that an srom that starts with 0xffff
1536 * is blank, regardless of the rest of the content, so declare
1537 * it bad.
1538 */
1539 BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __func__,
1540 buf[0]));
1541 return 1;
1542 }
1543
1544 /* fixup the endianness so crc8 will pass */
1545 htol16_buf(buf, bufsz);
1546 if (hndcrc8((uint8 *) buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) !=
1547 CRC8_GOOD_VALUE) {
1548 BS_ERROR(("%s: bad crc\n", __func__));
1549 err = 1;
1550 }
1551 /* now correct the endianness of the byte array */
1552 ltoh16_buf(buf, bufsz);
1553
1554 return err;
1555}
1556#endif /* defined(BCMNVRAMR) */
1557/*
1558* Create variable table from memory.
1559* Return 0 on success, nonzero on error.
1560*/
1561static int
7cc4a4c0
JC
1562BCMATTACHFN(initvars_table) (osl_t *osh, char *start, char *end, char **vars,
1563 uint *count) {
a9533e7e
HP
1564 int c = (int)(end - start);
1565
1566 /* do it only when there is more than just the null string */
1567 if (c > 1) {
1568 char *vp = MALLOC(osh, c);
1569 ASSERT(vp != NULL);
1570 if (!vp)
1571 return BCME_NOMEM;
1572 bcopy(start, vp, c);
1573 *vars = vp;
1574 *count = c;
1575 } else {
1576 *vars = NULL;
1577 *count = 0;
1578 }
1579
1580 return 0;
1581}
1582
1583/*
1584 * Find variables with <devpath> from flash. 'base' points to the beginning
1585 * of the table upon enter and to the end of the table upon exit when success.
1586 * Return 0 on success, nonzero on error.
1587 */
1588static int
a2627bc0
JC
1589BCMATTACHFN(initvars_flash) (si_t *sih, osl_t *osh, char **base, uint len)
1590{
a9533e7e
HP
1591 char *vp = *base;
1592 char *flash;
1593 int err;
1594 char *s;
1595 uint l, dl, copy_len;
1596 char devpath[SI_DEVPATH_BUFSZ];
1597
1598 /* allocate memory and read in flash */
ca8c1e59
JC
1599 flash = MALLOC(osh, NVRAM_SPACE);
1600 if (!flash)
a9533e7e 1601 return BCME_NOMEM;
ca8c1e59
JC
1602 err = nvram_getall(flash, NVRAM_SPACE);
1603 if (err)
a9533e7e
HP
1604 goto exit;
1605
1606 si_devpath(sih, devpath, sizeof(devpath));
1607
1608 /* grab vars with the <devpath> prefix in name */
1609 dl = strlen(devpath);
1610 for (s = flash; s && *s; s += l + 1) {
1611 l = strlen(s);
1612
1613 /* skip non-matching variable */
1614 if (strncmp(s, devpath, dl))
1615 continue;
1616
1617 /* is there enough room to copy? */
1618 copy_len = l - dl + 1;
1619 if (len < copy_len) {
1620 err = BCME_BUFTOOSHORT;
1621 goto exit;
1622 }
1623
1624 /* no prefix, just the name=value */
1625 strncpy(vp, &s[dl], copy_len);
1626 vp += copy_len;
1627 len -= copy_len;
1628 }
1629
1630 /* add null string as terminator */
1631 if (len < 1) {
1632 err = BCME_BUFTOOSHORT;
1633 goto exit;
1634 }
1635 *vp++ = '\0';
1636
1637 *base = vp;
1638
1639 exit: MFREE(osh, flash, NVRAM_SPACE);
1640 return err;
1641}
1642
1643/*
1644 * Initialize nonvolatile variable table from flash.
1645 * Return 0 on success, nonzero on error.
1646 */
1647static int
a2627bc0
JC
1648BCMATTACHFN(initvars_flash_si) (si_t *sih, char **vars, uint *count)
1649{
a9533e7e
HP
1650 osl_t *osh = si_osh(sih);
1651 char *vp, *base;
1652 int err;
1653
1654 ASSERT(vars != NULL);
1655 ASSERT(count != NULL);
1656
1657 base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS);
1658 ASSERT(vp != NULL);
1659 if (!vp)
1660 return BCME_NOMEM;
1661
ca8c1e59
JC
1662 err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS);
1663 if (err == 0)
a9533e7e
HP
1664 err = initvars_table(osh, base, vp, vars, count);
1665
1666 MFREE(osh, base, MAXSZ_NVRAM_VARS);
1667
1668 return err;
1669}
1670
1671/* Parse SROM and create name=value pairs. 'srom' points to
1672 * the SROM word array. 'off' specifies the offset of the
1673 * first word 'srom' points to, which should be either 0 or
1674 * SROM3_SWRG_OFF (full SROM or software region).
1675 */
1676
1677static uint mask_shift(uint16 mask)
1678{
1679 uint i;
1680 for (i = 0; i < (sizeof(mask) << 3); i++) {
1681 if (mask & (1 << i))
1682 return i;
1683 }
1684 ASSERT(mask);
1685 return 0;
1686}
1687
1688static uint mask_width(uint16 mask)
1689{
1690 int i;
1691 for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) {
1692 if (mask & (1 << i))
1693 return (uint) (i - mask_shift(mask) + 1);
1694 }
1695 ASSERT(mask);
1696 return 0;
1697}
1698
1699#if defined(BCMDBG)
1700static bool mask_valid(uint16 mask)
1701{
1702 uint shift = mask_shift(mask);
1703 uint width = mask_width(mask);
1704 return mask == ((~0 << shift) & ~(~0 << (shift + width)));
1705}
1706#endif /* BCMDBG */
1707
1708static void
7cc4a4c0
JC
1709BCMATTACHFN(_initvars_srom_pci) (uint8 sromrev, uint16 *srom, uint off,
1710 varbuf_t *b) {
a9533e7e
HP
1711 uint16 w;
1712 uint32 val;
1713 const sromvar_t *srv;
1714 uint width;
1715 uint flags;
1716 uint32 sr = (1 << sromrev);
1717
1718 varbuf_append(b, "sromrev=%d", sromrev);
1719
1720 for (srv = pci_sromvars; srv->name != NULL; srv++) {
1721 const char *name;
1722
1723 if ((srv->revmask & sr) == 0)
1724 continue;
1725
1726 if (srv->off < off)
1727 continue;
1728
1729 flags = srv->flags;
1730 name = srv->name;
1731
1732 /* This entry is for mfgc only. Don't generate param for it, */
1733 if (flags & SRFL_NOVAR)
1734 continue;
1735
1736 if (flags & SRFL_ETHADDR) {
1737 char eabuf[ETHER_ADDR_STR_LEN];
1738 struct ether_addr ea;
1739
1740 ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff;
1741 ea.octet[1] = srom[srv->off - off] & 0xff;
1742 ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
1743 ea.octet[3] = srom[srv->off + 1 - off] & 0xff;
1744 ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
1745 ea.octet[5] = srom[srv->off + 2 - off] & 0xff;
1746 bcm_ether_ntoa(&ea, eabuf);
1747
1748 varbuf_append(b, "%s=%s", name, eabuf);
1749 } else {
1750 ASSERT(mask_valid(srv->mask));
1751 ASSERT(mask_width(srv->mask));
1752
1753 w = srom[srv->off - off];
1754 val = (w & srv->mask) >> mask_shift(srv->mask);
1755 width = mask_width(srv->mask);
1756
1757 while (srv->flags & SRFL_MORE) {
1758 srv++;
1759 ASSERT(srv->name != NULL);
1760
1761 if (srv->off == 0 || srv->off < off)
1762 continue;
1763
1764 ASSERT(mask_valid(srv->mask));
1765 ASSERT(mask_width(srv->mask));
1766
1767 w = srom[srv->off - off];
1768 val +=
1769 ((w & srv->mask) >> mask_shift(srv->
1770 mask)) <<
1771 width;
1772 width += mask_width(srv->mask);
1773 }
1774
1775 if ((flags & SRFL_NOFFS)
1776 && ((int)val == (1 << width) - 1))
1777 continue;
1778
1779 if (flags & SRFL_CCODE) {
1780 if (val == 0)
1781 varbuf_append(b, "ccode=");
1782 else
1783 varbuf_append(b, "ccode=%c%c",
1784 (val >> 8), (val & 0xff));
1785 }
1786 /* LED Powersave duty cycle has to be scaled:
1787 *(oncount >> 24) (offcount >> 8)
1788 */
1789 else if (flags & SRFL_LEDDC) {
1790 uint32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */
1791 (((val & 0xff)) << 8); /* offcount */
1792 varbuf_append(b, "leddc=%d", w32);
1793 } else if (flags & SRFL_PRHEX)
1794 varbuf_append(b, "%s=0x%x", name, val);
1795 else if ((flags & SRFL_PRSIGN)
1796 && (val & (1 << (width - 1))))
1797 varbuf_append(b, "%s=%d", name,
1798 (int)(val | (~0 << width)));
1799 else
1800 varbuf_append(b, "%s=%u", name, val);
1801 }
1802 }
1803
1804 if (sromrev >= 4) {
1805 /* Do per-path variables */
1806 uint p, pb, psz;
1807
1808 if (sromrev >= 8) {
1809 pb = SROM8_PATH0;
1810 psz = SROM8_PATH1 - SROM8_PATH0;
1811 } else {
1812 pb = SROM4_PATH0;
1813 psz = SROM4_PATH1 - SROM4_PATH0;
1814 }
1815
1816 for (p = 0; p < MAX_PATH_SROM; p++) {
1817 for (srv = perpath_pci_sromvars; srv->name != NULL;
1818 srv++) {
1819 if ((srv->revmask & sr) == 0)
1820 continue;
1821
1822 if (pb + srv->off < off)
1823 continue;
1824
1825 /* This entry is for mfgc only. Don't generate param for it, */
1826 if (srv->flags & SRFL_NOVAR)
1827 continue;
1828
1829 w = srom[pb + srv->off - off];
1830
1831 ASSERT(mask_valid(srv->mask));
1832 val = (w & srv->mask) >> mask_shift(srv->mask);
1833 width = mask_width(srv->mask);
1834
1835 /* Cheating: no per-path var is more than 1 word */
1836
1837 if ((srv->flags & SRFL_NOFFS)
1838 && ((int)val == (1 << width) - 1))
1839 continue;
1840
1841 if (srv->flags & SRFL_PRHEX)
1842 varbuf_append(b, "%s%d=0x%x", srv->name,
1843 p, val);
1844 else
1845 varbuf_append(b, "%s%d=%d", srv->name,
1846 p, val);
1847 }
1848 pb += psz;
1849 }
1850 }
1851}
1852
1853/*
1854 * Initialize nonvolatile variable table from sprom.
1855 * Return 0 on success, nonzero on error.
1856 */
1857static int
7cc4a4c0
JC
1858BCMATTACHFN(initvars_srom_pci) (si_t *sih, void *curmap, char **vars,
1859 uint *count) {
a9533e7e
HP
1860 uint16 *srom, *sromwindow;
1861 uint8 sromrev = 0;
1862 uint32 sr;
1863 varbuf_t b;
1864 char *vp, *base = NULL;
1865 osl_t *osh = si_osh(sih);
1866 bool flash = FALSE;
1867 int err = 0;
1868
1869 /*
1870 * Apply CRC over SROM content regardless SROM is present or not,
1871 * and use variable <devpath>sromrev's existance in flash to decide
1872 * if we should return an error when CRC fails or read SROM variables
1873 * from flash.
1874 */
1875 srom = MALLOC(osh, SROM_MAX);
1876 ASSERT(srom != NULL);
1877 if (!srom)
1878 return -2;
1879
1880 sromwindow = (uint16 *) SROM_OFFSET(sih);
1881 if (si_is_sprom_available(sih)) {
1882 err =
1883 sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM_WORDS,
1884 TRUE);
1885
1886 if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
1887 (((sih->buscoretype == PCIE_CORE_ID)
1888 && (sih->buscorerev >= 6))
1889 || ((sih->buscoretype == PCI_CORE_ID)
1890 && (sih->buscorerev >= 0xe)))) {
1891 /* sromrev >= 4, read more */
1892 err =
1893 sprom_read_pci(osh, sih, sromwindow, 0, srom,
1894 SROM4_WORDS, TRUE);
1895 sromrev = srom[SROM4_CRCREV] & 0xff;
1896 if (err)
1897 BS_ERROR(("%s: srom %d, bad crc\n", __func__,
1898 sromrev));
1899
1900 } else if (err == 0) {
1901 /* srom is good and is rev < 4 */
1902 /* top word of sprom contains version and crc8 */
1903 sromrev = srom[SROM_CRCREV] & 0xff;
1904 /* bcm4401 sroms misprogrammed */
1905 if (sromrev == 0x10)
1906 sromrev = 1;
1907 }
1908 }
1909#if defined(BCMNVRAMR)
1910 /* Use OTP if SPROM not available */
1911 else if ((err = otp_read_pci(osh, sih, srom, SROM_MAX)) == 0) {
1912 /* OTP only contain SROM rev8/rev9 for now */
1913 sromrev = srom[SROM4_CRCREV] & 0xff;
1914 }
1915#endif
1916 else {
1917 err = 1;
1918 BS_ERROR(("Neither SPROM nor OTP has valid image\n"));
1919 }
1920
1921 /* We want internal/wltest driver to come up with default sromvars so we can
1922 * program a blank SPROM/OTP.
1923 */
1924 if (err) {
1925 char *value;
1926 uint32 val;
1927 val = 0;
1928
ca8c1e59
JC
1929 value = si_getdevpathvar(sih, "sromrev");
1930 if (value) {
a9533e7e
HP
1931 sromrev = (uint8) bcm_strtoul(value, NULL, 0);
1932 flash = TRUE;
1933 goto varscont;
1934 }
1935
1936 BS_ERROR(("%s, SROM CRC Error\n", __func__));
1937
ca8c1e59
JC
1938 value = si_getnvramflvar(sih, "sromrev");
1939 if (value) {
a9533e7e
HP
1940 err = 0;
1941 goto errout;
1942 }
1943
1944 {
1945 err = -1;
1946 goto errout;
1947 }
1948 }
1949
1950 varscont:
1951 /* Bitmask for the sromrev */
1952 sr = 1 << sromrev;
1953
1954 /* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, 9 */
1955 if ((sr & 0x33e) == 0) {
1956 err = -2;
1957 goto errout;
1958 }
1959
1960 ASSERT(vars != NULL);
1961 ASSERT(count != NULL);
1962
1963 base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS);
1964 ASSERT(vp != NULL);
1965 if (!vp) {
1966 err = -2;
1967 goto errout;
1968 }
1969
1970 /* read variables from flash */
1971 if (flash) {
ca8c1e59
JC
1972 err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS);
1973 if (err)
a9533e7e
HP
1974 goto errout;
1975 goto varsdone;
1976 }
1977
1978 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
1979
1980 /* parse SROM into name=value pairs. */
1981 _initvars_srom_pci(sromrev, srom, 0, &b);
1982
1983 /* final nullbyte terminator */
1984 ASSERT(b.size >= 1);
1985 vp = b.buf;
1986 *vp++ = '\0';
1987
1988 ASSERT((vp - base) <= MAXSZ_NVRAM_VARS);
1989
1990 varsdone:
1991 err = initvars_table(osh, base, vp, vars, count);
1992
1993 errout:
1994 if (base)
1995 MFREE(osh, base, MAXSZ_NVRAM_VARS);
1996
1997 MFREE(osh, srom, SROM_MAX);
1998 return err;
1999}
2000
2001#ifdef BCMSDIO
2002/*
2003 * Read the SDIO cis and call parsecis to initialize the vars.
2004 * Return 0 on success, nonzero on error.
2005 */
2006static int
a2627bc0
JC
2007BCMATTACHFN(initvars_cis_sdio) (osl_t *osh, char **vars, uint *count)
2008{
a9533e7e
HP
2009 uint8 *cis[SBSDIO_NUM_FUNCTION + 1];
2010 uint fn, numfn;
2011 int rc = 0;
2012
2013 numfn = bcmsdh_query_iofnum(NULL);
2014 ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
2015
2016 for (fn = 0; fn <= numfn; fn++) {
ca8c1e59
JC
2017 cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT)
2018 if (cis[fn] == NULL) {
a9533e7e
HP
2019 rc = -1;
2020 break;
2021 }
2022
2023 bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT);
2024
2025 if (bcmsdh_cis_read(NULL, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT) !=
2026 0) {
2027 MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
2028 rc = -2;
2029 break;
2030 }
2031 }
2032
2033 if (!rc)
2034 rc = srom_parsecis(osh, cis, fn, vars, count);
2035
2036 while (fn-- > 0)
2037 MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
2038
90ea2296 2039 return rc;
a9533e7e
HP
2040}
2041
2042/* set SDIO sprom command register */
a2627bc0
JC
2043static int BCMATTACHFN(sprom_cmd_sdio) (osl_t *osh, uint8 cmd)
2044{
a9533e7e
HP
2045 uint8 status = 0;
2046 uint wait_cnt = 1000;
2047
2048 /* write sprom command register */
2049 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, cmd, NULL);
2050
2051 /* wait status */
2052 while (wait_cnt--) {
2053 status =
2054 bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, NULL);
2055 if (status & SBSDIO_SPROM_DONE)
2056 return 0;
2057 }
2058
2059 return 1;
2060}
2061
2062/* read a word from the SDIO srom */
7cc4a4c0 2063static int sprom_read_sdio(osl_t *osh, uint16 addr, uint16 *data)
a9533e7e
HP
2064{
2065 uint8 addr_l, addr_h, data_l, data_h;
2066
2067 addr_l = (uint8) ((addr * 2) & 0xff);
2068 addr_h = (uint8) (((addr * 2) >> 8) & 0xff);
2069
2070 /* set address */
2071 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_HIGH, addr_h,
2072 NULL);
2073 bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_LOW, addr_l,
2074 NULL);
2075
2076 /* do read */
2077 if (sprom_cmd_sdio(osh, SBSDIO_SPROM_READ))
2078 return 1;
2079
2080 /* read data */
2081 data_h =
2082 bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_HIGH, NULL);
2083 data_l =
2084 bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_LOW, NULL);
2085
2086 *data = (data_h << 8) | data_l;
2087 return 0;
2088}
2089#endif /* BCMSDIO */
2090
2091static int
7cc4a4c0
JC
2092BCMATTACHFN(initvars_srom_si) (si_t *sih, osl_t *osh, void *curmap,
2093 char **vars, uint *varsz) {
a9533e7e
HP
2094 /* Search flash nvram section for srom variables */
2095 return initvars_flash_si(sih, vars, varsz);
2096}
This page took 0.123728 seconds and 5 git commands to generate.