allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / shared / bcmsrom.c
blob47112de59dcb277c08cdc4227d8a88b302954058
1 /*
2 * Routines to access SPROM and to parse SROM/CIS variables.
4 * Copyright (C) 2011, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: bcmsrom.c 323253 2012-03-23 17:21:10Z $
21 #include <bcm_cfg.h>
22 #include <typedefs.h>
23 #include <bcmdefs.h>
24 #include <osl.h>
25 #if defined(__FreeBSD__) || defined(__NetBSD__)
26 #include <machine/stdarg.h>
27 #else
28 #include <stdarg.h>
29 #endif
30 #include <bcmutils.h>
31 #include <hndsoc.h>
32 #include <sbchipc.h>
33 #include <bcmdevs.h>
34 #include <bcmendian.h>
35 #include <sbpcmcia.h>
36 #include <pcicfg.h>
37 #include <siutils.h>
38 #include <bcmsrom.h>
39 #include <bcmsrom_tbl.h>
40 #ifdef BCMSPI
41 #include <spid.h>
42 #endif
44 #include <bcmnvram.h>
45 #include <bcmotp.h>
47 #if defined(BCMUSBDEV)
48 #include <sbsdio.h>
49 #include <sbhnddma.h>
50 #include <sbsdpcmdev.h>
51 #endif
53 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
54 #include <sbsprom.h>
55 #endif
56 #include <proto/ethernet.h> /* for sprom content groking */
59 #if defined(BCMDBG_ERR) || defined(WLTEST)
60 #define BS_ERROR(args) printf args
61 #else
62 #define BS_ERROR(args)
63 #endif
65 #define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \
66 (((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \
67 ((uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \
68 ((uint8 *)curmap + PCI_BAR0_SPROM_OFFSET))
70 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
71 #define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
72 #define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
73 #endif
75 typedef struct varbuf {
76 char *base; /* pointer to buffer base */
77 char *buf; /* pointer to current position */
78 unsigned int size; /* current (residual) size in bytes */
79 } varbuf_t;
80 extern char *_vars;
81 extern uint _varsz;
83 #define SROM_CIS_SINGLE 1
86 static int initvars_srom_si(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *count);
87 static void _initvars_srom_pci(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b);
88 static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count);
89 static int initvars_cis_pcmcia(si_t *sih, osl_t *osh, char **vars, uint *count);
90 #if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED)
91 static int initvars_flash_si(si_t *sih, char **vars, uint *count);
92 #endif
93 #ifdef BCMSPI
94 static int initvars_cis_spi(osl_t *osh, char **vars, uint *count);
95 #endif /* BCMSPI */
96 static int sprom_cmd_pcmcia(osl_t *osh, uint8 cmd);
97 static int sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data);
98 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
99 static int sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data);
100 #endif
101 static int sprom_read_pci(osl_t *osh, si_t *sih, uint16 *sprom, uint wordoff, uint16 *buf,
102 uint nwords, bool check_crc);
103 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
104 static int otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz);
105 #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */
106 static uint16 srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, uint32 cmd, uint wordoff,
107 uint16 data);
109 static int initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count);
110 static int initvars_flash(si_t *sih, osl_t *osh, char **vp, uint len);
112 #if defined(BCMUSBDEV)
113 static int get_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs,
114 uint boff, uint16 *srom, uint bsz, bool check_crc);
115 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
116 static int set_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs,
117 uint boff, uint16 *srom, uint bsz);
118 #endif
119 #endif
121 #if defined(BCMUSBDEV)
122 #if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND)
123 /* default to bcm94323 P200, other boards should have OTP programmed */
124 static char BCMATTACHDATA(defaultsromvars_4322usb)[] =
125 "vendid=0x14e4\0"
126 "subvendid=0x0a5c\0"
127 "subdevid=0xbdc\0"
128 "macaddr=00:90:4c:d3:04:73\0"
129 "sromrev=8\0"
130 "devid=0x432b\0"
131 "boardrev=0x1200\0"
132 "boardflags=0xa00\0"
133 "boardflags2=0x602\0"
134 "boardtype=0x04a8\0"
135 "tssipos2g=0x1\0"
136 "extpagain2g=0x0\0"
137 "pdetrange2g=0x0\0"
138 "triso2g=0x3\0"
139 "antswctl2g=0x2\0"
140 "tssipos5g=0x1\0"
141 "extpagain5g=0x0\0"
142 "pdetrange5g=0x0\0"
143 "triso5g=0x3\0"
144 "antswctl5g=0x2\0"
145 "maxp2ga0=0x48\0"
146 "itt2ga0=0x20\0"
147 "pa2gw0a0=0xFEA8\0"
148 "pa2gw1a0=0x16CD\0"
149 "pa2gw2a0=0xFAA5\0"
150 "maxp5ga0=0x40\0"
151 "itt5ga0=0x3e\0"
152 "maxp5gha0=0x3c\0"
153 "maxp5gla0=0x40\0"
154 "pa5gw0a0=0xFEB2\0"
155 "pa5gw1a0=0x1471\0"
156 "pa5gw2a0=0xFB1F\0"
157 "pa5glw0a0=0xFEA2\0"
158 "pa5glw1a0=0x149A\0"
159 "pa5glw2a0=0xFAFC\0"
160 "pa5ghw0a0=0xFEC6\0"
161 "pa5ghw1a0=0x13DD\0"
162 "pa5ghw2a0=0xFB48\0"
163 "maxp2ga1=0x48\0"
164 "itt2ga1=0x20\0"
165 "pa2gw0a1=0xFEA3\0"
166 "pa2gw1a1=0x1687\0"
167 "pa2gw2a1=0xFAAA\0"
168 "maxp5ga1=0x40\0"
169 "itt5ga1=0x3e\0"
170 "maxp5gha1=0x3c\0"
171 "maxp5gla1=0x40\0"
172 "pa5gw0a1=0xFEBC\0"
173 "pa5gw1a1=0x14F9\0"
174 "pa5gw2a1=0xFB05\0"
175 "pa5glw0a1=0xFEBE\0"
176 "pa5glw1a1=0x1478\0"
177 "pa5glw2a1=0xFB1A\0"
178 "pa5ghw0a1=0xFEE1\0"
179 "pa5ghw1a1=0x14FD\0"
180 "pa5ghw2a1=0xFB38\0"
181 "cctl=0\0"
182 "ccode=US\0"
183 "regrev=0x0\0"
184 "ledbh0=0xff\0"
185 "ledbh1=0x2\0"
186 "ledbh2=0x3\0"
187 "ledbh3=0xff\0"
188 "leddc=0xa0a0\0"
189 "aa2g=0x3\0"
190 "aa5g=0x3\0"
191 "ag0=0x2\0"
192 "ag1=0x2\0"
193 "ag2=0xff\0"
194 "ag3=0xff\0"
195 "txchain=0x3\0"
196 "rxchain=0x3\0"
197 "antswitch=0\0"
198 "END\0";
200 static char BCMATTACHDATA(defaultsromvars_43234usb)[] =
201 "vendid=0x14e4\0"
202 "subvendid=0x0a5c\0"
203 "subdevid=0xbdc\0"
204 "macaddr=00:90:4c:03:21:23\0"
205 "cctl=0\0"
206 "ccode=US\0"
207 "regrev=0x0\0"
208 "ledbh0=0x82\0"
209 "ledbh1=0xff\0"
210 "ledbh2=0xff\0"
211 "ledbh3=0xff\0"
212 "leddc=0x0\0"
213 "aa2g=0x2\0"
214 "aa5g=0x2\0"
215 "ag0=0x2\0"
216 "ag1=0x2\0"
217 "ag2=0x2\0"
218 "ag3=0xff\0"
219 "txchain=0x2\0"
220 "rxchain=0x2\0"
221 "antswitch=0\0"
222 "sromrev=8\0"
223 "devid=0x4346\0"
224 "boardrev=0x1403\0"
225 "boardflags=0x200\0"
226 "boardflags2=0x2000\0"
227 "boardtype=0x0521\0"
228 "tssipos2g=0x1\0"
229 "extpagain2g=0x2\0"
230 "pdetrange2g=0x2\0"
231 "triso2g=0x3\0"
232 "antswctl2g=0x0\0"
233 "tssipos5g=0x1\0"
234 "extpagain5g=0x2\0"
235 "pdetrange5g=0x2\0"
236 "triso5g=0x3\0"
237 "antswctl5g=0x0\0"
238 "ofdm2gpo=0x0\0"
239 "ofdm5gpo=0x0\0"
240 "ofdm5glpo=0x0\0"
241 "ofdm5ghpo=0x0\0"
242 "mcs2gpo0=0x0\0"
243 "mcs2gpo1=0x0\0"
244 "mcs2gpo2=0x0\0"
245 "mcs2gpo3=0x0\0"
246 "mcs2gpo4=0x4444\0"
247 "mcs2gpo5=0x4444\0"
248 "mcs2gpo6=0x4444\0"
249 "mcs2gpo7=0x4444\0"
250 "mcs5gpo4=0x2222\0"
251 "mcs5gpo5=0x2222\0"
252 "mcs5gpo6=0x2222\0"
253 "mcs5gpo7=0x2222\0"
254 "mcs5glpo4=0x2222\0"
255 "mcs5glpo5=0x2222\0"
256 "mcs5glpo6=0x2222\0"
257 "mcs5glpo7=0x2222\0"
258 "mcs5ghpo4=0x2222\0"
259 "mcs5ghpo5=0x2222\0"
260 "mcs5ghpo6=0x2222\0"
261 "mcs5ghpo7=0x2222\0"
262 "maxp2ga0=0x42\0"
263 "itt2ga0=0x20\0"
264 "itt5ga0=0x3e\0"
265 "pa2gw0a0=0xFF21\0"
266 "pa2gw1a0=0x13B7\0"
267 "pa2gw2a0=0xFB44\0"
268 "maxp5ga0=0x3E\0"
269 "maxp5gha0=0x3a\0"
270 "maxp5gla0=0x3c\0"
271 "pa5gw0a0=0xFEB2\0"
272 "pa5gw1a0=0x1570\0"
273 "pa5gw2a0=0xFAD6\0"
274 "pa5glw0a0=0xFE64\0"
275 "pa5glw1a0=0x13F7\0"
276 "pa5glw2a0=0xFAF6\0"
277 "pa5ghw0a0=0xFEAB\0"
278 "pa5ghw1a0=0x15BB\0"
279 "pa5ghw2a0=0xFAC6\0"
280 "maxp2ga1=0x42\0"
281 "itt2ga1=0x20\0"
282 "itt5ga1=0x3e\0"
283 "pa2gw0a1=0xFF17\0"
284 "pa2gw1a1=0x13C4\0"
285 "pa2gw2a1=0xFB3C\0"
286 "maxp5ga1=0x3E\0"
287 "maxp5gha1=0x3a\0"
288 "maxp5gla1=0x3c\0"
289 "pa5gw0a1=0xFE6F\0"
290 "pa5gw1a1=0x13CC\0"
291 "pa5gw2a1=0xFAF8\0"
292 "pa5glw0a1=0xFE87\0"
293 "pa5glw1a1=0x14BE\0"
294 "pa5glw2a1=0xFAD6\0"
295 "pa5ghw0a1=0xFE68\0"
296 "pa5ghw1a1=0x13E9\0"
297 "pa5ghw2a1=0xFAF6\0"
298 "END\0";
300 static char BCMATTACHDATA(defaultsromvars_43235usb)[] =
301 "vendid=0x14e4\0"
302 "subvendid=0x0a5c\0"
303 "subdevid=0xbdc\0"
304 "macaddr=00:90:4c:05:30:01\0"
305 "ccode=US\0"
306 "regrev=0x0\0"
307 "ledbh0=0x82\0"
308 "ledbh1=0xff\0"
309 "ledbh2=0xff\0"
310 "ledbh3=0xff\0"
311 "leddc=0x0\0"
312 "aa2g=0x3\0"
313 "ag0=0x2\0"
314 "ag1=0x2\0"
315 "ag2=0xff\0"
316 "ag3=0xff\0"
317 "txchain=0x3\0"
318 "rxchain=0x3\0"
319 "antswitch=0\0"
320 "sromrev=8\0"
321 "devid=0x4347\0"
322 "boardrev=0x1113\0"
323 "boardflags=0x200\0"
324 "boardflags2=0x0\0"
325 "boardtype=0x0571\0"
326 "tssipos2g=0x1\0"
327 "extpagain2g=0x2\0"
328 "pdetrange2g=0x2\0"
329 "triso2g=0x3\0"
330 "antswctl2g=0x0\0"
331 "antswctl5g=0x0\0"
332 "ofdm2gpo=0x0\0"
333 "mcs2gpo0=0x0\0"
334 "mcs2gpo1=0x0\0"
335 "mcs2gpo2=0x0\0"
336 "mcs2gpo3=0x0\0"
337 "mcs2gpo4=0x2222\0"
338 "mcs2gpo5=0x2222\0"
339 "mcs2gpo6=0x2222\0"
340 "mcs2gpo7=0x4444\0"
341 "maxp2ga0=0x42\0"
342 "itt2ga0=0x20\0"
343 "pa2gw0a0=0xFF00\0"
344 "pa2gw1a0=0x143C\0"
345 "pa2gw2a0=0xFB27\0"
346 "maxp2ga1=0x42\0"
347 "itt2ga1=0x20\0"
348 "pa2gw0a1=0xFF22\0"
349 "pa2gw1a1=0x142E\0"
350 "pa2gw2a1=0xFB45\0"
351 "tempthresh=120\0"
352 "temps_period=5\0"
353 "temp_hysteresis=5\0"
354 "END\0";
356 static char BCMATTACHDATA(defaultsromvars_43236usb)[] =
357 "vendid=0x14e4\0"
358 "subvendid=0x0a5c\0"
359 "subdevid=0xbdc\0"
360 "macaddr=00:90:4c:03:21:23\0"
361 "cctl=0\0"
362 "ccode=US\0"
363 "regrev=0x0\0"
364 "ledbh0=0x82\0"
365 "ledbh1=0xff\0"
366 "ledbh2=0xff\0"
367 "ledbh3=0xff\0"
368 "leddc=0x0\0"
369 "aa2g=0x3\0"
370 "aa5g=0x3\0"
371 "ag0=0x2\0"
372 "ag1=0x2\0"
373 "ag2=0x2\0"
374 "ag3=0xff\0"
375 "txchain=0x3\0"
376 "rxchain=0x3\0"
377 "antswitch=0\0"
378 "sromrev=8\0"
379 "devid=0x4346\0"
380 "boardrev=0x1532\0"
381 "boardflags=0x200\0"
382 "boardflags2=0x2000\0"
383 "boardtype=0x0521\0"
384 "tssipos2g=0x1\0"
385 "extpagain2g=0x2\0"
386 "pdetrange2g=0x2\0"
387 "triso2g=0x3\0"
388 "antswctl2g=0x0\0"
389 "tssipos5g=0x1\0"
390 "extpagain5g=0x2\0"
391 "pdetrange5g=0x2\0"
392 "triso5g=0x3\0"
393 "antswctl5g=0x0\0"
394 "ofdm2gpo=0x33333333\0"
395 "ofdm5gpo=0x0\0"
396 "ofdm5glpo=0x0\0"
397 "ofdm5ghpo=0x0\0"
398 "mcs2gpo0=0x3333\0"
399 "mcs2gpo1=0x3333\0"
400 "mcs2gpo2=0x3333\0"
401 "mcs2gpo3=0x3333\0"
402 "mcs2gpo4=0x5555\0"
403 "mcs2gpo5=0x5555\0"
404 "mcs2gpo6=0x5555\0"
405 "mcs2gpo7=0x5555\0"
406 "mcs5gpo4=0x2222\0"
407 "mcs5gpo5=0x2222\0"
408 "mcs5gpo6=0x2222\0"
409 "mcs5gpo7=0x2222\0"
410 "mcs5glpo4=0x2222\0"
411 "mcs5glpo5=0x2222\0"
412 "mcs5glpo6=0x2222\0"
413 "mcs5glpo7=0x2222\0"
414 "mcs5ghpo4=0x2222\0"
415 "mcs5ghpo5=0x2222\0"
416 "mcs5ghpo6=0x2222\0"
417 "mcs5ghpo7=0x2222\0"
418 "maxp2ga0=0x48\0"
419 "itt2ga0=0x20\0"
420 "itt5ga0=0x3e\0"
421 "pa2gw0a0=0xFFD8\0"
422 "pa2gw1a0=0x171C\0"
423 "pa2gw2a0=0xFB14\0"
424 "maxp5ga0=0x3e\0"
425 "maxp5gha0=0x3a\0"
426 "maxp5gla0=0x3c\0"
427 "pa5gw0a0=0xFE88\0"
428 "pa5gw1a0=0x141C\0"
429 "pa5gw2a0=0xFB17\0"
430 "pa5glw0a0=0xFE8C\0"
431 "pa5glw1a0=0x1493\0"
432 "pa5glw2a0=0xFAFC\0"
433 "pa5ghw0a0=0xFE86\0"
434 "pa5ghw1a0=0x13CC\0"
435 "pa5ghw2a0=0xFB20\0"
436 "maxp2ga1=0x48\0"
437 "itt2ga1=0x20\0"
438 "itt5ga1=0x3e\0"
439 "pa2gw0a1=0x0020\0"
440 "pa2gw1a1=0x1791\0"
441 "pa2gw2a1=0xFB5F\0"
442 "maxp5ga1=0x3e\0"
443 "maxp5gha1=0x3a\0"
444 "maxp5gla1=0x3c\0"
445 "pa5gw0a1=0xFE7E\0"
446 "pa5gw1a1=0x1399\0"
447 "pa5gw2a1=0xFB27\0"
448 "pa5glw0a1=0xFE82\0"
449 "pa5glw1a1=0x13F3\0"
450 "pa5glw2a1=0xFB14\0"
451 "pa5ghw0a1=0xFE96\0"
452 "pa5ghw1a1=0x13BF\0"
453 "pa5ghw2a1=0xFB30\0"
454 "tempthresh=120\0"
455 "temps_period=5\0"
456 "temp_hysteresis=5\0"
457 "END\0";
459 static char BCMATTACHDATA(defaultsromvars_4319usb)[] =
460 "sromrev=3\0"
461 "vendid=0x14e4\0"
462 "devid=0x4338\0"
463 "boardtype=0x4e7\0"
464 "boardrev=0x1508\0"
465 "boardflags=0x200\0"
466 "xtalfreq=30000\0"
467 "aa2g=3\0"
468 "aa5g=0\0"
469 "ag0=255\0"
470 "opo=0\0"
471 "pa0b0=5756\0"
472 "pa0b1=64121\0"
473 "pa0b2=65153\0"
474 "pa0itssit=62\0"
475 "pa0maxpwr=76\0"
476 "rssismf2g=0xa\0"
477 "rssismc2g=0xb\0"
478 "rssisav2g=0x3\0"
479 "bxa2g=0\0"
480 "tri2g=78\0"
481 "cckdigfilttype=6\0"
482 "rxpo2g=2\0"
483 "cckpo=0\0"
484 "ofdmpo=0x44441111\0"
485 "mcs2gpo0=0xaaaa\0"
486 "mcs2gpo1=0xaaaa\0"
487 "boardnum=1\0"
488 "macaddr=00:90:4c:16:${maclo}\0"
489 "otpimagesize=182\0"
490 "END\0";
492 static char BCMATTACHDATA(defaultsromvars_4360usb)[] =
493 "sromrev=11\0"
494 "boardtype=0x623\0"
495 "venid=0x14e4\0"
496 "boardvendor=0x14e4\0"
497 "devid=0x43a0\0"
498 "boardrev=0x1101\0"
499 "boardflags=0x10001000\0"
500 "boardflags2=0x0\0"
501 "boardflags3=0x0\0"
502 "macaddr=00:90:4c:0e:60:01\0"
503 "ccode=0\0"
504 "regrev=0\0"
505 "aa2g=0x3\0"
506 "aa5g=0x3\0"
507 "agbg0=0x2\0"
508 "agbg1=0x2\0"
509 "agbg2=0xff\0"
510 "aga0=0x2\0"
511 "aga1=0x2\0"
512 "aga2=0xff\0"
513 "txchain=0x3\0"
514 "rxchain=0x3\0"
515 "antswitch=0\0"
516 "tssiposslope2g=1\0"
517 "epagain2g=0\0"
518 "pdgain2g=2\0"
519 "tworangetssi2g=0\0"
520 "papdcap2g=0\0"
521 "femctrl=1\0"
522 "tssiposslope5g=1\0"
523 "epagain5g=0\0"
524 "pdgain5g=2\0"
525 "tworangetssi5g=0\0"
526 "papdcap5g=0\0"
527 "gainctrlsph=0\0"
528 "tempthresh=0xff\0"
529 "tempoffset=0xff\0"
530 "rawtempsense=0x1ff\0"
531 "measpower=0x7f\0"
532 "tempsense_slope=0xff\0"
533 "tempcorrx=0x3f\0"
534 "tempsense_option=0x3\0"
535 "phycal_tempdelta=255\0"
536 "temps_period=15\0"
537 "temps_hysteresis=15\0"
538 "measpower1=0x7f\0"
539 "subband5gver=0x4\0"
540 "pcieingress_war=15\0"
541 "sar2g=18\0"
542 "sar5g=15\0"
543 "noiselvl2ga0=31\0"
544 "noiselvl2ga1=31\0"
545 "noiselvl2ga2=31\0"
546 "noiselvl5gla0=31\0"
547 "noiselvl5gla1=31\0"
548 "noiselvl5gla2=31\0"
549 "noiselvl5gma0=31\0"
550 "noiselvl5gma1=31\0"
551 "noiselvl5gma2=31\0"
552 "noiselvl5gha0=31\0"
553 "noiselvl5gha1=31\0"
554 "noiselvl5gha2=31\0"
555 "noiselvl5gua0=31\0"
556 "noiselvl5gua1=31\0"
557 "noiselvl5gua2=31\0"
558 "rxgainerr2g=0xffff\0"
559 "rxgainerr5g=0xffff,0xffff,0xffff,0xffff\0"
560 "maxp2ga0=76\0"
561 "pa2ga0=0xfe72,0x14c0,0xfac7\0"
562 "rxgains2gelnagaina0=4\0"
563 "rxgains2gtrisoa0=10\0"
564 "rxgains2gtrelnabypa0=1\0"
565 "rxgains5gelnagaina0=4\0"
566 "rxgains5gtrisoa0=11\0"
567 "rxgains5gtrelnabypa0=1\0"
568 "maxp5ga0=72,72,76,76\0"
569 "pa5ga0=0xfe75,0x14b5,0xfad4,0xfe97,0x121a,0xfb6e,0xfe7f,0x149d,0xfad0,0xfe7c,0x1431,0xfae6\0"
570 "maxp2ga1=76\0"
571 "pa2ga1=0xfe80,0x1472,0xfabc\0"
572 "rxgains2gelnagaina1=4\0"
573 "rxgains2gtrisoa1=10\0"
574 "rxgains2gtrelnabypa1=1\0"
575 "rxgains5gelnagaina1=4\0"
576 "rxgains5gtrisoa1=11\0"
577 "rxgains5gtrelnabypa1=1\0"
578 "maxp5ga1=72,72,76,76\0"
579 "pa5ga1=0xfe72,0x155e,0xfa96,0xfea1,0x125d,0xfb55,0xfe77,0x1596,0xfa8e,0xfe78,0x15e1,0xfa7a\0"
580 "END\0";
582 #endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */
583 #endif /* BCMUSBDEV */
586 /* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */
587 #if defined(BCMHOSTVARS)
588 /* Also used by wl_readconfigdata for vars download */
589 char BCMATTACHDATA(mfgsromvars)[VARS_MAX];
590 int BCMATTACHDATA(defvarslen) = 0;
591 #endif
593 /* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */
594 #if defined(BCMHOSTVARS)
595 static char BCMATTACHDATA(defaultsromvars_4331)[] =
596 "sromrev=9\0"
597 "boardrev=0x1104\0"
598 "boardflags=0x200\0"
599 "boardflags2=0x0\0"
600 "boardtype=0x524\0"
601 "boardvendor=0x14e4\0"
602 "boardnum=0x2064\0"
603 "macaddr=00:90:4c:1a:20:64\0"
604 "ccode=0x0\0"
605 "regrev=0x0\0"
606 "ledbh0=0xff\0"
607 "ledbh1=0xff\0"
608 "ledbh2=0xff\0"
609 "ledbh3=0xff\0"
610 "leddc=0xffff\0"
611 "opo=0x0\0"
612 "aa2g=0x7\0"
613 "aa5g=0x7\0"
614 "ag0=0x2\0"
615 "ag1=0x2\0"
616 "ag2=0x2\0"
617 "ag3=0xff\0"
618 "pa0b0=0xfe7f\0"
619 "pa0b1=0x15d9\0"
620 "pa0b2=0xfac6\0"
621 "pa0itssit=0x20\0"
622 "pa0maxpwr=0x48\0"
623 "pa1b0=0xfe89\0"
624 "pa1b1=0x14b1\0"
625 "pa1b2=0xfada\0"
626 "pa1lob0=0xffff\0"
627 "pa1lob1=0xffff\0"
628 "pa1lob2=0xffff\0"
629 "pa1hib0=0xfe8f\0"
630 "pa1hib1=0x13df\0"
631 "pa1hib2=0xfafa\0"
632 "pa1itssit=0x3e\0"
633 "pa1maxpwr=0x3c\0"
634 "pa1lomaxpwr=0x3c\0"
635 "pa1himaxpwr=0x3c\0"
636 "bxa2g=0x3\0"
637 "rssisav2g=0x7\0"
638 "rssismc2g=0xf\0"
639 "rssismf2g=0xf\0"
640 "bxa5g=0x3\0"
641 "rssisav5g=0x7\0"
642 "rssismc5g=0xf\0"
643 "rssismf5g=0xf\0"
644 "tri2g=0xff\0"
645 "tri5g=0xff\0"
646 "tri5gl=0xff\0"
647 "tri5gh=0xff\0"
648 "rxpo2g=0xff\0"
649 "rxpo5g=0xff\0"
650 "txchain=0x7\0"
651 "rxchain=0x7\0"
652 "antswitch=0x0\0"
653 "tssipos2g=0x1\0"
654 "extpagain2g=0x2\0"
655 "pdetrange2g=0x4\0"
656 "triso2g=0x3\0"
657 "antswctl2g=0x0\0"
658 "tssipos5g=0x1\0"
659 "elna2g=0xff\0"
660 "extpagain5g=0x2\0"
661 "pdetrange5g=0x4\0"
662 "triso5g=0x3\0"
663 "antswctl5g=0x0\0"
664 "elna5g=0xff\0"
665 "cckbw202gpo=0x0\0"
666 "cckbw20ul2gpo=0x0\0"
667 "legofdmbw202gpo=0x0\0"
668 "legofdmbw20ul2gpo=0x0\0"
669 "legofdmbw205glpo=0x0\0"
670 "legofdmbw20ul5glpo=0x0\0"
671 "legofdmbw205gmpo=0x0\0"
672 "legofdmbw20ul5gmpo=0x0\0"
673 "legofdmbw205ghpo=0x0\0"
674 "legofdmbw20ul5ghpo=0x0\0"
675 "mcsbw202gpo=0x0\0"
676 "mcsbw20ul2gpo=0x0\0"
677 "mcsbw402gpo=0x0\0"
678 "mcsbw205glpo=0x0\0"
679 "mcsbw20ul5glpo=0x0\0"
680 "mcsbw405glpo=0x0\0"
681 "mcsbw205gmpo=0x0\0"
682 "mcsbw20ul5gmpo=0x0\0"
683 "mcsbw405gmpo=0x0\0"
684 "mcsbw205ghpo=0x0\0"
685 "mcsbw20ul5ghpo=0x0\0"
686 "mcsbw405ghpo=0x0\0"
687 "mcs32po=0x0\0"
688 "legofdm40duppo=0x0\0"
689 "maxp2ga0=0x48\0"
690 "itt2ga0=0x20\0"
691 "itt5ga0=0x3e\0"
692 "pa2gw0a0=0xfe7f\0"
693 "pa2gw1a0=0x15d9\0"
694 "pa2gw2a0=0xfac6\0"
695 "maxp5ga0=0x3c\0"
696 "maxp5gha0=0x3c\0"
697 "maxp5gla0=0x3c\0"
698 "pa5gw0a0=0xfe89\0"
699 "pa5gw1a0=0x14b1\0"
700 "pa5gw2a0=0xfada\0"
701 "pa5glw0a0=0xffff\0"
702 "pa5glw1a0=0xffff\0"
703 "pa5glw2a0=0xffff\0"
704 "pa5ghw0a0=0xfe8f\0"
705 "pa5ghw1a0=0x13df\0"
706 "pa5ghw2a0=0xfafa\0"
707 "maxp2ga1=0x48\0"
708 "itt2ga1=0x20\0"
709 "itt5ga1=0x3e\0"
710 "pa2gw0a1=0xfe54\0"
711 "pa2gw1a1=0x1563\0"
712 "pa2gw2a1=0xfa7f\0"
713 "maxp5ga1=0x3c\0"
714 "maxp5gha1=0x3c\0"
715 "maxp5gla1=0x3c\0"
716 "pa5gw0a1=0xfe53\0"
717 "pa5gw1a1=0x14fe\0"
718 "pa5gw2a1=0xfa94\0"
719 "pa5glw0a1=0xffff\0"
720 "pa5glw1a1=0xffff\0"
721 "pa5glw2a1=0xffff\0"
722 "pa5ghw0a1=0xfe6e\0"
723 "pa5ghw1a1=0x1457\0"
724 "pa5ghw2a1=0xfab9\0"
725 "END\0";
726 #endif
728 /* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */
729 #if defined(BCMHOSTVARS)
730 static char BCMATTACHDATA(defaultsromvars_wltest)[] =
731 "macaddr=00:90:4c:f8:00:01\0"
732 "et0macaddr=00:11:22:33:44:52\0"
733 "et0phyaddr=30\0"
734 "et0mdcport=0\0"
735 "gpio2=robo_reset\0"
736 "boardvendor=0x14e4\0"
737 "boardflags=0x210\0"
738 "boardflags2=0\0"
739 "boardtype=0x04c3\0"
740 "boardrev=0x1100\0"
741 "sromrev=8\0"
742 "devid=0x432c\0"
743 "ccode=0\0"
744 "regrev=0\0"
745 "ledbh0=255\0"
746 "ledbh1=255\0"
747 "ledbh2=255\0"
748 "ledbh3=255\0"
749 "leddc=0xffff\0"
750 "aa2g=3\0"
751 "ag0=2\0"
752 "ag1=2\0"
753 "aa5g=3\0"
754 "aa0=2\0"
755 "aa1=2\0"
756 "txchain=3\0"
757 "rxchain=3\0"
758 "antswitch=0\0"
759 "itt2ga0=0x20\0"
760 "maxp2ga0=0x48\0"
761 "pa2gw0a0=0xfe9e\0"
762 "pa2gw1a0=0x15d5\0"
763 "pa2gw2a0=0xfae9\0"
764 "itt2ga1=0x20\0"
765 "maxp2ga1=0x48\0"
766 "pa2gw0a1=0xfeb3\0"
767 "pa2gw1a1=0x15c9\0"
768 "pa2gw2a1=0xfaf7\0"
769 "tssipos2g=1\0"
770 "extpagain2g=0\0"
771 "pdetrange2g=0\0"
772 "triso2g=3\0"
773 "antswctl2g=0\0"
774 "tssipos5g=1\0"
775 "extpagain5g=0\0"
776 "pdetrange5g=0\0"
777 "triso5g=3\0"
778 "antswctl5g=0\0"
779 "cck2gpo=0\0"
780 "ofdm2gpo=0\0"
781 "mcs2gpo0=0\0"
782 "mcs2gpo1=0\0"
783 "mcs2gpo2=0\0"
784 "mcs2gpo3=0\0"
785 "mcs2gpo4=0\0"
786 "mcs2gpo5=0\0"
787 "mcs2gpo6=0\0"
788 "mcs2gpo7=0\0"
789 "cddpo=0\0"
790 "stbcpo=0\0"
791 "bw40po=4\0"
792 "bwduppo=0\0"
793 "END\0";
794 #endif
796 static bool srvars_inited = FALSE; /* Use OTP/SROM as global variables */
798 /* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */
799 #if defined(BCMHOSTVARS) || (defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND))
800 /* It must end with pattern of "END" */
801 static uint
802 BCMATTACHFN(srom_vars_len)(char *vars)
804 uint pos = 0;
805 uint len;
806 char *s;
808 for (s = vars; s && *s;) {
810 if (strcmp(s, "END") == 0)
811 break;
813 len = strlen(s);
814 s += strlen(s) + 1;
815 pos += len + 1;
816 /* BS_ERROR(("len %d vars[pos] %s\n", pos, s)); */
817 if (pos > 4000) {
818 return 0;
822 return pos + 4; /* include the "END\0" */
824 #endif
826 /* Initialization of varbuf structure */
827 static void
828 BCMATTACHFN(varbuf_init)(varbuf_t *b, char *buf, uint size)
830 b->size = size;
831 b->base = b->buf = buf;
834 /* append a null terminated var=value string */
835 static int
836 BCMATTACHFN(varbuf_append)(varbuf_t *b, const char *fmt, ...)
838 va_list ap;
839 int r;
840 size_t len;
841 char *s;
843 if (b->size < 2)
844 return 0;
846 va_start(ap, fmt);
847 r = vsnprintf(b->buf, b->size, fmt, ap);
848 va_end(ap);
850 /* C99 snprintf behavior returns r >= size on overflow,
851 * others return -1 on overflow.
852 * All return -1 on format error.
853 * We need to leave room for 2 null terminations, one for the current var
854 * string, and one for final null of the var table. So check that the
855 * strlen written, r, leaves room for 2 chars.
857 if ((r == -1) || (r > (int)(b->size - 2))) {
858 b->size = 0;
859 return 0;
862 /* Remove any earlier occurrence of the same variable */
863 if ((s = strchr(b->buf, '=')) != NULL) {
864 len = (size_t)(s - b->buf);
865 for (s = b->base; s < b->buf;) {
866 if ((bcmp(s, b->buf, len) == 0) && s[len] == '=') {
867 len = strlen(s) + 1;
868 memmove(s, (s + len), ((b->buf + r + 1) - (s + len)));
869 b->buf -= len;
870 b->size += (unsigned int)len;
871 break;
874 while (*s++)
879 /* skip over this string's null termination */
880 r++;
881 b->size -= r;
882 b->buf += r;
884 return r;
888 * Initialize local vars from the right source for this platform.
889 * Return 0 on success, nonzero on error.
892 BCMATTACHFN(srom_var_init)(si_t *sih, uint bustype, void *curmap, osl_t *osh,
893 char **vars, uint *count)
895 ASSERT(bustype == BUSTYPE(bustype));
896 if (vars == NULL || count == NULL)
897 return (0);
899 *vars = NULL;
900 *count = 0;
902 switch (BUSTYPE(bustype)) {
903 case SI_BUS:
904 case JTAG_BUS:
905 return initvars_srom_si(sih, osh, curmap, vars, count);
907 case PCI_BUS:
908 ASSERT(curmap != NULL);
909 if (curmap == NULL)
910 return (-1);
912 return initvars_srom_pci(sih, curmap, vars, count);
914 case PCMCIA_BUS:
915 return initvars_cis_pcmcia(sih, osh, vars, count);
918 #ifdef BCMSPI
919 case SPI_BUS:
920 return initvars_cis_spi(osh, vars, count);
921 #endif /* BCMSPI */
923 default:
924 ASSERT(0);
926 return (-1);
929 /* support only 16-bit word read from srom */
931 srom_read(si_t *sih, uint bustype, void *curmap, osl_t *osh,
932 uint byteoff, uint nbytes, uint16 *buf, bool check_crc)
934 uint i, off, nw;
936 ASSERT(bustype == BUSTYPE(bustype));
938 /* check input - 16-bit access only */
939 if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > SROM_MAX)
940 return 1;
942 off = byteoff / 2;
943 nw = nbytes / 2;
945 if (BUSTYPE(bustype) == PCI_BUS) {
946 if (!curmap)
947 return 1;
949 if (si_is_sprom_available(sih)) {
950 uint16 *srom;
952 srom = (uint16 *)SROM_OFFSET(sih);
953 if (srom == NULL)
954 return 1;
956 if (sprom_read_pci(osh, sih, srom, off, buf, nw, check_crc))
957 return 1;
959 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
960 else {
961 if (otp_read_pci(osh, sih, buf, SROM_MAX))
962 return 1;
964 #endif
965 } else if (BUSTYPE(bustype) == PCMCIA_BUS) {
966 for (i = 0; i < nw; i++) {
967 if (sprom_read_pcmcia(osh, (uint16)(off + i), (uint16 *)(buf + i)))
968 return 1;
970 #ifdef BCMSPI
971 } else if (BUSTYPE(bustype) == SPI_BUS) {
972 if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, (uint8 *)buf, byteoff + nbytes) != 0)
973 return 1;
974 #endif /* BCMSPI */
975 } else if (BUSTYPE(bustype) == SI_BUS) {
976 #if defined(BCMUSBDEV)
977 if (SPROMBUS == PCMCIA_BUS) {
978 uint origidx;
979 void *regs;
980 int rc;
981 bool wasup;
983 /* Don't bother if we can't talk to SPROM */
984 if (!si_is_sprom_available(sih))
985 return 1;
987 origidx = si_coreidx(sih);
988 regs = si_setcore(sih, PCMCIA_CORE_ID, 0);
989 if (!regs)
990 regs = si_setcore(sih, SDIOD_CORE_ID, 0);
991 ASSERT(regs != NULL);
993 if (!(wasup = si_iscoreup(sih)))
994 si_core_reset(sih, 0, 0);
996 rc = get_si_pcmcia_srom(sih, osh, regs, byteoff, buf, nbytes, check_crc);
998 if (!wasup)
999 si_core_disable(sih, 0);
1001 si_setcoreidx(sih, origidx);
1002 return rc;
1004 #endif
1006 return 1;
1007 } else {
1008 return 1;
1011 return 0;
1014 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
1015 /* support only 16-bit word write into srom */
1017 srom_write(si_t *sih, uint bustype, void *curmap, osl_t *osh,
1018 uint byteoff, uint nbytes, uint16 *buf)
1020 uint i, nw, crc_range;
1021 uint16 *old, *new;
1022 uint8 crc;
1023 volatile uint32 val32;
1024 int rc = 1;
1026 ASSERT(bustype == BUSTYPE(bustype));
1028 old = MALLOC(osh, SROM_MAXW * sizeof(uint16));
1029 new = MALLOC(osh, SROM_MAXW * sizeof(uint16));
1031 if (old == NULL || new == NULL)
1032 goto done;
1034 /* check input - 16-bit access only. use byteoff 0x55aa to indicate
1035 * srclear
1037 if ((byteoff != 0x55aa) && ((byteoff & 1) || (nbytes & 1)))
1038 goto done;
1040 if ((byteoff != 0x55aa) && ((byteoff + nbytes) > SROM_MAX))
1041 goto done;
1043 if (BUSTYPE(bustype) == PCMCIA_BUS) {
1044 crc_range = SROM_MAX;
1046 #if defined(BCMUSBDEV)
1047 else {
1048 crc_range = srom_size(sih, osh);
1050 #else
1051 else {
1052 crc_range = (SROM8_SIGN + 1) * 2; /* must big enough for SROM8 */
1054 #endif
1056 nw = crc_range / 2;
1057 /* read first small number words from srom, then adjust the length, read all */
1058 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE))
1059 goto done;
1061 BS_ERROR(("%s: old[SROM4_SIGN] 0x%x, old[SROM8_SIGN] 0x%x\n",
1062 __FUNCTION__, old[SROM4_SIGN], old[SROM8_SIGN]));
1063 /* Deal with blank srom */
1064 if (old[0] == 0xffff) {
1065 /* see if the input buffer is valid SROM image or not */
1066 if (buf[SROM11_SIGN] == SROM11_SIGNATURE) {
1067 BS_ERROR(("%s: buf[SROM11_SIGN] 0x%x\n",
1068 __FUNCTION__, buf[SROM11_SIGN]));
1070 /* block invalid buffer size */
1071 if (nbytes < SROM11_WORDS * 2) {
1072 rc = BCME_BUFTOOSHORT;
1073 goto done;
1074 } else if (nbytes > SROM11_WORDS * 2) {
1075 rc = BCME_BUFTOOLONG;
1076 goto done;
1079 nw = SROM11_WORDS;
1080 } else if ((buf[SROM4_SIGN] == SROM4_SIGNATURE) ||
1081 (buf[SROM8_SIGN] == SROM4_SIGNATURE)) {
1082 BS_ERROR(("%s: buf[SROM4_SIGN] 0x%x, buf[SROM8_SIGN] 0x%x\n",
1083 __FUNCTION__, buf[SROM4_SIGN], buf[SROM8_SIGN]));
1085 /* block invalid buffer size */
1086 if (nbytes < SROM4_WORDS * 2) {
1087 rc = BCME_BUFTOOSHORT;
1088 goto done;
1089 } else if (nbytes > SROM4_WORDS * 2) {
1090 rc = BCME_BUFTOOLONG;
1091 goto done;
1094 nw = SROM4_WORDS;
1095 } else if (nbytes == SROM_WORDS * 2){ /* the other possible SROM format */
1096 BS_ERROR(("%s: Not SROM4 or SROM8.\n", __FUNCTION__));
1098 nw = SROM_WORDS;
1099 } else {
1100 BS_ERROR(("%s: Invalid input file signature\n", __FUNCTION__));
1101 rc = BCME_BADARG;
1102 goto done;
1104 crc_range = nw * 2;
1105 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE))
1106 goto done;
1107 } else if (old[SROM11_SIGN] == SROM11_SIGNATURE) {
1108 nw = SROM11_WORDS;
1109 crc_range = nw * 2;
1110 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE))
1111 goto done;
1112 } else if ((old[SROM4_SIGN] == SROM4_SIGNATURE) ||
1113 (old[SROM8_SIGN] == SROM4_SIGNATURE)) {
1114 nw = SROM4_WORDS;
1115 crc_range = nw * 2;
1116 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE))
1117 goto done;
1118 } else {
1119 /* Assert that we have already read enough for sromrev 2 */
1120 ASSERT(crc_range >= SROM_WORDS * 2);
1121 nw = SROM_WORDS;
1122 crc_range = nw * 2;
1125 if (byteoff == 0x55aa) {
1126 /* Erase request */
1127 crc_range = 0;
1128 memset((void *)new, 0xff, nw * 2);
1129 } else {
1130 /* Copy old contents */
1131 bcopy((void *)old, (void *)new, nw * 2);
1132 /* make changes */
1133 bcopy((void *)buf, (void *)&new[byteoff / 2], nbytes);
1136 if (crc_range) {
1137 /* calculate crc */
1138 htol16_buf(new, crc_range);
1139 crc = ~hndcrc8((uint8 *)new, crc_range - 1, CRC8_INIT_VALUE);
1140 ltoh16_buf(new, crc_range);
1141 new[nw - 1] = (crc << 8) | (new[nw - 1] & 0xff);
1144 if (BUSTYPE(bustype) == PCI_BUS) {
1145 uint16 *srom = NULL;
1146 void *ccregs = NULL;
1147 uint32 ccval = 0;
1149 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
1150 (CHIPID(sih->chip) == BCM43431_CHIP_ID) ||
1151 (CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1152 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1153 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
1154 /* save current control setting */
1155 ccval = si_chipcontrl_read(sih);
1158 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
1159 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
1160 /* Disable Ext PA lines to allow reading from SROM */
1161 si_chipcontrl_epa4331(sih, FALSE);
1162 } else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1163 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1164 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
1165 si_chipcontrl_srom4360(sih, TRUE);
1168 /* enable writes to the SPROM */
1169 if (sih->ccrev > 31) {
1170 ccregs = (void *)((uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET);
1171 srom = (uint16 *)((uint8 *)ccregs + CC_SROM_OTP);
1172 (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WREN, 0, 0);
1173 } else {
1174 srom = (uint16 *)((uint8 *)curmap + PCI_BAR0_SPROM_OFFSET);
1175 val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
1176 val32 |= SPROM_WRITEEN;
1177 OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32);
1179 bcm_mdelay(WRITE_ENABLE_DELAY);
1180 /* write srom */
1181 for (i = 0; i < nw; i++) {
1182 if (old[i] != new[i]) {
1183 if (sih->ccrev > 31) {
1184 if ((sih->cccaps & CC_CAP_SROM) == 0) {
1185 /* No srom support in this chip */
1186 BS_ERROR(("srom_write, invalid srom, skip\n"));
1187 } else
1188 (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRITE,
1189 i, new[i]);
1190 } else {
1191 W_REG(osh, &srom[i], new[i]);
1193 bcm_mdelay(WRITE_WORD_DELAY);
1196 /* disable writes to the SPROM */
1197 if (sih->ccrev > 31) {
1198 (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRDIS, 0, 0);
1199 } else {
1200 OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 &
1201 ~SPROM_WRITEEN);
1204 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
1205 (CHIPID(sih->chip) == BCM43431_CHIP_ID) ||
1206 (CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1207 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1208 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
1209 /* Restore config after reading SROM */
1210 si_chipcontrl_restore(sih, ccval);
1213 } else if (BUSTYPE(bustype) == PCMCIA_BUS) {
1214 /* enable writes to the SPROM */
1215 if (sprom_cmd_pcmcia(osh, SROM_WEN))
1216 goto done;
1217 bcm_mdelay(WRITE_ENABLE_DELAY);
1218 /* write srom */
1219 for (i = 0; i < nw; i++) {
1220 if (old[i] != new[i]) {
1221 sprom_write_pcmcia(osh, (uint16)(i), new[i]);
1222 bcm_mdelay(WRITE_WORD_DELAY);
1225 /* disable writes to the SPROM */
1226 if (sprom_cmd_pcmcia(osh, SROM_WDS))
1227 goto done;
1228 } else if (BUSTYPE(bustype) == SI_BUS) {
1229 #if defined(BCMUSBDEV)
1230 if (SPROMBUS == PCMCIA_BUS) {
1231 uint origidx;
1232 void *regs;
1233 bool wasup;
1235 origidx = si_coreidx(sih);
1236 regs = si_setcore(sih, PCMCIA_CORE_ID, 0);
1237 if (!regs)
1238 regs = si_setcore(sih, SDIOD_CORE_ID, 0);
1239 ASSERT(regs != NULL);
1241 if (!(wasup = si_iscoreup(sih)))
1242 si_core_reset(sih, 0, 0);
1244 rc = set_si_pcmcia_srom(sih, osh, regs, byteoff, buf, nbytes);
1246 if (!wasup)
1247 si_core_disable(sih, 0);
1249 si_setcoreidx(sih, origidx);
1250 goto done;
1252 #endif
1253 goto done;
1254 } else {
1255 goto done;
1258 bcm_mdelay(WRITE_ENABLE_DELAY);
1259 rc = 0;
1261 done:
1262 if (old != NULL)
1263 MFREE(osh, old, SROM_MAXW * sizeof(uint16));
1264 if (new != NULL)
1265 MFREE(osh, new, SROM_MAXW * sizeof(uint16));
1267 return rc;
1269 #endif
1271 #if defined(BCMUSBDEV)
1272 #define SI_PCMCIA_READ(osh, regs, fcr) \
1273 R_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2)
1274 #define SI_PCMCIA_WRITE(osh, regs, fcr, v) \
1275 W_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2, v)
1277 /* set PCMCIA srom command register */
1278 static int
1279 srom_cmd_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint8 cmd)
1281 uint8 status = 0;
1282 uint wait_cnt = 0;
1284 /* write srom command register */
1285 SI_PCMCIA_WRITE(osh, pcmregs, SROM_CS, cmd);
1287 /* wait status */
1288 while (++wait_cnt < 1000000) {
1289 status = SI_PCMCIA_READ(osh, pcmregs, SROM_CS);
1290 if (status & SROM_DONE)
1291 return 0;
1292 OSL_DELAY(1);
1295 BS_ERROR(("sr_cmd: Give up after %d tries, stat = 0x%x\n", wait_cnt, status));
1296 return 1;
1299 /* read a word from the PCMCIA srom over SI */
1300 static int
1301 srom_read_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint16 addr, uint16 *data)
1303 uint8 addr_l, addr_h, data_l, data_h;
1305 addr_l = (uint8)((addr * 2) & 0xff);
1306 addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
1308 /* set address */
1309 SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRH, addr_h);
1310 SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRL, addr_l);
1312 /* do read */
1313 if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_READ))
1314 return 1;
1316 /* read data */
1317 data_h = SI_PCMCIA_READ(osh, pcmregs, SROM_DATAH);
1318 data_l = SI_PCMCIA_READ(osh, pcmregs, SROM_DATAL);
1319 *data = ((uint16)data_h << 8) | data_l;
1321 return 0;
1324 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
1325 /* write a word to the PCMCIA srom over SI */
1326 static int
1327 srom_write_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint16 addr, uint16 data)
1329 uint8 addr_l, addr_h, data_l, data_h;
1330 int rc;
1332 addr_l = (uint8)((addr * 2) & 0xff);
1333 addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
1335 /* set address */
1336 SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRH, addr_h);
1337 SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRL, addr_l);
1339 data_l = (uint8)(data & 0xff);
1340 data_h = (uint8)((data >> 8) & 0xff);
1342 /* write data */
1343 SI_PCMCIA_WRITE(osh, pcmregs, SROM_DATAH, data_h);
1344 SI_PCMCIA_WRITE(osh, pcmregs, SROM_DATAL, data_l);
1346 /* do write */
1347 rc = srom_cmd_si_pcmcia(osh, pcmregs, SROM_WRITE);
1348 OSL_DELAY(20000);
1349 return rc;
1351 #endif
1354 * Read the srom for the pcmcia-srom over si case.
1355 * Return 0 on success, nonzero on error.
1357 static int
1358 get_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs,
1359 uint boff, uint16 *srom, uint bsz, bool check_crc)
1361 uint i, nw, woff, wsz;
1362 int err = 0;
1364 /* read must be at word boundary */
1365 ASSERT((boff & 1) == 0 && (bsz & 1) == 0);
1367 /* read sprom size and validate the parms */
1368 if ((nw = srom_size(sih, osh)) == 0) {
1369 BS_ERROR(("get_si_pcmcia_srom: sprom size unknown\n"));
1370 err = -1;
1371 goto out;
1373 if (boff + bsz > 2 * nw) {
1374 BS_ERROR(("get_si_pcmcia_srom: sprom size exceeded\n"));
1375 err = -2;
1376 goto out;
1379 /* read in sprom contents */
1380 for (woff = boff / 2, wsz = bsz / 2, i = 0;
1381 woff < nw && i < wsz; woff ++, i ++) {
1382 if (srom_read_si_pcmcia(osh, pcmregs, (uint16)woff, &srom[i])) {
1383 BS_ERROR(("get_si_pcmcia_srom: sprom read failed\n"));
1384 err = -3;
1385 goto out;
1389 if (check_crc) {
1390 if (srom[0] == 0xffff) {
1391 /* The hardware thinks that an srom that starts with 0xffff
1392 * is blank, regardless of the rest of the content, so declare
1393 * it bad.
1395 BS_ERROR(("%s: srom[0] == 0xffff, assuming unprogrammed srom\n",
1396 __FUNCTION__));
1397 err = -4;
1398 goto out;
1401 /* fixup the endianness so crc8 will pass */
1402 htol16_buf(srom, nw * 2);
1403 if (hndcrc8((uint8 *)srom, nw * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) {
1404 BS_ERROR(("%s: bad crc\n", __FUNCTION__));
1405 err = -5;
1407 /* now correct the endianness of the byte array */
1408 ltoh16_buf(srom, nw * 2);
1411 out:
1412 return err;
1415 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
1417 * Write the srom for the pcmcia-srom over si case.
1418 * Return 0 on success, nonzero on error.
1420 static int
1421 set_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs,
1422 uint boff, uint16 *srom, uint bsz)
1424 uint i, nw, woff, wsz;
1425 uint16 word;
1426 uint8 crc;
1427 int err = 0;
1429 /* write must be at word boundary */
1430 ASSERT((boff & 1) == 0 && (bsz & 1) == 0);
1432 /* read sprom size and validate the parms */
1433 if ((nw = srom_size(sih, osh)) == 0) {
1434 BS_ERROR(("set_si_pcmcia_srom: sprom size unknown\n"));
1435 err = -1;
1436 goto out;
1438 if (boff + bsz > 2 * nw) {
1439 BS_ERROR(("set_si_pcmcia_srom: sprom size exceeded\n"));
1440 err = -2;
1441 goto out;
1444 /* enable write */
1445 if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_WEN)) {
1446 BS_ERROR(("set_si_pcmcia_srom: sprom wen failed\n"));
1447 err = -3;
1448 goto out;
1451 /* write buffer to sprom */
1452 for (woff = boff / 2, wsz = bsz / 2, i = 0;
1453 woff < nw && i < wsz; woff ++, i ++) {
1454 if (srom_write_si_pcmcia(osh, pcmregs, (uint16)woff, srom[i])) {
1455 BS_ERROR(("set_si_pcmcia_srom: sprom write failed\n"));
1456 err = -4;
1457 goto out;
1461 /* fix crc */
1462 crc = CRC8_INIT_VALUE;
1463 for (woff = 0; woff < nw; woff ++) {
1464 if (srom_read_si_pcmcia(osh, pcmregs, (uint16)woff, &word)) {
1465 BS_ERROR(("set_si_pcmcia_srom: sprom fix crc read failed\n"));
1466 err = -5;
1467 goto out;
1469 word = htol16(word);
1470 crc = hndcrc8((uint8 *)&word, woff != nw - 1 ? 2 : 1, crc);
1472 word = (~crc << 8) + (ltoh16(word) & 0xff);
1473 if (srom_write_si_pcmcia(osh, pcmregs, (uint16)(woff - 1), word)) {
1474 BS_ERROR(("set_si_pcmcia_srom: sprom fix crc write failed\n"));
1475 err = -6;
1476 goto out;
1479 /* disable write */
1480 if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_WDS)) {
1481 BS_ERROR(("set_si_pcmcia_srom: sprom wds failed\n"));
1482 err = -7;
1483 goto out;
1486 out:
1487 return err;
1489 #endif
1490 #endif
1492 static const char BCMATTACHDATA(vstr_manf)[] = "manf=%s";
1493 static const char BCMATTACHDATA(vstr_productname)[] = "productname=%s";
1494 static const char BCMATTACHDATA(vstr_manfid)[] = "manfid=0x%x";
1495 static const char BCMATTACHDATA(vstr_prodid)[] = "prodid=0x%x";
1496 static const char BCMATTACHDATA(vstr_regwindowsz)[] = "regwindowsz=%d";
1497 static const char BCMATTACHDATA(vstr_sromrev)[] = "sromrev=%d";
1498 static const char BCMATTACHDATA(vstr_chiprev)[] = "chiprev=%d";
1499 static const char BCMATTACHDATA(vstr_subvendid)[] = "subvendid=0x%x";
1500 static const char BCMATTACHDATA(vstr_subdevid)[] = "subdevid=0x%x";
1501 static const char BCMATTACHDATA(vstr_boardrev)[] = "boardrev=0x%x";
1502 static const char BCMATTACHDATA(vstr_aa2g)[] = "aa2g=0x%x";
1503 static const char BCMATTACHDATA(vstr_aa5g)[] = "aa5g=0x%x";
1504 static const char BCMATTACHDATA(vstr_ag)[] = "ag%d=0x%x";
1505 static const char BCMATTACHDATA(vstr_cc)[] = "cc=%d";
1506 static const char BCMATTACHDATA(vstr_opo)[] = "opo=%d";
1507 static const char BCMATTACHDATA(vstr_pa0b)[][9] = { "pa0b0=%d", "pa0b1=%d", "pa0b2=%d" };
1508 static const char BCMATTACHDATA(vstr_pa0itssit)[] = "pa0itssit=%d";
1509 static const char BCMATTACHDATA(vstr_pa0maxpwr)[] = "pa0maxpwr=%d";
1510 static const char BCMATTACHDATA(vstr_pa1b)[][9] = { "pa1b0=%d", "pa1b1=%d", "pa1b2=%d" };
1511 static const char BCMATTACHDATA(vstr_pa1lob)[][11] =
1512 { "pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d" };
1513 static const char BCMATTACHDATA(vstr_pa1hib)[][11] =
1514 { "pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d" };
1515 static const char BCMATTACHDATA(vstr_pa1itssit)[] = "pa1itssit=%d";
1516 static const char BCMATTACHDATA(vstr_pa1maxpwr)[] = "pa1maxpwr=%d";
1517 static const char BCMATTACHDATA(vstr_pa1lomaxpwr)[] = "pa1lomaxpwr=%d";
1518 static const char BCMATTACHDATA(vstr_pa1himaxpwr)[] = "pa1himaxpwr=%d";
1519 static const char BCMATTACHDATA(vstr_oem)[] = "oem=%02x%02x%02x%02x%02x%02x%02x%02x";
1520 static const char BCMATTACHDATA(vstr_boardflags)[] = "boardflags=0x%x";
1521 static const char BCMATTACHDATA(vstr_boardflags2)[] = "boardflags2=0x%x";
1522 static const char BCMATTACHDATA(vstr_boardflags3)[] = "boardflags3=0x%x";
1523 static const char BCMATTACHDATA(vstr_ledbh)[] = "ledbh%d=0x%x";
1524 static const char BCMATTACHDATA(vstr_noccode)[] = "ccode=0x0";
1525 static const char BCMATTACHDATA(vstr_ccode)[] = "ccode=%c%c";
1526 static const char BCMATTACHDATA(vstr_cctl)[] = "cctl=0x%x";
1527 static const char BCMATTACHDATA(vstr_cckpo)[] = "cckpo=0x%x";
1528 static const char BCMATTACHDATA(vstr_ofdmpo)[] = "ofdmpo=0x%x";
1529 static const char BCMATTACHDATA(vstr_rdlid)[] = "rdlid=0x%x";
1530 static const char BCMATTACHDATA(vstr_rdlrndis)[] = "rdlrndis=%d";
1531 static const char BCMATTACHDATA(vstr_rdlrwu)[] = "rdlrwu=%d";
1532 static const char BCMATTACHDATA(vstr_usbfs)[] = "usbfs=%d";
1533 static const char BCMATTACHDATA(vstr_wpsgpio)[] = "wpsgpio=%d";
1534 static const char BCMATTACHDATA(vstr_wpsled)[] = "wpsled=%d";
1535 static const char BCMATTACHDATA(vstr_rdlsn)[] = "rdlsn=%d";
1536 static const char BCMATTACHDATA(vstr_rssismf2g)[] = "rssismf2g=%d";
1537 static const char BCMATTACHDATA(vstr_rssismc2g)[] = "rssismc2g=%d";
1538 static const char BCMATTACHDATA(vstr_rssisav2g)[] = "rssisav2g=%d";
1539 static const char BCMATTACHDATA(vstr_bxa2g)[] = "bxa2g=%d";
1540 static const char BCMATTACHDATA(vstr_rssismf5g)[] = "rssismf5g=%d";
1541 static const char BCMATTACHDATA(vstr_rssismc5g)[] = "rssismc5g=%d";
1542 static const char BCMATTACHDATA(vstr_rssisav5g)[] = "rssisav5g=%d";
1543 static const char BCMATTACHDATA(vstr_bxa5g)[] = "bxa5g=%d";
1544 static const char BCMATTACHDATA(vstr_tri2g)[] = "tri2g=%d";
1545 static const char BCMATTACHDATA(vstr_tri5gl)[] = "tri5gl=%d";
1546 static const char BCMATTACHDATA(vstr_tri5g)[] = "tri5g=%d";
1547 static const char BCMATTACHDATA(vstr_tri5gh)[] = "tri5gh=%d";
1548 static const char BCMATTACHDATA(vstr_rxpo2g)[] = "rxpo2g=%d";
1549 static const char BCMATTACHDATA(vstr_rxpo5g)[] = "rxpo5g=%d";
1550 static const char BCMATTACHDATA(vstr_boardtype)[] = "boardtype=0x%x";
1551 static const char BCMATTACHDATA(vstr_leddc)[] = "leddc=0x%04x";
1552 static const char BCMATTACHDATA(vstr_vendid)[] = "vendid=0x%x";
1553 static const char BCMATTACHDATA(vstr_devid)[] = "devid=0x%x";
1554 static const char BCMATTACHDATA(vstr_xtalfreq)[] = "xtalfreq=%d";
1555 static const char BCMATTACHDATA(vstr_txchain)[] = "txchain=0x%x";
1556 static const char BCMATTACHDATA(vstr_rxchain)[] = "rxchain=0x%x";
1557 static const char BCMNMIATTACHDATA(vstr_elna2g)[] = "elna2g=0x%x";
1558 static const char BCMNMIATTACHDATA(vstr_elna5g)[] = "elna5g=0x%x";
1559 static const char BCMATTACHDATA(vstr_antswitch)[] = "antswitch=0x%x";
1560 static const char BCMATTACHDATA(vstr_regrev)[] = "regrev=0x%x";
1561 static const char BCMATTACHDATA(vstr_antswctl2g)[] = "antswctl2g=0x%x";
1562 static const char BCMATTACHDATA(vstr_triso2g)[] = "triso2g=0x%x";
1563 static const char BCMATTACHDATA(vstr_pdetrange2g)[] = "pdetrange2g=0x%x";
1564 static const char BCMATTACHDATA(vstr_extpagain2g)[] = "extpagain2g=0x%x";
1565 static const char BCMATTACHDATA(vstr_tssipos2g)[] = "tssipos2g=0x%x";
1566 static const char BCMATTACHDATA(vstr_antswctl5g)[] = "antswctl5g=0x%x";
1567 static const char BCMATTACHDATA(vstr_triso5g)[] = "triso5g=0x%x";
1568 static const char BCMATTACHDATA(vstr_pdetrange5g)[] = "pdetrange5g=0x%x";
1569 static const char BCMATTACHDATA(vstr_extpagain5g)[] = "extpagain5g=0x%x";
1570 static const char BCMATTACHDATA(vstr_tssipos5g)[] = "tssipos5g=0x%x";
1571 static const char BCMATTACHDATA(vstr_maxp2ga)[] = "maxp2ga%d=0x%x";
1572 static const char BCMATTACHDATA(vstr_itt2ga0)[] = "itt2ga0=0x%x";
1573 static const char BCMATTACHDATA(vstr_pa)[] = "pa%dgw%da%d=0x%x";
1574 static const char BCMATTACHDATA(vstr_pahl)[] = "pa%dg%cw%da%d=0x%x";
1575 static const char BCMATTACHDATA(vstr_maxp5ga0)[] = "maxp5ga0=0x%x";
1576 static const char BCMATTACHDATA(vstr_itt5ga0)[] = "itt5ga0=0x%x";
1577 static const char BCMATTACHDATA(vstr_maxp5gha0)[] = "maxp5gha0=0x%x";
1578 static const char BCMATTACHDATA(vstr_maxp5gla0)[] = "maxp5gla0=0x%x";
1579 static const char BCMATTACHDATA(vstr_itt2ga1)[] = "itt2ga1=0x%x";
1580 static const char BCMATTACHDATA(vstr_maxp5ga1)[] = "maxp5ga1=0x%x";
1581 static const char BCMATTACHDATA(vstr_itt5ga1)[] = "itt5ga1=0x%x";
1582 static const char BCMATTACHDATA(vstr_maxp5gha1)[] = "maxp5gha1=0x%x";
1583 static const char BCMATTACHDATA(vstr_maxp5gla1)[] = "maxp5gla1=0x%x";
1584 static const char BCMATTACHDATA(vstr_cck2gpo)[] = "cck2gpo=0x%x";
1585 static const char BCMATTACHDATA(vstr_ofdm2gpo)[] = "ofdm2gpo=0x%x";
1586 static const char BCMATTACHDATA(vstr_ofdm5gpo)[] = "ofdm5gpo=0x%x";
1587 static const char BCMATTACHDATA(vstr_ofdm5glpo)[] = "ofdm5glpo=0x%x";
1588 static const char BCMATTACHDATA(vstr_ofdm5ghpo)[] = "ofdm5ghpo=0x%x";
1589 static const char BCMATTACHDATA(vstr_cddpo)[] = "cddpo=0x%x";
1590 static const char BCMATTACHDATA(vstr_stbcpo)[] = "stbcpo=0x%x";
1591 static const char BCMATTACHDATA(vstr_bw40po)[] = "bw40po=0x%x";
1592 static const char BCMATTACHDATA(vstr_bwduppo)[] = "bwduppo=0x%x";
1593 static const char BCMATTACHDATA(vstr_mcspo)[] = "mcs%dgpo%d=0x%x";
1594 static const char BCMATTACHDATA(vstr_mcspohl)[] = "mcs%dg%cpo%d=0x%x";
1595 static const char BCMATTACHDATA(vstr_custom)[] = "customvar%d=0x%x";
1596 static const char BCMATTACHDATA(vstr_cckdigfilttype)[] = "cckdigfilttype=%d";
1597 static const char BCMATTACHDATA(vstr_usbflags)[] = "usbflags=0x%x";
1598 #ifdef BCM_BOOTLOADER
1599 static const char BCMATTACHDATA(vstr_mdio)[] = "mdio%d=0x%%x";
1600 static const char BCMATTACHDATA(vstr_mdioex)[] = "mdioex%d=0x%%x";
1601 static const char BCMATTACHDATA(vstr_brmin)[] = "brmin=0x%x";
1602 static const char BCMATTACHDATA(vstr_brmax)[] = "brmax=0x%x";
1603 static const char BCMATTACHDATA(vstr_pllreg)[] = "pll%d=0x%x";
1604 static const char BCMATTACHDATA(vstr_ccreg)[] = "chipc%d=0x%x";
1605 static const char BCMATTACHDATA(vstr_regctrl)[] = "reg%d=0x%x";
1606 static const char BCMATTACHDATA(vstr_time)[] = "r%dt=0x%x";
1607 static const char BCMATTACHDATA(vstr_depreg)[] = "r%dd=0x%x";
1608 static const char BCMATTACHDATA(vstr_usbpredly)[] = "usbpredly=0x%x";
1609 static const char BCMATTACHDATA(vstr_usbpostdly)[] = "usbpostdly=0x%x";
1610 static const char BCMATTACHDATA(vstr_usbrdy)[] = "usbrdy=0x%x";
1611 static const char BCMATTACHDATA(vstr_hsicphyctrl1)[] = "hsicphyctrl1=0x%x";
1612 static const char BCMATTACHDATA(vstr_hsicphyctrl2)[] = "hsicphyctrl2=0x%x";
1613 static const char BCMATTACHDATA(vstr_usbdevctrl)[] = "usbdevctrl=0x%x";
1614 static const char BCMATTACHDATA(vstr_bldr_reset_timeout)[] = "bldr_to=0x%x";
1615 static const char BCMATTACHDATA(vstr_muxenab)[] = "muxenab=0x%x";
1616 #endif /* BCM_BOOTLOADER */
1617 static const char BCMATTACHDATA(vstr_boardnum)[] = "boardnum=%d";
1618 static const char BCMATTACHDATA(vstr_macaddr)[] = "macaddr=%s";
1619 static const char BCMATTACHDATA(vstr_usbepnum)[] = "usbepnum=0x%x";
1621 /* Power per rate for SROM V9 */
1622 static const char BCMATTACHDATA(vstr_cckbw202gpo)[][19] =
1623 { "cckbw202gpo=0x%x", "cckbw20ul2gpo=0x%x" };
1624 static const char BCMATTACHDATA(vstr_legofdmbw202gpo)[][22] =
1625 { "legofdmbw202gpo=0x%x", "legofdmbw20ul2gpo=0x%x" };
1626 static const char BCMATTACHDATA(vstr_legofdmbw205gpo)[][24] =
1627 { "legofdmbw205glpo=0x%x", "legofdmbw20ul5glpo=0x%x",
1628 "legofdmbw205gmpo=0x%x", "legofdmbw20ul5gmpo=0x%x",
1629 "legofdmbw205ghpo=0x%x", "legofdmbw20ul5ghpo=0x%x" };
1631 static const char BCMATTACHDATA(vstr_mcs2gpo)[][19] =
1632 { "mcsbw202gpo=0x%x", "mcsbw20ul2gpo=0x%x", "mcsbw402gpo=0x%x"};
1634 static const char BCMATTACHDATA(vstr_mcs5glpo)[][20] =
1635 { "mcsbw205glpo=0x%x", "mcsbw20ul5glpo=0x%x", "mcsbw405glpo=0x%x"};
1637 static const char BCMATTACHDATA(vstr_mcs5gmpo)[][20] =
1638 { "mcsbw205gmpo=0x%x", "mcsbw20ul5gmpo=0x%x", "mcsbw405gmpo=0x%x"};
1640 static const char BCMATTACHDATA(vstr_mcs5ghpo)[][20] =
1641 { "mcsbw205ghpo=0x%x", "mcsbw20ul5ghpo=0x%x", "mcsbw405ghpo=0x%x"};
1643 static const char BCMATTACHDATA(vstr_mcs32po)[] = "mcs32po=0x%x";
1644 static const char BCMATTACHDATA(vstr_legofdm40duppo)[] = "legofdm40duppo=0x%x";
1646 /* SROM V11 */
1647 static const char BCMATTACHDATA(vstr_tempthresh)[] = "tempthresh=%d"; /* HNBU_TEMPTHRESH */
1648 static const char BCMATTACHDATA(vstr_temps_period)[] = "temps_period=%d";
1649 static const char BCMATTACHDATA(vstr_temp_hysteresis)[] = "temp_hysteresis=%d";
1650 static const char BCMATTACHDATA(vstr_tempoffset)[] = "tempoffset=%d";
1651 static const char BCMATTACHDATA(vstr_temp_corrx)[] = "tempcorrx=%d";
1652 static const char BCMATTACHDATA(vstr_tempsense_option)[] = "tempsense_option=%d";
1653 static const char BCMATTACHDATA(vstr_phycal_tempdelta)[] = "phycal_tempdelta=%d";
1654 static const char BCMATTACHDATA(vstr_tssiposslopeg)[] = "tssiposslope%dg=%d"; /* HNBU_FEM_CFG */
1655 static const char BCMATTACHDATA(vstr_epagaing)[] = "epagain%dg=%d";
1656 static const char BCMATTACHDATA(vstr_pdgaing)[] = "pdgain%dg=%d";
1657 static const char BCMATTACHDATA(vstr_tworangetssi)[] = "tworangetssi%dg=%d";
1658 static const char BCMATTACHDATA(vstr_papdcap)[] = "papdcap%dg=%d";
1659 static const char BCMATTACHDATA(vstr_femctrl)[] = "femctrl=%d";
1660 static const char BCMATTACHDATA(vstr_gainctrlsph)[] = "gainctrlsph=%d";
1661 static const char BCMATTACHDATA(vstr_subband5gver)[] = "subband5gver=%d"; /* HNBU_ACPA_CX */
1662 static const char BCMATTACHDATA(vstr_pa2ga)[] = "pa2ga%d=0x%x,0x%x,0x%x";
1663 static const char BCMATTACHDATA(vstr_maxp5ga)[] = "maxp5ga%d=0x%x,0x%x,0x%x,0x%x";
1664 static const char BCMATTACHDATA(vstr_pa5ga)[] = "pa5ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,"
1665 "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1666 static const char BCMATTACHDATA(vstr_rxgainsgelnagaina)[] = "rxgains%dgelnagaina=%d";
1667 static const char BCMATTACHDATA(vstr_rxgainsgtrisoa)[] = "rxgains%dgtrisoa%d=%d";
1668 static const char BCMATTACHDATA(vstr_rxgainsgtrelnabypa)[] = "rxgains%dgtrelnabypa%d=%d";
1669 static const char BCMATTACHDATA(vstr_measpower)[] = "measpower%d=0x%x"; /* HNBU_MEAS_PWR */
1670 static const char BCMATTACHDATA(vstr_measpowerX)[] = "measpower%d=0x%x";
1671 static const char BCMATTACHDATA(vstr_rawtempsense)[] = "rawtempsense=0x%x";
1672 /* HNBU_ACPPR_2GPO */
1673 static const char BCMATTACHDATA(vstr_dot11agofdmhrbw202gpo)[] = "dot11agofdmhrbw202gpo=0x%x";
1674 static const char BCMATTACHDATA(vstr_ofdmlrbw202gpo)[] = "ofdmlrbw202gpo=0x%x";
1675 static const char BCMATTACHDATA(vstr_mcsbw805glpo)[] = "mcsbw805glpo=0x%x"; /* HNBU_ACPPR_5GPO */
1676 static const char BCMATTACHDATA(vstr_mcsbw1605glpo)[] = "mcsbw1605glpo=0x%x";
1677 static const char BCMATTACHDATA(vstr_mcsbw805gmpo)[] = "mcsbw805gmpo=0x%x";
1678 static const char BCMATTACHDATA(vstr_mcsbw1605gmpo)[] = "mcsbw1605gmpo=0x%x";
1679 static const char BCMATTACHDATA(vstr_mcsbw805ghpo)[] = "mcsbw805ghpo=0x%x";
1680 static const char BCMATTACHDATA(vstr_mcsbw1605ghpo)[] = "mcsbw1605ghpo=0x%x";
1681 static const char BCMATTACHDATA(vstr_mcslr5rlpo)[] = "mcslr5rlpo=0x%x";
1682 static const char BCMATTACHDATA(vstr_mcslr5gmpo)[] = "mcslr5gmpo=0x%x";
1683 static const char BCMATTACHDATA(vstr_mcslr5ghpo)[] = "mcslr5ghpo=0x%x";
1684 static const char BCMATTACHDATA(vstr_sb20in40rrpo)[] = "sb20in40%crrpo=0x%x"; /* HNBU_ACPPR_SBPO */
1685 static const char BCMATTACHDATA(vstr_sb20in80and160r5gpo)[] = "sb20in80and160%cr5g%cpo=0x%x";
1686 static const char BCMATTACHDATA(vstr_sb40and80r5gpo)[] = "sb40and80%cr5g%cpo=0x%x";
1687 static const char BCMATTACHDATA(vstr_dot11agduprpo)[] = "dot11agdup%crpo=0x%x";
1688 static const char BCMATTACHDATA(vstr_noiselvl2ga)[] = "noiselvl2ga%d=%d"; /* HNBU_NOISELVL */
1689 static const char BCMATTACHDATA(vstr_noiselvl5ga)[] = "noiselvl5g%ca%d=%d";
1690 static const char BCMATTACHDATA(vstr_rxgainerr2g)[] = "rxgainerr2g=0x%x"; /* HNBU_RXGAIN_ERR */
1691 static const char BCMATTACHDATA(vstr_rxgainerr5g)[] = "rxgainerr5g=0x%x,0x%x,0x%x,0x%x";
1692 static const char BCMATTACHDATA(vstr_agbg)[] = "agbg%d=0x%x"; /* HNBU_AGBGA */
1693 static const char BCMATTACHDATA(vstr_aga)[] = "aga%d=0x%x";
1695 static const char BCMATTACHDATA(vstr_uuid)[] = "uuid=%s";
1697 static const char BCMATTACHDATA(vstr_end)[] = "END\0";
1699 uint8 patch_pair = 0;
1701 /* For dongle HW, accept partial calibration parameters */
1702 #if defined(BCMUSBDEV)
1703 #define BCMDONGLECASE(n) case n:
1704 #else
1705 #define BCMDONGLECASE(n)
1706 #endif
1708 #ifdef BCM_BOOTLOADER
1709 /* The format of the PMUREGS OTP Tuple ->
1710 * 1 byte -> Lower 5 bits has the address of the register
1711 * Higher 3 bits has the mode of the register like
1712 * PLL, ChipCtrl, RegCtrl, UpDwn or Dependency mask
1713 * 4 bytes -> Value of the register to be updated.
1715 #define PMUREGS_MODE_MASK 0xE0
1716 #define PMUREGS_MODE_SHIFT 5
1717 #define PMUREGS_ADDR_MASK 0x1F
1718 #define PMUREGS_TPL_SIZE 5
1720 enum {
1721 PMU_PLLREG_MODE,
1722 PMU_CCREG_MODE,
1723 PMU_VOLTREG_MODE,
1724 PMU_RES_TIME_MODE,
1725 PMU_RESDEPEND_MODE
1728 #define USBREGS_TPL_SIZE 5
1729 enum {
1730 USB_DEV_CTRL_REG,
1731 HSIC_PHY_CTRL1_REG,
1732 HSIC_PHY_CTRL2_REG
1735 #define USBRDY_DLY_TYPE 0x8000 /* Bit indicating if the byte is pre or post delay value */
1736 #define USBRDY_DLY_MASK 0x7FFF /* Bits indicating the amount of delay */
1737 #define USBRDY_MAXOTP_SIZE 5 /* Max size of the OTP parameter */
1739 #endif /* BCM_BOOTLOADER */
1741 #ifdef BCM_BMAC_VARS_APPEND
1743 BCMATTACHFN(srom_probe_boardtype)(uint8 *pcis[], uint ciscnt)
1745 int i;
1746 uint cisnum;
1747 uint8 *cis, tup, tlen;
1749 for (cisnum = 0; cisnum < ciscnt; cisnum++) {
1750 cis = *pcis++;
1751 i = 0;
1752 do {
1753 tup = cis[i++];
1754 if (tup == CISTPL_NULL || tup == CISTPL_END)
1755 tlen = 0;
1756 else
1757 tlen = cis[i++];
1759 if ((i + tlen) >= CIS_SIZE)
1760 break;
1762 if ((tup == CISTPL_BRCM_HNBU) && (cis[i] == HNBU_BOARDTYPE)) {
1763 return (int)((cis[i + 2] << 8) + cis[i + 1]);
1766 i += tlen;
1768 } while (tup != CISTPL_END);
1771 return 0;
1773 #endif /* BCM_BMAC_VARS_APPEND */
1776 BCMATTACHFN(srom_parsecis)(osl_t *osh, uint8 *pcis[], uint ciscnt, char **vars, uint *count)
1778 char eabuf[32];
1779 char *base;
1780 varbuf_t b;
1781 uint8 *cis, tup, tlen, sromrev = 1;
1782 int i, j;
1783 #ifndef BCM_BOOTLOADER
1784 bool ag_init = FALSE;
1785 #endif
1786 uint32 w32;
1787 uint funcid;
1788 uint cisnum;
1789 int32 boardnum;
1790 int err;
1791 bool standard_cis;
1793 ASSERT(vars != NULL);
1794 ASSERT(count != NULL);
1796 boardnum = -1;
1798 base = MALLOC(osh, MAXSZ_NVRAM_VARS);
1799 ASSERT(base != NULL);
1800 if (!base)
1801 return -2;
1803 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
1804 bzero(base, MAXSZ_NVRAM_VARS);
1805 #ifdef BCM_BMAC_VARS_APPEND
1806 /* 43236 use defaultsromvars_43236usb as the base,
1807 * then append and update it with the content from OTP.
1808 * Only revision/board specfic content or updates used to override
1809 * the driver default will be stored in OTP
1811 *count -= (strlen(vstr_end) + 1 + 1); /* back off the termnating END\0\0 from fakenvram */
1812 bcopy(*vars, base, *count);
1813 b.buf += *count;
1814 #endif /* BCM_BMAC_VARS_APPEND */
1815 eabuf[0] = '\0';
1816 for (cisnum = 0; cisnum < ciscnt; cisnum++) {
1817 cis = *pcis++;
1818 i = 0;
1819 funcid = 0;
1820 standard_cis = TRUE;
1821 do {
1822 if (standard_cis) {
1823 tup = cis[i++];
1824 if (tup == CISTPL_NULL || tup == CISTPL_END)
1825 tlen = 0;
1826 else
1827 tlen = cis[i++];
1828 } else {
1829 if (cis[i] == CISTPL_NULL || cis[i] == CISTPL_END) {
1830 tlen = 0;
1831 tup = cis[i];
1832 } else {
1833 tlen = cis[i];
1834 tup = CISTPL_BRCM_HNBU;
1836 ++i;
1838 if ((i + tlen) >= CIS_SIZE)
1839 break;
1841 switch (tup) {
1842 case CISTPL_VERS_1:
1843 /* assume the strings are good if the version field checks out */
1844 if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) {
1845 varbuf_append(&b, vstr_manf, &cis[i + 2]);
1846 varbuf_append(&b, vstr_productname,
1847 &cis[i + 3 + strlen((char *)&cis[i + 2])]);
1848 break;
1851 case CISTPL_MANFID:
1852 varbuf_append(&b, vstr_manfid, (cis[i + 1] << 8) + cis[i]);
1853 varbuf_append(&b, vstr_prodid, (cis[i + 3] << 8) + cis[i + 2]);
1854 break;
1856 case CISTPL_FUNCID:
1857 funcid = cis[i];
1858 break;
1860 case CISTPL_FUNCE:
1861 switch (funcid) {
1862 case CISTPL_FID_SDIO:
1863 funcid = 0;
1864 break;
1865 default:
1866 /* set macaddr if HNBU_MACADDR not seen yet */
1867 if (eabuf[0] == '\0' && cis[i] == LAN_NID &&
1868 !(ETHER_ISNULLADDR(&cis[i + 2])) &&
1869 !(ETHER_ISMULTI(&cis[i + 2]))) {
1870 ASSERT(cis[i + 1] == ETHER_ADDR_LEN);
1871 bcm_ether_ntoa((struct ether_addr *)&cis[i + 2],
1872 eabuf);
1874 /* set boardnum if HNBU_BOARDNUM not seen yet */
1875 if (boardnum == -1)
1876 boardnum = (cis[i + 6] << 8) + cis[i + 7];
1878 break;
1880 break;
1882 case CISTPL_CFTABLE:
1883 varbuf_append(&b, vstr_regwindowsz, (cis[i + 7] << 8) | cis[i + 6]);
1884 break;
1886 case CISTPL_BRCM_HNBU:
1887 switch (cis[i]) {
1888 case HNBU_SROMREV:
1889 sromrev = cis[i + 1];
1890 varbuf_append(&b, vstr_sromrev, sromrev);
1891 break;
1893 case HNBU_XTALFREQ:
1894 varbuf_append(&b, vstr_xtalfreq,
1895 (cis[i + 4] << 24) |
1896 (cis[i + 3] << 16) |
1897 (cis[i + 2] << 8) |
1898 cis[i + 1]);
1899 break;
1901 case HNBU_CHIPID:
1902 varbuf_append(&b, vstr_vendid, (cis[i + 2] << 8) +
1903 cis[i + 1]);
1904 varbuf_append(&b, vstr_devid, (cis[i + 4] << 8) +
1905 cis[i + 3]);
1906 if (tlen >= 7) {
1907 varbuf_append(&b, vstr_chiprev,
1908 (cis[i + 6] << 8) + cis[i + 5]);
1910 if (tlen >= 9) {
1911 varbuf_append(&b, vstr_subvendid,
1912 (cis[i + 8] << 8) + cis[i + 7]);
1914 if (tlen >= 11) {
1915 varbuf_append(&b, vstr_subdevid,
1916 (cis[i + 10] << 8) + cis[i + 9]);
1917 /* subdevid doubles for boardtype */
1918 varbuf_append(&b, vstr_boardtype,
1919 (cis[i + 10] << 8) + cis[i + 9]);
1921 break;
1923 case HNBU_BOARDNUM:
1924 boardnum = (cis[i + 2] << 8) + cis[i + 1];
1925 break;
1927 case HNBU_PATCH:
1929 char vstr_paddr[16];
1930 char vstr_pdata[16];
1932 /* retrieve the patch pairs
1933 * from tlen/6; where 6 is
1934 * sizeof(patch addr(2)) +
1935 * sizeof(patch data(4)).
1937 patch_pair = tlen/6;
1939 for (j = 0; j < patch_pair; j++) {
1940 snprintf(vstr_paddr, sizeof(vstr_paddr),
1941 "pa%d=0x%%x", j);
1942 snprintf(vstr_pdata, sizeof(vstr_pdata),
1943 "pd%d=0x%%x", j);
1945 varbuf_append(&b, vstr_paddr,
1946 (cis[i + (j*6) + 2] << 8) |
1947 cis[i + (j*6) + 1]);
1949 varbuf_append(&b, vstr_pdata,
1950 (cis[i + (j*6) + 6] << 24) |
1951 (cis[i + (j*6) + 5] << 16) |
1952 (cis[i + (j*6) + 4] << 8) |
1953 cis[i + (j*6) + 3]);
1956 break;
1958 case HNBU_BOARDREV:
1959 if (tlen == 2)
1960 varbuf_append(&b, vstr_boardrev, cis[i + 1]);
1961 else
1962 varbuf_append(&b, vstr_boardrev,
1963 (cis[i + 2] << 8) + cis[i + 1]);
1964 break;
1966 case HNBU_BOARDFLAGS:
1967 w32 = (cis[i + 2] << 8) + cis[i + 1];
1968 if (tlen >= 5)
1969 w32 |= ((cis[i + 4] << 24) + (cis[i + 3] << 16));
1970 varbuf_append(&b, vstr_boardflags, w32);
1972 if (tlen >= 7) {
1973 w32 = (cis[i + 6] << 8) + cis[i + 5];
1974 if (tlen >= 9)
1975 w32 |= ((cis[i + 8] << 24) +
1976 (cis[i + 7] << 16));
1977 varbuf_append(&b, vstr_boardflags2, w32);
1979 if (tlen >= 11) {
1980 w32 = (cis[i + 10] << 8) + cis[i + 9];
1981 if (tlen >= 13)
1982 w32 |= ((cis[i + 12] << 24) +
1983 (cis[i + 11] << 16));
1984 varbuf_append(&b, vstr_boardflags3, w32);
1986 break;
1988 case HNBU_USBFS:
1989 varbuf_append(&b, vstr_usbfs, cis[i + 1]);
1990 break;
1992 case HNBU_BOARDTYPE:
1993 varbuf_append(&b, vstr_boardtype,
1994 (cis[i + 2] << 8) + cis[i + 1]);
1995 break;
1997 case HNBU_HNBUCIS:
1999 * what follows is a nonstandard HNBU CIS
2000 * that lacks CISTPL_BRCM_HNBU tags
2002 * skip 0xff (end of standard CIS)
2003 * after this tuple
2005 tlen++;
2006 standard_cis = FALSE;
2007 break;
2009 case HNBU_USBEPNUM:
2010 varbuf_append(&b, vstr_usbepnum,
2011 (cis[i + 2] << 8) | cis[i + 1]);
2012 break;
2014 case HNBU_PATCH_AUTOINC: {
2015 char vstr_paddr[16];
2016 char vstr_pdata[16];
2017 uint32 addr_inc;
2018 uint8 pcnt;
2020 addr_inc = (cis[i + 4] << 24) |
2021 (cis[i + 3] << 16) |
2022 (cis[i + 2] << 8) |
2023 (cis[i + 1]);
2025 pcnt = (tlen - 5)/4;
2026 for (j = 0; j < pcnt; j++) {
2027 snprintf(vstr_paddr, sizeof(vstr_paddr),
2028 "pa%d=0x%%x", j + patch_pair);
2029 snprintf(vstr_pdata, sizeof(vstr_pdata),
2030 "pd%d=0x%%x", j + patch_pair);
2032 varbuf_append(&b, vstr_paddr, addr_inc);
2033 varbuf_append(&b, vstr_pdata,
2034 (cis[i + (j*4) + 8] << 24) |
2035 (cis[i + (j*4) + 7] << 16) |
2036 (cis[i + (j*4) + 6] << 8) |
2037 cis[i + (j*4) + 5]);
2038 addr_inc += 4;
2040 patch_pair += pcnt;
2042 break;
2043 case HNBU_PATCH2:
2045 char vstr_paddr[16];
2046 char vstr_pdata[16];
2048 /* retrieve the patch pairs
2049 * from tlen/8; where 8 is
2050 * sizeof(patch addr(4)) +
2051 * sizeof(patch data(4)).
2053 patch_pair = tlen/8;
2055 for (j = 0; j < patch_pair; j++) {
2056 snprintf(vstr_paddr, sizeof(vstr_paddr),
2057 "pa%d=0x%%x", j);
2058 snprintf(vstr_pdata, sizeof(vstr_pdata),
2059 "pd%d=0x%%x", j);
2061 varbuf_append(&b, vstr_paddr,
2062 (cis[i + (j*8) + 4] << 24) |
2063 (cis[i + (j*8) + 3] << 16) |
2064 (cis[i + (j*8) + 2] << 8) |
2065 cis[i + (j*8) + 1]);
2067 varbuf_append(&b, vstr_pdata,
2068 (cis[i + (j*8) + 8] << 24) |
2069 (cis[i + (j*8) + 7] << 16) |
2070 (cis[i + (j*8) + 6] << 8) |
2071 cis[i + (j*8) + 5]);
2074 break;
2075 case HNBU_USBFLAGS:
2076 varbuf_append(&b, vstr_usbflags,
2077 (cis[i + 4] << 24) |
2078 (cis[i + 3] << 16) |
2079 (cis[i + 2] << 8) |
2080 cis[i + 1]);
2081 break;
2082 #ifdef BCM_BOOTLOADER
2083 case HNBU_MDIOEX_REGLIST:
2084 case HNBU_MDIO_REGLIST: {
2085 /* Format: addr (8 bits) | val (16 bits) */
2086 const uint8 msize = 3;
2087 char mdiostr[24];
2088 const char *mdiodesc;
2089 uint8 *st;
2091 mdiodesc = (cis[i] == HNBU_MDIO_REGLIST) ?
2092 vstr_mdio : vstr_mdioex;
2094 ASSERT(((tlen - 1) % msize) == 0);
2096 st = &cis[i + 1]; /* start of reg list */
2097 for (j = 0; j < (tlen - 1); j += msize, st += msize) {
2098 snprintf(mdiostr, sizeof(mdiostr),
2099 mdiodesc, st[0]);
2100 varbuf_append(&b, mdiostr, (st[2] << 8) | st[1]);
2103 break;
2104 case HNBU_BRMIN:
2105 varbuf_append(&b, vstr_brmin,
2106 (cis[i + 4] << 24) |
2107 (cis[i + 3] << 16) |
2108 (cis[i + 2] << 8) |
2109 cis[i + 1]);
2110 break;
2112 case HNBU_BRMAX:
2113 varbuf_append(&b, vstr_brmax,
2114 (cis[i + 4] << 24) |
2115 (cis[i + 3] << 16) |
2116 (cis[i + 2] << 8) |
2117 cis[i + 1]);
2118 break;
2119 #endif /* BCM_BOOTLOADER */
2121 case HNBU_RDLID:
2122 varbuf_append(&b, vstr_rdlid,
2123 (cis[i + 2] << 8) | cis[i + 1]);
2124 break;
2126 case HNBU_GCI_CCR:
2128 /* format:
2129 * |0x80 | <== brcm
2130 * |len| <== variable, multiple of 5
2131 * |tup| <== tupletype
2132 * |ccreg_ix0|<== ix of ccreg [1byte]
2133 * |ccreg_val0|<= corr value [4bytes]
2134 * ---
2135 * Multiple registers are possible. for eg: we
2136 * can specify reg_ix3val3 and reg_ix5val5, etc
2138 char vstr_gci_ccreg_entry[16];
2139 int num_entries = 0;
2141 /* retrieve the index-value pairs
2142 * from tlen/5; where 5 is
2143 * sizeof(ccreg_ix(1)) +
2144 * sizeof(ccreg_val(4)).
2146 num_entries = tlen/5;
2148 for (j = 0; j < num_entries; j++) {
2149 snprintf(vstr_gci_ccreg_entry,
2150 sizeof(vstr_gci_ccreg_entry),
2151 "gcr%d=0x%%x", cis[i + (j*5) + 1]);
2153 varbuf_append(&b, vstr_gci_ccreg_entry,
2154 (cis[i + (j*5) + 5] << 24) |
2155 (cis[i + (j*5) + 4] << 16) |
2156 (cis[i + (j*5) + 3] << 8) |
2157 cis[i + (j*5) + 2]);
2160 break;
2162 #ifdef BCM_BOOTLOADER
2163 case HNBU_RDLRNDIS:
2164 varbuf_append(&b, vstr_rdlrndis, cis[i + 1]);
2165 break;
2167 case HNBU_RDLRWU:
2168 varbuf_append(&b, vstr_rdlrwu, cis[i + 1]);
2169 break;
2171 case HNBU_RDLSN:
2172 if (tlen >= 5)
2173 varbuf_append(&b, vstr_rdlsn,
2174 (cis[i + 4] << 24) |
2175 (cis[i + 3] << 16) |
2176 (cis[i + 2] << 8) |
2177 cis[i + 1]);
2178 else
2179 varbuf_append(&b, vstr_rdlsn,
2180 (cis[i + 2] << 8) |
2181 cis[i + 1]);
2182 break;
2184 case HNBU_PMUREGS:
2186 uint8 offset = 1, mode_addr, mode, addr;
2187 const char *fmt;
2189 do {
2190 mode_addr = cis[i+offset];
2192 mode = (mode_addr & PMUREGS_MODE_MASK)
2193 >> PMUREGS_MODE_SHIFT;
2194 addr = mode_addr & PMUREGS_ADDR_MASK;
2196 switch (mode) {
2197 case PMU_PLLREG_MODE:
2198 fmt = vstr_pllreg;
2199 break;
2200 case PMU_CCREG_MODE:
2201 fmt = vstr_ccreg;
2202 break;
2203 case PMU_VOLTREG_MODE:
2204 fmt = vstr_regctrl;
2205 break;
2206 case PMU_RES_TIME_MODE:
2207 fmt = vstr_time;
2208 break;
2209 case PMU_RESDEPEND_MODE:
2210 fmt = vstr_depreg;
2211 break;
2212 default:
2213 fmt = NULL;
2214 break;
2217 if (fmt != NULL) {
2218 varbuf_append(&b, fmt, addr,
2219 (cis[i + offset + 4] << 24) |
2220 (cis[i + offset + 3] << 16) |
2221 (cis[i + offset + 2] << 8) |
2222 cis[i + offset + 1]);
2225 offset += PMUREGS_TPL_SIZE;
2226 } while (offset < tlen);
2228 break;
2230 case HNBU_USBREGS:
2232 uint8 offset = 1, usb_reg;
2233 const char *fmt;
2235 do {
2236 usb_reg = cis[i+offset];
2238 switch (usb_reg) {
2239 case USB_DEV_CTRL_REG:
2240 fmt = vstr_usbdevctrl;
2241 break;
2242 case HSIC_PHY_CTRL1_REG:
2243 fmt = vstr_hsicphyctrl1;
2244 break;
2245 case HSIC_PHY_CTRL2_REG:
2246 fmt = vstr_hsicphyctrl2;
2247 break;
2248 default:
2249 fmt = NULL;
2250 break;
2253 if (fmt != NULL) {
2254 varbuf_append(&b, fmt,
2255 (cis[i + offset + 4] << 24) |
2256 (cis[i + offset + 3] << 16) |
2257 (cis[i + offset + 2] << 8) |
2258 cis[i + offset + 1]);
2261 offset += USBREGS_TPL_SIZE;
2262 } while (offset < tlen);
2264 break;
2266 case HNBU_USBRDY:
2267 /* The first byte of this tuple indicate if the host
2268 * needs to be informed about the readiness of
2269 * the HSIC/USB for enumeration on which GPIO should
2270 * the device assert this event.
2272 varbuf_append(&b, vstr_usbrdy, cis[i + 1]);
2274 /* The following fields in this OTP are optional.
2275 * The remaining bytes will indicate the delay required
2276 * before and/or after the ch_init(). The delay is defined
2277 * using 16-bits of this the MSB(bit15 of 15:0) will be
2278 * used indicate if the parameter is for Pre or Post delay.
2280 for (j = 2; j < USBRDY_MAXOTP_SIZE && j < tlen;
2281 j += 2) {
2282 uint16 usb_delay;
2284 usb_delay = cis[i + j] | (cis[i + j + 1] << 8);
2286 /* The bit-15 of the delay field will indicate the
2287 * type of delay (pre or post).
2289 if (usb_delay & USBRDY_DLY_TYPE) {
2290 varbuf_append(&b, vstr_usbpostdly,
2291 (usb_delay & USBRDY_DLY_MASK));
2292 } else {
2293 varbuf_append(&b, vstr_usbpredly,
2294 (usb_delay & USBRDY_DLY_MASK));
2297 break;
2299 case HNBU_BLDR_TIMEOUT:
2300 /* The Delay after USBConnect for timeout till dongle
2301 * receives get_descriptor request.
2303 varbuf_append(&b, vstr_bldr_reset_timeout,
2304 (cis[i + 1] | (cis[i + 2] << 8)));
2305 break;
2306 case HNBU_MUXENAB:
2307 varbuf_append(&b, vstr_muxenab, cis[i + 1]);
2308 break;
2309 #else
2310 case HNBU_AA:
2311 varbuf_append(&b, vstr_aa2g, cis[i + 1]);
2312 if (tlen >= 3)
2313 varbuf_append(&b, vstr_aa5g, cis[i + 2]);
2314 break;
2316 case HNBU_AG:
2317 varbuf_append(&b, vstr_ag, 0, cis[i + 1]);
2318 if (tlen >= 3)
2319 varbuf_append(&b, vstr_ag, 1, cis[i + 2]);
2320 if (tlen >= 4)
2321 varbuf_append(&b, vstr_ag, 2, cis[i + 3]);
2322 if (tlen >= 5)
2323 varbuf_append(&b, vstr_ag, 3, cis[i + 4]);
2324 ag_init = TRUE;
2325 break;
2327 case HNBU_ANT5G:
2328 varbuf_append(&b, vstr_aa5g, cis[i + 1]);
2329 varbuf_append(&b, vstr_ag, 1, cis[i + 2]);
2330 break;
2332 case HNBU_CC:
2333 ASSERT(sromrev == 1);
2334 varbuf_append(&b, vstr_cc, cis[i + 1]);
2335 break;
2337 case HNBU_PAPARMS:
2338 switch (tlen) {
2339 case 2:
2340 ASSERT(sromrev == 1);
2341 varbuf_append(&b, vstr_pa0maxpwr, cis[i + 1]);
2342 break;
2343 case 10:
2344 ASSERT(sromrev >= 2);
2345 varbuf_append(&b, vstr_opo, cis[i + 9]);
2346 /* FALLTHROUGH */
2347 case 9:
2348 varbuf_append(&b, vstr_pa0maxpwr, cis[i + 8]);
2349 /* FALLTHROUGH */
2350 BCMDONGLECASE(8)
2351 varbuf_append(&b, vstr_pa0itssit, cis[i + 7]);
2352 /* FALLTHROUGH */
2353 BCMDONGLECASE(7)
2354 for (j = 0; j < 3; j++) {
2355 varbuf_append(&b, vstr_pa0b[j],
2356 (cis[i + (j * 2) + 2] << 8) +
2357 cis[i + (j * 2) + 1]);
2359 break;
2360 default:
2361 ASSERT((tlen == 2) || (tlen == 9) || (tlen == 10));
2362 break;
2364 break;
2366 case HNBU_PAPARMS5G:
2367 ASSERT((sromrev == 2) || (sromrev == 3));
2368 switch (tlen) {
2369 case 23:
2370 varbuf_append(&b, vstr_pa1himaxpwr, cis[i + 22]);
2371 varbuf_append(&b, vstr_pa1lomaxpwr, cis[i + 21]);
2372 varbuf_append(&b, vstr_pa1maxpwr, cis[i + 20]);
2373 /* FALLTHROUGH */
2374 case 20:
2375 varbuf_append(&b, vstr_pa1itssit, cis[i + 19]);
2376 /* FALLTHROUGH */
2377 case 19:
2378 for (j = 0; j < 3; j++) {
2379 varbuf_append(&b, vstr_pa1b[j],
2380 (cis[i + (j * 2) + 2] << 8) +
2381 cis[i + (j * 2) + 1]);
2383 for (j = 3; j < 6; j++) {
2384 varbuf_append(&b, vstr_pa1lob[j - 3],
2385 (cis[i + (j * 2) + 2] << 8) +
2386 cis[i + (j * 2) + 1]);
2388 for (j = 6; j < 9; j++) {
2389 varbuf_append(&b, vstr_pa1hib[j - 6],
2390 (cis[i + (j * 2) + 2] << 8) +
2391 cis[i + (j * 2) + 1]);
2393 break;
2394 default:
2395 ASSERT((tlen == 19) ||
2396 (tlen == 20) || (tlen == 23));
2397 break;
2399 break;
2401 case HNBU_OEM:
2402 ASSERT(sromrev == 1);
2403 varbuf_append(&b, vstr_oem,
2404 cis[i + 1], cis[i + 2],
2405 cis[i + 3], cis[i + 4],
2406 cis[i + 5], cis[i + 6],
2407 cis[i + 7], cis[i + 8]);
2408 break;
2410 case HNBU_LEDS:
2411 for (j = 1; j <= 4; j++) {
2412 if (cis[i + j] != 0xff) {
2413 varbuf_append(&b, vstr_ledbh, j-1,
2414 cis[i + j]);
2417 break;
2419 case HNBU_CCODE:
2420 ASSERT(sromrev > 1);
2421 if ((cis[i + 1] == 0) || (cis[i + 2] == 0))
2422 varbuf_append(&b, vstr_noccode);
2423 else
2424 varbuf_append(&b, vstr_ccode,
2425 cis[i + 1], cis[i + 2]);
2426 varbuf_append(&b, vstr_cctl, cis[i + 3]);
2427 break;
2429 case HNBU_CCKPO:
2430 ASSERT(sromrev > 2);
2431 varbuf_append(&b, vstr_cckpo,
2432 (cis[i + 2] << 8) | cis[i + 1]);
2433 break;
2435 case HNBU_OFDMPO:
2436 ASSERT(sromrev > 2);
2437 varbuf_append(&b, vstr_ofdmpo,
2438 (cis[i + 4] << 24) |
2439 (cis[i + 3] << 16) |
2440 (cis[i + 2] << 8) |
2441 cis[i + 1]);
2442 break;
2444 case HNBU_WPS:
2445 varbuf_append(&b, vstr_wpsgpio, cis[i + 1]);
2446 if (tlen >= 3)
2447 varbuf_append(&b, vstr_wpsled, cis[i + 2]);
2448 break;
2450 case HNBU_RSSISMBXA2G:
2451 ASSERT(sromrev == 3);
2452 varbuf_append(&b, vstr_rssismf2g, cis[i + 1] & 0xf);
2453 varbuf_append(&b, vstr_rssismc2g, (cis[i + 1] >> 4) & 0xf);
2454 varbuf_append(&b, vstr_rssisav2g, cis[i + 2] & 0x7);
2455 varbuf_append(&b, vstr_bxa2g, (cis[i + 2] >> 3) & 0x3);
2456 break;
2458 case HNBU_RSSISMBXA5G:
2459 ASSERT(sromrev == 3);
2460 varbuf_append(&b, vstr_rssismf5g, cis[i + 1] & 0xf);
2461 varbuf_append(&b, vstr_rssismc5g, (cis[i + 1] >> 4) & 0xf);
2462 varbuf_append(&b, vstr_rssisav5g, cis[i + 2] & 0x7);
2463 varbuf_append(&b, vstr_bxa5g, (cis[i + 2] >> 3) & 0x3);
2464 break;
2466 case HNBU_TRI2G:
2467 ASSERT(sromrev == 3);
2468 varbuf_append(&b, vstr_tri2g, cis[i + 1]);
2469 break;
2471 case HNBU_TRI5G:
2472 ASSERT(sromrev == 3);
2473 varbuf_append(&b, vstr_tri5gl, cis[i + 1]);
2474 varbuf_append(&b, vstr_tri5g, cis[i + 2]);
2475 varbuf_append(&b, vstr_tri5gh, cis[i + 3]);
2476 break;
2478 case HNBU_RXPO2G:
2479 ASSERT(sromrev == 3);
2480 varbuf_append(&b, vstr_rxpo2g, cis[i + 1]);
2481 break;
2483 case HNBU_RXPO5G:
2484 ASSERT(sromrev == 3);
2485 varbuf_append(&b, vstr_rxpo5g, cis[i + 1]);
2486 break;
2488 case HNBU_MACADDR:
2489 if (!(ETHER_ISNULLADDR(&cis[i+1])) &&
2490 !(ETHER_ISMULTI(&cis[i+1]))) {
2491 bcm_ether_ntoa((struct ether_addr *)&cis[i + 1],
2492 eabuf);
2494 /* set boardnum if HNBU_BOARDNUM not seen yet */
2495 if (boardnum == -1)
2496 boardnum = (cis[i + 5] << 8) + cis[i + 6];
2498 break;
2500 case HNBU_LEDDC:
2501 /* CIS leddc only has 16bits, convert it to 32bits */
2502 w32 = ((cis[i + 2] << 24) | /* oncount */
2503 (cis[i + 1] << 8)); /* offcount */
2504 varbuf_append(&b, vstr_leddc, w32);
2505 break;
2507 case HNBU_CHAINSWITCH:
2508 varbuf_append(&b, vstr_txchain, cis[i + 1]);
2509 varbuf_append(&b, vstr_rxchain, cis[i + 2]);
2510 varbuf_append(&b, vstr_antswitch,
2511 (cis[i + 4] << 8) + cis[i + 3]);
2512 break;
2514 case HNBU_ELNA2G:
2515 varbuf_append(&b, vstr_elna2g, cis[i + 1]);
2516 break;
2518 case HNBU_ELNA5G:
2519 varbuf_append(&b, vstr_elna5g, cis[i + 1]);
2520 break;
2522 case HNBU_REGREV:
2523 varbuf_append(&b, vstr_regrev, cis[i + 1]);
2524 break;
2526 case HNBU_FEM: {
2527 uint16 fem = (cis[i + 2] << 8) + cis[i + 1];
2528 varbuf_append(&b, vstr_antswctl2g, (fem &
2529 SROM8_FEM_ANTSWLUT_MASK) >>
2530 SROM8_FEM_ANTSWLUT_SHIFT);
2531 varbuf_append(&b, vstr_triso2g, (fem &
2532 SROM8_FEM_TR_ISO_MASK) >>
2533 SROM8_FEM_TR_ISO_SHIFT);
2534 varbuf_append(&b, vstr_pdetrange2g, (fem &
2535 SROM8_FEM_PDET_RANGE_MASK) >>
2536 SROM8_FEM_PDET_RANGE_SHIFT);
2537 varbuf_append(&b, vstr_extpagain2g, (fem &
2538 SROM8_FEM_EXTPA_GAIN_MASK) >>
2539 SROM8_FEM_EXTPA_GAIN_SHIFT);
2540 varbuf_append(&b, vstr_tssipos2g, (fem &
2541 SROM8_FEM_TSSIPOS_MASK) >>
2542 SROM8_FEM_TSSIPOS_SHIFT);
2543 if (tlen < 5) break;
2545 fem = (cis[i + 4] << 8) + cis[i + 3];
2546 varbuf_append(&b, vstr_antswctl5g, (fem &
2547 SROM8_FEM_ANTSWLUT_MASK) >>
2548 SROM8_FEM_ANTSWLUT_SHIFT);
2549 varbuf_append(&b, vstr_triso5g, (fem &
2550 SROM8_FEM_TR_ISO_MASK) >>
2551 SROM8_FEM_TR_ISO_SHIFT);
2552 varbuf_append(&b, vstr_pdetrange5g, (fem &
2553 SROM8_FEM_PDET_RANGE_MASK) >>
2554 SROM8_FEM_PDET_RANGE_SHIFT);
2555 varbuf_append(&b, vstr_extpagain5g, (fem &
2556 SROM8_FEM_EXTPA_GAIN_MASK) >>
2557 SROM8_FEM_EXTPA_GAIN_SHIFT);
2558 varbuf_append(&b, vstr_tssipos5g, (fem &
2559 SROM8_FEM_TSSIPOS_MASK) >>
2560 SROM8_FEM_TSSIPOS_SHIFT);
2561 break;
2564 case HNBU_PAPARMS_C0:
2565 varbuf_append(&b, vstr_maxp2ga, 0, cis[i + 1]);
2566 varbuf_append(&b, vstr_itt2ga0, cis[i + 2]);
2567 varbuf_append(&b, vstr_pa, 2, 0, 0,
2568 (cis[i + 4] << 8) + cis[i + 3]);
2569 varbuf_append(&b, vstr_pa, 2, 1, 0,
2570 (cis[i + 6] << 8) + cis[i + 5]);
2571 varbuf_append(&b, vstr_pa, 2, 2, 0,
2572 (cis[i + 8] << 8) + cis[i + 7]);
2573 if (tlen < 31) break;
2575 varbuf_append(&b, vstr_maxp5ga0, cis[i + 9]);
2576 varbuf_append(&b, vstr_itt5ga0, cis[i + 10]);
2577 varbuf_append(&b, vstr_maxp5gha0, cis[i + 11]);
2578 varbuf_append(&b, vstr_maxp5gla0, cis[i + 12]);
2579 varbuf_append(&b, vstr_pa, 5, 0, 0,
2580 (cis[i + 14] << 8) + cis[i + 13]);
2581 varbuf_append(&b, vstr_pa, 5, 1, 0,
2582 (cis[i + 16] << 8) + cis[i + 15]);
2583 varbuf_append(&b, vstr_pa, 5, 2, 0,
2584 (cis[i + 18] << 8) + cis[i + 17]);
2585 varbuf_append(&b, vstr_pahl, 5, 'l', 0, 0,
2586 (cis[i + 20] << 8) + cis[i + 19]);
2587 varbuf_append(&b, vstr_pahl, 5, 'l', 1, 0,
2588 (cis[i + 22] << 8) + cis[i + 21]);
2589 varbuf_append(&b, vstr_pahl, 5, 'l', 2, 0,
2590 (cis[i + 24] << 8) + cis[i + 23]);
2591 varbuf_append(&b, vstr_pahl, 5, 'h', 0, 0,
2592 (cis[i + 26] << 8) + cis[i + 25]);
2593 varbuf_append(&b, vstr_pahl, 5, 'h', 1, 0,
2594 (cis[i + 28] << 8) + cis[i + 27]);
2595 varbuf_append(&b, vstr_pahl, 5, 'h', 2, 0,
2596 (cis[i + 30] << 8) + cis[i + 29]);
2597 break;
2599 case HNBU_PAPARMS_C1:
2600 varbuf_append(&b, vstr_maxp2ga, 1, cis[i + 1]);
2601 varbuf_append(&b, vstr_itt2ga1, cis[i + 2]);
2602 varbuf_append(&b, vstr_pa, 2, 0, 1,
2603 (cis[i + 4] << 8) + cis[i + 3]);
2604 varbuf_append(&b, vstr_pa, 2, 1, 1,
2605 (cis[i + 6] << 8) + cis[i + 5]);
2606 varbuf_append(&b, vstr_pa, 2, 2, 1,
2607 (cis[i + 8] << 8) + cis[i + 7]);
2608 if (tlen < 31) break;
2610 varbuf_append(&b, vstr_maxp5ga1, cis[i + 9]);
2611 varbuf_append(&b, vstr_itt5ga1, cis[i + 10]);
2612 varbuf_append(&b, vstr_maxp5gha1, cis[i + 11]);
2613 varbuf_append(&b, vstr_maxp5gla1, cis[i + 12]);
2614 varbuf_append(&b, vstr_pa, 5, 0, 1,
2615 (cis[i + 14] << 8) + cis[i + 13]);
2616 varbuf_append(&b, vstr_pa, 5, 1, 1,
2617 (cis[i + 16] << 8) + cis[i + 15]);
2618 varbuf_append(&b, vstr_pa, 5, 2, 1,
2619 (cis[i + 18] << 8) + cis[i + 17]);
2620 varbuf_append(&b, vstr_pahl, 5, 'l', 0, 1,
2621 (cis[i + 20] << 8) + cis[i + 19]);
2622 varbuf_append(&b, vstr_pahl, 5, 'l', 1, 1,
2623 (cis[i + 22] << 8) + cis[i + 21]);
2624 varbuf_append(&b, vstr_pahl, 5, 'l', 2, 1,
2625 (cis[i + 24] << 8) + cis[i + 23]);
2626 varbuf_append(&b, vstr_pahl, 5, 'h', 0, 1,
2627 (cis[i + 26] << 8) + cis[i + 25]);
2628 varbuf_append(&b, vstr_pahl, 5, 'h', 1, 1,
2629 (cis[i + 28] << 8) + cis[i + 27]);
2630 varbuf_append(&b, vstr_pahl, 5, 'h', 2, 1,
2631 (cis[i + 30] << 8) + cis[i + 29]);
2632 break;
2634 case HNBU_PO_CCKOFDM:
2635 varbuf_append(&b, vstr_cck2gpo,
2636 (cis[i + 2] << 8) + cis[i + 1]);
2637 varbuf_append(&b, vstr_ofdm2gpo,
2638 (cis[i + 6] << 24) + (cis[i + 5] << 16) +
2639 (cis[i + 4] << 8) + cis[i + 3]);
2640 if (tlen < 19) break;
2642 varbuf_append(&b, vstr_ofdm5gpo,
2643 (cis[i + 10] << 24) + (cis[i + 9] << 16) +
2644 (cis[i + 8] << 8) + cis[i + 7]);
2645 varbuf_append(&b, vstr_ofdm5glpo,
2646 (cis[i + 14] << 24) + (cis[i + 13] << 16) +
2647 (cis[i + 12] << 8) + cis[i + 11]);
2648 varbuf_append(&b, vstr_ofdm5ghpo,
2649 (cis[i + 18] << 24) + (cis[i + 17] << 16) +
2650 (cis[i + 16] << 8) + cis[i + 15]);
2651 break;
2653 case HNBU_PO_MCS2G:
2654 for (j = 0; j <= (tlen/2); j++) {
2655 varbuf_append(&b, vstr_mcspo, 2, j,
2656 (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]);
2658 break;
2660 case HNBU_PO_MCS5GM:
2661 for (j = 0; j <= (tlen/2); j++) {
2662 varbuf_append(&b, vstr_mcspo, 5, j,
2663 (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]);
2665 break;
2667 case HNBU_PO_MCS5GLH:
2668 for (j = 0; j <= (tlen/4); j++) {
2669 varbuf_append(&b, vstr_mcspohl, 5, 'l', j,
2670 (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]);
2673 for (j = 0; j <= (tlen/4); j++) {
2674 varbuf_append(&b, vstr_mcspohl, 5, 'h', j,
2675 (cis[i + ((tlen/2)+2) + 2*j] << 8) +
2676 cis[i + ((tlen/2)+1) + 2*j]);
2679 break;
2681 case HNBU_PO_CDD:
2682 varbuf_append(&b, vstr_cddpo,
2683 (cis[i + 2] << 8) + cis[i + 1]);
2684 break;
2686 case HNBU_PO_STBC:
2687 varbuf_append(&b, vstr_stbcpo,
2688 (cis[i + 2] << 8) + cis[i + 1]);
2689 break;
2691 case HNBU_PO_40M:
2692 varbuf_append(&b, vstr_bw40po,
2693 (cis[i + 2] << 8) + cis[i + 1]);
2694 break;
2696 case HNBU_PO_40MDUP:
2697 varbuf_append(&b, vstr_bwduppo,
2698 (cis[i + 2] << 8) + cis[i + 1]);
2699 break;
2701 case HNBU_OFDMPO5G:
2702 varbuf_append(&b, vstr_ofdm5gpo,
2703 (cis[i + 4] << 24) + (cis[i + 3] << 16) +
2704 (cis[i + 2] << 8) + cis[i + 1]);
2705 varbuf_append(&b, vstr_ofdm5glpo,
2706 (cis[i + 8] << 24) + (cis[i + 7] << 16) +
2707 (cis[i + 6] << 8) + cis[i + 5]);
2708 varbuf_append(&b, vstr_ofdm5ghpo,
2709 (cis[i + 12] << 24) + (cis[i + 11] << 16) +
2710 (cis[i + 10] << 8) + cis[i + 9]);
2711 break;
2712 /* Power per rate for SROM V9 */
2713 case HNBU_CCKBW202GPO:
2714 varbuf_append(&b, vstr_cckbw202gpo[0],
2715 ((cis[i + 2] << 8) + cis[i + 1]));
2716 if (tlen > 4)
2717 varbuf_append(&b, vstr_cckbw202gpo[1],
2718 ((cis[i + 4] << 8) + cis[i + 3]));
2719 break;
2721 case HNBU_LEGOFDMBW202GPO:
2722 varbuf_append(&b, vstr_legofdmbw202gpo[0],
2723 ((cis[i + 4] << 24) + (cis[i + 3] << 16) +
2724 (cis[i + 2] << 8) + cis[i + 1]));
2725 if (tlen > 6) {
2726 varbuf_append(&b, vstr_legofdmbw202gpo[1],
2727 ((cis[i + 8] << 24) + (cis[i + 7] << 16) +
2728 (cis[i + 6] << 8) + cis[i + 5]));
2730 break;
2732 case HNBU_LEGOFDMBW205GPO:
2733 for (j = 0; j < 6; j++) {
2734 if (tlen < (2 + 4 * j))
2735 break;
2736 varbuf_append(&b, vstr_legofdmbw205gpo[j],
2737 ((cis[4 * j + i + 4] << 24)
2738 + (cis[4 * j + i + 3] << 16)
2739 + (cis[4 * j + i + 2] << 8)
2740 + cis[4 * j + i + 1]));
2742 break;
2744 case HNBU_MCS2GPO:
2745 for (j = 0; j < 3; j++) {
2746 if (tlen < (2 + 4 * j))
2747 break;
2748 varbuf_append(&b, vstr_mcs2gpo[j],
2749 ((cis[4 * j + i + 4] << 24)
2750 + (cis[4 * j + i + 3] << 16)
2751 + (cis[4 * j + i + 2] << 8)
2752 + cis[4 * j + i + 1]));
2754 break;
2756 case HNBU_MCS5GLPO:
2757 for (j = 0; j < 3; j++) {
2758 if (tlen < (2 + 4 * j))
2759 break;
2760 varbuf_append(&b, vstr_mcs5glpo[j],
2761 ((cis[4 * j + i + 4] << 24)
2762 + (cis[4 * j + i + 3] << 16)
2763 + (cis[4 * j + i + 2] << 8)
2764 + cis[4 * j + i + 1]));
2766 break;
2768 case HNBU_MCS5GMPO:
2769 for (j = 0; j < 3; j++) {
2770 if (tlen < (2 + 4 * j))
2771 break;
2772 varbuf_append(&b, vstr_mcs5gmpo[j],
2773 ((cis[4 * j + i + 4] << 24)
2774 + (cis[4 * j + i + 3] << 16)
2775 + (cis[4 * j + i + 2] << 8)
2776 + cis[4 * j + i + 1]));
2778 break;
2780 case HNBU_MCS5GHPO:
2781 for (j = 0; j < 3; j++) {
2782 if (tlen < (2 + 4 * j))
2783 break;
2784 varbuf_append(&b, vstr_mcs5ghpo[j],
2785 ((cis[4 * j + i + 4] << 24)
2786 + (cis[4 * j + i + 3] << 16)
2787 + (cis[4 * j + i + 2] << 8)
2788 + cis[4 * j + i + 1]));
2790 break;
2792 case HNBU_MCS32PO:
2793 varbuf_append(&b, vstr_mcs32po,
2794 (cis[i + 2] << 8) + cis[i + 1]);
2795 break;
2797 case HNBU_LEG40DUPPO:
2798 varbuf_append(&b, vstr_legofdm40duppo,
2799 (cis[i + 2] << 8) + cis[i + 1]);
2800 break;
2802 case HNBU_CUSTOM1:
2803 varbuf_append(&b, vstr_custom, 1, ((cis[i + 4] << 24) +
2804 (cis[i + 3] << 16) + (cis[i + 2] << 8) +
2805 cis[i + 1]));
2806 break;
2808 #if defined(BCMCCISSR3)
2809 case HNBU_SROM3SWRGN:
2810 if (tlen >= 73) {
2811 uint16 srom[35];
2812 uint8 srev = cis[i + 1 + 70];
2813 ASSERT(srev == 3);
2814 /* make tuple value 16-bit aligned and parse it */
2815 bcopy(&cis[i + 1], srom, sizeof(srom));
2816 _initvars_srom_pci(srev, srom, SROM3_SWRGN_OFF, &b);
2817 /* 2.4G antenna gain is included in SROM */
2818 ag_init = TRUE;
2819 /* Ethernet MAC address is included in SROM */
2820 eabuf[0] = 0;
2821 boardnum = -1;
2823 /* create extra variables */
2824 if (tlen >= 75)
2825 varbuf_append(&b, vstr_vendid,
2826 (cis[i + 1 + 73] << 8) +
2827 cis[i + 1 + 72]);
2828 if (tlen >= 77)
2829 varbuf_append(&b, vstr_devid,
2830 (cis[i + 1 + 75] << 8) +
2831 cis[i + 1 + 74]);
2832 if (tlen >= 79)
2833 varbuf_append(&b, vstr_xtalfreq,
2834 (cis[i + 1 + 77] << 8) +
2835 cis[i + 1 + 76]);
2836 break;
2837 #endif
2839 case HNBU_CCKFILTTYPE:
2840 varbuf_append(&b, vstr_cckdigfilttype,
2841 (cis[i + 1]));
2842 break;
2844 case HNBU_TEMPTHRESH:
2845 varbuf_append(&b, vstr_tempthresh,
2846 (cis[i + 1]));
2847 /* period in msb nibble */
2848 varbuf_append(&b, vstr_temps_period,
2849 (cis[i + 2] >> 4));
2850 /* hysterisis in lsb nibble */
2851 varbuf_append(&b, vstr_temp_hysteresis,
2852 (cis[i + 2] & 0xF));
2853 if (tlen >= 4)
2854 varbuf_append(&b, vstr_tempoffset,
2855 (cis[i + 3]));
2856 if (tlen >= 5) {
2857 varbuf_append(&b, vstr_temp_corrx,
2858 (cis[i + 4] >> 2));
2859 varbuf_append(&b, vstr_tempsense_option,
2860 (cis[i + 4] & 0x3));
2862 if (tlen >= 6)
2863 varbuf_append(&b, vstr_phycal_tempdelta,
2864 (cis[i + 5]));
2865 break;
2867 case HNBU_FEM_CFG:
2868 /* fem_cfg1 */
2869 varbuf_append(&b, vstr_tssiposslopeg, 2,
2870 (cis[i + 1] & 0x1));
2871 varbuf_append(&b, vstr_epagaing, 2,
2872 (cis[i + 1] & 0xe) >> 1);
2873 varbuf_append(&b, vstr_pdgaing, 2,
2874 ((cis[i + 2] & 0x1) << 8) +
2875 ((cis[i + 1] & 0xf0) >> 4));
2876 varbuf_append(&b, vstr_tworangetssi, 2,
2877 (cis[i + 2] & 0x2) >> 1);
2878 varbuf_append(&b, vstr_papdcap, 2,
2879 (cis[i + 2] & 0x4) >> 2);
2880 varbuf_append(&b, vstr_femctrl,
2881 (cis[i + 2] & 0xf8) >> 3);
2882 /* fem_cfg2 */
2883 varbuf_append(&b, vstr_tssiposslopeg, 5,
2884 (cis[i + 3] & 0x1));
2885 varbuf_append(&b, vstr_epagaing, 5,
2886 (cis[i + 3] & 0xe) >> 1);
2887 varbuf_append(&b, vstr_pdgaing, 5,
2888 ((cis[i + 4] & 0x1) << 8) +
2889 ((cis[i + 3] & 0xf0) >> 4));
2890 varbuf_append(&b, vstr_tworangetssi, 2,
2891 (cis[i + 4] & 0x2) >> 1);
2892 varbuf_append(&b, vstr_papdcap, 5,
2893 (cis[i + 4] & 0x4) >> 2);
2894 varbuf_append(&b, vstr_gainctrlsph,
2895 (cis[i + 4] & 0xf8) >> 3);
2896 break;
2898 case HNBU_ACPA_C0:
2900 const int a = 0;
2902 varbuf_append(&b, vstr_subband5gver,
2903 (cis[i + 2] << 8) + cis[i + 1]);
2904 varbuf_append(&b, vstr_maxp2ga, a,
2905 (cis[i + 4] << 8) + cis[i + 3]);
2906 /* pa2g */
2907 varbuf_append(&b, vstr_pa2ga, 2, a,
2908 (cis[i + 6] << 8) + cis[i + 5],
2909 (cis[i + 8] << 8) + cis[i + 7],
2910 (cis[i + 10] << 8) + cis[i + 9]);
2911 /* rxgains */
2912 varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a,
2913 cis[i + 11] & 0x7);
2914 varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a,
2915 (cis[i + 11] & 0x78) >> 3);
2916 varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a,
2917 (cis[i + 11] & 0x80) >> 7);
2918 varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a,
2919 cis[i + 12] & 0x7);
2920 varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a,
2921 (cis[i + 12] & 0x78) >> 3);
2922 varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a,
2923 (cis[i + 12] & 0x80) >> 7);
2924 /* maxp5g */
2925 varbuf_append(&b, vstr_maxp5ga, a,
2926 cis[i + 13],
2927 cis[i + 14],
2928 cis[i + 15],
2929 cis[i + 16]);
2930 /* pa5g */
2931 varbuf_append(&b, vstr_pa5ga, a,
2932 (cis[i + 18] << 8) + cis[i + 17],
2933 (cis[i + 20] << 8) + cis[i + 19],
2934 (cis[i + 22] << 8) + cis[i + 21],
2935 (cis[i + 24] << 8) + cis[i + 23],
2936 (cis[i + 26] << 8) + cis[i + 25],
2937 (cis[i + 28] << 8) + cis[i + 27],
2938 (cis[i + 30] << 8) + cis[i + 29],
2939 (cis[i + 32] << 8) + cis[i + 31],
2940 (cis[i + 34] << 8) + cis[i + 33],
2941 (cis[i + 36] << 8) + cis[i + 35],
2942 (cis[i + 38] << 8) + cis[i + 37],
2943 (cis[i + 40] << 8) + cis[i + 39]);
2944 break;
2947 case HNBU_ACPA_C1:
2949 const int a = 1;
2951 varbuf_append(&b, vstr_maxp2ga, a,
2952 (cis[i + 2] << 8) + cis[i + 1]);
2953 /* pa2g */
2954 varbuf_append(&b, vstr_pa2ga, 2, a,
2955 (cis[i + 4] << 8) + cis[i + 3],
2956 (cis[i + 6] << 8) + cis[i + 5],
2957 (cis[i + 8] << 8) + cis[i + 7]);
2958 /* rxgains */
2959 varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a,
2960 cis[i + 9] & 0x7);
2961 varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a,
2962 (cis[i + 9] & 0x78) >> 3);
2963 varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a,
2964 (cis[i + 9] & 0x80) >> 7);
2965 varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a,
2966 cis[i + 10] & 0x7);
2967 varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a,
2968 (cis[i + 10] & 0x78) >> 3);
2969 varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a,
2970 (cis[i + 10] & 0x80) >> 7);
2971 /* maxp5g */
2972 varbuf_append(&b, vstr_maxp5ga, a,
2973 cis[i + 11],
2974 cis[i + 12],
2975 cis[i + 13],
2976 cis[i + 14]);
2977 /* pa5g */
2978 varbuf_append(&b, vstr_pa5ga, a,
2979 (cis[i + 16] << 8) + cis[i + 15],
2980 (cis[i + 18] << 8) + cis[i + 17],
2981 (cis[i + 20] << 8) + cis[i + 19],
2982 (cis[i + 22] << 8) + cis[i + 21],
2983 (cis[i + 24] << 8) + cis[i + 23],
2984 (cis[i + 26] << 8) + cis[i + 25],
2985 (cis[i + 28] << 8) + cis[i + 27],
2986 (cis[i + 30] << 8) + cis[i + 29],
2987 (cis[i + 32] << 8) + cis[i + 31],
2988 (cis[i + 34] << 8) + cis[i + 33],
2989 (cis[i + 36] << 8) + cis[i + 35],
2990 (cis[i + 38] << 8) + cis[i + 37]);
2991 break;
2994 case HNBU_ACPA_C2:
2996 const int a = 2;
2998 varbuf_append(&b, vstr_maxp2ga, a,
2999 (cis[i + 2] << 8) + cis[i + 1]);
3000 /* pa2g */
3001 varbuf_append(&b, vstr_pa2ga, 2, a,
3002 (cis[i + 4] << 8) + cis[i + 3],
3003 (cis[i + 6] << 8) + cis[i + 5],
3004 (cis[i + 8] << 8) + cis[i + 7]);
3005 /* rxgains */
3006 varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a,
3007 cis[i + 9] & 0x7);
3008 varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a,
3009 (cis[i + 9] & 0x78) >> 3);
3010 varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a,
3011 (cis[i + 9] & 0x80) >> 7);
3012 varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a,
3013 cis[i + 10] & 0x7);
3014 varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a,
3015 (cis[i + 10] & 0x78) >> 3);
3016 varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a,
3017 (cis[i + 10] & 0x80) >> 7);
3018 /* maxp5g */
3019 varbuf_append(&b, vstr_maxp5ga, a,
3020 cis[i + 11],
3021 cis[i + 12],
3022 cis[i + 13],
3023 cis[i + 14]);
3024 /* pa5g */
3025 varbuf_append(&b, vstr_pa5ga, a,
3026 (cis[i + 16] << 8) + cis[i + 15],
3027 (cis[i + 18] << 8) + cis[i + 17],
3028 (cis[i + 20] << 8) + cis[i + 19],
3029 (cis[i + 22] << 8) + cis[i + 21],
3030 (cis[i + 24] << 8) + cis[i + 23],
3031 (cis[i + 26] << 8) + cis[i + 25],
3032 (cis[i + 28] << 8) + cis[i + 27],
3033 (cis[i + 30] << 8) + cis[i + 29],
3034 (cis[i + 32] << 8) + cis[i + 31],
3035 (cis[i + 34] << 8) + cis[i + 33],
3036 (cis[i + 36] << 8) + cis[i + 35],
3037 (cis[i + 38] << 8) + cis[i + 37]);
3038 break;
3041 case HNBU_MEAS_PWR:
3042 varbuf_append(&b, vstr_measpower, cis[i + 1]);
3043 varbuf_append(&b, vstr_measpowerX, 1, (cis[i + 2]));
3044 varbuf_append(&b, vstr_measpowerX, 2, (cis[i + 3]));
3045 varbuf_append(&b, vstr_rawtempsense,
3046 ((cis[i + 5] & 0x1) << 8) + cis[i + 4]);
3047 break;
3049 case HNBU_ACPPR_2GPO:
3050 varbuf_append(&b, vstr_dot11agofdmhrbw202gpo,
3051 (cis[i + 2] << 8) + cis[i + 1]);
3052 varbuf_append(&b, vstr_ofdmlrbw202gpo,
3053 (cis[i + 4] << 8) + cis[i + 3]);
3054 break;
3056 case HNBU_ACPPR_5GPO:
3057 varbuf_append(&b, vstr_mcsbw805glpo,
3058 (cis[i + 2] << 8) + cis[i + 1]);
3059 varbuf_append(&b, vstr_mcsbw1605glpo,
3060 (cis[i + 4] << 8) + cis[i + 3]);
3061 varbuf_append(&b, vstr_mcsbw805gmpo,
3062 (cis[i + 6] << 8) + cis[i + 5]);
3063 varbuf_append(&b, vstr_mcsbw1605gmpo,
3064 (cis[i + 8] << 8) + cis[i + 7]);
3065 varbuf_append(&b, vstr_mcsbw805ghpo,
3066 (cis[i + 10] << 8) + cis[i + 9]);
3067 varbuf_append(&b, vstr_mcsbw1605ghpo,
3068 (cis[i + 12] << 8) + cis[i + 11]);
3069 varbuf_append(&b, vstr_mcslr5rlpo,
3070 (cis[i + 14] << 8) + cis[i + 13]);
3071 varbuf_append(&b, vstr_mcslr5gmpo,
3072 (cis[i + 16] << 8) + cis[i + 15]);
3073 varbuf_append(&b, vstr_mcslr5ghpo,
3074 (cis[i + 18] << 8) + cis[i + 17]);
3075 break;
3077 case HNBU_ACPPR_SBPO:
3078 varbuf_append(&b, vstr_sb20in40rrpo, 'h',
3079 (cis[i + 2] << 8) + cis[i + 1]);
3080 varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'l',
3081 (cis[i + 4] << 8) + cis[i + 3]);
3082 varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'l',
3083 (cis[i + 6] << 8) + cis[i + 5]);
3084 varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'm',
3085 (cis[i + 8] << 8) + cis[i + 7]);
3086 varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'm',
3087 (cis[i + 10] << 8) + cis[i + 9]);
3088 varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'h',
3089 (cis[i + 12] << 8) + cis[i + 11]);
3090 varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'h',
3091 (cis[i + 14] << 8) + cis[i + 13]);
3092 varbuf_append(&b, vstr_sb20in40rrpo, 'l',
3093 (cis[i + 16] << 8) + cis[i + 15]);
3094 varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'l',
3095 (cis[i + 18] << 8) + cis[i + 17]);
3096 varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'l',
3097 (cis[i + 20] << 8) + cis[i + 19]);
3098 varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'm',
3099 (cis[i + 22] << 8) + cis[i + 21]);
3100 varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'm',
3101 (cis[i + 24] << 8) + cis[i + 23]);
3102 varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'h',
3103 (cis[i + 26] << 8) + cis[i + 25]);
3104 varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'h',
3105 (cis[i + 28] << 8) + cis[i + 27]);
3106 varbuf_append(&b, vstr_dot11agduprpo, 'h',
3107 (cis[i + 30] << 8) + cis[i + 24]);
3108 varbuf_append(&b, vstr_dot11agduprpo, 'l',
3109 (cis[i + 32] << 8) + cis[i + 26]);
3110 break;
3112 case HNBU_NOISELVL:
3113 /* noiselvl2g */
3114 varbuf_append(&b, vstr_noiselvl2ga, 0,
3115 (cis[i + 1] & 0x1f));
3116 varbuf_append(&b, vstr_noiselvl2ga, 1,
3117 ((cis[i + 2] & 0x3) << 4) +
3118 ((cis[i + 1] & 0xe0) >> 4));
3119 varbuf_append(&b, vstr_noiselvl2ga, 2,
3120 (cis[i + 2] & 0x7c) >> 2);
3121 /* noiselvl5gl */
3122 varbuf_append(&b, vstr_noiselvl5ga, 'l', 0,
3123 (cis[i + 3] & 0x1f));
3124 varbuf_append(&b, vstr_noiselvl5ga, 'l', 1,
3125 ((cis[i + 4] & 0x3) << 4) +
3126 ((cis[i + 3] & 0xe0) >> 4));
3127 varbuf_append(&b, vstr_noiselvl5ga, 'l', 2,
3128 (cis[i + 4] & 0x7c) >> 2);
3129 /* noiselvl5gm */
3130 varbuf_append(&b, vstr_noiselvl5ga, 'm', 0,
3131 (cis[i + 5] & 0x1f));
3132 varbuf_append(&b, vstr_noiselvl5ga, 'm', 1,
3133 ((cis[i + 6] & 0x3) << 4) +
3134 ((cis[i + 5] & 0xe0) >> 4));
3135 varbuf_append(&b, vstr_noiselvl5ga, 'm', 2,
3136 (cis[i + 6] & 0x7c) >> 2);
3137 /* noiselvl5gh */
3138 varbuf_append(&b, vstr_noiselvl5ga, 'h', 0,
3139 (cis[i + 7] & 0x1f));
3140 varbuf_append(&b, vstr_noiselvl5ga, 'h', 1,
3141 ((cis[i + 8] & 0x3) << 4) +
3142 ((cis[i + 7] & 0xe0) >> 4));
3143 varbuf_append(&b, vstr_noiselvl5ga, 'h', 2,
3144 (cis[i + 8] & 0x7c) >> 2);
3145 /* noiselvl5gu */
3146 varbuf_append(&b, vstr_noiselvl5ga, 'u', 0,
3147 (cis[i + 9] & 0x1f));
3148 varbuf_append(&b, vstr_noiselvl5ga, 'u', 1,
3149 ((cis[i + 10] & 0x3) << 4) +
3150 ((cis[i + 9] & 0xe0) >> 4));
3151 varbuf_append(&b, vstr_noiselvl5ga, 'u', 2,
3152 (cis[i + 10] & 0x7c) >> 2);
3153 break;
3155 case HNBU_RXGAIN_ERR:
3156 varbuf_append(&b, vstr_rxgainerr2g,
3157 (cis[i + 2] << 8) + cis[i + 1]);
3158 varbuf_append(&b, vstr_rxgainerr5g,
3159 (cis[i + 4] << 8) + cis[i + 3],
3160 (cis[i + 6] << 8) + cis[i + 5],
3161 (cis[i + 8] << 8) + cis[i + 7],
3162 (cis[i + 10] << 8) + cis[i + 9]);
3163 break;
3165 case HNBU_AGBGA:
3166 varbuf_append(&b, vstr_agbg, 0, cis[i + 1]);
3167 varbuf_append(&b, vstr_agbg, 1, cis[i + 2]);
3168 varbuf_append(&b, vstr_agbg, 2, cis[i + 3]);
3169 varbuf_append(&b, vstr_aga, 3, cis[i + 4]);
3170 varbuf_append(&b, vstr_aga, 4, cis[i + 5]);
3171 varbuf_append(&b, vstr_aga, 5, cis[i + 6]);
3172 break;
3174 case HNBU_UUID:
3176 /* uuid format 12345678-1234-5678-1234-567812345678 */
3178 char uuidstr[37]; /* 32 ids, 4 '-', 1 Null */
3180 snprintf(uuidstr, sizeof(uuidstr),
3181 "%02X%02X%02X%02X-%02X%02X-%02X%02X-"
3182 "%02X%02X-%02X%02X%02X%02X%02X%02X",
3183 cis[i + 1], cis[i + 2], cis[i + 3], cis[i + 4],
3184 cis[i + 5], cis[i + 6], cis[i + 7], cis[i + 8],
3185 cis[i + 9], cis[i + 10], cis[i + 11], cis[i + 12],
3186 cis[i + 13], cis[i + 14], cis[i + 15], cis[i + 16]);
3188 varbuf_append(&b, vstr_uuid, uuidstr);
3189 break;
3192 #endif /* !BCM_BOOTLOADER */
3195 break;
3197 i += tlen;
3198 } while (tup != CISTPL_END);
3201 if (boardnum != -1) {
3202 varbuf_append(&b, vstr_boardnum, boardnum);
3205 if (eabuf[0]) {
3206 varbuf_append(&b, vstr_macaddr, eabuf);
3209 #ifndef BCM_BOOTLOADER
3210 /* if there is no antenna gain field, set default */
3211 if (getvar(NULL, "ag0") == NULL && ag_init == FALSE) {
3212 varbuf_append(&b, vstr_ag, 0, 0xff);
3214 #endif
3216 #if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND)
3217 varbuf_append(&b, vstr_end, NULL);
3218 #endif /* BCMUSBDEV_BMAC */
3220 /* final nullbyte terminator */
3221 ASSERT(b.size >= 1);
3222 *b.buf++ = '\0';
3224 ASSERT(b.buf - base <= MAXSZ_NVRAM_VARS);
3225 err = initvars_table(osh, base, b.buf, vars, count);
3227 MFREE(osh, base, MAXSZ_NVRAM_VARS);
3228 return err;
3231 /* set PCMCIA sprom command register */
3232 static int
3233 sprom_cmd_pcmcia(osl_t *osh, uint8 cmd)
3235 uint8 status = 0;
3236 uint wait_cnt = 1000;
3238 /* write sprom command register */
3239 OSL_PCMCIA_WRITE_ATTR(osh, SROM_CS, &cmd, 1);
3241 /* wait status */
3242 while (wait_cnt--) {
3243 OSL_PCMCIA_READ_ATTR(osh, SROM_CS, &status, 1);
3244 if (status & SROM_DONE)
3245 return 0;
3248 return 1;
3251 /* read a word from the PCMCIA srom */
3252 static int
3253 sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data)
3255 uint8 addr_l, addr_h, data_l, data_h;
3257 addr_l = (uint8)((addr * 2) & 0xff);
3258 addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
3260 /* set address */
3261 OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1);
3262 OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1);
3264 /* do read */
3265 if (sprom_cmd_pcmcia(osh, SROM_READ))
3266 return 1;
3268 /* read data */
3269 data_h = data_l = 0;
3270 OSL_PCMCIA_READ_ATTR(osh, SROM_DATAH, &data_h, 1);
3271 OSL_PCMCIA_READ_ATTR(osh, SROM_DATAL, &data_l, 1);
3273 *data = (data_h << 8) | data_l;
3274 return 0;
3277 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
3278 /* write a word to the PCMCIA srom */
3279 static int
3280 sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data)
3282 uint8 addr_l, addr_h, data_l, data_h;
3284 addr_l = (uint8)((addr * 2) & 0xff);
3285 addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
3286 data_l = (uint8)(data & 0xff);
3287 data_h = (uint8)((data >> 8) & 0xff);
3289 /* set address */
3290 OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1);
3291 OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1);
3293 /* write data */
3294 OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAH, &data_h, 1);
3295 OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAL, &data_l, 1);
3297 /* do write */
3298 return sprom_cmd_pcmcia(osh, SROM_WRITE);
3300 #endif
3302 /* In chips with chipcommon rev 32 and later, the srom is in chipcommon,
3303 * not in the bus cores.
3305 static uint16
3306 srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, uint32 cmd, uint wordoff, uint16 data)
3308 chipcregs_t *cc = (chipcregs_t *)ccregs;
3309 uint wait_cnt = 1000;
3311 if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
3312 W_REG(osh, &cc->sromaddress, wordoff * 2);
3313 if (cmd == SRC_OP_WRITE)
3314 W_REG(osh, &cc->sromdata, data);
3317 W_REG(osh, &cc->sromcontrol, SRC_START | cmd);
3319 while (wait_cnt--) {
3320 if ((R_REG(osh, &cc->sromcontrol) & SRC_BUSY) == 0)
3321 break;
3324 if (!wait_cnt) {
3325 BS_ERROR(("%s: Command 0x%x timed out\n", __FUNCTION__, cmd));
3326 return 0xffff;
3328 if (cmd == SRC_OP_READ)
3329 return (uint16)R_REG(osh, &cc->sromdata);
3330 else
3331 return 0xffff;
3335 * Read in and validate sprom.
3336 * Return 0 on success, nonzero on error.
3338 static int
3339 sprom_read_pci(osl_t *osh, si_t *sih, uint16 *sprom, uint wordoff, uint16 *buf, uint nwords,
3340 bool check_crc)
3342 int err = 0;
3343 uint i;
3344 void *ccregs = NULL;
3345 uint32 ccval = 0;
3347 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
3348 (CHIPID(sih->chip) == BCM43431_CHIP_ID) ||
3349 (CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
3350 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
3351 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
3352 /* save current control setting */
3353 ccval = si_chipcontrl_read(sih);
3356 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
3357 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
3358 /* Disable Ext PA lines to allow reading from SROM */
3359 si_chipcontrl_epa4331(sih, FALSE);
3360 } else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
3361 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
3362 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
3363 si_chipcontrl_srom4360(sih, TRUE);
3366 /* read the sprom */
3367 for (i = 0; i < nwords; i++) {
3369 if (sih->ccrev > 31 && ISSIM_ENAB(sih)) {
3370 /* use indirect since direct is too slow on QT */
3371 if ((sih->cccaps & CC_CAP_SROM) == 0) {
3372 err = 1;
3373 goto error;
3376 ccregs = (void *)((uint8 *)sprom - CC_SROM_OTP);
3377 buf[i] = srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ, wordoff + i, 0);
3379 } else {
3380 if (ISSIM_ENAB(sih))
3381 buf[i] = R_REG(osh, &sprom[wordoff + i]);
3383 buf[i] = R_REG(osh, &sprom[wordoff + i]);
3388 /* bypass crc checking for simulation to allow srom hack */
3389 if (ISSIM_ENAB(sih)) {
3390 goto error;
3393 if (check_crc) {
3395 if (buf[0] == 0xffff) {
3396 /* The hardware thinks that an srom that starts with 0xffff
3397 * is blank, regardless of the rest of the content, so declare
3398 * it bad.
3400 BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__, buf[0]));
3401 err = 1;
3402 goto error;
3405 /* fixup the endianness so crc8 will pass */
3406 htol16_buf(buf, nwords * 2);
3407 if (hndcrc8((uint8 *)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) {
3408 /* DBG only pci always read srom4 first, then srom8/9 */
3409 /* BS_ERROR(("%s: bad crc\n", __FUNCTION__)); */
3410 err = 1;
3412 /* now correct the endianness of the byte array */
3413 ltoh16_buf(buf, nwords * 2);
3416 error:
3417 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
3418 (CHIPID(sih->chip) == BCM43431_CHIP_ID) ||
3419 (CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
3420 (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
3421 (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
3423 /* Restore config after reading SROM */
3424 si_chipcontrl_restore(sih, ccval);
3427 return err;
3430 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
3431 static int
3432 otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz)
3434 uint8 *otp;
3435 uint sz = OTP_SZ_MAX/2; /* size in words */
3436 int err = 0;
3438 ASSERT(bufsz <= OTP_SZ_MAX);
3440 if ((otp = MALLOC(osh, OTP_SZ_MAX)) == NULL) {
3441 return BCME_ERROR;
3444 bzero(otp, OTP_SZ_MAX);
3446 err = otp_read_region(sih, OTP_HW_RGN, (uint16 *)otp, &sz);
3448 if (err) {
3449 MFREE(osh, otp, OTP_SZ_MAX);
3450 return err;
3453 bcopy(otp, buf, bufsz);
3455 MFREE(osh, otp, OTP_SZ_MAX);
3457 /* Check CRC */
3458 if (buf[0] == 0xffff) {
3459 /* The hardware thinks that an srom that starts with 0xffff
3460 * is blank, regardless of the rest of the content, so declare
3461 * it bad.
3463 BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__, buf[0]));
3464 return 1;
3467 /* fixup the endianness so crc8 will pass */
3468 htol16_buf(buf, bufsz);
3469 if (hndcrc8((uint8 *)buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE &&
3470 hndcrc8((uint8 *)buf, SROM10_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) {
3471 BS_ERROR(("%s: bad crc\n", __FUNCTION__));
3472 err = 1;
3474 /* now correct the endianness of the byte array */
3475 ltoh16_buf(buf, bufsz);
3477 return err;
3479 #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */
3481 #if defined(WLTEST) || defined(BCMDBG)
3483 srom_otp_write_region_crc(si_t *sih, uint nbytes, uint16* buf16, bool write)
3485 int err = 0, crc = 0;
3486 uint8 *buf8;
3488 /* Check nbytes is not odd or too big */
3489 if ((nbytes & 1) || (nbytes > SROM_MAX))
3490 return 1;
3492 /* block invalid buffer size */
3493 if (nbytes < SROM4_WORDS * 2)
3494 return BCME_BUFTOOSHORT;
3495 else if (nbytes > SROM10_WORDS * 2)
3496 return BCME_BUFTOOLONG;
3498 /* Verify signatures */
3499 if (!((buf16[SROM4_SIGN] == SROM4_SIGNATURE) ||
3500 (buf16[SROM8_SIGN] == SROM4_SIGNATURE) ||
3501 (buf16[SROM10_SIGN] == SROM4_SIGNATURE))) {
3502 BS_ERROR(("%s: wrong signature SROM4_SIGN %x SROM8_SIGN %x SROM10_SIGN %x\n",
3503 __FUNCTION__, buf16[SROM4_SIGN], buf16[SROM8_SIGN], buf16[SROM10_SIGN]));
3504 return BCME_ERROR;
3507 /* Check CRC */
3508 if (buf16[0] == 0xffff) {
3509 /* The hardware thinks that an srom that starts with 0xffff
3510 * is blank, regardless of the rest of the content, so declare
3511 * it bad.
3513 BS_ERROR(("%s: invalid buf16[0] = 0x%x\n", __FUNCTION__, buf16[0]));
3514 goto out;
3517 buf8 = (uint8*)buf16;
3518 /* fixup the endianness and then calculate crc */
3519 htol16_buf(buf8, nbytes);
3520 crc = ~hndcrc8(buf8, nbytes - 1, CRC8_INIT_VALUE);
3521 /* now correct the endianness of the byte array */
3522 ltoh16_buf(buf8, nbytes);
3523 if (nbytes == SROM10_WORDS * 2)
3524 buf16[SROM10_CRCREV] = (crc << 8) | (buf16[SROM10_CRCREV] & 0xff);
3525 else
3526 buf16[SROM4_CRCREV] = (crc << 8) | (buf16[SROM4_CRCREV] & 0xff);
3528 #ifdef BCMNVRAMW
3529 /* Write the CRC back */
3530 if (write)
3531 err = otp_write_region(sih, OTP_HW_RGN, buf16, nbytes/2);
3532 #endif /* BCMNVRAMW */
3534 out:
3535 return write ? err : crc;
3537 #endif
3540 * Create variable table from memory.
3541 * Return 0 on success, nonzero on error.
3543 static int
3544 BCMATTACHFN(initvars_table)(osl_t *osh, char *start, char *end, char **vars, uint *count)
3546 int c = (int)(end - start);
3548 /* do it only when there is more than just the null string */
3549 if (c > 1) {
3550 char *vp = MALLOC(osh, c);
3551 ASSERT(vp != NULL);
3552 if (!vp)
3553 return BCME_NOMEM;
3554 bcopy(start, vp, c);
3555 *vars = vp;
3556 *count = c;
3558 else {
3559 *vars = NULL;
3560 *count = 0;
3563 return 0;
3567 * Find variables with <devpath> from flash. 'base' points to the beginning
3568 * of the table upon enter and to the end of the table upon exit when success.
3569 * Return 0 on success, nonzero on error.
3571 static int
3572 BCMATTACHFN(initvars_flash)(si_t *sih, osl_t *osh, char **base, uint len)
3574 char *vp = *base;
3575 char *flash;
3576 int err;
3577 char *s;
3578 uint l, dl, copy_len;
3579 char devpath[SI_DEVPATH_BUFSZ];
3580 char coded_name[SI_DEVPATH_BUFSZ] = {0};
3581 int path_len, coded_len, devid_len;
3583 /* allocate memory and read in flash */
3584 if (!(flash = MALLOC(osh, NVRAM_SPACE)))
3585 return BCME_NOMEM;
3586 if ((err = nvram_getall(flash, NVRAM_SPACE)))
3587 goto exit;
3589 /* create legacy devpath prefix */
3590 si_devpath(sih, devpath, sizeof(devpath));
3591 path_len = strlen(devpath);
3593 /* create coded devpath prefix */
3594 si_coded_devpathvar(sih, coded_name, sizeof(coded_name), "devid");
3596 /* coded_name now is 'xx:devid, eat ending 'devid' */
3597 /* to be 'xx:' */
3598 devid_len = strlen("devid");
3599 coded_len = strlen(coded_name);
3600 if (coded_len > devid_len) {
3601 coded_name[coded_len - devid_len] = '\0';
3602 coded_len -= devid_len;
3604 else
3605 coded_len = 0;
3607 /* grab vars with the <devpath> prefix or <coded_name> previx in name */
3608 for (s = flash; s && *s; s += l + 1) {
3609 l = strlen(s);
3611 /* skip non-matching variable */
3612 if (strncmp(s, devpath, path_len) == 0)
3613 dl = path_len;
3614 else if (coded_len && strncmp(s, coded_name, coded_len) == 0)
3615 dl = coded_len;
3616 else
3617 continue;
3619 /* is there enough room to copy? */
3620 copy_len = l - dl + 1;
3621 if (len < copy_len) {
3622 err = BCME_BUFTOOSHORT;
3623 goto exit;
3626 /* no prefix, just the name=value */
3627 strncpy(vp, &s[dl], copy_len);
3628 vp += copy_len;
3629 len -= copy_len;
3632 /* add null string as terminator */
3633 if (len < 1) {
3634 err = BCME_BUFTOOSHORT;
3635 goto exit;
3637 *vp++ = '\0';
3639 *base = vp;
3641 exit: MFREE(osh, flash, NVRAM_SPACE);
3642 return err;
3645 #if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED)
3647 * Initialize nonvolatile variable table from flash.
3648 * Return 0 on success, nonzero on error.
3650 static int
3651 BCMATTACHFN(initvars_flash_si)(si_t *sih, char **vars, uint *count)
3653 osl_t *osh = si_osh(sih);
3654 char *vp, *base;
3655 int err;
3657 ASSERT(vars != NULL);
3658 ASSERT(count != NULL);
3660 base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS);
3661 ASSERT(vp != NULL);
3662 if (!vp)
3663 return BCME_NOMEM;
3665 if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS)) == 0)
3666 err = initvars_table(osh, base, vp, vars, count);
3668 MFREE(osh, base, MAXSZ_NVRAM_VARS);
3670 return err;
3672 #endif
3674 /* Parse SROM and create name=value pairs. 'srom' points to
3675 * the SROM word array. 'off' specifies the offset of the
3676 * first word 'srom' points to, which should be either 0 or
3677 * SROM3_SWRG_OFF (full SROM or software region).
3680 static uint
3681 mask_shift(uint16 mask)
3683 uint i;
3684 for (i = 0; i < (sizeof(mask) << 3); i ++) {
3685 if (mask & (1 << i))
3686 return i;
3688 ASSERT(mask);
3689 return 0;
3692 static uint
3693 mask_width(uint16 mask)
3695 int i;
3696 for (i = (sizeof(mask) << 3) - 1; i >= 0; i --) {
3697 if (mask & (1 << i))
3698 return (uint)(i - mask_shift(mask) + 1);
3700 ASSERT(mask);
3701 return 0;
3704 #ifdef BCMASSERT_SUPPORT
3705 static bool
3706 mask_valid(uint16 mask)
3708 uint shift = mask_shift(mask);
3709 uint width = mask_width(mask);
3710 return mask == ((~0 << shift) & ~(~0 << (shift + width)));
3712 #endif
3714 static void
3715 BCMATTACHFN(_initvars_srom_pci)(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b)
3717 uint16 w;
3718 uint32 val;
3719 const sromvar_t *srv;
3720 uint width;
3721 uint flags;
3722 uint32 sr = (1 << sromrev);
3723 bool in_array = FALSE;
3724 static char array_temp[256];
3725 uint array_curr = 0;
3726 const char* array_name = NULL;
3728 varbuf_append(b, "sromrev=%d", sromrev);
3730 for (srv = pci_sromvars; srv->name != NULL; srv ++) {
3731 const char *name;
3732 static bool in_array = FALSE;
3733 static char array_temp[256];
3734 static uint array_curr = 0;
3735 static const char* array_name = NULL;
3737 if ((srv->revmask & sr) == 0)
3738 continue;
3740 if (srv->off < off)
3741 continue;
3743 flags = srv->flags;
3744 name = srv->name;
3746 /* This entry is for mfgc only. Don't generate param for it, */
3747 if (flags & SRFL_NOVAR)
3748 continue;
3750 if (flags & SRFL_ETHADDR) {
3751 char eabuf[ETHER_ADDR_STR_LEN];
3752 struct ether_addr ea;
3754 ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff;
3755 ea.octet[1] = srom[srv->off - off] & 0xff;
3756 ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
3757 ea.octet[3] = srom[srv->off + 1 - off] & 0xff;
3758 ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
3759 ea.octet[5] = srom[srv->off + 2 - off] & 0xff;
3760 bcm_ether_ntoa(&ea, eabuf);
3762 varbuf_append(b, "%s=%s", name, eabuf);
3764 else {
3765 ASSERT(mask_valid(srv->mask));
3766 ASSERT(mask_width(srv->mask));
3768 /* Start of an array */
3769 if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array) {
3770 array_curr = 0;
3771 array_name = (const char*)srv->name;
3772 memset((void*)array_temp, 0, sizeof(array_temp));
3773 in_array = TRUE;
3776 w = srom[srv->off - off];
3777 val = (w & srv->mask) >> mask_shift(srv->mask);
3778 width = mask_width(srv->mask);
3780 while (srv->flags & SRFL_MORE) {
3781 srv ++;
3782 ASSERT(srv->name != NULL);
3784 if (srv->off == 0 || srv->off < off)
3785 continue;
3787 ASSERT(mask_valid(srv->mask));
3788 ASSERT(mask_width(srv->mask));
3790 w = srom[srv->off - off];
3791 val += ((w & srv->mask) >> mask_shift(srv->mask)) << width;
3792 width += mask_width(srv->mask);
3795 if ((flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1))
3796 continue;
3798 /* Array support starts in sromrev 10. Skip arrays for sromrev <= 9 */
3799 if (sromrev <= 9 && srv->flags & SRFL_ARRAY) {
3800 while (srv->flags & SRFL_ARRAY)
3801 srv ++;
3802 srv ++;
3805 if (in_array) {
3806 int ret;
3808 if (flags & SRFL_PRHEX) {
3809 ret = snprintf(array_temp + array_curr,
3810 sizeof(array_temp) - array_curr, "0x%x,", val);
3811 } else if ((flags & SRFL_PRSIGN) &&
3812 (val & (1 << (width - 1)))) {
3813 ret = snprintf(array_temp + array_curr,
3814 sizeof(array_temp) - array_curr, "%d,",
3815 (int)(val | (~0 << width)));
3816 } else {
3817 ret = snprintf(array_temp + array_curr,
3818 sizeof(array_temp) - array_curr, "%u,", val);
3821 if (ret > 0) {
3822 array_curr += ret;
3823 } else {
3824 BS_ERROR(("%s: array %s parsing error. buffer too short.\n",
3825 __FUNCTION__, array_name));
3826 ASSERT(0);
3828 /* buffer too small, skip this param */
3829 while (srv->flags & SRFL_ARRAY)
3830 srv ++;
3831 srv ++;
3832 in_array = FALSE;
3833 continue;
3836 if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */
3837 /* Remove the last ',' */
3838 array_temp[array_curr-1] = '\0';
3839 in_array = FALSE;
3840 varbuf_append(b, "%s=%s", array_name, array_temp);
3842 } else if (flags & SRFL_CCODE) {
3843 if (val == 0)
3844 varbuf_append(b, "ccode=");
3845 else
3846 varbuf_append(b, "ccode=%c%c", (val >> 8), (val & 0xff));
3848 /* LED Powersave duty cycle has to be scaled:
3849 *(oncount >> 24) (offcount >> 8)
3851 else if (flags & SRFL_LEDDC) {
3852 uint32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */
3853 (((val & 0xff)) << 8); /* offcount */
3854 varbuf_append(b, "leddc=%d", w32);
3856 else if (flags & SRFL_PRHEX)
3857 varbuf_append(b, "%s=0x%x", name, val);
3858 else if ((flags & SRFL_PRSIGN) && (val & (1 << (width - 1))))
3859 varbuf_append(b, "%s=%d", name, (int)(val | (~0 << width)));
3860 else
3861 varbuf_append(b, "%s=%u", name, val);
3865 if (sromrev >= 4) {
3866 /* Do per-path variables */
3867 uint p, pb, psz, path_num;
3869 if (sromrev >= 11) {
3870 pb = SROM11_PATH0;
3871 psz = SROM11_PATH1 - SROM11_PATH0;
3872 path_num = MAX_PATH_SROM_11;
3873 } else if (sromrev >= 8) {
3874 pb = SROM8_PATH0;
3875 psz = SROM8_PATH1 - SROM8_PATH0;
3876 path_num = MAX_PATH_SROM;
3877 } else {
3878 pb = SROM4_PATH0;
3879 psz = SROM4_PATH1 - SROM4_PATH0;
3880 path_num = MAX_PATH_SROM;
3883 for (p = 0; p < path_num; p++) {
3884 for (srv = perpath_pci_sromvars; srv->name != NULL; srv ++) {
3885 if ((srv->revmask & sr) == 0)
3886 continue;
3888 if (pb + srv->off < off)
3889 continue;
3891 /* This entry is for mfgc only. Don't generate param for it, */
3892 if (srv->flags & SRFL_NOVAR)
3893 continue;
3895 /* Start of an array */
3896 if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array) {
3897 array_curr = 0;
3898 array_name = (const char*)srv->name;
3899 memset((void*)array_temp, 0, sizeof(array_temp));
3900 in_array = TRUE;
3903 w = srom[pb + srv->off - off];
3905 ASSERT(mask_valid(srv->mask));
3906 val = (w & srv->mask) >> mask_shift(srv->mask);
3907 width = mask_width(srv->mask);
3909 flags = srv->flags;
3911 /* Cheating: no per-path var is more than 1 word */
3913 if ((srv->flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1))
3914 continue;
3916 if (in_array) {
3917 int ret;
3919 if (flags & SRFL_PRHEX) {
3920 ret = snprintf(array_temp + array_curr,
3921 sizeof(array_temp) - array_curr, "0x%x,", val);
3922 } else if ((flags & SRFL_PRSIGN) &&
3923 (val & (1 << (width - 1)))) {
3924 ret = snprintf(array_temp + array_curr,
3925 sizeof(array_temp) - array_curr, "%d,",
3926 (int)(val | (~0 << width)));
3927 } else {
3928 ret = snprintf(array_temp + array_curr,
3929 sizeof(array_temp) - array_curr, "%u,", val);
3932 if (ret > 0) {
3933 array_curr += ret;
3934 } else {
3935 BS_ERROR(
3936 ("%s: array %s parsing error. buffer too short.\n",
3937 __FUNCTION__, array_name));
3938 ASSERT(0);
3940 /* buffer too small, skip this param */
3941 while (srv->flags & SRFL_ARRAY)
3942 srv ++;
3943 srv ++;
3944 in_array = FALSE;
3945 continue;
3948 if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */
3949 /* Remove the last ',' */
3950 array_temp[array_curr-1] = '\0';
3951 in_array = FALSE;
3952 varbuf_append(b, "%s%d=%s",
3953 array_name, p, array_temp);
3955 } else if (srv->flags & SRFL_PRHEX)
3956 varbuf_append(b, "%s%d=0x%x", srv->name, p, val);
3957 else
3958 varbuf_append(b, "%s%d=%d", srv->name, p, val);
3960 pb += psz;
3966 * Initialize nonvolatile variable table from sprom.
3967 * Return 0 on success, nonzero on error.
3969 static int
3970 BCMATTACHFN(initvars_srom_pci)(si_t *sih, void *curmap, char **vars, uint *count)
3972 uint16 *srom, *sromwindow;
3973 uint8 sromrev = 0;
3974 uint32 sr;
3975 varbuf_t b;
3976 char *vp, *base = NULL;
3977 osl_t *osh = si_osh(sih);
3978 bool flash = FALSE;
3979 int err = 0;
3982 * Apply CRC over SROM content regardless SROM is present or not,
3983 * and use variable <devpath>sromrev's existance in flash to decide
3984 * if we should return an error when CRC fails or read SROM variables
3985 * from flash.
3987 srom = MALLOC(osh, SROM_MAX);
3988 ASSERT(srom != NULL);
3989 if (!srom)
3990 return -2;
3992 sromwindow = (uint16 *)SROM_OFFSET(sih);
3993 if (si_is_sprom_available(sih)) {
3994 err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM11_WORDS, TRUE);
3996 if (err == 0) {
3997 if (srom[SROM11_SIGN] == SROM11_SIGNATURE) /* srom 11 */
3998 sromrev = srom[SROM11_CRCREV] & 0xff;
3999 } else {
4000 err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM4_WORDS, TRUE);
4002 if (err == 0) {
4003 if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || /* srom 4 */
4004 (srom[SROM8_SIGN] == SROM4_SIGNATURE) ) { /* srom 8, 9 */
4005 sromrev = srom[SROM4_CRCREV] & 0xff;
4007 } else {
4008 err = sprom_read_pci(osh, sih, sromwindow, 0,
4009 srom, SROM_WORDS, TRUE);
4011 if (err == 0) {
4012 /* srom is good and is rev < 4 */
4013 /* top word of sprom contains version and crc8 */
4014 sromrev = srom[SROM_CRCREV] & 0xff;
4015 /* bcm4401 sroms misprogrammed */
4016 if (sromrev == 0x10)
4017 sromrev = 1;
4023 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
4024 /* Use OTP if SPROM not available */
4025 else if ((err = otp_read_pci(osh, sih, srom, SROM_MAX)) == 0) {
4026 /* OTP only contain SROM rev8/rev9/rev10/Rev11 for now */
4027 if (srom[SROM11_SIGN] == SROM11_SIGNATURE)
4028 sromrev = srom[SROM11_CRCREV] & 0xff;
4029 else if (srom[SROM10_SIGN] == SROM10_SIGNATURE)
4030 sromrev = srom[SROM10_CRCREV] & 0xff;
4031 else
4032 sromrev = srom[SROM4_CRCREV] & 0xff;
4034 #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */
4035 else {
4036 err = 1;
4037 BS_ERROR(("Neither SPROM nor OTP has valid image\n"));
4040 BS_ERROR(("srom rev:%d\n", sromrev));
4043 /* We want internal/wltest driver to come up with default sromvars so we can
4044 * program a blank SPROM/OTP.
4046 if (err) {
4047 char *value;
4048 uint32 val;
4049 val = 0;
4050 BCM_REFERENCE(val);
4052 if ((value = si_getdevpathvar(sih, "sromrev"))) {
4053 sromrev = (uint8)bcm_strtoul(value, NULL, 0);
4054 flash = TRUE;
4055 goto varscont;
4058 BS_ERROR(("%s, SROM CRC Error\n", __FUNCTION__));
4060 #ifndef DONGLEBUILD
4061 if ((value = si_getnvramflvar(sih, "sromrev"))) {
4062 err = 0;
4063 goto errout;
4065 #endif
4066 /* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */
4067 #if defined(BCMHOSTVARS)
4068 val = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
4069 if ((si_is_sprom_available(sih) && srom[0] == 0xffff) ||
4070 (val & SPROM_OTPIN_USE)) {
4071 vp = base = mfgsromvars;
4073 if (defvarslen == 0) {
4074 BS_ERROR(("No nvm file, use generic default (for programming"
4075 " SPROM/OTP only)\n"));
4077 if (((sih->chip == BCM4331_CHIP_ID) ||
4078 (sih->chip == BCM43431_CHIP_ID)) &&
4079 (sih->chiprev < 3)) {
4081 defvarslen = srom_vars_len(defaultsromvars_4331);
4082 bcopy(defaultsromvars_4331, vp, defvarslen);
4084 } else {
4085 /* For 4311 A1 there is no signature to indicate that OTP is
4086 * programmed, so can't really verify the OTP is
4087 * unprogrammed or a bad OTP.
4089 if (sih->chip == BCM4311_CHIP_ID) {
4090 const char *devid = "devid=0x4311";
4091 const size_t devid_strlen = strlen(devid);
4092 BS_ERROR(("setting the devid to be 4311\n"));
4093 bcopy(devid, vp, devid_strlen + 1);
4094 vp += devid_strlen + 1;
4096 defvarslen = srom_vars_len(defaultsromvars_wltest);
4097 bcopy(defaultsromvars_wltest, vp, defvarslen);
4099 } else {
4100 BS_ERROR(("Use nvm file as default\n"));
4103 vp += defvarslen;
4104 /* add final null terminator */
4105 *vp++ = '\0';
4107 BS_ERROR(("Used %d bytes of defaultsromvars\n", defvarslen));
4108 goto varsdone;
4110 } else if ((((sih->chip == BCM4331_CHIP_ID) ||
4111 (sih->chip == BCM43431_CHIP_ID)) &&
4112 (sih->chiprev < 3)) || (sih->chip == BCM4360_CHIP_ID) ||
4113 (sih->chip == BCM43460_CHIP_ID) ||
4114 (sih->chip == BCM4352_CHIP_ID)) {
4115 base = vp = mfgsromvars;
4117 if ((sih->chip == BCM4360_CHIP_ID) ||
4118 (sih->chip == BCM43460_CHIP_ID) ||
4119 (sih->chip == BCM4352_CHIP_ID))
4120 BS_ERROR(("4360 BOOT w/o SPROM or OTP\n"));
4121 else
4122 BS_ERROR(("4331 BOOT w/o SPROM or OTP\n"));
4124 defvarslen = srom_vars_len(defaultsromvars_4331);
4125 bcopy(defaultsromvars_4331, vp, defvarslen);
4126 vp += defvarslen;
4127 *vp++ = '\0';
4128 goto varsdone;
4129 } else
4130 #endif
4132 err = -1;
4133 goto errout;
4137 varscont:
4138 /* Bitmask for the sromrev */
4139 sr = 1 << sromrev;
4141 /* srom version check: Current valid versions: 1-5, 8-11, SROM_MAXREV */
4142 if ((sr & 0xf3e) == 0) {
4143 BS_ERROR(("Invalid SROM rev %d\n", sromrev));
4144 err = -2;
4145 goto errout;
4148 ASSERT(vars != NULL);
4149 ASSERT(count != NULL);
4151 base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS);
4152 ASSERT(vp != NULL);
4153 if (!vp) {
4154 err = -2;
4155 goto errout;
4158 /* read variables from flash */
4159 if (flash) {
4160 if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS)))
4161 goto errout;
4162 goto varsdone;
4165 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
4167 /* parse SROM into name=value pairs. */
4168 _initvars_srom_pci(sromrev, srom, 0, &b);
4171 /* final nullbyte terminator */
4172 ASSERT(b.size >= 1);
4173 vp = b.buf;
4174 *vp++ = '\0';
4176 ASSERT((vp - base) <= MAXSZ_NVRAM_VARS);
4178 varsdone:
4179 err = initvars_table(osh, base, vp, vars, count);
4181 errout:
4182 /* BCMHOSTVARS are enabled only if WLTEST is enabled or BCMEXTNVM is enabled */
4183 #if defined(BCMHOSTVARS)
4184 if (base && (base != mfgsromvars))
4185 #else
4186 if (base)
4187 #endif
4188 MFREE(osh, base, MAXSZ_NVRAM_VARS);
4190 MFREE(osh, srom, SROM_MAX);
4191 return err;
4195 * Read the cis and call parsecis to initialize the vars.
4196 * Return 0 on success, nonzero on error.
4198 static int
4199 BCMATTACHFN(initvars_cis_pcmcia)(si_t *sih, osl_t *osh, char **vars, uint *count)
4201 uint8 *cis = NULL;
4202 int rc;
4203 uint data_sz;
4205 data_sz = (sih->buscorerev == 1) ? SROM_MAX : CIS_SIZE;
4207 if ((cis = MALLOC(osh, data_sz)) == NULL)
4208 return (-2);
4210 if (sih->buscorerev == 1) {
4211 if (srom_read(sih, PCMCIA_BUS, (void *)NULL, osh, 0, data_sz, (uint16 *)cis,
4212 TRUE)) {
4213 MFREE(osh, cis, data_sz);
4214 return (-1);
4216 /* fix up endianess for 16-bit data vs 8-bit parsing */
4217 htol16_buf((uint16 *)cis, data_sz);
4218 } else
4219 OSL_PCMCIA_READ_ATTR(osh, 0, cis, data_sz);
4221 rc = srom_parsecis(osh, &cis, SROM_CIS_SINGLE, vars, count);
4223 MFREE(osh, cis, data_sz);
4225 return (rc);
4229 #ifdef BCMSPI
4231 * Read the SPI cis and call parsecis to initialize the vars.
4232 * Return 0 on success, nonzero on error.
4234 static int
4235 BCMATTACHFN(initvars_cis_spi)(osl_t *osh, char **vars, uint *count)
4237 uint8 *cis;
4238 int rc;
4240 #if defined(NDIS) && !defined(UNDER_CE)
4241 uint8 cisd[SBSDIO_CIS_SIZE_LIMIT];
4242 cis = (uint8*)cisd;
4243 #else
4244 if ((cis = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT)) == NULL) {
4245 return -1;
4247 #endif /* defined(NDIS) && (!defined(UNDER_CE)) */
4249 bzero(cis, SBSDIO_CIS_SIZE_LIMIT);
4251 if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, cis, SBSDIO_CIS_SIZE_LIMIT) != 0) {
4252 #if defined(NDIS) && !defined(UNDER_CE)
4253 /* nothing to do */
4254 #else
4255 MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT);
4256 #endif /* defined(NDIS) && (!defined(UNDER_CE)) */
4257 return -2;
4260 rc = srom_parsecis(osh, &cis, SDIO_FUNC_1, vars, count);
4262 #if defined(NDIS) && !defined(UNDER_CE)
4263 /* nothing to do here */
4264 #else
4265 MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT);
4266 #endif
4268 return (rc);
4270 #endif /* BCMSPI */
4272 #if defined(BCMUSBDEV)
4273 /* Return sprom size in 16-bit words */
4274 uint
4275 srom_size(si_t *sih, osl_t *osh)
4277 uint size = 0;
4278 if (SPROMBUS == PCMCIA_BUS) {
4279 uint32 origidx;
4280 sdpcmd_regs_t *pcmregs;
4281 bool wasup;
4283 origidx = si_coreidx(sih);
4284 pcmregs = si_setcore(sih, PCMCIA_CORE_ID, 0);
4285 if (!pcmregs)
4286 pcmregs = si_setcore(sih, SDIOD_CORE_ID, 0);
4287 ASSERT(pcmregs);
4289 if (!(wasup = si_iscoreup(sih)))
4290 si_core_reset(sih, 0, 0);
4292 /* not worry about earlier core revs */
4293 /* valid for only pcmcia core */
4294 if (si_coreid(sih) == PCMCIA_CORE_ID)
4295 if (si_corerev(sih) < 8)
4296 goto done;
4299 switch (SI_PCMCIA_READ(osh, pcmregs, SROM_INFO) & SRI_SZ_MASK) {
4300 case 1:
4301 size = 256; /* SROM_INFO == 1 means 4kbit */
4302 break;
4303 case 2:
4304 size = 1024; /* SROM_INFO == 2 means 16kbit */
4305 break;
4306 default:
4307 break;
4310 done:
4311 if (!wasup)
4312 si_core_disable(sih, 0);
4314 si_setcoreidx(sih, origidx);
4316 return size;
4318 #endif
4321 * initvars are different for BCMUSBDEV and BCMSDIODEV. This is OK when supporting both at
4322 * the same time, but only because all of the code is in attach functions and not in ROM.
4325 #if defined(BCMUSBDEV_ENABLED)
4326 #if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND)
4328 * Read the USB cis and call parsecis to initialize the vars.
4329 * Return 0 on success, nonzero on error.
4331 static int
4332 BCMATTACHFN(initvars_cis_usbdriver)(si_t *sih, osl_t *osh, char **vars, uint *count)
4334 uint8 *cis;
4335 uint sz = OTP_SZ_MAX/2; /* size in words */
4336 int rc = BCME_OK;
4338 if ((cis = MALLOC(osh, OTP_SZ_MAX)) == NULL) {
4339 return -1;
4342 bzero(cis, OTP_SZ_MAX);
4344 if (otp_read_region(sih, OTP_SW_RGN, (uint16 *)cis, &sz)) {
4345 BS_ERROR(("%s: OTP read SW region failure.\n*", __FUNCTION__));
4346 rc = -2;
4347 } else {
4348 BS_ERROR(("%s: OTP programmed. use OTP for srom vars\n*", __FUNCTION__));
4349 rc = srom_parsecis(osh, &cis, SROM_CIS_SINGLE, vars, count);
4352 MFREE(osh, cis, OTP_SZ_MAX);
4354 return (rc);
4357 /* For driver(not bootloader), if nvram is not downloadable or missing, use default */
4358 static int
4359 BCMATTACHFN(initvars_srom_si_usbdriver)(si_t *sih, osl_t *osh, char **vars, uint *varsz)
4361 uint len;
4362 char *base;
4363 char *fakevars;
4364 int rc = -1;
4366 base = fakevars = NULL;
4367 len = 0;
4368 switch (CHIPID(sih->chip)) {
4369 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
4370 fakevars = defaultsromvars_4322usb;
4371 break;
4372 case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID:
4373 case BCM43234_CHIP_ID:
4374 /* check against real chipid instead of compile time flag */
4375 if (sih->chip == BCM43234_CHIP_ID) {
4376 fakevars = defaultsromvars_43234usb;
4377 } else if (sih->chip == BCM43235_CHIP_ID) {
4378 fakevars = defaultsromvars_43235usb;
4379 } else
4380 fakevars = defaultsromvars_43236usb;
4381 break;
4383 case BCM4319_CHIP_ID:
4384 fakevars = defaultsromvars_4319usb;
4385 break;
4386 case BCM4360_CHIP_ID:
4387 case BCM43460_CHIP_ID:
4388 case BCM43526_CHIP_ID:
4389 fakevars = defaultsromvars_4360usb;
4390 break;
4391 default:
4392 ASSERT(0);
4393 return rc;
4396 #ifndef BCM_BMAC_VARS_APPEND
4397 if (BCME_OK == initvars_cis_usbdriver(sih, osh, vars, varsz)) {
4398 /* Make OTP/SROM variables global */
4399 if (srvars_inited == FALSE)
4400 nvram_append((void *)sih, *vars, *varsz);
4401 return BCME_OK;
4403 #endif /* BCM_BMAC_VARS_APPEND */
4405 /* NO OTP, if nvram downloaded, use it */
4406 if ((_varsz != 0) && (_vars != NULL)) {
4407 len = _varsz + (strlen(vstr_end));
4408 base = MALLOC(osh, len + 2); /* plus 2 terminating \0 */
4409 if (base == NULL) {
4410 BS_ERROR(("initvars_srom_si: MALLOC failed.\n"));
4411 return BCME_ERROR;
4413 bzero(base, len + 2);
4415 /* make a copy of the _vars, _vars is at the top of the memory, cannot append
4416 * END\0\0 to it. copy the download vars to base, back of the terminating \0,
4417 * then append END\0\0
4419 bcopy((void *)_vars, base, _varsz);
4420 /* backoff all the terminating \0s except the one the for the last string */
4421 len = _varsz;
4422 while (!base[len - 1])
4423 len--;
4424 len++; /* \0 for the last string */
4425 /* append END\0\0 to the end */
4426 bcopy((void *)vstr_end, (base + len), strlen(vstr_end));
4427 len += (strlen(vstr_end) + 2);
4428 *vars = base;
4429 *varsz = len;
4431 BS_ERROR(("%s USB nvram downloaded %d bytes\n", __FUNCTION__, _varsz));
4432 } else {
4433 /* Fall back to fake srom vars if OTP not programmed */
4434 len = srom_vars_len(fakevars);
4435 base = MALLOC(osh, (len + 1));
4436 if (base == NULL) {
4437 BS_ERROR(("initvars_srom_si: MALLOC failed.\n"));
4438 return BCME_ERROR;
4440 bzero(base, (len + 1));
4441 bcopy(fakevars, base, len);
4442 *(base + len) = '\0'; /* add final nullbyte terminator */
4443 *vars = base;
4444 *varsz = len + 1;
4445 BS_ERROR(("initvars_srom_usbdriver: faked nvram %d bytes\n", len));
4448 #ifdef BCM_BMAC_VARS_APPEND
4449 if (BCME_OK == initvars_cis_usbdriver(sih, osh, vars, varsz)) {
4450 if (base)
4451 MFREE(osh, base, (len + 1));
4453 #endif /* BCM_BMAC_VARS_APPEND */
4454 /* Make OTP/SROM variables global */
4455 if (srvars_inited == FALSE) {
4456 nvram_append((void *)sih, *vars, *varsz);
4457 srvars_inited = TRUE;
4459 return BCME_OK;
4462 #endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */
4464 #ifdef BCM_DONGLEVARS
4465 static int
4466 BCMATTACHFN(initvars_srom_si_bl)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz)
4468 int sel = 0; /* where to read srom/cis: 0 - none, 1 - otp, 2 - sprom */
4469 uint sz = 0; /* srom size in bytes */
4470 void *oh = NULL;
4471 int rc = BCME_OK;
4473 if ((oh = otp_init(sih)) != NULL && (otp_status(oh) & OTPS_GUP_SW)) {
4474 /* Access OTP if it is present, powered on, and programmed */
4475 sz = otp_size(oh);
4476 sel = 1;
4477 } else if ((sz = srom_size(sih, osh)) != 0) {
4478 /* Access the SPROM if it is present */
4479 sz <<= 1;
4480 sel = 2;
4483 /* Read CIS in OTP/SPROM */
4484 if (sel != 0) {
4485 uint16 *srom;
4486 uint8 *body = NULL;
4487 uint otpsz = sz;
4489 ASSERT(sz);
4491 /* Allocate memory */
4492 if ((srom = (uint16 *)MALLOC(osh, sz)) == NULL)
4493 return BCME_NOMEM;
4495 /* Read CIS */
4496 switch (sel) {
4497 case 1:
4498 rc = otp_read_region(sih, OTP_SW_RGN, srom, &otpsz);
4499 sz = otpsz;
4500 body = (uint8 *)srom;
4501 break;
4502 case 2:
4503 rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, srom, TRUE);
4504 /* sprom has 8 byte h/w header */
4505 body = (uint8 *)srom + SBSDIO_SPROM_CIS_OFFSET;
4506 break;
4507 default:
4508 /* impossible to come here */
4509 ASSERT(0);
4510 break;
4513 /* Parse CIS */
4514 if (rc == BCME_OK) {
4515 /* each word is in host endian */
4516 htol16_buf((uint8 *)srom, sz);
4517 ASSERT(body);
4518 rc = srom_parsecis(osh, &body, SROM_CIS_SINGLE, vars, varsz);
4521 MFREE(osh, srom, sz); /* Clean up */
4523 /* Make SROM variables global */
4524 if (rc == BCME_OK)
4525 nvram_append((void *)sih, *vars, *varsz);
4528 return BCME_OK;
4530 #endif /* #ifdef BCM_DONGLEVARS */
4532 static int
4533 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz)
4536 /* Bail out if we've dealt with OTP/SPROM before! */
4537 if (srvars_inited)
4538 goto exit;
4540 #if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND)
4541 /* read OTP or use faked var array */
4542 switch (CHIPID(sih->chip)) {
4543 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
4544 case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID:
4545 case BCM43234_CHIP_ID:
4546 case BCM4319_CHIP_ID:
4547 case BCM4360_CHIP_ID:
4548 case BCM43460_CHIP_ID:
4549 case BCM4352_CHIP_ID:
4550 if (BCME_OK != initvars_srom_si_usbdriver(sih, osh, vars, varsz))
4551 goto exit;
4552 return BCME_OK;
4553 default:
4554 UNUSED_PARAMETER(defaultsromvars_4322usb);
4555 UNUSED_PARAMETER(defaultsromvars_43234usb);
4556 UNUSED_PARAMETER(defaultsromvars_43235usb);
4557 UNUSED_PARAMETER(defaultsromvars_43236usb);
4558 UNUSED_PARAMETER(defaultsromvars_4319usb);
4560 #endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */
4562 #ifdef BCM_DONGLEVARS /* this flag should be defined for usb bootloader, to read \
4563 OTP or SROM */
4564 if (BCME_OK != initvars_srom_si_bl(sih, osh, curmap, vars, varsz))
4565 return BCME_ERROR;
4566 #endif
4568 /* update static local var to skip for next call */
4569 srvars_inited = TRUE;
4571 exit:
4572 /* Tell the caller there is no individual SROM variables */
4573 *vars = NULL;
4574 *varsz = 0;
4576 /* return OK so the driver will load & use defaults if bad srom/otp */
4577 return BCME_OK;
4580 #elif defined(BCMSDIODEV_ENABLED)
4582 #ifdef BCM_DONGLEVARS
4583 static uint8 BCMATTACHDATA(defcis4325)[] = { 0x20, 0x4, 0xd0, 0x2, 0x25, 0x43, 0xff, 0xff };
4584 static uint8 BCMATTACHDATA(defcis4315)[] = { 0x20, 0x4, 0xd0, 0x2, 0x15, 0x43, 0xff, 0xff };
4585 static uint8 BCMATTACHDATA(defcis4329)[] = { 0x20, 0x4, 0xd0, 0x2, 0x29, 0x43, 0xff, 0xff };
4586 static uint8 BCMATTACHDATA(defcis4319)[] = { 0x20, 0x4, 0xd0, 0x2, 0x19, 0x43, 0xff, 0xff };
4587 static uint8 BCMATTACHDATA(defcis4336)[] = { 0x20, 0x4, 0xd0, 0x2, 0x36, 0x43, 0xff, 0xff };
4588 static uint8 BCMATTACHDATA(defcis4330)[] = { 0x20, 0x4, 0xd0, 0x2, 0x30, 0x43, 0xff, 0xff };
4589 static uint8 BCMATTACHDATA(defcis43237)[] = { 0x20, 0x4, 0xd0, 0x2, 0xe5, 0xa8, 0xff, 0xff };
4590 static uint8 BCMATTACHDATA(defcis4324)[] = { 0x20, 0x4, 0xd0, 0x2, 0x24, 0x43, 0xff, 0xff };
4591 static uint8 BCMATTACHDATA(defcis4335)[] = { 0x20, 0x4, 0xd0, 0x2, 0x24, 0x43, 0xff, 0xff };
4593 #ifdef BCM_BMAC_VARS_APPEND
4595 static char BCMATTACHDATA(defaultsromvars_4319sdio)[] =
4596 "sromrev=3\0"
4597 "vendid=0x14e4\0"
4598 "devid=0x4338\0"
4599 "boardtype=0x05a1\0"
4600 "boardrev=0x1102\0"
4601 "boardflags=0x400201\0"
4602 "boardflags2=0x80\0"
4603 "xtalfreq=26000\0"
4604 "aa2g=3\0"
4605 "aa5g=0\0"
4606 "ag0=0\0"
4607 "opo=0\0"
4608 "pa0b0=0x1675\0"
4609 "pa0b1=0xfa74\0"
4610 "pa0b2=0xfea1\0"
4611 "pa0itssit=62\0"
4612 "pa0maxpwr=78\0"
4613 "rssismf2g=0xa\0"
4614 "rssismc2g=0xb\0"
4615 "rssisav2g=0x3\0"
4616 "bxa2g=0\0"
4617 "cckdigfilttype=6\0"
4618 "rxpo2g=2\0"
4619 "cckpo=0\0"
4620 "ofdmpo=0x55553333\0"
4621 "mcs2gpo0=0x9999\0"
4622 "mcs2gpo1=0x9999\0"
4623 "mcs2gpo2=0x0000\0"
4624 "mcs2gpo3=0x0000\0"
4625 "mcs2gpo4=0x9999\0"
4626 "mcs2gpo5=0x9999\0"
4627 "macaddr=00:90:4c:06:c0:19\0"
4628 "END\0";
4630 static char BCMATTACHDATA(defaultsromvars_4319sdio_hmb)[] =
4631 "sromrev=3\0"
4632 "vendid=0x14e4\0"
4633 "devid=0x4338\0"
4634 "boardtype=0x058c\0"
4635 "boardrev=0x1102\0"
4636 "boardflags=0x400201\0"
4637 "boardflags2=0x80\0"
4638 "xtalfreq=26000\0"
4639 "aa2g=3\0"
4640 "aa5g=0\0"
4641 "ag0=0\0"
4642 "opo=0\0"
4643 "pa0b0=0x1675\0"
4644 "pa0b1=0xfa74\0"
4645 "pa0b2=0xfea1\0"
4646 "pa0itssit=62\0"
4647 "pa0maxpwr=78\0"
4648 "rssismf2g=0xa \0"
4649 "rssismc2g=0xb \0"
4650 "rssisav2g=0x3 \0"
4651 "bxa2g=0\0"
4652 "cckdigfilttype=6\0"
4653 "rxpo2g=2\0"
4654 "cckpo=0\0"
4655 "ofdmpo=0x55553333\0"
4656 "mcs2gpo0=0x9999\0"
4657 "mcs2gpo1=0x9999\0"
4658 "mcs2gpo2=0x0000\0"
4659 "mcs2gpo3=0x0000\0"
4660 "mcs2gpo4=0x9999\0"
4661 "mcs2gpo5=0x9999\0"
4662 "macaddr=00:90:4c:06:c0:19\0"
4663 "END\0";
4665 static char BCMATTACHDATA(defaultsromvars_4319sdio_usbsd)[] =
4666 "sromrev=3\0"
4667 "vendid=0x14e4\0"
4668 "devid=0x4338\0"
4669 "boardtype=0x05a2\0"
4670 "boardrev=0x1100\0"
4671 "boardflags=0x400201\0"
4672 "boardflags2=0x80\0"
4673 "xtalfreq=30000\0"
4674 "aa2g=3\0"
4675 "aa5g=0\0"
4676 "ag0=0\0"
4677 "opo=0\0"
4678 "pa0b0=0x1675\0"
4679 "pa0b1=0xfa74\0"
4680 "pa0b2=0xfea1\0"
4681 "pa0itssit=62\0"
4682 "pa0maxpwr=78\0"
4683 "rssismf2g=0xa \0"
4684 "rssismc2g=0xb \0"
4685 "rssisav2g=0x3 \0"
4686 "bxa2g=0\0"
4687 "cckdigfilttype=6\0"
4688 "rxpo2g=2\0"
4689 "cckpo=0\0"
4690 "ofdmpo=0x55553333\0"
4691 "mcs2gpo0=0x9999\0"
4692 "mcs2gpo1=0x9999\0"
4693 "mcs2gpo2=0x0000\0"
4694 "mcs2gpo3=0x0000\0"
4695 "mcs2gpo4=0x9999\0"
4696 "mcs2gpo5=0x9999\0"
4697 "macaddr=00:90:4c:08:90:00\0"
4698 "END\0";
4700 static char BCMATTACHDATA(defaultsromvars_43237)[] =
4701 "vendid=0x14e4\0"
4702 "devid=0x4355\0"
4703 "boardtype=0x0583\0"
4704 "boardrev=0x1103\0"
4705 "boardnum=0x1\0"
4706 "boardflags=0x200\0"
4707 "boardflags2=0\0"
4708 "sromrev=8\0"
4709 "macaddr=00:90:4c:51:a8:e4\0"
4710 "ccode=0\0"
4711 "regrev=0\0"
4712 "ledbh0=0xff\0"
4713 "ledbh1=0xff\0"
4714 "ledbh2=0xff\0"
4715 "ledbh3=0xff\0"
4716 "leddc=0xffff\0"
4717 "opo=0x0\0"
4718 "aa2g=0x3\0"
4719 "aa5g=0x3\0"
4720 "ag0=0x2\0"
4721 "ag1=0x2\0"
4722 "ag2=0xff\0"
4723 "ag3=0xff\0"
4724 "pa0b0=0xfed1\0"
4725 "pa0b1=0x15fd\0"
4726 "pa0b2=0xfac2\0"
4727 "pa0itssit=0x20\0"
4728 "pa0maxpwr=0x4c\0"
4729 "pa1b0=0xfecd\0"
4730 "pa1b1=0x1497\0"
4731 "pa1b2=0xfae3\0"
4732 "pa1lob0=0xfe87\0"
4733 "pa1lob1=0x1637\0"
4734 "pa1lob2=0xfa8e\0"
4735 "pa1hib0=0xfedc\0"
4736 "pa1hib1=0x144b\0"
4737 "pa1hib2=0xfb01\0"
4738 "pa1itssit=0x3e\0"
4739 "pa1maxpwr=0x40\0"
4740 "pa1lomaxpwr=0x3a\0"
4741 "pa1himaxpwr=0x3c\0"
4742 "bxa2g=0x3\0"
4743 "rssisav2g=0x7\0"
4744 "rssismc2g=0xf\0"
4745 "rssismf2g=0xf\0"
4746 "bxa5g=0x3\0"
4747 "rssisav5g=0x7\0"
4748 "rssismc5g=0xf\0"
4749 "rssismf5g=0xf\0"
4750 "tri2g=0xff\0"
4751 "tri5g=0xff\0"
4752 "tri5gl=0xff\0"
4753 "tri5gh=0xff\0"
4754 "rxpo2g=0xff\0"
4755 "rxpo5g=0xff\0"
4756 "txchain=0x3\0"
4757 "rxchain=0x3\0"
4758 "antswitch=0x0\0"
4759 "tssipos2g=0x1\0"
4760 "extpagain2g=0x2\0"
4761 "pdetrange2g=0x2\0"
4762 "triso2g=0x3\0"
4763 "antswctl2g=0x0\0"
4764 "tssipos5g=0x1\0"
4765 "extpagain5g=0x2\0"
4766 "pdetrange5g=0x2\0"
4767 "triso5g=0x3\0"
4768 "cck2gpo=0x0\0"
4769 "ofdm2gpo=0x0\0"
4770 "ofdm5gpo=0x0\0"
4771 "ofdm5glpo=0x0\0"
4772 "ofdm5ghpo=0x0\0"
4773 "mcs2gpo0=0x0\0"
4774 "mcs2gpo1=0x0\0"
4775 "mcs2gpo2=0x0\0"
4776 "mcs2gpo3=0x0\0"
4777 "mcs2gpo4=0x0\0"
4778 "mcs2gpo5=0x0\0"
4779 "mcs2gpo6=0x0\0"
4780 "mcs2gpo7=0x0\0"
4781 "mcs5gpo0=0x0\0"
4782 "mcs5gpo1=0x0\0"
4783 "mcs5gpo2=0x0\0"
4784 "mcs5gpo3=0x0\0"
4785 "mcs5gpo4=0x0\0"
4786 "mcs5gpo5=0x0\0"
4787 "mcs5gpo6=0x0\0"
4788 "mcs5gpo7=0x0\0"
4789 "mcs5glpo0=0x0\0"
4790 "mcs5glpo1=0x0\0"
4791 "mcs5glpo2=0x0\0"
4792 "mcs5glpo3=0x0\0"
4793 "mcs5glpo4=0x0\0"
4794 "mcs5glpo5=0x0\0"
4795 "mcs5glpo6=0x0\0"
4796 "mcs5glpo7=0x0\0"
4797 "mcs5ghpo0=0x0\0"
4798 "mcs5ghpo1=0x0\0"
4799 "mcs5ghpo2=0x0\0"
4800 "mcs5ghpo3=0x0\0"
4801 "mcs5ghpo4=0x0\0"
4802 "mcs5ghpo5=0x0\0"
4803 "mcs5ghpo6=0x0\0"
4804 "mcs5ghpo7=0x0\0"
4805 "cddpo=0x0\0"
4806 "stbcpo=0x0\0"
4807 "bw40po=0x0\0"
4808 "bwduppo=0x0\0"
4809 "maxp2ga0=0x4c\0"
4810 "pa2gw0a0=0xfed1\0"
4811 "pa2gw1a0=0x15fd\0"
4812 "pa2gw2a0=0xfac2\0"
4813 "maxp5ga0=0x3c\0"
4814 "maxp5gha0=0x3c\0"
4815 "maxp5gla0=0x3c\0"
4816 "pa5gw0a0=0xfeb0\0"
4817 "pa5gw1a0=0x1491\0"
4818 "pa5gw2a0=0xfaf8\0"
4819 "pa5glw0a0=0xfeaa\0"
4820 "pa5glw1a0=0x14b9\0"
4821 "pa5glw2a0=0xfaf0\0"
4822 "pa5ghw0a0=0xfec5\0"
4823 "pa5ghw1a0=0x1439\0"
4824 "pa5ghw2a0=0xfb18\0"
4825 "maxp2ga1=0x4c\0"
4826 "itt2ga0=0x20\0"
4827 "itt5ga0=0x3e\0"
4828 "itt2ga1=0x20\0"
4829 "itt5ga1=0x3e\0"
4830 "pa2gw0a1=0xfed2\0"
4831 "pa2gw1a1=0x15d9\0"
4832 "pa2gw2a1=0xfac6\0"
4833 "maxp5ga1=0x3a\0"
4834 "maxp5gha1=0x3a\0"
4835 "maxp5gla1=0x3a\0"
4836 "pa5gw0a1=0xfebe\0"
4837 "pa5gw1a1=0x1306\0"
4838 "pa5gw2a1=0xfb63\0"
4839 "pa5glw0a1=0xfece\0"
4840 "pa5glw1a1=0x1361\0"
4841 "pa5glw2a1=0xfb5f\0"
4842 "pa5ghw0a1=0xfe9e\0"
4843 "pa5ghw1a1=0x12ca\0"
4844 "pa5ghw2a1=0xfb41\0"
4845 "END\0";
4847 static int
4848 srom_load_nvram(si_t *sih, osl_t *osh, uint8 *pcis[], uint ciscnt, char **vars, uint *varsz)
4850 uint len = 0, base_len;
4851 char *base;
4852 char *fakevars;
4854 base = fakevars = NULL;
4855 switch (CHIPID(sih->chip)) {
4856 case BCM4319_CHIP_ID:
4857 printf("load driver default for chip %x\n", CHIPID(sih->chip));
4858 fakevars = defaultsromvars_4319sdio;
4859 if (si_cis_source(sih) == CIS_OTP) {
4860 switch (srom_probe_boardtype(pcis, ciscnt)) {
4861 case BCM94319SDHMB_SSID:
4862 fakevars = defaultsromvars_4319sdio_hmb;
4863 break;
4864 case BCM94319USBSDB_SSID:
4865 fakevars = defaultsromvars_4319sdio_usbsd;
4866 break;
4867 default:
4868 fakevars = defaultsromvars_4319sdio;
4869 break;
4872 break;
4873 case BCM43237_CHIP_ID:
4874 printf("load driver default for chip %x\n", CHIPID(sih->chip));
4875 fakevars = defaultsromvars_43237;
4876 break;
4877 default:
4878 printf("unknown chip %x\n", CHIPID(sih->chip));
4879 return BCME_ERROR; /* fakevars == NULL for switch default */
4883 /* NO OTP, if nvram downloaded, use it */
4884 if ((_varsz != 0) && (_vars != NULL)) {
4885 len = _varsz + (strlen(vstr_end));
4886 base_len = len + 2; /* plus 2 terminating \0 */
4887 base = MALLOC(osh, base_len);
4888 if (base == NULL) {
4889 BS_ERROR(("initvars_srom_si: MALLOC failed.\n"));
4890 return BCME_ERROR;
4892 bzero(base, base_len);
4894 /* make a copy of the _vars, _vars is at the top of the memory, cannot append
4895 * END\0\0 to it. copy the download vars to base, back of the terminating \0,
4896 * then append END\0\0
4898 bcopy((void *)_vars, base, _varsz);
4899 /* backoff all the terminating \0s except the one the for the last string */
4900 len = _varsz;
4901 while (!base[len - 1])
4902 len--;
4903 len++; /* \0 for the last string */
4904 /* append END\0\0 to the end */
4905 bcopy((void *)vstr_end, (base + len), strlen(vstr_end));
4906 len += (strlen(vstr_end) + 2);
4907 *vars = base;
4908 *varsz = len;
4910 BS_ERROR(("%s nvram downloaded %d bytes\n", __FUNCTION__, _varsz));
4911 } else {
4912 /* Fall back to fake srom vars if OTP not programmed */
4913 len = srom_vars_len(fakevars);
4914 base = MALLOC(osh, (len + 1));
4915 base_len = len + 1;
4916 if (base == NULL) {
4917 BS_ERROR(("initvars_srom_si: MALLOC failed.\n"));
4918 return BCME_ERROR;
4920 bzero(base, base_len);
4921 bcopy(fakevars, base, len);
4922 *(base + len) = '\0'; /* add final nullbyte terminator */
4923 *vars = base;
4924 *varsz = len + 1;
4925 BS_ERROR(("srom_load_driver)default: faked nvram %d bytes\n", len));
4927 /* Parse the CIS */
4928 if ((srom_parsecis(osh, pcis, ciscnt, vars, varsz)) == BCME_OK)
4929 nvram_append((void *)sih, *vars, *varsz);
4930 MFREE(osh, base, base_len);
4931 return BCME_OK;
4934 #endif /* BCM_BMAC_VARS_APPEND */
4936 static int
4937 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz)
4939 int cis_src;
4940 uint msz = 0;
4941 uint sz = 0;
4942 void *oh = NULL;
4943 int rc = BCME_OK;
4944 bool new_cisformat = FALSE;
4946 uint16 *cisbuf = NULL;
4948 /* # sdiod fns + common + extra */
4949 uint8 *cis[SBSDIO_NUM_FUNCTION + 2] = { 0 };
4951 uint ciss = 0;
4952 uint8 *defcis;
4953 uint hdrsz;
4955 /* Bail out if we've dealt with OTP/SPROM before! */
4956 if (srvars_inited)
4957 goto exit;
4959 /* Initialize default and cis format count */
4960 switch (CHIPID(sih->chip)) {
4961 case BCM4325_CHIP_ID: ciss = 3; defcis = defcis4325; hdrsz = 8; break;
4962 case BCM4315_CHIP_ID: ciss = 3; defcis = defcis4315; hdrsz = 8; break;
4963 case BCM4329_CHIP_ID: ciss = 4; defcis = defcis4329; hdrsz = 12; break;
4964 case BCM4319_CHIP_ID: ciss = 3; defcis = defcis4319; hdrsz = 12; break;
4965 case BCM4336_CHIP_ID: ciss = 1; defcis = defcis4336; hdrsz = 4; break;
4966 case BCM43362_CHIP_ID: ciss = 1; defcis = defcis4336; hdrsz = 4; break;
4967 case BCM4330_CHIP_ID: ciss = 1; defcis = defcis4330; hdrsz = 4; break;
4968 case BCM43237_CHIP_ID: ciss = 1; defcis = defcis43237; hdrsz = 4; break;
4969 case BCM4324_CHIP_ID: ciss = 1; defcis = defcis4324; hdrsz = 4; break;
4970 case BCM4314_CHIP_ID: ciss = 1; defcis = defcis4330; hdrsz = 4; break;
4971 case BCM4334_CHIP_ID: ciss = 1; defcis = defcis4330; hdrsz = 4; break;
4972 case BCM4335_CHIP_ID: ciss = 1; defcis = defcis4335; hdrsz = 4; break;
4973 default:
4974 BS_ERROR(("%s: Unknown chip 0x%04x\n", __FUNCTION__, sih->chip));
4975 return BCME_ERROR;
4977 if (sih->ccrev >= 36) {
4978 uint32 otplayout;
4979 otplayout = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, otplayout), 0, 0);
4980 if (otplayout & OTP_CISFORMAT_NEW) {
4981 ciss = 1;
4982 hdrsz = 2;
4983 new_cisformat = TRUE;
4985 else {
4986 ciss = 3;
4987 hdrsz = 12;
4991 cis_src = si_cis_source(sih);
4992 switch (cis_src) {
4993 case CIS_SROM:
4994 sz = srom_size(sih, osh) << 1;
4995 break;
4996 case CIS_OTP:
4997 if (((oh = otp_init(sih)) != NULL) && (otp_status(oh) & OTPS_GUP_HW))
4998 sz = otp_size(oh);
4999 break;
5002 if (sz != 0) {
5003 if ((cisbuf = (uint16*)MALLOC(osh, sz)) == NULL)
5004 return BCME_NOMEM;
5005 msz = sz;
5007 switch (cis_src) {
5008 case CIS_SROM:
5009 rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, cisbuf, FALSE);
5010 break;
5011 case CIS_OTP:
5012 sz >>= 1;
5013 rc = otp_read_region(sih, OTP_HW_RGN, cisbuf, &sz);
5014 sz <<= 1;
5015 break;
5018 ASSERT(sz > hdrsz);
5019 if (rc == BCME_OK) {
5020 if ((cisbuf[0] == 0xffff) || (cisbuf[0] == 0)) {
5021 MFREE(osh, cisbuf, msz);
5022 cisbuf = NULL;
5023 } else if (new_cisformat) {
5024 cis[0] = (uint8*)(cisbuf + hdrsz);
5025 } else {
5026 cis[0] = (uint8*)cisbuf + hdrsz;
5027 cis[1] = (uint8*)cisbuf + hdrsz +
5028 (cisbuf[1] >> 8) + ((cisbuf[2] & 0x00ff) << 8) -
5029 SBSDIO_CIS_BASE_COMMON;
5030 cis[2] = (uint8*)cisbuf + hdrsz +
5031 cisbuf[3] - SBSDIO_CIS_BASE_COMMON;
5032 cis[3] = (uint8*)cisbuf + hdrsz +
5033 cisbuf[4] - SBSDIO_CIS_BASE_COMMON;
5034 ASSERT((cis[1] >= cis[0]) && (cis[1] < (uint8*)cisbuf + sz));
5035 ASSERT((cis[2] >= cis[0]) && (cis[2] < (uint8*)cisbuf + sz));
5036 ASSERT(((cis[3] >= cis[0]) && (cis[3] < (uint8*)cisbuf + sz)) ||
5037 (ciss <= 3));
5042 /* Use default if strapped to, or strapped source empty */
5043 if (cisbuf == NULL) {
5044 ciss = 1;
5045 cis[0] = defcis;
5048 #ifdef BCM_BMAC_VARS_APPEND
5049 srom_load_nvram(sih, osh, cis, ciss, vars, varsz);
5050 #else
5051 /* Parse the CIS */
5052 if (rc == BCME_OK) {
5053 if ((rc = srom_parsecis(osh, cis, ciss, vars, varsz)) == BCME_OK)
5054 nvram_append((void *)sih, *vars, *varsz);
5056 #endif /* BCM_BMAC_VARS_APPEND */
5057 /* Clean up */
5058 if (cisbuf != NULL)
5059 MFREE(osh, cisbuf, msz);
5061 srvars_inited = TRUE;
5062 exit:
5063 /* Tell the caller there is no individual SROM variables */
5064 *vars = NULL;
5065 *varsz = 0;
5067 /* return OK so the driver will load & use defaults if bad srom/otp */
5068 return BCME_OK;
5070 #else /* BCM_DONGLEVARS */
5071 static int
5072 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz)
5074 *vars = NULL;
5075 *varsz = 0;
5076 return BCME_OK;
5078 #endif /* BCM_DONGLEVARS */
5080 #else /* !BCMUSBDEV && !BCMSDIODEV */
5082 static int
5083 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz)
5085 /* Search flash nvram section for srom variables */
5086 return initvars_flash_si(sih, vars, varsz);
5088 #endif
5090 void
5091 srom_var_deinit(si_t *sih)
5093 srvars_inited = FALSE;
5096 extern void _make_gcc_happy_about_unused_variabe_(void);
5097 void
5098 _make_gcc_happy_about_unused_variabe_(void)
5100 #if defined(BCMUSBDEV)
5101 #if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND)
5102 UNUSED_PARAMETER(defaultsromvars_4322usb);
5103 UNUSED_PARAMETER(defaultsromvars_43234usb);
5104 UNUSED_PARAMETER(defaultsromvars_43235usb);
5105 UNUSED_PARAMETER(defaultsromvars_43236usb);
5106 UNUSED_PARAMETER(defaultsromvars_4319usb);
5107 #endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */
5108 #endif /* BCMUSBDEV */