usbmodeswitch: Updated to v.1.2.6 from shibby's branch.
[tomato.git] / release / src-rt / shared / bcmsrom.c
blobc40ee385aa3ddb564c666a4be854ef2e35b8bd52
1 /*
2 * Routines to access SPROM and to parse SROM/CIS variables.
4 * Copyright (C) 2010, 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,v 1.336.8.71 2011-01-28 00:42:43 Exp $
21 #include <typedefs.h>
22 #include <bcmdefs.h>
23 #include <osl.h>
24 #include <stdarg.h>
25 #include <bcmutils.h>
26 #include <hndsoc.h>
27 #include <sbchipc.h>
28 #include <bcmdevs.h>
29 #include <bcmendian.h>
30 #include <sbpcmcia.h>
31 #include <pcicfg.h>
32 #include <siutils.h>
33 #include <bcmsrom.h>
34 #include <bcmsrom_tbl.h>
35 #ifdef BCMSPI
36 #include <spid.h>
37 #endif
39 #include <bcmnvram.h>
40 #include <bcmotp.h>
42 #if defined(BCMUSBDEV)
43 #include <sbsdio.h>
44 #include <sbhnddma.h>
45 #include <sbsdpcmdev.h>
46 #endif
48 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
49 #include <sbsprom.h>
50 #endif
51 #include <proto/ethernet.h> /* for sprom content groking */
54 #if defined(BCMDBG_ERR) || defined(WLTEST)
55 #define BS_ERROR(args) printf args
56 #else
57 #define BS_ERROR(args)
58 #endif
60 #define SROM_OFFSET(sih) ((sih->ccrev > 31) ? \
61 (((sih->cccaps & CC_CAP_SROM) == 0) ? NULL : \
62 ((uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP)) : \
63 ((uint8 *)curmap + PCI_BAR0_SPROM_OFFSET))
65 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
66 #define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
67 #define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
68 #endif
70 typedef struct varbuf {
71 char *base; /* pointer to buffer base */
72 char *buf; /* pointer to current position */
73 unsigned int size; /* current (residual) size in bytes */
74 } varbuf_t;
75 extern char *_vars;
76 extern uint _varsz;
78 #define SROM_CIS_SINGLE 1
81 static int initvars_srom_si(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *count);
82 static void _initvars_srom_pci(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b);
83 static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count);
84 static int initvars_cis_pcmcia(si_t *sih, osl_t *osh, char **vars, uint *count);
85 #if !defined(BCMUSBDEV)
86 static int initvars_flash_si(si_t *sih, char **vars, uint *count);
87 #endif
88 #ifdef BCMSPI
89 static int initvars_cis_spi(osl_t *osh, char **vars, uint *count);
90 #endif /* BCMSPI */
91 static int sprom_cmd_pcmcia(osl_t *osh, uint8 cmd);
92 static int sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data);
93 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
94 static int sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data);
95 #endif
96 static int sprom_read_pci(osl_t *osh, si_t *sih, uint16 *sprom, uint wordoff, uint16 *buf,
97 uint nwords, bool check_crc);
98 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
99 static int otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz);
100 #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */
101 static uint16 srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, uint32 cmd, uint wordoff,
102 uint16 data);
104 static int initvars_table(osl_t *osh, char *start, char *end, char **vars, uint *count);
105 static int initvars_flash(si_t *sih, osl_t *osh, char **vp, uint len);
107 #if defined(BCMUSBDEV)
108 static int get_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs,
109 uint boff, uint16 *srom, uint bsz, bool check_crc);
110 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
111 static int set_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs,
112 uint boff, uint16 *srom, uint bsz);
113 #endif
114 #endif
116 #if defined(BCMUSBDEV_BMAC)
117 /* default to bcm94323 P200, other boards should have OTP programmed */
118 static char BCMATTACHDATA(defaultsromvars_4322usb)[] =
119 "vendid=0x14e4\0"
120 "subvendid=0x0a5c\0"
121 "subdevid=0xbdc\0"
122 "macaddr=00:90:4c:d3:04:73\0"
123 "sromrev=8\0"
124 "devid=0x432b\0"
125 "boardrev=0x1200\0"
126 "boardflags=0xa00\0"
127 "boardflags2=0x602\0"
128 "boardtype=0x04a8\0"
129 "tssipos2g=0x1\0"
130 "extpagain2g=0x0\0"
131 "pdetrange2g=0x0\0"
132 "triso2g=0x3\0"
133 "antswctl2g=0x2\0"
134 "tssipos5g=0x1\0"
135 "extpagain5g=0x0\0"
136 "pdetrange5g=0x0\0"
137 "triso5g=0x3\0"
138 "antswctl5g=0x2\0"
139 "maxp2ga0=0x48\0"
140 "itt2ga0=0x20\0"
141 "pa2gw0a0=0xFEA8\0"
142 "pa2gw1a0=0x16CD\0"
143 "pa2gw2a0=0xFAA5\0"
144 "maxp5ga0=0x40\0"
145 "itt5ga0=0x3e\0"
146 "maxp5gha0=0x3c\0"
147 "maxp5gla0=0x40\0"
148 "pa5gw0a0=0xFEB2\0"
149 "pa5gw1a0=0x1471\0"
150 "pa5gw2a0=0xFB1F\0"
151 "pa5glw0a0=0xFEA2\0"
152 "pa5glw1a0=0x149A\0"
153 "pa5glw2a0=0xFAFC\0"
154 "pa5ghw0a0=0xFEC6\0"
155 "pa5ghw1a0=0x13DD\0"
156 "pa5ghw2a0=0xFB48\0"
157 "maxp2ga1=0x48\0"
158 "itt2ga1=0x20\0"
159 "pa2gw0a1=0xFEA3\0"
160 "pa2gw1a1=0x1687\0"
161 "pa2gw2a1=0xFAAA\0"
162 "maxp5ga1=0x40\0"
163 "itt5ga1=0x3e\0"
164 "maxp5gha1=0x3c\0"
165 "maxp5gla1=0x40\0"
166 "pa5gw0a1=0xFEBC\0"
167 "pa5gw1a1=0x14F9\0"
168 "pa5gw2a1=0xFB05\0"
169 "pa5glw0a1=0xFEBE\0"
170 "pa5glw1a1=0x1478\0"
171 "pa5glw2a1=0xFB1A\0"
172 "pa5ghw0a1=0xFEE1\0"
173 "pa5ghw1a1=0x14FD\0"
174 "pa5ghw2a1=0xFB38\0"
175 "cctl=0\0"
176 "ccode=US\0"
177 "regrev=0x0\0"
178 "ledbh0=0xff\0"
179 "ledbh1=0x2\0"
180 "ledbh2=0x3\0"
181 "ledbh3=0xff\0"
182 "leddc=0xa0a0\0"
183 "aa2g=0x3\0"
184 "aa5g=0x3\0"
185 "ag0=0x2\0"
186 "ag1=0x2\0"
187 "ag2=0xff\0"
188 "ag3=0xff\0"
189 "txchain=0x3\0"
190 "rxchain=0x3\0"
191 "antswitch=0\0"
192 "END\0";
194 static char BCMATTACHDATA(defaultsromvars_43234usb)[] =
195 "vendid=0x14e4\0"
196 "subvendid=0x0a5c\0"
197 "subdevid=0xbdc\0"
198 "macaddr=00:90:4c:03:21:23\0"
199 "cctl=0\0"
200 "ccode=US\0"
201 "regrev=0x0\0"
202 "ledbh0=0x82\0"
203 "ledbh1=0xff\0"
204 "ledbh2=0xff\0"
205 "ledbh3=0xff\0"
206 "leddc=0x0\0"
207 "aa2g=0x2\0"
208 "aa5g=0x2\0"
209 "ag0=0x2\0"
210 "ag1=0x2\0"
211 "ag2=0x2\0"
212 "ag3=0xff\0"
213 "txchain=0x2\0"
214 "rxchain=0x2\0"
215 "antswitch=0\0"
216 "sromrev=8\0"
217 "devid=0x4346\0"
218 "boardrev=0x1113\0"
219 "boardflags=0x200\0"
220 "boardflags2=0x0\0"
221 "boardtype=0x0521\0"
222 "tssipos2g=0x1\0"
223 "extpagain2g=0x2\0"
224 "pdetrange2g=0x2\0"
225 "triso2g=0x3\0"
226 "antswctl2g=0x0\0"
227 "tssipos5g=0x1\0"
228 "extpagain5g=0x2\0"
229 "pdetrange5g=0x2\0"
230 "triso5g=0x3\0"
231 "antswctl5g=0x0\0"
232 "ofdm2gpo=0x44444444\0"
233 "ofdm5gpo=0x0\0"
234 "ofdm5glpo=0x0\0"
235 "ofdm5ghpo=0x0\0"
236 "mcs2gpo0=0x4444\0"
237 "mcs2gpo1=0x4444\0"
238 "mcs2gpo2=0x4444\0"
239 "mcs2gpo3=0x4444\0"
240 "mcs2gpo4=0x9999\0"
241 "mcs2gpo5=0x9999\0"
242 "mcs2gpo6=0x9999\0"
243 "mcs2gpo7=0x9999\0"
244 "mcs5gpo4=0x2222\0"
245 "mcs5gpo5=0x2222\0"
246 "mcs5gpo6=0x2222\0"
247 "mcs5gpo7=0x2222\0"
248 "mcs5glpo4=0x2222\0"
249 "mcs5glpo5=0x2222\0"
250 "mcs5glpo6=0x2222\0"
251 "mcs5glpo7=0x2222\0"
252 "mcs5ghpo4=0x2222\0"
253 "mcs5ghpo5=0x2222\0"
254 "mcs5ghpo6=0x2222\0"
255 "mcs5ghpo7=0x2222\0"
256 "maxp2ga0=0x4c\0"
257 "itt2ga0=0x20\0"
258 "itt5ga0=0x3e\0"
259 "pa2gw0a0=0xFF15\0"
260 "pa2gw1a0=0x135B\0"
261 "pa2gw2a0=0xFB5C\0"
262 "maxp5ga0=0x3c\0"
263 "maxp5gha0=0x3a\0"
264 "maxp5gla0=0x3c\0"
265 "pa5gw0a0=0xFE6A\0"
266 "pa5gw1a0=0x1430\0"
267 "pa5gw2a0=0xFAEB\0"
268 "pa5glw0a0=0xFE64\0"
269 "pa5glw1a0=0x13F7\0"
270 "pa5glw2a0=0xFAF6\0"
271 "pa5ghw0a0=0xFE70\0"
272 "pa5ghw1a0=0x14DE\0"
273 "pa5ghw2a0=0xFAC7\0"
274 "maxp2ga1=0x4c\0"
275 "itt2ga1=0x20\0"
276 "itt5ga1=0x3e\0"
277 "pa2gw0a1=0xFF11\0"
278 "pa2gw1a1=0x1324\0"
279 "pa2gw2a1=0xFB5E\0"
280 "maxp5ga1=0x3c\0"
281 "maxp5gha1=0x3a\0"
282 "maxp5gla1=0x3c\0"
283 "pa5gw0a1=0xFE7D\0"
284 "pa5gw1a1=0x1449\0"
285 "pa5gw2a1=0xFAED\0"
286 "pa5glw0a1=0xFE87\0"
287 "pa5glw1a1=0x14BE\0"
288 "pa5glw2a1=0xFAD6\0"
289 "pa5ghw0a1=0xFE62\0"
290 "pa5ghw1a1=0x137E\0"
291 "pa5ghw2a1=0xFB12\0"
292 "END\0";
294 static char BCMATTACHDATA(defaultsromvars_43235usb)[] =
295 "vendid=0x14e4\0"
296 "subvendid=0x0a5c\0"
297 "subdevid=0xbdc\0"
298 "macaddr=00:90:4c:05:30:01\0"
299 "ccode=US\0"
300 "regrev=0x0\0"
301 "ledbh0=0x82\0"
302 "ledbh1=0xff\0"
303 "ledbh2=0xff\0"
304 "ledbh3=0xff\0"
305 "leddc=0x0\0"
306 "aa2g=0x3\0"
307 "ag0=0x2\0"
308 "ag1=0x2\0"
309 "ag2=0xff\0"
310 "ag3=0xff\0"
311 "txchain=0x3\0"
312 "rxchain=0x3\0"
313 "antswitch=0\0"
314 "sromrev=8\0"
315 "devid=0x4347\0"
316 "boardrev=0x1113\0"
317 "boardflags=0x200\0"
318 "boardflags2=0x0\0"
319 "boardtype=0x0571\0"
320 "tssipos2g=0x1\0"
321 "extpagain2g=0x2\0"
322 "pdetrange2g=0x2\0"
323 "triso2g=0x3\0"
324 "antswctl2g=0x0\0"
325 "antswctl5g=0x0\0"
326 "ofdm2gpo=0x0\0"
327 "mcs2gpo0=0x0\0"
328 "mcs2gpo1=0x0\0"
329 "mcs2gpo2=0x0\0"
330 "mcs2gpo3=0x0\0"
331 "mcs2gpo4=0x2222\0"
332 "mcs2gpo5=0x2222\0"
333 "mcs2gpo6=0x2222\0"
334 "mcs2gpo7=0x4444\0"
335 "maxp2ga0=0x42\0"
336 "itt2ga0=0x20\0"
337 "pa2gw0a0=0xFF00\0"
338 "pa2gw1a0=0x143C\0"
339 "pa2gw2a0=0xFB27\0"
340 "maxp2ga1=0x42\0"
341 "itt2ga1=0x20\0"
342 "pa2gw0a1=0xFF22\0"
343 "pa2gw1a1=0x142E\0"
344 "pa2gw2a1=0xFB45\0"
345 "tempthresh=120\0"
346 "temps_period=5\0"
347 "temp_hysteresis=5\0"
348 "END\0";
350 static char BCMATTACHDATA(defaultsromvars_43236usb)[] =
351 "vendid=0x14e4\0"
352 "subvendid=0x0a5c\0"
353 "subdevid=0xbdc\0"
354 "macaddr=00:90:4c:03:21:23\0"
355 "cctl=0\0"
356 "ccode=US\0"
357 "regrev=0x0\0"
358 "ledbh0=0x82\0"
359 "ledbh1=0xff\0"
360 "ledbh2=0xff\0"
361 "ledbh3=0xff\0"
362 "leddc=0x0\0"
363 "aa2g=0x3\0"
364 "aa5g=0x3\0"
365 "ag0=0x2\0"
366 "ag1=0x2\0"
367 "ag2=0x2\0"
368 "ag3=0xff\0"
369 "txchain=0x3\0"
370 "rxchain=0x3\0"
371 "antswitch=0\0"
372 "sromrev=8\0"
373 "devid=0x4346\0"
374 "boardrev=0x1409\0"
375 "boardflags=0x200\0"
376 "boardflags2=0x2000\0"
377 "boardtype=0x0521\0"
378 "tssipos2g=0x1\0"
379 "extpagain2g=0x2\0"
380 "pdetrange2g=0x2\0"
381 "triso2g=0x3\0"
382 "antswctl2g=0x0\0"
383 "tssipos5g=0x1\0"
384 "extpagain5g=0x2\0"
385 "pdetrange5g=0x2\0"
386 "triso5g=0x3\0"
387 "antswctl5g=0x0\0"
388 "ofdm2gpo=0x0\0"
389 "ofdm5gpo=0x0\0"
390 "ofdm5glpo=0x0\0"
391 "ofdm5ghpo=0x0\0"
392 "mcs2gpo0=0x0\0"
393 "mcs2gpo1=0x0\0"
394 "mcs2gpo2=0x0\0"
395 "mcs2gpo3=0x0\0"
396 "mcs2gpo4=0x4444\0"
397 "mcs2gpo5=0x4444\0"
398 "mcs2gpo6=0x4444\0"
399 "mcs2gpo7=0x4444\0"
400 "mcs5gpo4=0x2222\0"
401 "mcs5gpo5=0x2222\0"
402 "mcs5gpo6=0x2222\0"
403 "mcs5gpo7=0x2222\0"
404 "mcs5glpo4=0x2222\0"
405 "mcs5glpo5=0x2222\0"
406 "mcs5glpo6=0x2222\0"
407 "mcs5glpo7=0x2222\0"
408 "mcs5ghpo4=0x2222\0"
409 "mcs5ghpo5=0x2222\0"
410 "mcs5ghpo6=0x2222\0"
411 "mcs5ghpo7=0x2222\0"
412 "maxp2ga0=0x42\0"
413 "itt2ga0=0x20\0"
414 "itt5ga0=0x3e\0"
415 "pa2gw0a0=0xFF21\0"
416 "pa2gw1a0=0x13B7\0"
417 "pa2gw2a0=0xFB44\0"
418 "maxp5ga0=0x3e\0"
419 "maxp5gha0=0x3a\0"
420 "maxp5gla0=0x3c\0"
421 "pa5gw0a0=0xFEB2\0"
422 "pa5gw1a0=0x1570\0"
423 "pa5gw2a0=0xFAD6\0"
424 "pa5glw0a0=0xFE64\0"
425 "pa5glw1a0=0x13F7\0"
426 "pa5glw2a0=0xFAF6\0"
427 "pa5ghw0a0=0xFEAB\0"
428 "pa5ghw1a0=0x15BB\0"
429 "pa5ghw2a0=0xFAC6\0"
430 "maxp2ga1=0x42\0"
431 "itt2ga1=0x20\0"
432 "itt5ga1=0x3e\0"
433 "pa2gw0a1=0xFF17\0"
434 "pa2gw1a1=0x13C4\0"
435 "pa2gw2a1=0xFB3C\0"
436 "maxp5ga1=0x3e\0"
437 "maxp5gha1=0x3a\0"
438 "maxp5gla1=0x3c\0"
439 "pa5gw0a1=0xFE6F\0"
440 "pa5gw1a1=0x13CC\0"
441 "pa5gw2a1=0xFAF8\0"
442 "pa5glw0a1=0xFE87\0"
443 "pa5glw1a1=0x14BE\0"
444 "pa5glw2a1=0xFAD6\0"
445 "pa5ghw0a1=0xFE68\0"
446 "pa5ghw1a1=0x13E9\0"
447 "pa5ghw2a1=0xFAF6\0"
448 "tempthresh=120\0"
449 "temps_period=5\0"
450 "temp_hysteresis=5\0"
451 "END\0";
453 static char BCMATTACHDATA(defaultsromvars_4319usb)[] =
454 "sromrev=3\0"
455 "vendid=0x14e4\0"
456 "devid=0x4338\0"
457 "boardtype=0x4ee\0"
458 "boardrev=0x1103\0"
459 "boardflags=0x400201\0"
460 "boardflags2=0x80\0"
461 "xtalfreq=30000\0"
462 "aa2g=1\0"
463 "aa5g=0\0"
464 "ag0=0\0"
465 "opo=0\0"
466 "pa0b0=0x1675\0"
467 "pa0b1=0xfa74\0"
468 "pa0b2=0xfea1\0"
469 "pa0itssit=62\0"
470 "pa0maxpwr=78\0"
471 "rssismf2g=0xa\0"
472 "rssismc2g=0xb\0"
473 "rssisav2g=0x3\0"
474 "bxa2g=0\0"
475 "cckdigfilttype=6\0"
476 "rxpo2g=2\0"
477 "cckpo=0\0"
478 "ofdmpo=0x22220000\0"
479 "mcs2gpo0=0x6666\0"
480 "mcs2gpo1=0x6666\0"
481 "mcs2gpo2=0x0\0"
482 "mcs2gpo3=0x0\0"
483 "mcs2gpo4=0x6666\0"
484 "mcs2gpo5=0x6666\0"
485 "boardnum=291\0"
486 "macaddr=00:90:4c:16:01:23\0"
487 "END\0";
488 #endif /* BCMUSBDEV_BMAC */
491 /* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */
492 #if defined(BCMHOSTVARS)
493 /* Also used by wl_readconfigdata for vars download */
494 char BCMATTACHDATA(mfgsromvars)[VARS_MAX];
495 int BCMATTACHDATA(defvarslen) = 0;
496 #endif
498 /* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */
499 #if defined(BCMHOSTVARS)
500 static char BCMATTACHDATA(defaultsromvars_4331)[] =
501 "sromrev=9\0"
502 "boardrev=0x1104\0"
503 "boardflags=0x200\0"
504 "boardflags2=0x0\0"
505 "boardtype=0x524\0"
506 "boardvendor=0x14e4\0"
507 "boardnum=0x2064\0"
508 "macaddr=00:90:4c:1a:20:64\0"
509 "ccode=0x0\0"
510 "regrev=0x0\0"
511 "ledbh0=0xff\0"
512 "ledbh1=0xff\0"
513 "ledbh2=0xff\0"
514 "ledbh3=0xff\0"
515 "leddc=0xffff\0"
516 "opo=0x0\0"
517 "aa2g=0x7\0"
518 "aa5g=0x7\0"
519 "ag0=0x2\0"
520 "ag1=0x2\0"
521 "ag2=0x2\0"
522 "ag3=0xff\0"
523 "pa0b0=0xfe7f\0"
524 "pa0b1=0x15d9\0"
525 "pa0b2=0xfac6\0"
526 "pa0itssit=0x20\0"
527 "pa0maxpwr=0x48\0"
528 "pa1b0=0xfe89\0"
529 "pa1b1=0x14b1\0"
530 "pa1b2=0xfada\0"
531 "pa1lob0=0xffff\0"
532 "pa1lob1=0xffff\0"
533 "pa1lob2=0xffff\0"
534 "pa1hib0=0xfe8f\0"
535 "pa1hib1=0x13df\0"
536 "pa1hib2=0xfafa\0"
537 "pa1itssit=0x3e\0"
538 "pa1maxpwr=0x3c\0"
539 "pa1lomaxpwr=0x3c\0"
540 "pa1himaxpwr=0x3c\0"
541 "bxa2g=0x3\0"
542 "rssisav2g=0x7\0"
543 "rssismc2g=0xf\0"
544 "rssismf2g=0xf\0"
545 "bxa5g=0x3\0"
546 "rssisav5g=0x7\0"
547 "rssismc5g=0xf\0"
548 "rssismf5g=0xf\0"
549 "tri2g=0xff\0"
550 "tri5g=0xff\0"
551 "tri5gl=0xff\0"
552 "tri5gh=0xff\0"
553 "rxpo2g=0xff\0"
554 "rxpo5g=0xff\0"
555 "txchain=0x7\0"
556 "rxchain=0x7\0"
557 "antswitch=0x0\0"
558 "tssipos2g=0x1\0"
559 "extpagain2g=0x2\0"
560 "pdetrange2g=0x4\0"
561 "triso2g=0x3\0"
562 "antswctl2g=0x0\0"
563 "tssipos5g=0x1\0"
564 "elna2g=0xff\0"
565 "extpagain5g=0x2\0"
566 "pdetrange5g=0x4\0"
567 "triso5g=0x3\0"
568 "antswctl5g=0x0\0"
569 "elna5g=0xff\0"
570 "cckbw202gpo=0x0\0"
571 "cckbw20ul2gpo=0x0\0"
572 "legofdmbw202gpo=0x0\0"
573 "legofdmbw20ul2gpo=0x0\0"
574 "legofdmbw205glpo=0x0\0"
575 "legofdmbw20ul5glpo=0x0\0"
576 "legofdmbw205gmpo=0x0\0"
577 "legofdmbw20ul5gmpo=0x0\0"
578 "legofdmbw205ghpo=0x0\0"
579 "legofdmbw20ul5ghpo=0x0\0"
580 "mcsbw202gpo=0x0\0"
581 "mcsbw20ul2gpo=0x0\0"
582 "mcsbw402gpo=0x0\0"
583 "mcsbw205glpo=0x0\0"
584 "mcsbw20ul5glpo=0x0\0"
585 "mcsbw405glpo=0x0\0"
586 "mcsbw205gmpo=0x0\0"
587 "mcsbw20ul5gmpo=0x0\0"
588 "mcsbw405gmpo=0x0\0"
589 "mcsbw205ghpo=0x0\0"
590 "mcsbw20ul5ghpo=0x0\0"
591 "mcsbw405ghpo=0x0\0"
592 "mcs32po=0x0\0"
593 "legofdm40duppo=0x0\0"
594 "maxp2ga0=0x48\0"
595 "itt2ga0=0x20\0"
596 "itt5ga0=0x3e\0"
597 "pa2gw0a0=0xfe7f\0"
598 "pa2gw1a0=0x15d9\0"
599 "pa2gw2a0=0xfac6\0"
600 "maxp5ga0=0x3c\0"
601 "maxp5gha0=0x3c\0"
602 "maxp5gla0=0x3c\0"
603 "pa5gw0a0=0xfe89\0"
604 "pa5gw1a0=0x14b1\0"
605 "pa5gw2a0=0xfada\0"
606 "pa5glw0a0=0xffff\0"
607 "pa5glw1a0=0xffff\0"
608 "pa5glw2a0=0xffff\0"
609 "pa5ghw0a0=0xfe8f\0"
610 "pa5ghw1a0=0x13df\0"
611 "pa5ghw2a0=0xfafa\0"
612 "maxp2ga1=0x48\0"
613 "itt2ga1=0x20\0"
614 "itt5ga1=0x3e\0"
615 "pa2gw0a1=0xfe54\0"
616 "pa2gw1a1=0x1563\0"
617 "pa2gw2a1=0xfa7f\0"
618 "maxp5ga1=0x3c\0"
619 "maxp5gha1=0x3c\0"
620 "maxp5gla1=0x3c\0"
621 "pa5gw0a1=0xfe53\0"
622 "pa5gw1a1=0x14fe\0"
623 "pa5gw2a1=0xfa94\0"
624 "pa5glw0a1=0xffff\0"
625 "pa5glw1a1=0xffff\0"
626 "pa5glw2a1=0xffff\0"
627 "pa5ghw0a1=0xfe6e\0"
628 "pa5ghw1a1=0x1457\0"
629 "pa5ghw2a1=0xfab9\0"
630 "END\0";
631 #endif
633 /* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */
634 #if defined(BCMHOSTVARS)
635 static char BCMATTACHDATA(defaultsromvars_wltest)[] =
636 "macaddr=00:90:4c:f8:00:01\0"
637 "et0macaddr=00:11:22:33:44:52\0"
638 "et0phyaddr=30\0"
639 "et0mdcport=0\0"
640 "gpio2=robo_reset\0"
641 "boardvendor=0x14e4\0"
642 "boardflags=0x210\0"
643 "boardflags2=0\0"
644 "boardtype=0x04c3\0"
645 "boardrev=0x1100\0"
646 "sromrev=8\0"
647 "devid=0x432c\0"
648 "ccode=0\0"
649 "regrev=0\0"
650 "ledbh0=255\0"
651 "ledbh1=255\0"
652 "ledbh2=255\0"
653 "ledbh3=255\0"
654 "leddc=0xffff\0"
655 "aa2g=3\0"
656 "ag0=2\0"
657 "ag1=2\0"
658 "aa5g=3\0"
659 "aa0=2\0"
660 "aa1=2\0"
661 "txchain=3\0"
662 "rxchain=3\0"
663 "antswitch=0\0"
664 "itt2ga0=0x20\0"
665 "maxp2ga0=0x48\0"
666 "pa2gw0a0=0xfe9e\0"
667 "pa2gw1a0=0x15d5\0"
668 "pa2gw2a0=0xfae9\0"
669 "itt2ga1=0x20\0"
670 "maxp2ga1=0x48\0"
671 "pa2gw0a1=0xfeb3\0"
672 "pa2gw1a1=0x15c9\0"
673 "pa2gw2a1=0xfaf7\0"
674 "tssipos2g=1\0"
675 "extpagain2g=0\0"
676 "pdetrange2g=0\0"
677 "triso2g=3\0"
678 "antswctl2g=0\0"
679 "tssipos5g=1\0"
680 "extpagain5g=0\0"
681 "pdetrange5g=0\0"
682 "triso5g=3\0"
683 "antswctl5g=0\0"
684 "cck2gpo=0\0"
685 "ofdm2gpo=0\0"
686 "mcs2gpo0=0\0"
687 "mcs2gpo1=0\0"
688 "mcs2gpo2=0\0"
689 "mcs2gpo3=0\0"
690 "mcs2gpo4=0\0"
691 "mcs2gpo5=0\0"
692 "mcs2gpo6=0\0"
693 "mcs2gpo7=0\0"
694 "cddpo=0\0"
695 "stbcpo=0\0"
696 "bw40po=4\0"
697 "bwduppo=0\0"
698 "END\0";
699 #endif
701 /* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */
702 #if defined(BCMHOSTVARS) || (defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND))
703 /* It must end with pattern of "END" */
704 static uint
705 BCMATTACHFN(srom_vars_len)(char *vars)
707 uint pos = 0;
708 uint len;
709 char *s;
711 for (s = vars; s && *s;) {
713 if (strcmp(s, "END") == 0)
714 break;
716 len = strlen(s);
717 s += strlen(s) + 1;
718 pos += len + 1;
719 /* BS_ERROR(("len %d vars[pos] %s\n", pos, s)); */
720 if (pos > 4000) {
721 return 0;
725 return pos + 4; /* include the "END\0" */
727 #endif
729 /* Initialization of varbuf structure */
730 static void
731 BCMATTACHFN(varbuf_init)(varbuf_t *b, char *buf, uint size)
733 b->size = size;
734 b->base = b->buf = buf;
737 /* append a null terminated var=value string */
738 static int
739 BCMATTACHFN(varbuf_append)(varbuf_t *b, const char *fmt, ...)
741 va_list ap;
742 int r;
743 size_t len;
744 char *s;
746 if (b->size < 2)
747 return 0;
749 va_start(ap, fmt);
750 r = vsnprintf(b->buf, b->size, fmt, ap);
751 va_end(ap);
753 /* C99 snprintf behavior returns r >= size on overflow,
754 * others return -1 on overflow.
755 * All return -1 on format error.
756 * We need to leave room for 2 null terminations, one for the current var
757 * string, and one for final null of the var table. So check that the
758 * strlen written, r, leaves room for 2 chars.
760 if ((r == -1) || (r > (int)(b->size - 2))) {
761 b->size = 0;
762 return 0;
765 /* Remove any earlier occurrence of the same variable */
766 if ((s = strchr(b->buf, '=')) != NULL) {
767 len = (size_t)(s - b->buf);
768 for (s = b->base; s < b->buf;) {
769 if ((bcmp(s, b->buf, len) == 0) && s[len] == '=') {
770 len = strlen(s) + 1;
771 memmove(s, (s + len), ((b->buf + r + 1) - (s + len)));
772 b->buf -= len;
773 b->size += (unsigned int)len;
774 break;
777 while (*s++)
782 /* skip over this string's null termination */
783 r++;
784 b->size -= r;
785 b->buf += r;
787 return r;
791 * Initialize local vars from the right source for this platform.
792 * Return 0 on success, nonzero on error.
795 BCMATTACHFN(srom_var_init)(si_t *sih, uint bustype, void *curmap, osl_t *osh,
796 char **vars, uint *count)
798 uint len;
800 len = 0;
802 ASSERT(bustype == BUSTYPE(bustype));
803 if (vars == NULL || count == NULL)
804 return (0);
806 *vars = NULL;
807 *count = 0;
809 switch (BUSTYPE(bustype)) {
810 case SI_BUS:
811 case JTAG_BUS:
812 return initvars_srom_si(sih, osh, curmap, vars, count);
814 case PCI_BUS:
815 ASSERT(curmap != NULL);
816 if (curmap == NULL)
817 return (-1);
819 return initvars_srom_pci(sih, curmap, vars, count);
821 case PCMCIA_BUS:
822 return initvars_cis_pcmcia(sih, osh, vars, count);
825 #ifdef BCMSPI
826 case SPI_BUS:
827 return initvars_cis_spi(osh, vars, count);
828 #endif /* BCMSPI */
830 default:
831 ASSERT(0);
833 return (-1);
836 /* support only 16-bit word read from srom */
838 srom_read(si_t *sih, uint bustype, void *curmap, osl_t *osh,
839 uint byteoff, uint nbytes, uint16 *buf, bool check_crc)
841 uint i, off, nw;
843 ASSERT(bustype == BUSTYPE(bustype));
845 /* check input - 16-bit access only */
846 if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > SROM_MAX)
847 return 1;
849 off = byteoff / 2;
850 nw = nbytes / 2;
852 if (BUSTYPE(bustype) == PCI_BUS) {
853 if (!curmap)
854 return 1;
856 if (si_is_sprom_available(sih)) {
857 uint16 *srom;
859 srom = (uint16 *)SROM_OFFSET(sih);
860 if (srom == NULL)
861 return 1;
863 if (sprom_read_pci(osh, sih, srom, off, buf, nw, check_crc))
864 return 1;
866 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
867 else {
868 if (otp_read_pci(osh, sih, buf, SROM_MAX))
869 return 1;
871 #endif
872 } else if (BUSTYPE(bustype) == PCMCIA_BUS) {
873 for (i = 0; i < nw; i++) {
874 if (sprom_read_pcmcia(osh, (uint16)(off + i), (uint16 *)(buf + i)))
875 return 1;
877 #ifdef BCMSPI
878 } else if (BUSTYPE(bustype) == SPI_BUS) {
879 if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, (uint8 *)buf, byteoff + nbytes) != 0)
880 return 1;
881 #endif /* BCMSPI */
882 } else if (BUSTYPE(bustype) == SI_BUS) {
883 #if defined(BCMUSBDEV)
884 if (SPROMBUS == PCMCIA_BUS) {
885 uint origidx;
886 void *regs;
887 int rc;
888 bool wasup;
890 /* Don't bother if we can't talk to SPROM */
891 if (!si_is_sprom_available(sih))
892 return 1;
894 origidx = si_coreidx(sih);
895 regs = si_setcore(sih, PCMCIA_CORE_ID, 0);
896 if (!regs)
897 regs = si_setcore(sih, SDIOD_CORE_ID, 0);
898 ASSERT(regs != NULL);
900 if (!(wasup = si_iscoreup(sih)))
901 si_core_reset(sih, 0, 0);
903 rc = get_si_pcmcia_srom(sih, osh, regs, byteoff, buf, nbytes, check_crc);
905 if (!wasup)
906 si_core_disable(sih, 0);
908 si_setcoreidx(sih, origidx);
909 return rc;
911 #endif
913 return 1;
914 } else {
915 return 1;
918 return 0;
921 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
922 /* support only 16-bit word write into srom */
924 srom_write(si_t *sih, uint bustype, void *curmap, osl_t *osh,
925 uint byteoff, uint nbytes, uint16 *buf)
927 uint i, nw, crc_range;
928 uint16 *old, *new;
929 uint8 crc;
930 volatile uint32 val32;
931 int rc = 1;
933 ASSERT(bustype == BUSTYPE(bustype));
935 old = MALLOC(osh, SROM_MAXW * sizeof(uint16));
936 new = MALLOC(osh, SROM_MAXW * sizeof(uint16));
938 if (old == NULL || new == NULL)
939 goto done;
941 /* check input - 16-bit access only. use byteoff 0x55aa to indicate
942 * srclear
944 if ((byteoff != 0x55aa) && ((byteoff & 1) || (nbytes & 1)))
945 goto done;
947 if ((byteoff != 0x55aa) && ((byteoff + nbytes) > SROM_MAX))
948 goto done;
950 if (BUSTYPE(bustype) == PCMCIA_BUS) {
951 crc_range = SROM_MAX;
953 #if defined(BCMUSBDEV)
954 else {
955 crc_range = srom_size(sih, osh);
957 #else
958 else {
959 crc_range = (SROM8_SIGN + 1) * 2; /* must big enough for SROM8 */
961 #endif
963 nw = crc_range / 2;
964 /* read first small number words from srom, then adjust the length, read all */
965 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE))
966 goto done;
968 BS_ERROR(("%s: old[SROM4_SIGN] 0x%x, old[SROM8_SIGN] 0x%x\n",
969 __FUNCTION__, old[SROM4_SIGN], old[SROM8_SIGN]));
970 /* Deal with blank srom */
971 if (old[0] == 0xffff) {
972 /* see if the input buffer is valid SROM image or not */
973 if ((buf[SROM4_SIGN] == SROM4_SIGNATURE) ||
974 (buf[SROM8_SIGN] == SROM4_SIGNATURE)) {
975 BS_ERROR(("%s: buf[SROM4_SIGN] 0x%x, buf[SROM8_SIGN] 0x%x\n",
976 __FUNCTION__, buf[SROM4_SIGN], buf[SROM8_SIGN]));
978 /* block invalid buffer size */
979 if (nbytes < SROM4_WORDS * 2) {
980 rc = BCME_BUFTOOSHORT;
981 goto done;
982 } else if (nbytes > SROM4_WORDS * 2) {
983 rc = BCME_BUFTOOLONG;
984 goto done;
987 nw = SROM4_WORDS;
988 } else if (nbytes == SROM_WORDS * 2){ /* the other possible SROM format */
989 BS_ERROR(("%s: Not SROM4 or SROM8.\n", __FUNCTION__));
991 nw = SROM_WORDS;
992 } else {
993 BS_ERROR(("%s: Invalid input file signature\n", __FUNCTION__));
994 rc = BCME_BADARG;
995 goto done;
997 crc_range = nw * 2;
998 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE))
999 goto done;
1000 } else if ((old[SROM4_SIGN] == SROM4_SIGNATURE) ||
1001 (old[SROM8_SIGN] == SROM4_SIGNATURE)) {
1002 nw = SROM4_WORDS;
1003 crc_range = nw * 2;
1004 if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE))
1005 goto done;
1006 } else {
1007 /* Assert that we have already read enough for sromrev 2 */
1008 ASSERT(crc_range >= SROM_WORDS * 2);
1009 nw = SROM_WORDS;
1010 crc_range = nw * 2;
1013 if (byteoff == 0x55aa) {
1014 /* Erase request */
1015 crc_range = 0;
1016 memset((void *)new, 0xff, nw * 2);
1017 } else {
1018 /* Copy old contents */
1019 bcopy((void *)old, (void *)new, nw * 2);
1020 /* make changes */
1021 bcopy((void *)buf, (void *)&new[byteoff / 2], nbytes);
1024 if (crc_range) {
1025 /* calculate crc */
1026 htol16_buf(new, crc_range);
1027 crc = ~hndcrc8((uint8 *)new, crc_range - 1, CRC8_INIT_VALUE);
1028 ltoh16_buf(new, crc_range);
1029 new[nw - 1] = (crc << 8) | (new[nw - 1] & 0xff);
1032 if (BUSTYPE(bustype) == PCI_BUS) {
1033 uint16 *srom = NULL;
1034 void *ccregs = NULL;
1035 uint32 ccval = 0;
1037 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
1038 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
1039 /* save current control setting */
1040 ccval = si_chipcontrl_epa4331_read(sih);
1041 /* Disable Ext PA lines to allow reading from SROM */
1042 si_chipcontrl_epa4331(sih, FALSE);
1045 /* enable writes to the SPROM */
1046 if (sih->ccrev > 31) {
1047 ccregs = (void *)((uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET);
1048 srom = (uint16 *)((uint8 *)ccregs + CC_SROM_OTP);
1049 (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WREN, 0, 0);
1050 } else {
1051 srom = (uint16 *)((uint8 *)curmap + PCI_BAR0_SPROM_OFFSET);
1052 val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
1053 val32 |= SPROM_WRITEEN;
1054 OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32);
1056 bcm_mdelay(WRITE_ENABLE_DELAY);
1057 /* write srom */
1058 for (i = 0; i < nw; i++) {
1059 if (old[i] != new[i]) {
1060 if (sih->ccrev > 31) {
1061 if ((sih->cccaps & CC_CAP_SROM) == 0) {
1062 /* No srom support in this chip */
1063 BS_ERROR(("srom_write, invalid srom, skip\n"));
1064 } else
1065 (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRITE,
1066 i, new[i]);
1067 } else {
1068 W_REG(osh, &srom[i], new[i]);
1070 bcm_mdelay(WRITE_WORD_DELAY);
1073 /* disable writes to the SPROM */
1074 if (sih->ccrev > 31) {
1075 (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRDIS, 0, 0);
1076 } else {
1077 OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 &
1078 ~SPROM_WRITEEN);
1081 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
1082 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
1083 /* Restore config after reading SROM */
1084 si_chipcontrl_epa4331_restore(sih, ccval);
1087 } else if (BUSTYPE(bustype) == PCMCIA_BUS) {
1088 /* enable writes to the SPROM */
1089 if (sprom_cmd_pcmcia(osh, SROM_WEN))
1090 goto done;
1091 bcm_mdelay(WRITE_ENABLE_DELAY);
1092 /* write srom */
1093 for (i = 0; i < nw; i++) {
1094 if (old[i] != new[i]) {
1095 sprom_write_pcmcia(osh, (uint16)(i), new[i]);
1096 bcm_mdelay(WRITE_WORD_DELAY);
1099 /* disable writes to the SPROM */
1100 if (sprom_cmd_pcmcia(osh, SROM_WDS))
1101 goto done;
1102 } else if (BUSTYPE(bustype) == SI_BUS) {
1103 #if defined(BCMUSBDEV)
1104 if (SPROMBUS == PCMCIA_BUS) {
1105 uint origidx;
1106 void *regs;
1107 bool wasup;
1109 origidx = si_coreidx(sih);
1110 regs = si_setcore(sih, PCMCIA_CORE_ID, 0);
1111 if (!regs)
1112 regs = si_setcore(sih, SDIOD_CORE_ID, 0);
1113 ASSERT(regs != NULL);
1115 if (!(wasup = si_iscoreup(sih)))
1116 si_core_reset(sih, 0, 0);
1118 rc = set_si_pcmcia_srom(sih, osh, regs, byteoff, buf, nbytes);
1120 if (!wasup)
1121 si_core_disable(sih, 0);
1123 si_setcoreidx(sih, origidx);
1124 goto done;
1126 #endif
1127 goto done;
1128 } else {
1129 goto done;
1132 bcm_mdelay(WRITE_ENABLE_DELAY);
1133 rc = 0;
1135 done:
1136 if (old != NULL)
1137 MFREE(osh, old, SROM_MAXW * sizeof(uint16));
1138 if (new != NULL)
1139 MFREE(osh, new, SROM_MAXW * sizeof(uint16));
1141 return rc;
1143 #endif
1145 #if defined(BCMUSBDEV)
1146 #define SI_PCMCIA_READ(osh, regs, fcr) \
1147 R_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2)
1148 #define SI_PCMCIA_WRITE(osh, regs, fcr, v) \
1149 W_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2, v)
1151 /* set PCMCIA srom command register */
1152 static int
1153 srom_cmd_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint8 cmd)
1155 uint8 status = 0;
1156 uint wait_cnt = 0;
1158 /* write srom command register */
1159 SI_PCMCIA_WRITE(osh, pcmregs, SROM_CS, cmd);
1161 /* wait status */
1162 while (++wait_cnt < 1000000) {
1163 status = SI_PCMCIA_READ(osh, pcmregs, SROM_CS);
1164 if (status & SROM_DONE)
1165 return 0;
1166 OSL_DELAY(1);
1169 BS_ERROR(("sr_cmd: Give up after %d tries, stat = 0x%x\n", wait_cnt, status));
1170 return 1;
1173 /* read a word from the PCMCIA srom over SI */
1174 static int
1175 srom_read_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint16 addr, uint16 *data)
1177 uint8 addr_l, addr_h, data_l, data_h;
1179 addr_l = (uint8)((addr * 2) & 0xff);
1180 addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
1182 /* set address */
1183 SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRH, addr_h);
1184 SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRL, addr_l);
1186 /* do read */
1187 if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_READ))
1188 return 1;
1190 /* read data */
1191 data_h = SI_PCMCIA_READ(osh, pcmregs, SROM_DATAH);
1192 data_l = SI_PCMCIA_READ(osh, pcmregs, SROM_DATAL);
1193 *data = ((uint16)data_h << 8) | data_l;
1195 return 0;
1198 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
1199 /* write a word to the PCMCIA srom over SI */
1200 static int
1201 srom_write_si_pcmcia(osl_t *osh, uint8 *pcmregs, uint16 addr, uint16 data)
1203 uint8 addr_l, addr_h, data_l, data_h;
1204 int rc;
1206 addr_l = (uint8)((addr * 2) & 0xff);
1207 addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
1209 /* set address */
1210 SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRH, addr_h);
1211 SI_PCMCIA_WRITE(osh, pcmregs, SROM_ADDRL, addr_l);
1213 data_l = (uint8)(data & 0xff);
1214 data_h = (uint8)((data >> 8) & 0xff);
1216 /* write data */
1217 SI_PCMCIA_WRITE(osh, pcmregs, SROM_DATAH, data_h);
1218 SI_PCMCIA_WRITE(osh, pcmregs, SROM_DATAL, data_l);
1220 /* do write */
1221 rc = srom_cmd_si_pcmcia(osh, pcmregs, SROM_WRITE);
1222 OSL_DELAY(20000);
1223 return rc;
1225 #endif
1228 * Read the srom for the pcmcia-srom over si case.
1229 * Return 0 on success, nonzero on error.
1231 static int
1232 get_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs,
1233 uint boff, uint16 *srom, uint bsz, bool check_crc)
1235 uint i, nw, woff, wsz;
1236 int err = 0;
1238 /* read must be at word boundary */
1239 ASSERT((boff & 1) == 0 && (bsz & 1) == 0);
1241 /* read sprom size and validate the parms */
1242 if ((nw = srom_size(sih, osh)) == 0) {
1243 BS_ERROR(("get_si_pcmcia_srom: sprom size unknown\n"));
1244 err = -1;
1245 goto out;
1247 if (boff + bsz > 2 * nw) {
1248 BS_ERROR(("get_si_pcmcia_srom: sprom size exceeded\n"));
1249 err = -2;
1250 goto out;
1253 /* read in sprom contents */
1254 for (woff = boff / 2, wsz = bsz / 2, i = 0;
1255 woff < nw && i < wsz; woff ++, i ++) {
1256 if (srom_read_si_pcmcia(osh, pcmregs, (uint16)woff, &srom[i])) {
1257 BS_ERROR(("get_si_pcmcia_srom: sprom read failed\n"));
1258 err = -3;
1259 goto out;
1263 if (check_crc) {
1264 if (srom[0] == 0xffff) {
1265 /* The hardware thinks that an srom that starts with 0xffff
1266 * is blank, regardless of the rest of the content, so declare
1267 * it bad.
1269 BS_ERROR(("%s: srom[0] == 0xffff, assuming unprogrammed srom\n",
1270 __FUNCTION__));
1271 err = -4;
1272 goto out;
1275 /* fixup the endianness so crc8 will pass */
1276 htol16_buf(srom, nw * 2);
1277 if (hndcrc8((uint8 *)srom, nw * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) {
1278 BS_ERROR(("%s: bad crc\n", __FUNCTION__));
1279 err = -5;
1281 /* now correct the endianness of the byte array */
1282 ltoh16_buf(srom, nw * 2);
1285 out:
1286 return err;
1289 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
1291 * Write the srom for the pcmcia-srom over si case.
1292 * Return 0 on success, nonzero on error.
1294 static int
1295 set_si_pcmcia_srom(si_t *sih, osl_t *osh, uint8 *pcmregs,
1296 uint boff, uint16 *srom, uint bsz)
1298 uint i, nw, woff, wsz;
1299 uint16 word;
1300 uint8 crc;
1301 int err = 0;
1303 /* write must be at word boundary */
1304 ASSERT((boff & 1) == 0 && (bsz & 1) == 0);
1306 /* read sprom size and validate the parms */
1307 if ((nw = srom_size(sih, osh)) == 0) {
1308 BS_ERROR(("set_si_pcmcia_srom: sprom size unknown\n"));
1309 err = -1;
1310 goto out;
1312 if (boff + bsz > 2 * nw) {
1313 BS_ERROR(("set_si_pcmcia_srom: sprom size exceeded\n"));
1314 err = -2;
1315 goto out;
1318 /* enable write */
1319 if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_WEN)) {
1320 BS_ERROR(("set_si_pcmcia_srom: sprom wen failed\n"));
1321 err = -3;
1322 goto out;
1325 /* write buffer to sprom */
1326 for (woff = boff / 2, wsz = bsz / 2, i = 0;
1327 woff < nw && i < wsz; woff ++, i ++) {
1328 if (srom_write_si_pcmcia(osh, pcmregs, (uint16)woff, srom[i])) {
1329 BS_ERROR(("set_si_pcmcia_srom: sprom write failed\n"));
1330 err = -4;
1331 goto out;
1335 /* fix crc */
1336 crc = CRC8_INIT_VALUE;
1337 for (woff = 0; woff < nw; woff ++) {
1338 if (srom_read_si_pcmcia(osh, pcmregs, (uint16)woff, &word)) {
1339 BS_ERROR(("set_si_pcmcia_srom: sprom fix crc read failed\n"));
1340 err = -5;
1341 goto out;
1343 word = htol16(word);
1344 crc = hndcrc8((uint8 *)&word, woff != nw - 1 ? 2 : 1, crc);
1346 word = (~crc << 8) + (ltoh16(word) & 0xff);
1347 if (srom_write_si_pcmcia(osh, pcmregs, (uint16)(woff - 1), word)) {
1348 BS_ERROR(("set_si_pcmcia_srom: sprom fix crc write failed\n"));
1349 err = -6;
1350 goto out;
1353 /* disable write */
1354 if (srom_cmd_si_pcmcia(osh, pcmregs, SROM_WDS)) {
1355 BS_ERROR(("set_si_pcmcia_srom: sprom wds failed\n"));
1356 err = -7;
1357 goto out;
1360 out:
1361 return err;
1363 #endif
1364 #endif
1366 static const char BCMATTACHDATA(vstr_manf)[] = "manf=%s";
1367 static const char BCMATTACHDATA(vstr_productname)[] = "productname=%s";
1368 static const char BCMATTACHDATA(vstr_manfid)[] = "manfid=0x%x";
1369 static const char BCMATTACHDATA(vstr_prodid)[] = "prodid=0x%x";
1370 static const char BCMATTACHDATA(vstr_regwindowsz)[] = "regwindowsz=%d";
1371 static const char BCMATTACHDATA(vstr_sromrev)[] = "sromrev=%d";
1372 static const char BCMATTACHDATA(vstr_chiprev)[] = "chiprev=%d";
1373 static const char BCMATTACHDATA(vstr_subvendid)[] = "subvendid=0x%x";
1374 static const char BCMATTACHDATA(vstr_subdevid)[] = "subdevid=0x%x";
1375 static const char BCMATTACHDATA(vstr_boardrev)[] = "boardrev=0x%x";
1376 static const char BCMATTACHDATA(vstr_aa2g)[] = "aa2g=0x%x";
1377 static const char BCMATTACHDATA(vstr_aa5g)[] = "aa5g=0x%x";
1378 static const char BCMATTACHDATA(vstr_ag)[] = "ag%d=0x%x";
1379 static const char BCMATTACHDATA(vstr_cc)[] = "cc=%d";
1380 static const char BCMATTACHDATA(vstr_opo)[] = "opo=%d";
1381 static const char BCMATTACHDATA(vstr_pa0b)[][9] = { "pa0b0=%d", "pa0b1=%d", "pa0b2=%d" };
1382 static const char BCMATTACHDATA(vstr_pa0itssit)[] = "pa0itssit=%d";
1383 static const char BCMATTACHDATA(vstr_pa0maxpwr)[] = "pa0maxpwr=%d";
1384 static const char BCMATTACHDATA(vstr_pa1b)[][9] = { "pa1b0=%d", "pa1b1=%d", "pa1b2=%d" };
1385 static const char BCMATTACHDATA(vstr_pa1lob)[][11] =
1386 { "pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d" };
1387 static const char BCMATTACHDATA(vstr_pa1hib)[][11] =
1388 { "pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d" };
1389 static const char BCMATTACHDATA(vstr_pa1itssit)[] = "pa1itssit=%d";
1390 static const char BCMATTACHDATA(vstr_pa1maxpwr)[] = "pa1maxpwr=%d";
1391 static const char BCMATTACHDATA(vstr_pa1lomaxpwr)[] = "pa1lomaxpwr=%d";
1392 static const char BCMATTACHDATA(vstr_pa1himaxpwr)[] = "pa1himaxpwr=%d";
1393 static const char BCMATTACHDATA(vstr_oem)[] = "oem=%02x%02x%02x%02x%02x%02x%02x%02x";
1394 static const char BCMATTACHDATA(vstr_boardflags)[] = "boardflags=0x%x";
1395 static const char BCMATTACHDATA(vstr_boardflags2)[] = "boardflags2=0x%x";
1396 static const char BCMATTACHDATA(vstr_ledbh)[] = "ledbh%d=0x%x";
1397 static const char BCMATTACHDATA(vstr_noccode)[] = "ccode=0x0";
1398 static const char BCMATTACHDATA(vstr_ccode)[] = "ccode=%c%c";
1399 static const char BCMATTACHDATA(vstr_cctl)[] = "cctl=0x%x";
1400 static const char BCMATTACHDATA(vstr_cckpo)[] = "cckpo=0x%x";
1401 static const char BCMATTACHDATA(vstr_ofdmpo)[] = "ofdmpo=0x%x";
1402 static const char BCMATTACHDATA(vstr_rdlid)[] = "rdlid=0x%x";
1403 static const char BCMATTACHDATA(vstr_rdlrndis)[] = "rdlrndis=%d";
1404 static const char BCMATTACHDATA(vstr_rdlrwu)[] = "rdlrwu=%d";
1405 static const char BCMATTACHDATA(vstr_usbfs)[] = "usbfs=%d";
1406 static const char BCMATTACHDATA(vstr_wpsgpio)[] = "wpsgpio=%d";
1407 static const char BCMATTACHDATA(vstr_wpsled)[] = "wpsled=%d";
1408 static const char BCMATTACHDATA(vstr_rdlsn)[] = "rdlsn=%d";
1409 static const char BCMATTACHDATA(vstr_rssismf2g)[] = "rssismf2g=%d";
1410 static const char BCMATTACHDATA(vstr_rssismc2g)[] = "rssismc2g=%d";
1411 static const char BCMATTACHDATA(vstr_rssisav2g)[] = "rssisav2g=%d";
1412 static const char BCMATTACHDATA(vstr_bxa2g)[] = "bxa2g=%d";
1413 static const char BCMATTACHDATA(vstr_rssismf5g)[] = "rssismf5g=%d";
1414 static const char BCMATTACHDATA(vstr_rssismc5g)[] = "rssismc5g=%d";
1415 static const char BCMATTACHDATA(vstr_rssisav5g)[] = "rssisav5g=%d";
1416 static const char BCMATTACHDATA(vstr_bxa5g)[] = "bxa5g=%d";
1417 static const char BCMATTACHDATA(vstr_tri2g)[] = "tri2g=%d";
1418 static const char BCMATTACHDATA(vstr_tri5gl)[] = "tri5gl=%d";
1419 static const char BCMATTACHDATA(vstr_tri5g)[] = "tri5g=%d";
1420 static const char BCMATTACHDATA(vstr_tri5gh)[] = "tri5gh=%d";
1421 static const char BCMATTACHDATA(vstr_rxpo2g)[] = "rxpo2g=%d";
1422 static const char BCMATTACHDATA(vstr_rxpo5g)[] = "rxpo5g=%d";
1423 static const char BCMATTACHDATA(vstr_boardtype)[] = "boardtype=0x%x";
1424 static const char BCMATTACHDATA(vstr_leddc)[] = "leddc=0x%04x";
1425 static const char BCMATTACHDATA(vstr_vendid)[] = "vendid=0x%x";
1426 static const char BCMATTACHDATA(vstr_devid)[] = "devid=0x%x";
1427 static const char BCMATTACHDATA(vstr_xtalfreq)[] = "xtalfreq=%d";
1428 static const char BCMATTACHDATA(vstr_txchain)[] = "txchain=0x%x";
1429 static const char BCMATTACHDATA(vstr_rxchain)[] = "rxchain=0x%x";
1430 static const char BCMATTACHDATA(vstr_antswitch)[] = "antswitch=0x%x";
1431 static const char BCMATTACHDATA(vstr_regrev)[] = "regrev=0x%x";
1432 static const char BCMATTACHDATA(vstr_antswctl2g)[] = "antswctl2g=0x%x";
1433 static const char BCMATTACHDATA(vstr_triso2g)[] = "triso2g=0x%x";
1434 static const char BCMATTACHDATA(vstr_pdetrange2g)[] = "pdetrange2g=0x%x";
1435 static const char BCMATTACHDATA(vstr_extpagain2g)[] = "extpagain2g=0x%x";
1436 static const char BCMATTACHDATA(vstr_tssipos2g)[] = "tssipos2g=0x%x";
1437 static const char BCMATTACHDATA(vstr_antswctl5g)[] = "antswctl5g=0x%x";
1438 static const char BCMATTACHDATA(vstr_triso5g)[] = "triso5g=0x%x";
1439 static const char BCMATTACHDATA(vstr_pdetrange5g)[] = "pdetrange5g=0x%x";
1440 static const char BCMATTACHDATA(vstr_extpagain5g)[] = "extpagain5g=0x%x";
1441 static const char BCMATTACHDATA(vstr_tssipos5g)[] = "tssipos5g=0x%x";
1442 static const char BCMATTACHDATA(vstr_maxp2ga0)[] = "maxp2ga0=0x%x";
1443 static const char BCMATTACHDATA(vstr_itt2ga0)[] = "itt2ga0=0x%x";
1444 static const char BCMATTACHDATA(vstr_pa)[] = "pa%dgw%da%d=0x%x";
1445 static const char BCMATTACHDATA(vstr_pahl)[] = "pa%dg%cw%da%d=0x%x";
1446 static const char BCMATTACHDATA(vstr_maxp5ga0)[] = "maxp5ga0=0x%x";
1447 static const char BCMATTACHDATA(vstr_itt5ga0)[] = "itt5ga0=0x%x";
1448 static const char BCMATTACHDATA(vstr_maxp5gha0)[] = "maxp5gha0=0x%x";
1449 static const char BCMATTACHDATA(vstr_maxp5gla0)[] = "maxp5gla0=0x%x";
1450 static const char BCMATTACHDATA(vstr_maxp2ga1)[] = "maxp2ga1=0x%x";
1451 static const char BCMATTACHDATA(vstr_itt2ga1)[] = "itt2ga1=0x%x";
1452 static const char BCMATTACHDATA(vstr_maxp5ga1)[] = "maxp5ga1=0x%x";
1453 static const char BCMATTACHDATA(vstr_itt5ga1)[] = "itt5ga1=0x%x";
1454 static const char BCMATTACHDATA(vstr_maxp5gha1)[] = "maxp5gha1=0x%x";
1455 static const char BCMATTACHDATA(vstr_maxp5gla1)[] = "maxp5gla1=0x%x";
1456 static const char BCMATTACHDATA(vstr_cck2gpo)[] = "cck2gpo=0x%x";
1457 static const char BCMATTACHDATA(vstr_ofdm2gpo)[] = "ofdm2gpo=0x%x";
1458 static const char BCMATTACHDATA(vstr_ofdm5gpo)[] = "ofdm5gpo=0x%x";
1459 static const char BCMATTACHDATA(vstr_ofdm5glpo)[] = "ofdm5glpo=0x%x";
1460 static const char BCMATTACHDATA(vstr_ofdm5ghpo)[] = "ofdm5ghpo=0x%x";
1461 static const char BCMATTACHDATA(vstr_cddpo)[] = "cddpo=0x%x";
1462 static const char BCMATTACHDATA(vstr_stbcpo)[] = "stbcpo=0x%x";
1463 static const char BCMATTACHDATA(vstr_bw40po)[] = "bw40po=0x%x";
1464 static const char BCMATTACHDATA(vstr_bwduppo)[] = "bwduppo=0x%x";
1465 static const char BCMATTACHDATA(vstr_mcspo)[] = "mcs%dgpo%d=0x%x";
1466 static const char BCMATTACHDATA(vstr_mcspohl)[] = "mcs%dg%cpo%d=0x%x";
1467 static const char BCMATTACHDATA(vstr_custom)[] = "customvar%d=0x%x";
1468 static const char BCMATTACHDATA(vstr_cckdigfilttype)[] = "cckdigfilttype=%d";
1469 #ifdef BCM_BOOTLOADER
1470 static const char BCMATTACHDATA(vstr_brmin)[] = "brmin=0x%x";
1471 static const char BCMATTACHDATA(vstr_brmax)[] = "brmax=0x%x";
1472 #endif /* BCM_BOOTLOADER */
1473 static const char BCMATTACHDATA(vstr_boardnum)[] = "boardnum=%d";
1474 static const char BCMATTACHDATA(vstr_macaddr)[] = "macaddr=%s";
1475 static const char BCMATTACHDATA(vstr_usbepnum)[] = "usbepnum=0x%x";
1477 /* Power per rate for SROM V9 */
1478 static const char BCMATTACHDATA(vstr_cckbw202gpo)[][19] =
1479 { "cckbw202gpo=0x%x", "cckbw20ul2gpo=0x%x" };
1480 static const char BCMATTACHDATA(vstr_legofdmbw202gpo)[][22] =
1481 { "legofdmbw202gpo=0x%x", "legofdmbw20ul2gpo=0x%x" };
1482 static const char BCMATTACHDATA(vstr_legofdmbw205gpo)[][24] =
1483 { "legofdmbw205glpo=0x%x", "legofdmbw20ul5glpo=0x%x",
1484 "legofdmbw205gmpo=0x%x", "legofdmbw20ul5gmpo=0x%x",
1485 "legofdmbw205ghpo=0x%x", "legofdmbw20ul5ghpo=0x%x" };
1487 static const char BCMATTACHDATA(vstr_mcs2gpo)[][19] =
1488 { "mcsbw202gpo=0x%x", "mcsbw20ul2gpo=0x%x", "mcsbw402gpo=0x%x"};
1490 static const char BCMATTACHDATA(vstr_mcs5glpo)[][20] =
1491 { "mcsbw205glpo=0x%x", "mcsbw20ul5glpo=0x%x", "mcsbw405glpo=0x%x"};
1493 static const char BCMATTACHDATA(vstr_mcs5gmpo)[][20] =
1494 { "mcsbw205gmpo=0x%x", "mcsbw20ul5gmpo=0x%x", "mcsbw405gmpo=0x%x"};
1496 static const char BCMATTACHDATA(vstr_mcs5ghpo)[][20] =
1497 { "mcsbw205ghpo=0x%x", "mcsbw20ul5ghpo=0x%x", "mcsbw405ghpo=0x%x"};
1499 static const char BCMATTACHDATA(vstr_mcs32po)[] = "mcs32po=0x%x";
1500 static const char BCMATTACHDATA(vstr_legofdm40duppo)[] = "legofdm40duppo=0x%x";
1502 static const char BCMATTACHDATA(vstr_tempthresh)[] = "tempthresh=%d";
1503 static const char BCMATTACHDATA(vstr_temps_period)[] = "temps_period=%d";
1504 static const char BCMATTACHDATA(vstr_temp_hysteresis)[] = "temp_hysteresis=%d";
1506 static const char BCMATTACHDATA(vstr_uuid)[] = "uuid=%s";
1508 static const char BCMATTACHDATA(vstr_end)[] = "END\0";
1510 uint8 patch_pair = 0;
1512 /* For dongle HW, accept partial calibration parameters */
1513 #if defined(BCMUSBDEV)
1514 #define BCMDONGLECASE(n) case n:
1515 #else
1516 #define BCMDONGLECASE(n)
1517 #endif
1520 BCMATTACHFN(srom_parsecis)(osl_t *osh, uint8 *pcis[], uint ciscnt, char **vars, uint *count)
1522 char eabuf[32];
1523 char *base;
1524 varbuf_t b;
1525 uint8 *cis, tup, tlen, sromrev = 1;
1526 int i, j;
1527 #ifndef BCM_BOOTLOADER
1528 bool ag_init = FALSE;
1529 #endif
1530 uint32 w32;
1531 uint funcid;
1532 uint cisnum;
1533 int32 boardnum;
1534 int err;
1535 bool standard_cis;
1537 ASSERT(vars != NULL);
1538 ASSERT(count != NULL);
1540 boardnum = -1;
1542 base = MALLOC(osh, MAXSZ_NVRAM_VARS);
1543 ASSERT(base != NULL);
1544 if (!base)
1545 return -2;
1547 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
1548 bzero(base, MAXSZ_NVRAM_VARS);
1549 #ifdef BCM_BMAC_VARS_APPEND
1550 /* 43236 use defaultsromvars_43236usb as the base,
1551 * then append and update it with the content from OTP.
1552 * Only revision/board specfic content or updates used to override
1553 * the driver default will be stored in OTP
1555 *count -= (strlen(vstr_end) + 1 + 1); /* back off the termnating END\0\0 from fakenvram */
1556 bcopy(*vars, base, *count);
1557 b.buf += *count;
1558 #endif /* BCM_BMAC_VARS_APPEND */
1559 eabuf[0] = '\0';
1560 for (cisnum = 0; cisnum < ciscnt; cisnum++) {
1561 cis = *pcis++;
1562 i = 0;
1563 funcid = 0;
1564 standard_cis = TRUE;
1565 do {
1566 if (standard_cis) {
1567 tup = cis[i++];
1568 if (tup == CISTPL_NULL || tup == CISTPL_END)
1569 tlen = 0;
1570 else
1571 tlen = cis[i++];
1572 } else {
1573 if (cis[i] == CISTPL_NULL || cis[i] == CISTPL_END) {
1574 tlen = 0;
1575 tup = cis[i];
1576 } else {
1577 tlen = cis[i];
1578 tup = CISTPL_BRCM_HNBU;
1580 ++i;
1582 if ((i + tlen) >= CIS_SIZE)
1583 break;
1585 switch (tup) {
1586 case CISTPL_VERS_1:
1587 /* assume the strings are good if the version field checks out */
1588 if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) {
1589 varbuf_append(&b, vstr_manf, &cis[i + 2]);
1590 varbuf_append(&b, vstr_productname,
1591 &cis[i + 3 + strlen((char *)&cis[i + 2])]);
1592 break;
1595 case CISTPL_MANFID:
1596 varbuf_append(&b, vstr_manfid, (cis[i + 1] << 8) + cis[i]);
1597 varbuf_append(&b, vstr_prodid, (cis[i + 3] << 8) + cis[i + 2]);
1598 break;
1600 case CISTPL_FUNCID:
1601 funcid = cis[i];
1602 break;
1604 case CISTPL_FUNCE:
1605 switch (funcid) {
1606 case CISTPL_FID_SDIO:
1607 funcid = 0;
1608 break;
1609 default:
1610 /* set macaddr if HNBU_MACADDR not seen yet */
1611 if (eabuf[0] == '\0' && cis[i] == LAN_NID &&
1612 !(ETHER_ISNULLADDR(&cis[i + 2])) &&
1613 !(ETHER_ISMULTI(&cis[i + 2]))) {
1614 ASSERT(cis[i + 1] == ETHER_ADDR_LEN);
1615 bcm_ether_ntoa((struct ether_addr *)&cis[i + 2],
1616 eabuf);
1618 /* set boardnum if HNBU_BOARDNUM not seen yet */
1619 if (boardnum == -1)
1620 boardnum = (cis[i + 6] << 8) + cis[i + 7];
1622 break;
1624 break;
1626 case CISTPL_CFTABLE:
1627 varbuf_append(&b, vstr_regwindowsz, (cis[i + 7] << 8) | cis[i + 6]);
1628 break;
1630 case CISTPL_BRCM_HNBU:
1631 switch (cis[i]) {
1632 case HNBU_SROMREV:
1633 sromrev = cis[i + 1];
1634 varbuf_append(&b, vstr_sromrev, sromrev);
1635 break;
1637 case HNBU_XTALFREQ:
1638 varbuf_append(&b, vstr_xtalfreq,
1639 (cis[i + 4] << 24) |
1640 (cis[i + 3] << 16) |
1641 (cis[i + 2] << 8) |
1642 cis[i + 1]);
1643 break;
1645 case HNBU_CHIPID:
1646 varbuf_append(&b, vstr_vendid, (cis[i + 2] << 8) +
1647 cis[i + 1]);
1648 varbuf_append(&b, vstr_devid, (cis[i + 4] << 8) +
1649 cis[i + 3]);
1650 if (tlen >= 7) {
1651 varbuf_append(&b, vstr_chiprev,
1652 (cis[i + 6] << 8) + cis[i + 5]);
1654 if (tlen >= 9) {
1655 varbuf_append(&b, vstr_subvendid,
1656 (cis[i + 8] << 8) + cis[i + 7]);
1658 if (tlen >= 11) {
1659 varbuf_append(&b, vstr_subdevid,
1660 (cis[i + 10] << 8) + cis[i + 9]);
1661 /* subdevid doubles for boardtype */
1662 varbuf_append(&b, vstr_boardtype,
1663 (cis[i + 10] << 8) + cis[i + 9]);
1665 break;
1667 case HNBU_BOARDNUM:
1668 boardnum = (cis[i + 2] << 8) + cis[i + 1];
1669 break;
1671 case HNBU_PATCH:
1673 char vstr_paddr[16];
1674 char vstr_pdata[16];
1676 /* retrieve the patch pairs
1677 * from tlen/6; where 6 is
1678 * sizeof(patch addr(2)) +
1679 * sizeof(patch data(4)).
1681 patch_pair = tlen/6;
1683 for (j = 0; j < patch_pair; j++) {
1684 snprintf(vstr_paddr, sizeof(vstr_paddr),
1685 "pa%d=0x%%x", j);
1686 snprintf(vstr_pdata, sizeof(vstr_pdata),
1687 "pd%d=0x%%x", j);
1689 varbuf_append(&b, vstr_paddr,
1690 (cis[i + (j*6) + 2] << 8) |
1691 cis[i + (j*6) + 1]);
1693 varbuf_append(&b, vstr_pdata,
1694 (cis[i + (j*6) + 6] << 24) |
1695 (cis[i + (j*6) + 5] << 16) |
1696 (cis[i + (j*6) + 4] << 8) |
1697 cis[i + (j*6) + 3]);
1700 break;
1702 case HNBU_BOARDREV:
1703 if (tlen == 2)
1704 varbuf_append(&b, vstr_boardrev, cis[i + 1]);
1705 else
1706 varbuf_append(&b, vstr_boardrev,
1707 (cis[i + 2] << 8) + cis[i + 1]);
1708 break;
1710 case HNBU_BOARDFLAGS:
1711 w32 = (cis[i + 2] << 8) + cis[i + 1];
1712 if (tlen >= 5)
1713 w32 |= ((cis[i + 4] << 24) + (cis[i + 3] << 16));
1714 varbuf_append(&b, vstr_boardflags, w32);
1716 if (tlen >= 7) {
1717 w32 = (cis[i + 6] << 8) + cis[i + 5];
1718 if (tlen >= 9)
1719 w32 |= ((cis[i + 8] << 24) +
1720 (cis[i + 7] << 16));
1721 varbuf_append(&b, vstr_boardflags2, w32);
1723 break;
1725 case HNBU_USBFS:
1726 varbuf_append(&b, vstr_usbfs, cis[i + 1]);
1727 break;
1729 case HNBU_BOARDTYPE:
1730 varbuf_append(&b, vstr_boardtype,
1731 (cis[i + 2] << 8) + cis[i + 1]);
1732 break;
1734 case HNBU_HNBUCIS:
1736 * what follows is a nonstandard HNBU CIS
1737 * that lacks CISTPL_BRCM_HNBU tags
1739 * skip 0xff (end of standard CIS)
1740 * after this tuple
1742 tlen++;
1743 standard_cis = FALSE;
1744 break;
1746 case HNBU_USBEPNUM:
1747 varbuf_append(&b, vstr_usbepnum,
1748 (cis[i + 2] << 8) | cis[i + 1]);
1749 break;
1751 #ifdef BCM_BOOTLOADER
1752 case HNBU_BRMIN:
1753 varbuf_append(&b, vstr_brmin,
1754 (cis[i + 4] << 24) |
1755 (cis[i + 3] << 16) |
1756 (cis[i + 2] << 8) |
1757 cis[i + 1]);
1758 break;
1760 case HNBU_BRMAX:
1761 varbuf_append(&b, vstr_brmax,
1762 (cis[i + 4] << 24) |
1763 (cis[i + 3] << 16) |
1764 (cis[i + 2] << 8) |
1765 cis[i + 1]);
1766 break;
1767 #endif /* BCM_BOOTLOADER */
1769 case HNBU_RDLID:
1770 varbuf_append(&b, vstr_rdlid,
1771 (cis[i + 2] << 8) | cis[i + 1]);
1772 break;
1774 #ifdef BCM_BOOTLOADER
1775 case HNBU_RDLRNDIS:
1776 varbuf_append(&b, vstr_rdlrndis, cis[i + 1]);
1777 break;
1779 case HNBU_RDLRWU:
1780 varbuf_append(&b, vstr_rdlrwu, cis[i + 1]);
1781 break;
1783 case HNBU_RDLSN:
1784 if (tlen >= 5)
1785 varbuf_append(&b, vstr_rdlsn,
1786 (cis[i + 4] << 24) |
1787 (cis[i + 3] << 16) |
1788 (cis[i + 2] << 8) |
1789 cis[i + 1]);
1790 else
1791 varbuf_append(&b, vstr_rdlsn,
1792 (cis[i + 2] << 8) |
1793 cis[i + 1]);
1794 break;
1796 #else
1797 case HNBU_AA:
1798 varbuf_append(&b, vstr_aa2g, cis[i + 1]);
1799 if (tlen >= 3)
1800 varbuf_append(&b, vstr_aa5g, cis[i + 2]);
1801 break;
1803 case HNBU_AG:
1804 varbuf_append(&b, vstr_ag, 0, cis[i + 1]);
1805 if (tlen >= 3)
1806 varbuf_append(&b, vstr_ag, 1, cis[i + 2]);
1807 if (tlen >= 4)
1808 varbuf_append(&b, vstr_ag, 2, cis[i + 3]);
1809 if (tlen >= 5)
1810 varbuf_append(&b, vstr_ag, 3, cis[i + 4]);
1811 ag_init = TRUE;
1812 break;
1814 case HNBU_ANT5G:
1815 varbuf_append(&b, vstr_aa5g, cis[i + 1]);
1816 varbuf_append(&b, vstr_ag, 1, cis[i + 2]);
1817 break;
1819 case HNBU_CC:
1820 ASSERT(sromrev == 1);
1821 varbuf_append(&b, vstr_cc, cis[i + 1]);
1822 break;
1824 case HNBU_PAPARMS:
1825 switch (tlen) {
1826 case 2:
1827 ASSERT(sromrev == 1);
1828 varbuf_append(&b, vstr_pa0maxpwr, cis[i + 1]);
1829 break;
1830 case 10:
1831 ASSERT(sromrev >= 2);
1832 varbuf_append(&b, vstr_opo, cis[i + 9]);
1833 /* FALLTHROUGH */
1834 case 9:
1835 varbuf_append(&b, vstr_pa0maxpwr, cis[i + 8]);
1836 /* FALLTHROUGH */
1837 BCMDONGLECASE(8)
1838 varbuf_append(&b, vstr_pa0itssit, cis[i + 7]);
1839 /* FALLTHROUGH */
1840 BCMDONGLECASE(7)
1841 for (j = 0; j < 3; j++) {
1842 varbuf_append(&b, vstr_pa0b[j],
1843 (cis[i + (j * 2) + 2] << 8) +
1844 cis[i + (j * 2) + 1]);
1846 break;
1847 default:
1848 ASSERT((tlen == 2) || (tlen == 9) || (tlen == 10));
1849 break;
1851 break;
1853 case HNBU_PAPARMS5G:
1854 ASSERT((sromrev == 2) || (sromrev == 3));
1855 switch (tlen) {
1856 case 23:
1857 varbuf_append(&b, vstr_pa1himaxpwr, cis[i + 22]);
1858 varbuf_append(&b, vstr_pa1lomaxpwr, cis[i + 21]);
1859 varbuf_append(&b, vstr_pa1maxpwr, cis[i + 20]);
1860 /* FALLTHROUGH */
1861 case 20:
1862 varbuf_append(&b, vstr_pa1itssit, cis[i + 19]);
1863 /* FALLTHROUGH */
1864 case 19:
1865 for (j = 0; j < 3; j++) {
1866 varbuf_append(&b, vstr_pa1b[j],
1867 (cis[i + (j * 2) + 2] << 8) +
1868 cis[i + (j * 2) + 1]);
1870 for (j = 3; j < 6; j++) {
1871 varbuf_append(&b, vstr_pa1lob[j - 3],
1872 (cis[i + (j * 2) + 2] << 8) +
1873 cis[i + (j * 2) + 1]);
1875 for (j = 6; j < 9; j++) {
1876 varbuf_append(&b, vstr_pa1hib[j - 6],
1877 (cis[i + (j * 2) + 2] << 8) +
1878 cis[i + (j * 2) + 1]);
1880 break;
1881 default:
1882 ASSERT((tlen == 19) ||
1883 (tlen == 20) || (tlen == 23));
1884 break;
1886 break;
1888 case HNBU_OEM:
1889 ASSERT(sromrev == 1);
1890 varbuf_append(&b, vstr_oem,
1891 cis[i + 1], cis[i + 2],
1892 cis[i + 3], cis[i + 4],
1893 cis[i + 5], cis[i + 6],
1894 cis[i + 7], cis[i + 8]);
1895 break;
1897 case HNBU_LEDS:
1898 for (j = 1; j <= 4; j++) {
1899 if (cis[i + j] != 0xff) {
1900 varbuf_append(&b, vstr_ledbh, j-1,
1901 cis[i + j]);
1904 break;
1906 case HNBU_CCODE:
1907 ASSERT(sromrev > 1);
1908 if ((cis[i + 1] == 0) || (cis[i + 2] == 0))
1909 varbuf_append(&b, vstr_noccode);
1910 else
1911 varbuf_append(&b, vstr_ccode,
1912 cis[i + 1], cis[i + 2]);
1913 varbuf_append(&b, vstr_cctl, cis[i + 3]);
1914 break;
1916 case HNBU_CCKPO:
1917 ASSERT(sromrev > 2);
1918 varbuf_append(&b, vstr_cckpo,
1919 (cis[i + 2] << 8) | cis[i + 1]);
1920 break;
1922 case HNBU_OFDMPO:
1923 ASSERT(sromrev > 2);
1924 varbuf_append(&b, vstr_ofdmpo,
1925 (cis[i + 4] << 24) |
1926 (cis[i + 3] << 16) |
1927 (cis[i + 2] << 8) |
1928 cis[i + 1]);
1929 break;
1931 case HNBU_WPS:
1932 varbuf_append(&b, vstr_wpsgpio, cis[i + 1]);
1933 if (tlen >= 3)
1934 varbuf_append(&b, vstr_wpsled, cis[i + 2]);
1935 break;
1937 case HNBU_RSSISMBXA2G:
1938 ASSERT(sromrev == 3);
1939 varbuf_append(&b, vstr_rssismf2g, cis[i + 1] & 0xf);
1940 varbuf_append(&b, vstr_rssismc2g, (cis[i + 1] >> 4) & 0xf);
1941 varbuf_append(&b, vstr_rssisav2g, cis[i + 2] & 0x7);
1942 varbuf_append(&b, vstr_bxa2g, (cis[i + 2] >> 3) & 0x3);
1943 break;
1945 case HNBU_RSSISMBXA5G:
1946 ASSERT(sromrev == 3);
1947 varbuf_append(&b, vstr_rssismf5g, cis[i + 1] & 0xf);
1948 varbuf_append(&b, vstr_rssismc5g, (cis[i + 1] >> 4) & 0xf);
1949 varbuf_append(&b, vstr_rssisav5g, cis[i + 2] & 0x7);
1950 varbuf_append(&b, vstr_bxa5g, (cis[i + 2] >> 3) & 0x3);
1951 break;
1953 case HNBU_TRI2G:
1954 ASSERT(sromrev == 3);
1955 varbuf_append(&b, vstr_tri2g, cis[i + 1]);
1956 break;
1958 case HNBU_TRI5G:
1959 ASSERT(sromrev == 3);
1960 varbuf_append(&b, vstr_tri5gl, cis[i + 1]);
1961 varbuf_append(&b, vstr_tri5g, cis[i + 2]);
1962 varbuf_append(&b, vstr_tri5gh, cis[i + 3]);
1963 break;
1965 case HNBU_RXPO2G:
1966 ASSERT(sromrev == 3);
1967 varbuf_append(&b, vstr_rxpo2g, cis[i + 1]);
1968 break;
1970 case HNBU_RXPO5G:
1971 ASSERT(sromrev == 3);
1972 varbuf_append(&b, vstr_rxpo5g, cis[i + 1]);
1973 break;
1975 case HNBU_MACADDR:
1976 if (!(ETHER_ISNULLADDR(&cis[i+1])) &&
1977 !(ETHER_ISMULTI(&cis[i+1]))) {
1978 bcm_ether_ntoa((struct ether_addr *)&cis[i + 1],
1979 eabuf);
1981 /* set boardnum if HNBU_BOARDNUM not seen yet */
1982 if (boardnum == -1)
1983 boardnum = (cis[i + 5] << 8) + cis[i + 6];
1985 break;
1987 case HNBU_LEDDC:
1988 /* CIS leddc only has 16bits, convert it to 32bits */
1989 w32 = ((cis[i + 2] << 24) | /* oncount */
1990 (cis[i + 1] << 8)); /* offcount */
1991 varbuf_append(&b, vstr_leddc, w32);
1992 break;
1994 case HNBU_CHAINSWITCH:
1995 varbuf_append(&b, vstr_txchain, cis[i + 1]);
1996 varbuf_append(&b, vstr_rxchain, cis[i + 2]);
1997 varbuf_append(&b, vstr_antswitch,
1998 (cis[i + 4] << 8) + cis[i + 3]);
1999 break;
2001 case HNBU_REGREV:
2002 varbuf_append(&b, vstr_regrev, cis[i + 1]);
2003 break;
2005 case HNBU_FEM: {
2006 uint16 fem = (cis[i + 2] << 8) + cis[i + 1];
2007 varbuf_append(&b, vstr_antswctl2g, (fem &
2008 SROM8_FEM_ANTSWLUT_MASK) >>
2009 SROM8_FEM_ANTSWLUT_SHIFT);
2010 varbuf_append(&b, vstr_triso2g, (fem &
2011 SROM8_FEM_TR_ISO_MASK) >>
2012 SROM8_FEM_TR_ISO_SHIFT);
2013 varbuf_append(&b, vstr_pdetrange2g, (fem &
2014 SROM8_FEM_PDET_RANGE_MASK) >>
2015 SROM8_FEM_PDET_RANGE_SHIFT);
2016 varbuf_append(&b, vstr_extpagain2g, (fem &
2017 SROM8_FEM_EXTPA_GAIN_MASK) >>
2018 SROM8_FEM_EXTPA_GAIN_SHIFT);
2019 varbuf_append(&b, vstr_tssipos2g, (fem &
2020 SROM8_FEM_TSSIPOS_MASK) >>
2021 SROM8_FEM_TSSIPOS_SHIFT);
2022 if (tlen < 5) break;
2024 fem = (cis[i + 4] << 8) + cis[i + 3];
2025 varbuf_append(&b, vstr_antswctl5g, (fem &
2026 SROM8_FEM_ANTSWLUT_MASK) >>
2027 SROM8_FEM_ANTSWLUT_SHIFT);
2028 varbuf_append(&b, vstr_triso5g, (fem &
2029 SROM8_FEM_TR_ISO_MASK) >>
2030 SROM8_FEM_TR_ISO_SHIFT);
2031 varbuf_append(&b, vstr_pdetrange5g, (fem &
2032 SROM8_FEM_PDET_RANGE_MASK) >>
2033 SROM8_FEM_PDET_RANGE_SHIFT);
2034 varbuf_append(&b, vstr_extpagain5g, (fem &
2035 SROM8_FEM_EXTPA_GAIN_MASK) >>
2036 SROM8_FEM_EXTPA_GAIN_SHIFT);
2037 varbuf_append(&b, vstr_tssipos5g, (fem &
2038 SROM8_FEM_TSSIPOS_MASK) >>
2039 SROM8_FEM_TSSIPOS_SHIFT);
2040 break;
2043 case HNBU_PAPARMS_C0:
2044 varbuf_append(&b, vstr_maxp2ga0, cis[i + 1]);
2045 varbuf_append(&b, vstr_itt2ga0, cis[i + 2]);
2046 varbuf_append(&b, vstr_pa, 2, 0, 0,
2047 (cis[i + 4] << 8) + cis[i + 3]);
2048 varbuf_append(&b, vstr_pa, 2, 1, 0,
2049 (cis[i + 6] << 8) + cis[i + 5]);
2050 varbuf_append(&b, vstr_pa, 2, 2, 0,
2051 (cis[i + 8] << 8) + cis[i + 7]);
2052 if (tlen < 31) break;
2054 varbuf_append(&b, vstr_maxp5ga0, cis[i + 9]);
2055 varbuf_append(&b, vstr_itt5ga0, cis[i + 10]);
2056 varbuf_append(&b, vstr_maxp5gha0, cis[i + 11]);
2057 varbuf_append(&b, vstr_maxp5gla0, cis[i + 12]);
2058 varbuf_append(&b, vstr_pa, 5, 0, 0,
2059 (cis[i + 14] << 8) + cis[i + 13]);
2060 varbuf_append(&b, vstr_pa, 5, 1, 0,
2061 (cis[i + 16] << 8) + cis[i + 15]);
2062 varbuf_append(&b, vstr_pa, 5, 2, 0,
2063 (cis[i + 18] << 8) + cis[i + 17]);
2064 varbuf_append(&b, vstr_pahl, 5, 'l', 0, 0,
2065 (cis[i + 20] << 8) + cis[i + 19]);
2066 varbuf_append(&b, vstr_pahl, 5, 'l', 1, 0,
2067 (cis[i + 22] << 8) + cis[i + 21]);
2068 varbuf_append(&b, vstr_pahl, 5, 'l', 2, 0,
2069 (cis[i + 24] << 8) + cis[i + 23]);
2070 varbuf_append(&b, vstr_pahl, 5, 'h', 0, 0,
2071 (cis[i + 26] << 8) + cis[i + 25]);
2072 varbuf_append(&b, vstr_pahl, 5, 'h', 1, 0,
2073 (cis[i + 28] << 8) + cis[i + 27]);
2074 varbuf_append(&b, vstr_pahl, 5, 'h', 2, 0,
2075 (cis[i + 30] << 8) + cis[i + 29]);
2076 break;
2078 case HNBU_PAPARMS_C1:
2079 varbuf_append(&b, vstr_maxp2ga1, cis[i + 1]);
2080 varbuf_append(&b, vstr_itt2ga1, cis[i + 2]);
2081 varbuf_append(&b, vstr_pa, 2, 0, 1,
2082 (cis[i + 4] << 8) + cis[i + 3]);
2083 varbuf_append(&b, vstr_pa, 2, 1, 1,
2084 (cis[i + 6] << 8) + cis[i + 5]);
2085 varbuf_append(&b, vstr_pa, 2, 2, 1,
2086 (cis[i + 8] << 8) + cis[i + 7]);
2087 if (tlen < 31) break;
2089 varbuf_append(&b, vstr_maxp5ga1, cis[i + 9]);
2090 varbuf_append(&b, vstr_itt5ga1, cis[i + 10]);
2091 varbuf_append(&b, vstr_maxp5gha1, cis[i + 11]);
2092 varbuf_append(&b, vstr_maxp5gla1, cis[i + 12]);
2093 varbuf_append(&b, vstr_pa, 5, 0, 1,
2094 (cis[i + 14] << 8) + cis[i + 13]);
2095 varbuf_append(&b, vstr_pa, 5, 1, 1,
2096 (cis[i + 16] << 8) + cis[i + 15]);
2097 varbuf_append(&b, vstr_pa, 5, 2, 1,
2098 (cis[i + 18] << 8) + cis[i + 17]);
2099 varbuf_append(&b, vstr_pahl, 5, 'l', 0, 1,
2100 (cis[i + 20] << 8) + cis[i + 19]);
2101 varbuf_append(&b, vstr_pahl, 5, 'l', 1, 1,
2102 (cis[i + 22] << 8) + cis[i + 21]);
2103 varbuf_append(&b, vstr_pahl, 5, 'l', 2, 1,
2104 (cis[i + 24] << 8) + cis[i + 23]);
2105 varbuf_append(&b, vstr_pahl, 5, 'h', 0, 1,
2106 (cis[i + 26] << 8) + cis[i + 25]);
2107 varbuf_append(&b, vstr_pahl, 5, 'h', 1, 1,
2108 (cis[i + 28] << 8) + cis[i + 27]);
2109 varbuf_append(&b, vstr_pahl, 5, 'h', 2, 1,
2110 (cis[i + 30] << 8) + cis[i + 29]);
2111 break;
2113 case HNBU_PO_CCKOFDM:
2114 varbuf_append(&b, vstr_cck2gpo,
2115 (cis[i + 2] << 8) + cis[i + 1]);
2116 varbuf_append(&b, vstr_ofdm2gpo,
2117 (cis[i + 6] << 24) + (cis[i + 5] << 16) +
2118 (cis[i + 4] << 8) + cis[i + 3]);
2119 if (tlen < 19) break;
2121 varbuf_append(&b, vstr_ofdm5gpo,
2122 (cis[i + 10] << 24) + (cis[i + 9] << 16) +
2123 (cis[i + 8] << 8) + cis[i + 7]);
2124 varbuf_append(&b, vstr_ofdm5glpo,
2125 (cis[i + 14] << 24) + (cis[i + 13] << 16) +
2126 (cis[i + 12] << 8) + cis[i + 11]);
2127 varbuf_append(&b, vstr_ofdm5ghpo,
2128 (cis[i + 18] << 24) + (cis[i + 17] << 16) +
2129 (cis[i + 16] << 8) + cis[i + 15]);
2130 break;
2132 case HNBU_PO_MCS2G:
2133 for (j = 0; j <= (tlen/2); j++) {
2134 varbuf_append(&b, vstr_mcspo, 2, j,
2135 (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]);
2137 break;
2139 case HNBU_PO_MCS5GM:
2140 for (j = 0; j <= (tlen/2); j++) {
2141 varbuf_append(&b, vstr_mcspo, 5, j,
2142 (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]);
2144 break;
2146 case HNBU_PO_MCS5GLH:
2147 for (j = 0; j <= (tlen/4); j++) {
2148 varbuf_append(&b, vstr_mcspohl, 5, 'l', j,
2149 (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]);
2152 for (j = 0; j <= (tlen/4); j++) {
2153 varbuf_append(&b, vstr_mcspohl, 5, 'h', j,
2154 (cis[i + ((tlen/2)+2) + 2*j] << 8) +
2155 cis[i + ((tlen/2)+1) + 2*j]);
2158 break;
2160 case HNBU_PO_CDD:
2161 varbuf_append(&b, vstr_cddpo,
2162 (cis[i + 2] << 8) + cis[i + 1]);
2163 break;
2165 case HNBU_PO_STBC:
2166 varbuf_append(&b, vstr_stbcpo,
2167 (cis[i + 2] << 8) + cis[i + 1]);
2168 break;
2170 case HNBU_PO_40M:
2171 varbuf_append(&b, vstr_bw40po,
2172 (cis[i + 2] << 8) + cis[i + 1]);
2173 break;
2175 case HNBU_PO_40MDUP:
2176 varbuf_append(&b, vstr_bwduppo,
2177 (cis[i + 2] << 8) + cis[i + 1]);
2178 break;
2180 case HNBU_OFDMPO5G:
2181 varbuf_append(&b, vstr_ofdm5gpo,
2182 (cis[i + 4] << 24) + (cis[i + 3] << 16) +
2183 (cis[i + 2] << 8) + cis[i + 1]);
2184 varbuf_append(&b, vstr_ofdm5glpo,
2185 (cis[i + 8] << 24) + (cis[i + 7] << 16) +
2186 (cis[i + 6] << 8) + cis[i + 5]);
2187 varbuf_append(&b, vstr_ofdm5ghpo,
2188 (cis[i + 12] << 24) + (cis[i + 11] << 16) +
2189 (cis[i + 10] << 8) + cis[i + 9]);
2190 break;
2191 /* Power per rate for SROM V9 */
2192 case HNBU_CCKBW202GPO:
2193 varbuf_append(&b, vstr_cckbw202gpo[0],
2194 ((cis[i + 2] << 8) + cis[i + 1]));
2195 if (tlen > 4)
2196 varbuf_append(&b, vstr_cckbw202gpo[1],
2197 ((cis[i + 4] << 8) + cis[i + 3]));
2198 break;
2200 case HNBU_LEGOFDMBW202GPO:
2201 varbuf_append(&b, vstr_legofdmbw202gpo[0],
2202 ((cis[i + 4] << 24) + (cis[i + 3] << 16) +
2203 (cis[i + 2] << 8) + cis[i + 1]));
2204 if (tlen > 6) {
2205 varbuf_append(&b, vstr_legofdmbw202gpo[1],
2206 ((cis[i + 8] << 24) + (cis[i + 7] << 16) +
2207 (cis[i + 6] << 8) + cis[i + 5]));
2209 break;
2211 case HNBU_LEGOFDMBW205GPO:
2212 for (j = 0; j < 6; j++) {
2213 if (tlen < (2 + 4 * j))
2214 break;
2215 varbuf_append(&b, vstr_legofdmbw205gpo[j],
2216 ((cis[4 * j + i + 4] << 24)
2217 + (cis[4 * j + i + 3] << 16)
2218 + (cis[4 * j + i + 2] << 8)
2219 + cis[4 * j + i + 1]));
2221 break;
2223 case HNBU_MCS2GPO:
2224 for (j = 0; j < 3; j++) {
2225 if (tlen < (2 + 4 * j))
2226 break;
2227 varbuf_append(&b, vstr_mcs2gpo[j],
2228 ((cis[4 * j + i + 4] << 24)
2229 + (cis[4 * j + i + 3] << 16)
2230 + (cis[4 * j + i + 2] << 8)
2231 + cis[4 * j + i + 1]));
2233 break;
2235 case HNBU_MCS5GLPO:
2236 for (j = 0; j < 3; j++) {
2237 if (tlen < (2 + 4 * j))
2238 break;
2239 varbuf_append(&b, vstr_mcs5glpo[j],
2240 ((cis[4 * j + i + 4] << 24)
2241 + (cis[4 * j + i + 3] << 16)
2242 + (cis[4 * j + i + 2] << 8)
2243 + cis[4 * j + i + 1]));
2245 break;
2247 case HNBU_MCS5GMPO:
2248 for (j = 0; j < 3; j++) {
2249 if (tlen < (2 + 4 * j))
2250 break;
2251 varbuf_append(&b, vstr_mcs5gmpo[j],
2252 ((cis[4 * j + i + 4] << 24)
2253 + (cis[4 * j + i + 3] << 16)
2254 + (cis[4 * j + i + 2] << 8)
2255 + cis[4 * j + i + 1]));
2257 break;
2259 case HNBU_MCS5GHPO:
2260 for (j = 0; j < 3; j++) {
2261 if (tlen < (2 + 4 * j))
2262 break;
2263 varbuf_append(&b, vstr_mcs5ghpo[j],
2264 ((cis[4 * j + i + 4] << 24)
2265 + (cis[4 * j + i + 3] << 16)
2266 + (cis[4 * j + i + 2] << 8)
2267 + cis[4 * j + i + 1]));
2269 break;
2271 case HNBU_MCS32PO:
2272 varbuf_append(&b, vstr_mcs32po,
2273 (cis[i + 2] << 8) + cis[i + 1]);
2274 break;
2276 case HNBU_LEG40DUPPO:
2277 varbuf_append(&b, vstr_legofdm40duppo,
2278 (cis[i + 2] << 8) + cis[i + 1]);
2279 break;
2281 case HNBU_CUSTOM1:
2282 varbuf_append(&b, vstr_custom, 1, ((cis[i + 4] << 24) +
2283 (cis[i + 3] << 16) + (cis[i + 2] << 8) +
2284 cis[i + 1]));
2285 break;
2287 #if defined(BCMCCISSR3)
2288 case HNBU_SROM3SWRGN:
2289 if (tlen >= 73) {
2290 uint16 srom[35];
2291 uint8 srev = cis[i + 1 + 70];
2292 ASSERT(srev == 3);
2293 /* make tuple value 16-bit aligned and parse it */
2294 bcopy(&cis[i + 1], srom, sizeof(srom));
2295 _initvars_srom_pci(srev, srom, SROM3_SWRGN_OFF, &b);
2296 /* 2.4G antenna gain is included in SROM */
2297 ag_init = TRUE;
2298 /* Ethernet MAC address is included in SROM */
2299 eabuf[0] = 0;
2300 boardnum = -1;
2302 /* create extra variables */
2303 if (tlen >= 75)
2304 varbuf_append(&b, vstr_vendid,
2305 (cis[i + 1 + 73] << 8) +
2306 cis[i + 1 + 72]);
2307 if (tlen >= 77)
2308 varbuf_append(&b, vstr_devid,
2309 (cis[i + 1 + 75] << 8) +
2310 cis[i + 1 + 74]);
2311 if (tlen >= 79)
2312 varbuf_append(&b, vstr_xtalfreq,
2313 (cis[i + 1 + 77] << 8) +
2314 cis[i + 1 + 76]);
2315 break;
2316 #endif
2318 case HNBU_CCKFILTTYPE:
2319 varbuf_append(&b, vstr_cckdigfilttype,
2320 (cis[i + 1]));
2321 break;
2323 case HNBU_TEMPTHRESH:
2324 varbuf_append(&b, vstr_tempthresh,
2325 (cis[i + 1]));
2326 /* period in msb nibble */
2327 varbuf_append(&b, vstr_temps_period,
2328 (cis[i + 2] >> 4));
2329 /* hysterisis in lsb nibble */
2330 varbuf_append(&b, vstr_temp_hysteresis,
2331 (cis[i + 2] & 0xF));
2332 break;
2333 case HNBU_UUID:
2335 /* uuid format 12345678-1234-5678-1234-567812345678 */
2337 char uuidstr[37]; /* 32 ids, 4 '-', 1 Null */
2339 snprintf(uuidstr, sizeof(uuidstr),
2340 "%02X%02X%02X%02X-%02X%02X-%02X%02X-"
2341 "%02X%02X-%02X%02X%02X%02X%02X%02X",
2342 cis[i + 1], cis[i + 2], cis[i + 3], cis[i + 4],
2343 cis[i + 5], cis[i + 6], cis[i + 7], cis[i + 8],
2344 cis[i + 9], cis[i + 10], cis[i + 11], cis[i + 12],
2345 cis[i + 13], cis[i + 14], cis[i + 15], cis[i + 16]);
2347 varbuf_append(&b, vstr_uuid, uuidstr);
2348 break;
2351 #endif /* !BCM_BOOTLOADER */
2354 break;
2356 i += tlen;
2357 } while (tup != CISTPL_END);
2360 if (boardnum != -1) {
2361 varbuf_append(&b, vstr_boardnum, boardnum);
2364 if (eabuf[0]) {
2365 varbuf_append(&b, vstr_macaddr, eabuf);
2368 #ifndef BCM_BOOTLOADER
2369 /* if there is no antenna gain field, set default */
2370 if (getvar(NULL, "ag0") == NULL && ag_init == FALSE) {
2371 varbuf_append(&b, vstr_ag, 0, 0xff);
2373 #endif
2375 #if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND)
2376 varbuf_append(&b, vstr_end, NULL);
2377 #endif /* BCMUSBDEV_BMAC */
2379 /* final nullbyte terminator */
2380 ASSERT(b.size >= 1);
2381 *b.buf++ = '\0';
2383 ASSERT(b.buf - base <= MAXSZ_NVRAM_VARS);
2384 err = initvars_table(osh, base, b.buf, vars, count);
2386 MFREE(osh, base, MAXSZ_NVRAM_VARS);
2387 return err;
2390 /* set PCMCIA sprom command register */
2391 static int
2392 sprom_cmd_pcmcia(osl_t *osh, uint8 cmd)
2394 uint8 status = 0;
2395 uint wait_cnt = 1000;
2397 /* write sprom command register */
2398 OSL_PCMCIA_WRITE_ATTR(osh, SROM_CS, &cmd, 1);
2400 /* wait status */
2401 while (wait_cnt--) {
2402 OSL_PCMCIA_READ_ATTR(osh, SROM_CS, &status, 1);
2403 if (status & SROM_DONE)
2404 return 0;
2407 return 1;
2410 /* read a word from the PCMCIA srom */
2411 static int
2412 sprom_read_pcmcia(osl_t *osh, uint16 addr, uint16 *data)
2414 uint8 addr_l, addr_h, data_l, data_h;
2416 addr_l = (uint8)((addr * 2) & 0xff);
2417 addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
2419 /* set address */
2420 OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1);
2421 OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1);
2423 /* do read */
2424 if (sprom_cmd_pcmcia(osh, SROM_READ))
2425 return 1;
2427 /* read data */
2428 data_h = data_l = 0;
2429 OSL_PCMCIA_READ_ATTR(osh, SROM_DATAH, &data_h, 1);
2430 OSL_PCMCIA_READ_ATTR(osh, SROM_DATAL, &data_l, 1);
2432 *data = (data_h << 8) | data_l;
2433 return 0;
2436 #if defined(WLTEST) || defined(DHD_SPROM) || defined(BCMDBG)
2437 /* write a word to the PCMCIA srom */
2438 static int
2439 sprom_write_pcmcia(osl_t *osh, uint16 addr, uint16 data)
2441 uint8 addr_l, addr_h, data_l, data_h;
2443 addr_l = (uint8)((addr * 2) & 0xff);
2444 addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
2445 data_l = (uint8)(data & 0xff);
2446 data_h = (uint8)((data >> 8) & 0xff);
2448 /* set address */
2449 OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRH, &addr_h, 1);
2450 OSL_PCMCIA_WRITE_ATTR(osh, SROM_ADDRL, &addr_l, 1);
2452 /* write data */
2453 OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAH, &data_h, 1);
2454 OSL_PCMCIA_WRITE_ATTR(osh, SROM_DATAL, &data_l, 1);
2456 /* do write */
2457 return sprom_cmd_pcmcia(osh, SROM_WRITE);
2459 #endif
2461 /* In chips with chipcommon rev 32 and later, the srom is in chipcommon,
2462 * not in the bus cores.
2464 static uint16
2465 srom_cc_cmd(si_t *sih, osl_t *osh, void *ccregs, uint32 cmd, uint wordoff, uint16 data)
2467 chipcregs_t *cc = (chipcregs_t *)ccregs;
2468 uint wait_cnt = 1000;
2470 if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
2471 W_REG(osh, &cc->sromaddress, wordoff * 2);
2472 if (cmd == SRC_OP_WRITE)
2473 W_REG(osh, &cc->sromdata, data);
2476 W_REG(osh, &cc->sromcontrol, SRC_START | cmd);
2478 while (wait_cnt--) {
2479 if ((R_REG(osh, &cc->sromcontrol) & SRC_BUSY) == 0)
2480 break;
2483 if (!wait_cnt) {
2484 BS_ERROR(("%s: Command 0x%x timed out\n", __FUNCTION__, cmd));
2485 return 0xffff;
2487 if (cmd == SRC_OP_READ)
2488 return (uint16)R_REG(osh, &cc->sromdata);
2489 else
2490 return 0xffff;
2494 * Read in and validate sprom.
2495 * Return 0 on success, nonzero on error.
2497 static int
2498 sprom_read_pci(osl_t *osh, si_t *sih, uint16 *sprom, uint wordoff, uint16 *buf, uint nwords,
2499 bool check_crc)
2501 int err = 0;
2502 uint i;
2503 void *ccregs = NULL;
2504 uint32 ccval = 0;
2506 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
2507 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
2508 /* save current control setting */
2509 ccval = si_chipcontrl_epa4331_read(sih);
2510 /* Disable Ext PA lines to allow reading from SROM */
2511 si_chipcontrl_epa4331(sih, FALSE);
2514 /* read the sprom */
2515 for (i = 0; i < nwords; i++) {
2517 if (sih->ccrev > 31 && ISSIM_ENAB(sih)) {
2518 /* use indirect since direct is too slow on QT */
2519 if ((sih->cccaps & CC_CAP_SROM) == 0) {
2520 err = 1;
2521 goto error;
2524 ccregs = (void *)((uint8 *)sprom - CC_SROM_OTP);
2525 buf[i] = srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ, wordoff + i, 0);
2527 } else {
2528 if (ISSIM_ENAB(sih))
2529 buf[i] = R_REG(osh, &sprom[wordoff + i]);
2531 buf[i] = R_REG(osh, &sprom[wordoff + i]);
2536 /* bypass crc checking for simulation to allow srom hack */
2537 if (ISSIM_ENAB(sih))
2538 goto error;
2540 if (check_crc) {
2542 if (buf[0] == 0xffff) {
2543 /* The hardware thinks that an srom that starts with 0xffff
2544 * is blank, regardless of the rest of the content, so declare
2545 * it bad.
2547 BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__, buf[0]));
2548 err = 1;
2549 goto error;
2552 /* fixup the endianness so crc8 will pass */
2553 htol16_buf(buf, nwords * 2);
2554 if (hndcrc8((uint8 *)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) {
2555 /* DBG only pci always read srom4 first, then srom8/9 */
2556 /* BS_ERROR(("%s: bad crc\n", __FUNCTION__)); */
2557 err = 1;
2559 /* now correct the endianness of the byte array */
2560 ltoh16_buf(buf, nwords * 2);
2563 error:
2564 if ((CHIPID(sih->chip) == BCM4331_CHIP_ID) ||
2565 (CHIPID(sih->chip) == BCM43431_CHIP_ID)) {
2566 /* Restore config after reading SROM */
2567 si_chipcontrl_epa4331_restore(sih, ccval);
2570 return err;
2573 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
2574 static int
2575 otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz)
2577 uint8 *otp;
2578 uint sz = OTP_SZ_MAX/2; /* size in words */
2579 int err = 0;
2581 ASSERT(bufsz <= OTP_SZ_MAX);
2583 if ((otp = MALLOC(osh, OTP_SZ_MAX)) == NULL) {
2584 return BCME_ERROR;
2587 bzero(otp, OTP_SZ_MAX);
2589 err = otp_read_region(sih, OTP_HW_RGN, (uint16 *)otp, &sz);
2591 bcopy(otp, buf, bufsz);
2593 if (otp)
2594 MFREE(osh, otp, OTP_SZ_MAX);
2596 /* Check CRC */
2597 if (buf[0] == 0xffff) {
2598 /* The hardware thinks that an srom that starts with 0xffff
2599 * is blank, regardless of the rest of the content, so declare
2600 * it bad.
2602 BS_ERROR(("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__, buf[0]));
2603 return 1;
2606 /* fixup the endianness so crc8 will pass */
2607 htol16_buf(buf, bufsz);
2608 if (hndcrc8((uint8 *)buf, SROM4_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) {
2609 BS_ERROR(("%s: bad crc\n", __FUNCTION__));
2610 err = 1;
2612 /* now correct the endianness of the byte array */
2613 ltoh16_buf(buf, bufsz);
2615 return err;
2617 #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */
2619 #if defined(WLTEST) || defined(BCMDBG)
2621 srom_otp_write_region_crc(si_t *sih, uint nbytes, uint16* buf16, bool write)
2623 int err = 0, crc = 0;
2624 uint8 *buf8;
2626 /* Check nbytes is not odd or too big */
2627 if ((nbytes & 1) || (nbytes > SROM_MAX))
2628 return 1;
2630 /* block invalid buffer size */
2631 if (nbytes < SROM4_WORDS * 2)
2632 return BCME_BUFTOOSHORT;
2633 else if (nbytes > SROM4_WORDS * 2)
2634 return BCME_BUFTOOLONG;
2636 /* Verify signatures */
2637 if (!((buf16[SROM4_SIGN] == SROM4_SIGNATURE) ||
2638 (buf16[SROM8_SIGN] == SROM4_SIGNATURE))) {
2639 BS_ERROR(("%s: wrong signature SROM4_SIGN %x SROM8_SIGN %x\n",
2640 __FUNCTION__, buf16[SROM4_SIGN], buf16[SROM8_SIGN]));
2641 return BCME_ERROR;
2644 /* Check CRC */
2645 if (buf16[0] == 0xffff) {
2646 /* The hardware thinks that an srom that starts with 0xffff
2647 * is blank, regardless of the rest of the content, so declare
2648 * it bad.
2650 BS_ERROR(("%s: invalid buf16[0] = 0x%x\n", __FUNCTION__, buf16[0]));
2651 goto out;
2654 buf8 = (uint8*)buf16;
2655 /* fixup the endianness and then calculate crc */
2656 htol16_buf(buf8, nbytes);
2657 crc = ~hndcrc8(buf8, nbytes - 1, CRC8_INIT_VALUE);
2658 /* now correct the endianness of the byte array */
2659 ltoh16_buf(buf8, nbytes);
2660 buf16[SROM4_CRCREV] = (crc << 8) | (buf16[SROM4_CRCREV] & 0xff);
2662 #ifdef BCMNVRAMW
2663 /* Write the CRC back */
2664 if (write)
2665 err = otp_cis_append_region(sih, OTP_HW_RGN, (char*)buf8, (int)nbytes);
2666 #endif /* BCMNVRAMW */
2668 out:
2669 return write ? err : crc;
2671 #endif
2674 * Create variable table from memory.
2675 * Return 0 on success, nonzero on error.
2677 static int
2678 BCMATTACHFN(initvars_table)(osl_t *osh, char *start, char *end, char **vars, uint *count)
2680 int c = (int)(end - start);
2682 /* do it only when there is more than just the null string */
2683 if (c > 1) {
2684 char *vp = MALLOC(osh, c);
2685 ASSERT(vp != NULL);
2686 if (!vp)
2687 return BCME_NOMEM;
2688 bcopy(start, vp, c);
2689 *vars = vp;
2690 *count = c;
2692 else {
2693 *vars = NULL;
2694 *count = 0;
2697 return 0;
2701 * Find variables with <devpath> from flash. 'base' points to the beginning
2702 * of the table upon enter and to the end of the table upon exit when success.
2703 * Return 0 on success, nonzero on error.
2705 static int
2706 BCMATTACHFN(initvars_flash)(si_t *sih, osl_t *osh, char **base, uint len)
2708 char *vp = *base;
2709 char *flash;
2710 int err;
2711 char *s;
2712 uint l, dl, copy_len;
2713 char devpath[SI_DEVPATH_BUFSZ];
2714 char coded_name[SI_DEVPATH_BUFSZ] = {0};
2715 int path_len, coded_len, devid_len;
2717 /* allocate memory and read in flash */
2718 if (!(flash = MALLOC(osh, NVRAM_SPACE)))
2719 return BCME_NOMEM;
2720 if ((err = nvram_getall(flash, NVRAM_SPACE)))
2721 goto exit;
2723 /* create legacy devpath prefix */
2724 si_devpath(sih, devpath, sizeof(devpath));
2725 path_len = strlen(devpath);
2727 /* create coded devpath prefix */
2728 si_coded_devpathvar(sih, coded_name, sizeof(coded_name), "devid");
2730 /* coded_name now is 'xx:devid, eat ending 'devid' */
2731 /* to be 'xx:' */
2732 devid_len = strlen("devid");
2733 coded_len = strlen(coded_name);
2734 if (coded_len > devid_len) {
2735 coded_name[coded_len - devid_len] = '\0';
2736 coded_len -= devid_len;
2738 else
2739 coded_len = 0;
2741 /* grab vars with the <devpath> prefix or <coded_name> previx in name */
2742 for (s = flash; s && *s; s += l + 1) {
2743 l = strlen(s);
2745 /* skip non-matching variable */
2746 if (strncmp(s, devpath, path_len) == 0)
2747 dl = path_len;
2748 else if (coded_len && strncmp(s, coded_name, coded_len) == 0)
2749 dl = coded_len;
2750 else
2751 continue;
2753 /* is there enough room to copy? */
2754 copy_len = l - dl + 1;
2755 if (len < copy_len) {
2756 err = BCME_BUFTOOSHORT;
2757 goto exit;
2760 /* no prefix, just the name=value */
2761 strncpy(vp, &s[dl], copy_len);
2762 vp += copy_len;
2763 len -= copy_len;
2766 /* add null string as terminator */
2767 if (len < 1) {
2768 err = BCME_BUFTOOSHORT;
2769 goto exit;
2771 *vp++ = '\0';
2773 *base = vp;
2775 exit: MFREE(osh, flash, NVRAM_SPACE);
2776 return err;
2779 #if !defined(BCMUSBDEV)
2781 * Initialize nonvolatile variable table from flash.
2782 * Return 0 on success, nonzero on error.
2784 static int
2785 BCMATTACHFN(initvars_flash_si)(si_t *sih, char **vars, uint *count)
2787 osl_t *osh = si_osh(sih);
2788 char *vp, *base;
2789 int err;
2791 ASSERT(vars != NULL);
2792 ASSERT(count != NULL);
2794 base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS);
2795 ASSERT(vp != NULL);
2796 if (!vp)
2797 return BCME_NOMEM;
2799 if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS)) == 0)
2800 err = initvars_table(osh, base, vp, vars, count);
2802 MFREE(osh, base, MAXSZ_NVRAM_VARS);
2804 return err;
2806 #endif
2808 /* Parse SROM and create name=value pairs. 'srom' points to
2809 * the SROM word array. 'off' specifies the offset of the
2810 * first word 'srom' points to, which should be either 0 or
2811 * SROM3_SWRG_OFF (full SROM or software region).
2814 static uint
2815 mask_shift(uint16 mask)
2817 uint i;
2818 for (i = 0; i < (sizeof(mask) << 3); i ++) {
2819 if (mask & (1 << i))
2820 return i;
2822 ASSERT(mask);
2823 return 0;
2826 static uint
2827 mask_width(uint16 mask)
2829 int i;
2830 for (i = (sizeof(mask) << 3) - 1; i >= 0; i --) {
2831 if (mask & (1 << i))
2832 return (uint)(i - mask_shift(mask) + 1);
2834 ASSERT(mask);
2835 return 0;
2838 #ifdef BCMASSERT_SUPPORT
2839 static bool
2840 mask_valid(uint16 mask)
2842 uint shift = mask_shift(mask);
2843 uint width = mask_width(mask);
2844 return mask == ((~0 << shift) & ~(~0 << (shift + width)));
2846 #endif
2848 static void
2849 BCMATTACHFN(_initvars_srom_pci)(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b)
2851 uint16 w;
2852 uint32 val;
2853 const sromvar_t *srv;
2854 uint width;
2855 uint flags;
2856 uint32 sr = (1 << sromrev);
2858 varbuf_append(b, "sromrev=%d", sromrev);
2860 for (srv = pci_sromvars; srv->name != NULL; srv ++) {
2861 const char *name;
2863 if ((srv->revmask & sr) == 0)
2864 continue;
2866 if (srv->off < off)
2867 continue;
2869 flags = srv->flags;
2870 name = srv->name;
2872 /* This entry is for mfgc only. Don't generate param for it, */
2873 if (flags & SRFL_NOVAR)
2874 continue;
2876 if (flags & SRFL_ETHADDR) {
2877 char eabuf[ETHER_ADDR_STR_LEN];
2878 struct ether_addr ea;
2880 ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff;
2881 ea.octet[1] = srom[srv->off - off] & 0xff;
2882 ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
2883 ea.octet[3] = srom[srv->off + 1 - off] & 0xff;
2884 ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
2885 ea.octet[5] = srom[srv->off + 2 - off] & 0xff;
2886 bcm_ether_ntoa(&ea, eabuf);
2888 varbuf_append(b, "%s=%s", name, eabuf);
2890 else {
2891 ASSERT(mask_valid(srv->mask));
2892 ASSERT(mask_width(srv->mask));
2894 w = srom[srv->off - off];
2895 val = (w & srv->mask) >> mask_shift(srv->mask);
2896 width = mask_width(srv->mask);
2898 while (srv->flags & SRFL_MORE) {
2899 srv ++;
2900 ASSERT(srv->name != NULL);
2902 if (srv->off == 0 || srv->off < off)
2903 continue;
2905 ASSERT(mask_valid(srv->mask));
2906 ASSERT(mask_width(srv->mask));
2908 w = srom[srv->off - off];
2909 val += ((w & srv->mask) >> mask_shift(srv->mask)) << width;
2910 width += mask_width(srv->mask);
2913 if ((flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1))
2914 continue;
2916 if (flags & SRFL_CCODE) {
2917 if (val == 0)
2918 varbuf_append(b, "ccode=");
2919 else
2920 varbuf_append(b, "ccode=%c%c", (val >> 8), (val & 0xff));
2922 /* LED Powersave duty cycle has to be scaled:
2923 *(oncount >> 24) (offcount >> 8)
2925 else if (flags & SRFL_LEDDC) {
2926 uint32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */
2927 (((val & 0xff)) << 8); /* offcount */
2928 varbuf_append(b, "leddc=%d", w32);
2930 else if (flags & SRFL_PRHEX)
2931 varbuf_append(b, "%s=0x%x", name, val);
2932 else if ((flags & SRFL_PRSIGN) && (val & (1 << (width - 1))))
2933 varbuf_append(b, "%s=%d", name, (int)(val | (~0 << width)));
2934 else
2935 varbuf_append(b, "%s=%u", name, val);
2939 if (sromrev >= 4) {
2940 /* Do per-path variables */
2941 uint p, pb, psz;
2943 if (sromrev >= 8) {
2944 pb = SROM8_PATH0;
2945 psz = SROM8_PATH1 - SROM8_PATH0;
2946 } else {
2947 pb = SROM4_PATH0;
2948 psz = SROM4_PATH1 - SROM4_PATH0;
2951 for (p = 0; p < MAX_PATH_SROM; p++) {
2952 for (srv = perpath_pci_sromvars; srv->name != NULL; srv ++) {
2953 if ((srv->revmask & sr) == 0)
2954 continue;
2956 if (pb + srv->off < off)
2957 continue;
2959 /* This entry is for mfgc only. Don't generate param for it, */
2960 if (srv->flags & SRFL_NOVAR)
2961 continue;
2963 w = srom[pb + srv->off - off];
2965 ASSERT(mask_valid(srv->mask));
2966 val = (w & srv->mask) >> mask_shift(srv->mask);
2967 width = mask_width(srv->mask);
2969 /* Cheating: no per-path var is more than 1 word */
2971 if ((srv->flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1))
2972 continue;
2974 if (srv->flags & SRFL_PRHEX)
2975 varbuf_append(b, "%s%d=0x%x", srv->name, p, val);
2976 else
2977 varbuf_append(b, "%s%d=%d", srv->name, p, val);
2979 pb += psz;
2985 * Initialize nonvolatile variable table from sprom.
2986 * Return 0 on success, nonzero on error.
2988 static int
2989 BCMATTACHFN(initvars_srom_pci)(si_t *sih, void *curmap, char **vars, uint *count)
2991 uint16 *srom, *sromwindow;
2992 uint8 sromrev = 0;
2993 uint32 sr;
2994 varbuf_t b;
2995 char *vp, *base = NULL;
2996 osl_t *osh = si_osh(sih);
2997 bool flash = FALSE;
2998 int err = 0;
3001 * Apply CRC over SROM content regardless SROM is present or not,
3002 * and use variable <devpath>sromrev's existance in flash to decide
3003 * if we should return an error when CRC fails or read SROM variables
3004 * from flash.
3006 srom = MALLOC(osh, SROM_MAX);
3007 ASSERT(srom != NULL);
3008 if (!srom)
3009 return -2;
3011 sromwindow = (uint16 *)SROM_OFFSET(sih);
3012 if (si_is_sprom_available(sih)) {
3013 err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM_WORDS, TRUE);
3015 if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
3016 (((sih->buscoretype == PCIE_CORE_ID) && (sih->buscorerev >= 6)) ||
3017 ((sih->buscoretype == PCI_CORE_ID) && (sih->buscorerev >= 0xe)))) {
3018 /* sromrev >= 4, read more */
3019 err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM4_WORDS, TRUE);
3020 sromrev = srom[SROM4_CRCREV] & 0xff;
3021 if (err)
3022 BS_ERROR(("%s: srom %d, bad crc\n", __FUNCTION__, sromrev));
3024 } else if (err == 0) {
3025 /* srom is good and is rev < 4 */
3026 /* top word of sprom contains version and crc8 */
3027 sromrev = srom[SROM_CRCREV] & 0xff;
3028 /* bcm4401 sroms misprogrammed */
3029 if (sromrev == 0x10)
3030 sromrev = 1;
3034 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
3035 /* Use OTP if SPROM not available */
3036 else if ((err = otp_read_pci(osh, sih, srom, SROM_MAX)) == 0) {
3037 /* OTP only contain SROM rev8/rev9 for now */
3038 sromrev = srom[SROM4_CRCREV] & 0xff;
3040 #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */
3041 else {
3042 err = 1;
3043 BS_ERROR(("Neither SPROM nor OTP has valid image\n"));
3047 /* We want internal/wltest driver to come up with default sromvars so we can
3048 * program a blank SPROM/OTP.
3050 if (err) {
3051 char *value;
3052 uint32 val;
3053 val = 0;
3055 if ((value = si_getdevpathvar(sih, "sromrev"))) {
3056 sromrev = (uint8)bcm_strtoul(value, NULL, 0);
3057 flash = TRUE;
3058 goto varscont;
3061 BS_ERROR(("%s, SROM CRC Error\n", __FUNCTION__));
3063 #ifndef DONGLEBUILD
3064 if ((value = si_getnvramflvar(sih, "sromrev"))) {
3065 err = 0;
3066 goto errout;
3068 #endif
3069 /* BCMHOSTVARS is enabled only if WLTEST is enabled or BCMEXTNVM is enabled */
3070 #if defined(BCMHOSTVARS)
3071 val = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
3072 if ((si_is_sprom_available(sih) && srom[0] == 0xffff) ||
3073 (val & SPROM_OTPIN_USE)) {
3074 vp = base = mfgsromvars;
3076 if (defvarslen == 0) {
3077 BS_ERROR(("No nvm file, use generic default (for programming"
3078 " SPROM/OTP only)\n"));
3080 if (((sih->chip == BCM4331_CHIP_ID) ||
3081 (sih->chip == BCM43431_CHIP_ID)) &&
3082 (sih->chiprev < 3)) {
3084 defvarslen = srom_vars_len(defaultsromvars_4331);
3085 bcopy(defaultsromvars_4331, vp, defvarslen);
3087 } else {
3088 /* For 4311 A1 there is no signature to indicate that OTP is
3089 * programmed, so can't really verify the OTP is
3090 * unprogrammed or a bad OTP.
3092 if (sih->chip == BCM4311_CHIP_ID) {
3093 const char *devid = "devid=0x4311";
3094 const size_t devid_strlen = strlen(devid);
3095 BS_ERROR(("setting the devid to be 4311\n"));
3096 bcopy(devid, vp, devid_strlen + 1);
3097 vp += devid_strlen + 1;
3099 defvarslen = srom_vars_len(defaultsromvars_wltest);
3100 bcopy(defaultsromvars_wltest, vp, defvarslen);
3102 } else {
3103 BS_ERROR(("Use nvm file as default\n"));
3106 vp += defvarslen;
3107 /* add final null terminator */
3108 *vp++ = '\0';
3110 BS_ERROR(("Used %d bytes of defaultsromvars\n", defvarslen));
3111 goto varsdone;
3113 } else if (((sih->chip == BCM4331_CHIP_ID) ||
3114 (sih->chip == BCM43431_CHIP_ID)) &&
3115 (sih->chiprev < 3)) {
3116 base = vp = mfgsromvars;
3118 BS_ERROR(("4331 BOOT w/o SPROM or OTP\n"));
3120 defvarslen = srom_vars_len(defaultsromvars_4331);
3121 bcopy(defaultsromvars_4331, vp, defvarslen);
3122 vp += defvarslen;
3123 *vp++ = '\0';
3124 goto varsdone;
3125 } else
3126 #endif
3128 err = -1;
3129 goto errout;
3133 varscont:
3134 /* Bitmask for the sromrev */
3135 sr = 1 << sromrev;
3137 /* srom version check: Current valid versions: 1, 2, 3, 4, 5, 8, SROM_MAXREV */
3138 if ((sr & 0x33e) == 0) {
3139 err = -2;
3140 goto errout;
3143 ASSERT(vars != NULL);
3144 ASSERT(count != NULL);
3146 base = vp = MALLOC(osh, MAXSZ_NVRAM_VARS);
3147 ASSERT(vp != NULL);
3148 if (!vp) {
3149 err = -2;
3150 goto errout;
3153 /* read variables from flash */
3154 if (flash) {
3155 if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS)))
3156 goto errout;
3157 goto varsdone;
3160 varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
3162 /* parse SROM into name=value pairs. */
3163 _initvars_srom_pci(sromrev, srom, 0, &b);
3166 /* final nullbyte terminator */
3167 ASSERT(b.size >= 1);
3168 vp = b.buf;
3169 *vp++ = '\0';
3171 ASSERT((vp - base) <= MAXSZ_NVRAM_VARS);
3173 varsdone:
3174 err = initvars_table(osh, base, vp, vars, count);
3176 errout:
3177 /* BCMHOSTVARS are enabled only if WLTEST is enabled or BCMEXTNVM is enabled */
3178 #if defined(BCMHOSTVARS)
3179 if (base && (base != mfgsromvars))
3180 #else
3181 if (base)
3182 #endif
3183 MFREE(osh, base, MAXSZ_NVRAM_VARS);
3185 MFREE(osh, srom, SROM_MAX);
3186 return err;
3190 * Read the cis and call parsecis to initialize the vars.
3191 * Return 0 on success, nonzero on error.
3193 static int
3194 BCMATTACHFN(initvars_cis_pcmcia)(si_t *sih, osl_t *osh, char **vars, uint *count)
3196 uint8 *cis = NULL;
3197 int rc;
3198 uint data_sz;
3200 data_sz = (sih->buscorerev == 1) ? SROM_MAX : CIS_SIZE;
3202 if ((cis = MALLOC(osh, data_sz)) == NULL)
3203 return (-2);
3205 if (sih->buscorerev == 1) {
3206 if (srom_read(sih, PCMCIA_BUS, (void *)NULL, osh, 0, data_sz, (uint16 *)cis,
3207 TRUE)) {
3208 MFREE(osh, cis, data_sz);
3209 return (-1);
3211 /* fix up endianess for 16-bit data vs 8-bit parsing */
3212 htol16_buf((uint16 *)cis, data_sz);
3213 } else
3214 OSL_PCMCIA_READ_ATTR(osh, 0, cis, data_sz);
3216 rc = srom_parsecis(osh, &cis, SROM_CIS_SINGLE, vars, count);
3218 MFREE(osh, cis, data_sz);
3220 return (rc);
3224 #ifdef BCMSPI
3226 * Read the SPI cis and call parsecis to initialize the vars.
3227 * Return 0 on success, nonzero on error.
3229 static int
3230 BCMATTACHFN(initvars_cis_spi)(osl_t *osh, char **vars, uint *count)
3232 uint8 *cis;
3233 int rc;
3235 #if defined(NDIS) && !defined(UNDER_CE)
3236 uint8 cisd[SBSDIO_CIS_SIZE_LIMIT];
3237 cis = (uint8*)cisd;
3238 #else
3239 if ((cis = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT)) == NULL) {
3240 return -1;
3242 #endif /* defined(NDIS) && (!defined(UNDER_CE)) */
3244 bzero(cis, SBSDIO_CIS_SIZE_LIMIT);
3246 if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, cis, SBSDIO_CIS_SIZE_LIMIT) != 0) {
3247 #if defined(NDIS) && !defined(UNDER_CE)
3248 /* nothing to do */
3249 #else
3250 MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT);
3251 #endif /* defined(NDIS) && (!defined(UNDER_CE)) */
3252 return -2;
3255 rc = srom_parsecis(osh, &cis, SDIO_FUNC_1, vars, count);
3257 #if defined(NDIS) && !defined(UNDER_CE)
3258 /* nothing to do here */
3259 #else
3260 MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT);
3261 #endif
3263 return (rc);
3265 #endif /* BCMSPI */
3267 #if defined(BCMUSBDEV)
3268 /* Return sprom size in 16-bit words */
3269 uint
3270 srom_size(si_t *sih, osl_t *osh)
3272 uint size = 0;
3273 if (SPROMBUS == PCMCIA_BUS) {
3274 uint32 origidx;
3275 sdpcmd_regs_t *pcmregs;
3276 bool wasup;
3278 origidx = si_coreidx(sih);
3279 pcmregs = si_setcore(sih, PCMCIA_CORE_ID, 0);
3280 if (!pcmregs)
3281 pcmregs = si_setcore(sih, SDIOD_CORE_ID, 0);
3282 ASSERT(pcmregs);
3284 if (!(wasup = si_iscoreup(sih)))
3285 si_core_reset(sih, 0, 0);
3287 /* not worry about earlier core revs */
3288 /* valid for only pcmcia core */
3289 if (si_coreid(sih) == PCMCIA_CORE_ID)
3290 if (si_corerev(sih) < 8)
3291 goto done;
3294 switch (SI_PCMCIA_READ(osh, pcmregs, SROM_INFO) & SRI_SZ_MASK) {
3295 case 1:
3296 size = 256; /* SROM_INFO == 1 means 4kbit */
3297 break;
3298 case 2:
3299 size = 1024; /* SROM_INFO == 2 means 16kbit */
3300 break;
3301 default:
3302 break;
3305 done:
3306 if (!wasup)
3307 si_core_disable(sih, 0);
3309 si_setcoreidx(sih, origidx);
3311 return size;
3313 #endif
3316 * initvars are different for BCMUSBDEV and BCMSDIODEV. This is OK when supporting both at
3317 * the same time, but only because all of the code is in attach functions and not in ROM.
3320 #if defined(BCMUSBDEV)
3321 #if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND)
3323 * Read the USB cis and call parsecis to initialize the vars.
3324 * Return 0 on success, nonzero on error.
3326 static int
3327 BCMATTACHFN(initvars_cis_usbdriver)(si_t *sih, osl_t *osh, char **vars, uint *count)
3329 uint8 *cis;
3330 uint sz = OTP_SZ_MAX/2; /* size in words */
3331 int rc = BCME_OK;
3333 if ((cis = MALLOC(osh, OTP_SZ_MAX)) == NULL) {
3334 return -1;
3337 bzero(cis, OTP_SZ_MAX);
3339 if (otp_read_region(sih, OTP_SW_RGN, (uint16 *)cis, &sz)) {
3340 BS_ERROR(("%s: OTP read SW region failure.\n*", __FUNCTION__));
3341 rc = -2;
3342 } else {
3343 BS_ERROR(("%s: OTP programmed. use OTP for srom vars\n*", __FUNCTION__));
3344 rc = srom_parsecis(osh, &cis, SROM_CIS_SINGLE, vars, count);
3347 MFREE(osh, cis, OTP_SZ_MAX);
3349 return (rc);
3352 /* For driver(not bootloader), if nvram is not downloadable or missing, use default */
3353 static int
3354 BCMATTACHFN(initvars_srom_si_usbdriver)(si_t *sih, osl_t *osh, char **vars, uint *varsz)
3356 uint len;
3357 char *base;
3358 char *fakevars;
3359 int rc = -1;
3360 static bool srvars = FALSE; /* Use OTP/SROM as global variables */
3362 base = fakevars = NULL;
3363 len = 0;
3364 switch (CHIPID(sih->chip)) {
3365 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
3366 fakevars = defaultsromvars_4322usb;
3367 break;
3368 case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID:
3369 case BCM43234_CHIP_ID:
3370 /* check against real chipid instead of compile time flag */
3371 if (sih->chip == BCM43234_CHIP_ID) {
3372 fakevars = defaultsromvars_43234usb;
3373 } else if (sih->chip == BCM43235_CHIP_ID) {
3374 fakevars = defaultsromvars_43235usb;
3375 } else
3376 fakevars = defaultsromvars_43236usb;
3377 break;
3379 case BCM4319_CHIP_ID:
3380 fakevars = defaultsromvars_4319usb;
3381 break;
3382 default:
3383 ASSERT(0);
3384 return rc;
3387 #ifndef BCM_BMAC_VARS_APPEND
3388 if (BCME_OK == initvars_cis_usbdriver(sih, osh, vars, varsz)) {
3389 /* Make OTP/SROM variables global */
3390 if (srvars == FALSE)
3391 nvram_append((void *)sih, *vars, *varsz);
3392 return BCME_OK;
3394 #endif /* BCM_BMAC_VARS_APPEND */
3396 /* NO OTP, if nvram downloaded, use it */
3397 if ((_varsz != 0) && (_vars != NULL)) {
3398 len = _varsz + (strlen(vstr_end));
3399 base = MALLOC(osh, len + 2); /* plus 2 terminating \0 */
3400 if (base == NULL) {
3401 BS_ERROR(("initvars_srom_si: MALLOC failed.\n"));
3402 return BCME_ERROR;
3404 bzero(base, len + 2);
3406 /* make a copy of the _vars, _vars is at the top of the memory, cannot append
3407 * END\0\0 to it. copy the download vars to base, back of the terminating \0,
3408 * then append END\0\0
3410 bcopy((void *)_vars, base, _varsz);
3411 /* backoff all the terminating \0s except the one the for the last string */
3412 len = _varsz;
3413 while (!base[len - 1])
3414 len--;
3415 len++; /* \0 for the last string */
3416 /* append END\0\0 to the end */
3417 bcopy((void *)vstr_end, (base + len), strlen(vstr_end));
3418 len += (strlen(vstr_end) + 2);
3419 *vars = base;
3420 *varsz = len;
3422 BS_ERROR(("%s USB nvram downloaded %d bytes\n", __FUNCTION__, _varsz));
3423 } else {
3424 /* Fall back to fake srom vars if OTP not programmed */
3425 len = srom_vars_len(fakevars);
3426 base = MALLOC(osh, (len + 1));
3427 if (base == NULL) {
3428 BS_ERROR(("initvars_srom_si: MALLOC failed.\n"));
3429 return BCME_ERROR;
3431 bzero(base, (len + 1));
3432 bcopy(fakevars, base, len);
3433 *(base + len) = '\0'; /* add final nullbyte terminator */
3434 *vars = base;
3435 *varsz = len + 1;
3436 BS_ERROR(("initvars_srom_usbdriver: faked nvram %d bytes\n", len));
3439 #ifdef BCM_BMAC_VARS_APPEND
3440 if (BCME_OK == initvars_cis_usbdriver(sih, osh, vars, varsz)) {
3441 if (base)
3442 MFREE(osh, base, (len + 1));
3444 #endif /* BCM_BMAC_VARS_APPEND */
3445 /* Make OTP/SROM variables global */
3446 if (srvars == FALSE) {
3447 nvram_append((void *)sih, *vars, *varsz);
3448 srvars = TRUE;
3450 return BCME_OK;
3453 #endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */
3455 #ifdef BCM_DONGLEVARS
3456 static int
3457 BCMATTACHFN(initvars_srom_si_bl)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz)
3459 int sel = 0; /* where to read srom/cis: 0 - none, 1 - otp, 2 - sprom */
3460 uint sz = 0; /* srom size in bytes */
3461 void *oh = NULL;
3462 int rc = BCME_OK;
3464 if ((oh = otp_init(sih)) != NULL && (otp_status(oh) & OTPS_GUP_SW)) {
3465 /* Access OTP if it is present, powered on, and programmed */
3466 sz = otp_size(oh);
3467 sel = 1;
3468 } else if ((sz = srom_size(sih, osh)) != 0) {
3469 /* Access the SPROM if it is present */
3470 sz <<= 1;
3471 sel = 2;
3474 /* Read CIS in OTP/SPROM */
3475 if (sel != 0) {
3476 uint16 *srom;
3477 uint8 *body = NULL;
3478 uint otpsz = sz;
3480 ASSERT(sz);
3482 /* Allocate memory */
3483 if ((srom = (uint16 *)MALLOC(osh, sz)) == NULL)
3484 return BCME_NOMEM;
3486 /* Read CIS */
3487 switch (sel) {
3488 case 1:
3489 rc = otp_read_region(sih, OTP_SW_RGN, srom, &otpsz);
3490 sz = otpsz;
3491 body = (uint8 *)srom;
3492 break;
3493 case 2:
3494 rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, srom, TRUE);
3495 /* sprom has 8 byte h/w header */
3496 body = (uint8 *)srom + SBSDIO_SPROM_CIS_OFFSET;
3497 break;
3498 default:
3499 /* impossible to come here */
3500 ASSERT(0);
3501 break;
3504 /* Parse CIS */
3505 if (rc == BCME_OK) {
3506 /* each word is in host endian */
3507 htol16_buf((uint8 *)srom, sz);
3508 ASSERT(body);
3509 rc = srom_parsecis(osh, &body, SROM_CIS_SINGLE, vars, varsz);
3512 MFREE(osh, srom, sz); /* Clean up */
3514 /* Make SROM variables global */
3515 if (rc == BCME_OK)
3516 nvram_append((void *)sih, *vars, *varsz);
3519 return BCME_OK;
3521 #endif /* #ifdef BCM_DONGLEVARS */
3523 static int
3524 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz)
3526 static bool srvars = FALSE; /* Use OTP/SPROM as global variables */
3528 /* Bail out if we've dealt with OTP/SPROM before! */
3529 if (srvars)
3530 goto exit;
3532 #if defined(BCMUSBDEV_BMAC) || defined(BCM_BMAC_VARS_APPEND)
3533 /* read OTP or use faked var array */
3534 switch (CHIPID(sih->chip)) {
3535 case BCM4322_CHIP_ID: case BCM43221_CHIP_ID: case BCM43231_CHIP_ID:
3536 case BCM43236_CHIP_ID: case BCM43235_CHIP_ID: case BCM43238_CHIP_ID:
3537 case BCM43234_CHIP_ID:
3538 case BCM4319_CHIP_ID:
3539 if (BCME_OK != initvars_srom_si_usbdriver(sih, osh, vars, varsz))
3540 goto exit;
3541 return BCME_OK;
3542 default:
3543 UNUSED_PARAMETER(defaultsromvars_4322usb);
3544 UNUSED_PARAMETER(defaultsromvars_43234usb);
3545 UNUSED_PARAMETER(defaultsromvars_43235usb);
3546 UNUSED_PARAMETER(defaultsromvars_43236usb);
3547 UNUSED_PARAMETER(defaultsromvars_4319usb);
3549 #endif /* BCMUSBDEV_BMAC || BCM_BMAC_VARS_APPEND */
3551 #ifdef BCM_DONGLEVARS /* this flag should be defined for usb bootloader, to read \
3552 OTP or SROM */
3553 if (BCME_OK != initvars_srom_si_bl(sih, osh, curmap, vars, varsz))
3554 return BCME_ERROR;
3555 #endif
3557 /* update static local var to skip for next call */
3558 srvars = TRUE;
3560 exit:
3561 /* Tell the caller there is no individual SROM variables */
3562 *vars = NULL;
3563 *varsz = 0;
3565 /* return OK so the driver will load & use defaults if bad srom/otp */
3566 return BCME_OK;
3569 #else /* !BCMUSBDEV && !BCMSDIODEV */
3571 static int
3572 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, void *curmap, char **vars, uint *varsz)
3574 /* Search flash nvram section for srom variables */
3575 return initvars_flash_si(sih, vars, varsz);
3577 #endif