• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Routines to access SPROM and to parse SROM/CIS variables.
3  *
4  * Despite its file name, OTP contents is also parsed in this file.
5  *
6  * Copyright (C) 2020, Broadcom.
7  *
8  *      Unless you and Broadcom execute a separate written software license
9  * agreement governing use of this software, this software is licensed to you
10  * under the terms of the GNU General Public License version 2 (the "GPL"),
11  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
12  * following added to such license:
13  *
14  *      As a special exception, the copyright holders of this software give you
15  * permission to link this software with independent modules, and to copy and
16  * distribute the resulting executable under terms of your choice, provided that
17  * you also meet, for each linked independent module, the terms and conditions of
18  * the license of that module.  An independent module is a module which is not
19  * derived from this software.  The special exception does not apply to any
20  * modifications of the software.
21  *
22  *
23  * <<Broadcom-WL-IPTag/Dual:>>
24  */
25 
26 /*
27  * List of non obvious preprocessor defines used in this file and their meaning:
28  * DONGLEBUILD    : building firmware that runs on the dongle's CPU
29  * BCM_DONGLEVARS : NVRAM variables can be read from OTP/S(P)ROM.
30  * When host may supply nvram vars in addition to the ones in OTP/SROM:
31  * 	BCMHOSTVARS    		: full nic / full dongle
32  * BCMDONGLEHOST  : defined when building DHD, code executes on the host in a dongle environment.
33  * DHD_SPROM      : defined when building a DHD that supports reading/writing to SPROM
34  */
35 
36 #include <typedefs.h>
37 #include <bcmdefs.h>
38 #include <osl.h>
39 #include <stdarg.h>
40 #include <bcmutils.h>
41 #include <hndsoc.h>
42 #include <sbchipc.h>
43 #include <bcmdevs.h>
44 #include <bcmendian.h>
45 #include <sbpcmcia.h>
46 #include <pcicfg.h>
47 #include <siutils.h>
48 #include <bcmsrom.h>
49 #include <bcmsrom_tbl.h>
50 #ifdef BCMSDIO
51 #include <bcmsdh.h>
52 #include <sdio.h>
53 #endif
54 #ifdef BCMSPI
55 #include <spid.h>
56 #endif
57 
58 #include <bcmnvram.h>
59 #include <bcmotp.h>
60 #ifndef BCMUSBDEV_COMPOSITE
61 #define BCMUSBDEV_COMPOSITE
62 #endif
63 #if defined(BCMUSBDEV) || defined(BCMSDIO) || defined(BCMSDIODEV)
64 #include <sbsdio.h>
65 #include <sbhnddma.h>
66 #include <sbsdpcmdev.h>
67 #endif
68 
69 #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG)
70 #include <sbsprom.h>
71 #endif
72 #include <ethernet.h>	/* for sprom content groking */
73 
74 #include <sbgci.h>
75 #ifdef EVENT_LOG_COMPILE
76 #include <event_log.h>
77 #endif
78 
79 #if defined(EVENT_LOG_COMPILE) && defined(BCMDBG_ERR) && defined(ERR_USE_EVENT_LOG)
80 #if defined(ERR_USE_EVENT_LOG_RA)
81 #define	BS_ERROR(args)	EVENT_LOG_RA(EVENT_LOG_TAG_BSROM_ERROR, args)
82 #else
83 #define	BS_ERROR(args)	EVENT_LOG_COMPACT_CAST_PAREN_ARGS(EVENT_LOG_TAG_BSROM_ERROR, args)
84 #endif /* ERR_USE_EVENT_LOG_RA */
85 #elif defined(BCMDBG_ERR) || defined(WLTEST)
86 #define BS_ERROR(args)	printf args
87 #else
88 #define BS_ERROR(args)
89 #endif	/* defined(BCMDBG_ERR) && defined(ERR_USE_EVENT_LOG) */
90 
91 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
92 static bool BCMATTACHDATA(is_caldata_prsnt) = FALSE;
93 static uint16 BCMATTACHDATA(caldata_array)[SROM_MAX / 2];
94 static uint8 BCMATTACHDATA(srom_sromrev);
95 #endif
96 
97 static const char BCMATTACHDATA(rstr_uuidstr)[] =
98 	"%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X";
99 static const char BCMATTACHDATA(rstr_paddr)[] = "pa%d=0x%%x";
100 static const char BCMATTACHDATA(rstr_pdata)[] = "pd%d=0x%%x";
101 static const char BCMATTACHDATA(rstr_pdatah)[] = "pdh%d=0x%%x";
102 static const char BCMATTACHDATA(rstr_pdatal)[] = "pdl%d=0x%%x";
103 static const char BCMATTACHDATA(rstr_gci_ccreg_entry)[] = "gcr%d=0x%%x";
104 static const char BCMATTACHDATA(rstr_hex)[] = "0x%x";
105 
106 /** curmap: contains host start address of PCI BAR0 window */
srom_offset(si_t * sih,volatile void * curmap)107 static volatile uint8* srom_offset(si_t *sih, volatile void *curmap)
108 {
109 	if (sih->ccrev <= 31)
110 		return (volatile uint8*)curmap + PCI_BAR0_SPROM_OFFSET;
111 	if ((sih->cccaps & CC_CAP_SROM) == 0)
112 		return NULL;
113 
114 	if (BUSTYPE(sih->bustype) == SI_BUS)
115 		return (uint8 *)((uintptr)SI_ENUM_BASE(sih) + CC_SROM_OTP);
116 
117 	return (volatile uint8*)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP;
118 }
119 
120 #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG)
121 #define WRITE_ENABLE_DELAY	500	/* 500 ms after write enable/disable toggle */
122 #define WRITE_WORD_DELAY	20	/* 20 ms between each word write */
123 #endif
124 
125 srom_info_t *sromh = NULL;
126 
127 extern char *_vars;
128 extern uint _varsz;
129 #ifdef DONGLEBUILD
130 char * BCMATTACHDATA(_vars_otp) = NULL;
131 #define DONGLE_STORE_VARS_OTP_PTR(v)	(_vars_otp = (v))
132 #else
133 #define DONGLE_STORE_VARS_OTP_PTR(v)
134 #endif
135 
136 #define SROM_CIS_SINGLE	1
137 
138 #if !defined(BCMDONGLEHOST)
139 static int initvars_srom_si(si_t *sih, osl_t *osh, volatile void *curmap, char **vars, uint *count);
140 static void _initvars_srom_pci(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b);
141 static int initvars_srom_pci(si_t *sih, volatile void *curmap, char **vars, uint *count);
142 static int initvars_cis_pci(si_t *sih, osl_t *osh, volatile void *curmap, char **vars, uint *count);
143 #endif /* !defined(BCMDONGLEHOST) */
144 #if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED) &&\
145 	!defined(BCMDONGLEHOST) && !defined(BCMPCIEDEV_ENABLED)
146 static int initvars_flash_si(si_t *sih, char **vars, uint *count);
147 #endif /* !defined(BCMUSBDEV) && !defined(BCMSDIODEV) && !defined(BCMDONGLEHOST) */
148 #ifdef BCMSDIO
149 #if !defined(BCMDONGLEHOST)
150 static int initvars_cis_sdio(si_t *sih, osl_t *osh, char **vars, uint *count);
151 #endif /* !defined(BCMDONGLEHOST) */
152 static int sprom_cmd_sdio(osl_t *osh, uint8 cmd);
153 static int sprom_read_sdio(osl_t *osh, uint16 addr, uint16 *data);
154 #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG)
155 static int sprom_write_sdio(osl_t *osh, uint16 addr, uint16 data);
156 #endif /* defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) */
157 #endif /* BCMSDIO */
158 #if !defined(BCMDONGLEHOST)
159 #ifdef BCMSPI
160 static int initvars_cis_spi(si_t *sih, osl_t *osh, char **vars, uint *count);
161 #endif /* BCMSPI */
162 #endif /* !defined(BCMDONGLEHOST) */
163 static int sprom_read_pci(osl_t *osh, si_t *sih, volatile uint16 *sprom, uint wordoff, uint16 *buf,
164                           uint nwords, bool check_crc);
165 #if !defined(BCMDONGLEHOST)
166 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
167 static int otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz);
168 #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */
169 #endif /* !defined(BCMDONGLEHOST) */
170 static uint16 srom_cc_cmd(si_t *sih, osl_t *osh, volatile void *ccregs, uint32 cmd, uint wordoff,
171                           uint16 data);
172 
173 #if !defined(BCMDONGLEHOST)
174 static int initvars_flash(si_t *sih, osl_t *osh, char **vp, uint len);
175 int dbushost_initvars_flash(si_t *sih, osl_t *osh, char **base, uint len);
176 static uint get_max_cis_size(si_t *sih);
177 #endif /* !defined(BCMDONGLEHOST) */
178 
179 #if defined (BCMHOSTVARS)
180 /* Also used by wl_readconfigdata for vars download */
181 char BCMATTACHDATA(mfgsromvars)[VARS_MAX];
182 int BCMATTACHDATA(defvarslen) = 0;
183 #endif /* defined(BCMHOSTVARS) */
184 
185 #if !defined(BCMDONGLEHOST)
186 #if defined (BCMHOSTVARS)
187 /* FIXME: Fake 4331 SROM to boot 4331 driver on QT w/o SPROM/OTP */
188 static char BCMATTACHDATA(defaultsromvars_4331)[] =
189 	"sromrev=9\0"
190 	"boardrev=0x1104\0"
191 	"boardflags=0x200\0"
192 	"boardflags2=0x0\0"
193 	"boardtype=0x524\0"
194 	"boardvendor=0x14e4\0"
195 	"boardnum=0x2064\0"
196 	"macaddr=00:90:4c:1a:20:64\0"
197 	"ccode=0x0\0"
198 	"regrev=0x0\0"
199 	"opo=0x0\0"
200 	"aa2g=0x7\0"
201 	"aa5g=0x7\0"
202 	"ag0=0x2\0"
203 	"ag1=0x2\0"
204 	"ag2=0x2\0"
205 	"ag3=0xff\0"
206 	"pa0b0=0xfe7f\0"
207 	"pa0b1=0x15d9\0"
208 	"pa0b2=0xfac6\0"
209 	"pa0itssit=0x20\0"
210 	"pa0maxpwr=0x48\0"
211 	"pa1b0=0xfe89\0"
212 	"pa1b1=0x14b1\0"
213 	"pa1b2=0xfada\0"
214 	"pa1lob0=0xffff\0"
215 	"pa1lob1=0xffff\0"
216 	"pa1lob2=0xffff\0"
217 	"pa1hib0=0xfe8f\0"
218 	"pa1hib1=0x13df\0"
219 	"pa1hib2=0xfafa\0"
220 	"pa1itssit=0x3e\0"
221 	"pa1maxpwr=0x3c\0"
222 	"pa1lomaxpwr=0x3c\0"
223 	"pa1himaxpwr=0x3c\0"
224 	"bxa2g=0x3\0"
225 	"rssisav2g=0x7\0"
226 	"rssismc2g=0xf\0"
227 	"rssismf2g=0xf\0"
228 	"bxa5g=0x3\0"
229 	"rssisav5g=0x7\0"
230 	"rssismc5g=0xf\0"
231 	"rssismf5g=0xf\0"
232 	"tri2g=0xff\0"
233 	"tri5g=0xff\0"
234 	"tri5gl=0xff\0"
235 	"tri5gh=0xff\0"
236 	"rxpo2g=0xff\0"
237 	"rxpo5g=0xff\0"
238 	"txchain=0x7\0"
239 	"rxchain=0x7\0"
240 	"antswitch=0x0\0"
241 	"tssipos2g=0x1\0"
242 	"extpagain2g=0x2\0"
243 	"pdetrange2g=0x4\0"
244 	"triso2g=0x3\0"
245 	"antswctl2g=0x0\0"
246 	"tssipos5g=0x1\0"
247 	"elna2g=0xff\0"
248 	"extpagain5g=0x2\0"
249 	"pdetrange5g=0x4\0"
250 	"triso5g=0x3\0"
251 	"antswctl5g=0x0\0"
252 	"elna5g=0xff\0"
253 	"cckbw202gpo=0x0\0"
254 	"cckbw20ul2gpo=0x0\0"
255 	"legofdmbw202gpo=0x0\0"
256 	"legofdmbw20ul2gpo=0x0\0"
257 	"legofdmbw205glpo=0x0\0"
258 	"legofdmbw20ul5glpo=0x0\0"
259 	"legofdmbw205gmpo=0x0\0"
260 	"legofdmbw20ul5gmpo=0x0\0"
261 	"legofdmbw205ghpo=0x0\0"
262 	"legofdmbw20ul5ghpo=0x0\0"
263 	"mcsbw202gpo=0x0\0"
264 	"mcsbw20ul2gpo=0x0\0"
265 	"mcsbw402gpo=0x0\0"
266 	"mcsbw205glpo=0x0\0"
267 	"mcsbw20ul5glpo=0x0\0"
268 	"mcsbw405glpo=0x0\0"
269 	"mcsbw205gmpo=0x0\0"
270 	"mcsbw20ul5gmpo=0x0\0"
271 	"mcsbw405gmpo=0x0\0"
272 	"mcsbw205ghpo=0x0\0"
273 	"mcsbw20ul5ghpo=0x0\0"
274 	"mcsbw405ghpo=0x0\0"
275 	"mcs32po=0x0\0"
276 	"legofdm40duppo=0x0\0"
277 	"maxp2ga0=0x48\0"
278 	"itt2ga0=0x20\0"
279 	"itt5ga0=0x3e\0"
280 	"pa2gw0a0=0xfe7f\0"
281 	"pa2gw1a0=0x15d9\0"
282 	"pa2gw2a0=0xfac6\0"
283 	"maxp5ga0=0x3c\0"
284 	"maxp5gha0=0x3c\0"
285 	"maxp5gla0=0x3c\0"
286 	"pa5gw0a0=0xfe89\0"
287 	"pa5gw1a0=0x14b1\0"
288 	"pa5gw2a0=0xfada\0"
289 	"pa5glw0a0=0xffff\0"
290 	"pa5glw1a0=0xffff\0"
291 	"pa5glw2a0=0xffff\0"
292 	"pa5ghw0a0=0xfe8f\0"
293 	"pa5ghw1a0=0x13df\0"
294 	"pa5ghw2a0=0xfafa\0"
295 	"maxp2ga1=0x48\0"
296 	"itt2ga1=0x20\0"
297 	"itt5ga1=0x3e\0"
298 	"pa2gw0a1=0xfe54\0"
299 	"pa2gw1a1=0x1563\0"
300 	"pa2gw2a1=0xfa7f\0"
301 	"maxp5ga1=0x3c\0"
302 	"maxp5gha1=0x3c\0"
303 	"maxp5gla1=0x3c\0"
304 	"pa5gw0a1=0xfe53\0"
305 	"pa5gw1a1=0x14fe\0"
306 	"pa5gw2a1=0xfa94\0"
307 	"pa5glw0a1=0xffff\0"
308 	"pa5glw1a1=0xffff\0"
309 	"pa5glw2a1=0xffff\0"
310 	"pa5ghw0a1=0xfe6e\0"
311 	"pa5ghw1a1=0x1457\0"
312 	"pa5ghw2a1=0xfab9\0"
313 	"END\0";
314 
315 static char BCMATTACHDATA(defaultsromvars_4360)[] =
316 	"sromrev=11\0"
317 	"boardrev=0x1421\0"
318 	"boardflags=0x10401001\0"
319 	"boardflags2=0x0\0"
320 	"boardtype=0x61b\0"
321 	"subvid=0x14e4\0"
322 	"boardflags3=0x1\0"
323 	"boardnum=62526\0"
324 	"macaddr=00:90:4c:0d:f4:3e\0"
325 	"ccode=X0\0"
326 	"regrev=15\0"
327 	"aa2g=7\0"
328 	"aa5g=7\0"
329 	"agbg0=71\0"
330 	"agbg1=71\0"
331 	"agbg2=133\0"
332 	"aga0=71\0"
333 	"aga1=133\0"
334 	"aga2=133\0"
335 	"antswitch=0\0"
336 	"tssiposslope2g=1\0"
337 	"epagain2g=0\0"
338 	"pdgain2g=9\0"
339 	"tworangetssi2g=0\0"
340 	"papdcap2g=0\0"
341 	"femctrl=2\0"
342 	"tssiposslope5g=1\0"
343 	"epagain5g=0\0"
344 	"pdgain5g=9\0"
345 	"tworangetssi5g=0\0"
346 	"papdcap5g=0\0"
347 	"gainctrlsph=0\0"
348 	"tempthresh=255\0"
349 	"tempoffset=255\0"
350 	"rawtempsense=0x1ff\0"
351 	"measpower=0x7f\0"
352 	"tempsense_slope=0xff\0"
353 	"tempcorrx=0x3f\0"
354 	"tempsense_option=0x3\0"
355 	"xtalfreq=65535\0"
356 	"phycal_tempdelta=255\0"
357 	"temps_period=15\0"
358 	"temps_hysteresis=15\0"
359 	"measpower1=0x7f\0"
360 	"measpower2=0x7f\0"
361 	"pdoffset2g40ma0=15\0"
362 	"pdoffset2g40ma1=15\0"
363 	"pdoffset2g40ma2=15\0"
364 	"pdoffset2g40mvalid=1\0"
365 	"pdoffset40ma0=9010\0"
366 	"pdoffset40ma1=12834\0"
367 	"pdoffset40ma2=8994\0"
368 	"pdoffset80ma0=16\0"
369 	"pdoffset80ma1=4096\0"
370 	"pdoffset80ma2=0\0"
371 	"subband5gver=0x4\0"
372 	"cckbw202gpo=0\0"
373 	"cckbw20ul2gpo=0\0"
374 	"mcsbw202gpo=2571386880\0"
375 	"mcsbw402gpo=2571386880\0"
376 	"dot11agofdmhrbw202gpo=17408\0"
377 	"ofdmlrbw202gpo=0\0"
378 	"mcsbw205glpo=4001923072\0"
379 	"mcsbw405glpo=4001923072\0"
380 	"mcsbw805glpo=4001923072\0"
381 	"mcsbw1605glpo=0\0"
382 	"mcsbw205gmpo=3431497728\0"
383 	"mcsbw405gmpo=3431497728\0"
384 	"mcsbw805gmpo=3431497728\0"
385 	"mcsbw1605gmpo=0\0"
386 	"mcsbw205ghpo=3431497728\0"
387 	"mcsbw405ghpo=3431497728\0"
388 	"mcsbw805ghpo=3431497728\0"
389 	"mcsbw1605ghpo=0\0"
390 	"mcslr5glpo=0\0"
391 	"mcslr5gmpo=0\0"
392 	"mcslr5ghpo=0\0"
393 	"sb20in40hrpo=0\0"
394 	"sb20in80and160hr5glpo=0\0"
395 	"sb40and80hr5glpo=0\0"
396 	"sb20in80and160hr5gmpo=0\0"
397 	"sb40and80hr5gmpo=0\0"
398 	"sb20in80and160hr5ghpo=0\0"
399 	"sb40and80hr5ghpo=0\0"
400 	"sb20in40lrpo=0\0"
401 	"sb20in80and160lr5glpo=0\0"
402 	"sb40and80lr5glpo=0\0"
403 	"sb20in80and160lr5gmpo=0\0"
404 	"sb40and80lr5gmpo=0\0"
405 	"sb20in80and160lr5ghpo=0\0"
406 	"sb40and80lr5ghpo=0\0"
407 	"dot11agduphrpo=0\0"
408 	"dot11agduplrpo=0\0"
409 	"pcieingress_war=15\0"
410 	"sar2g=18\0"
411 	"sar5g=15\0"
412 	"noiselvl2ga0=31\0"
413 	"noiselvl2ga1=31\0"
414 	"noiselvl2ga2=31\0"
415 	"noiselvl5ga0=31,31,31,31\0"
416 	"noiselvl5ga1=31,31,31,31\0"
417 	"noiselvl5ga2=31,31,31,31\0"
418 	"rxgainerr2ga0=63\0"
419 	"rxgainerr2ga1=31\0"
420 	"rxgainerr2ga2=31\0"
421 	"rxgainerr5ga0=63,63,63,63\0"
422 	"rxgainerr5ga1=31,31,31,31\0"
423 	"rxgainerr5ga2=31,31,31,31\0"
424 	"maxp2ga0=76\0"
425 	"pa2ga0=0xff3c,0x172c,0xfd20\0"
426 	"rxgains5gmelnagaina0=7\0"
427 	"rxgains5gmtrisoa0=15\0"
428 	"rxgains5gmtrelnabypa0=1\0"
429 	"rxgains5ghelnagaina0=7\0"
430 	"rxgains5ghtrisoa0=15\0"
431 	"rxgains5ghtrelnabypa0=1\0"
432 	"rxgains2gelnagaina0=4\0"
433 	"rxgains2gtrisoa0=7\0"
434 	"rxgains2gtrelnabypa0=1\0"
435 	"rxgains5gelnagaina0=3\0"
436 	"rxgains5gtrisoa0=7\0"
437 	"rxgains5gtrelnabypa0=1\0"
438 	"maxp5ga0=76,76,76,76\0"
439 "pa5ga0=0xff3a,0x14d4,0xfd5f,0xff36,0x1626,0xfd2e,0xff42,0x15bd,0xfd47,0xff39,0x15a3,0xfd3d\0"
440 	"maxp2ga1=76\0"
441 	"pa2ga1=0xff2a,0x16b2,0xfd28\0"
442 	"rxgains5gmelnagaina1=7\0"
443 	"rxgains5gmtrisoa1=15\0"
444 	"rxgains5gmtrelnabypa1=1\0"
445 	"rxgains5ghelnagaina1=7\0"
446 	"rxgains5ghtrisoa1=15\0"
447 	"rxgains5ghtrelnabypa1=1\0"
448 	"rxgains2gelnagaina1=3\0"
449 	"rxgains2gtrisoa1=6\0"
450 	"rxgains2gtrelnabypa1=1\0"
451 	"rxgains5gelnagaina1=3\0"
452 	"rxgains5gtrisoa1=6\0"
453 	"rxgains5gtrelnabypa1=1\0"
454 	"maxp5ga1=76,76,76,76\0"
455 "pa5ga1=0xff4e,0x1530,0xfd53,0xff58,0x15b4,0xfd4d,0xff58,0x1671,0xfd2f,0xff55,0x15e2,0xfd46\0"
456 	"maxp2ga2=76\0"
457 	"pa2ga2=0xff3c,0x1736,0xfd1f\0"
458 	"rxgains5gmelnagaina2=7\0"
459 	"rxgains5gmtrisoa2=15\0"
460 	"rxgains5gmtrelnabypa2=1\0"
461 	"rxgains5ghelnagaina2=7\0"
462 	"rxgains5ghtrisoa2=15\0"
463 	"rxgains5ghtrelnabypa2=1\0"
464 	"rxgains2gelnagaina2=4\0"
465 	"rxgains2gtrisoa2=7\0"
466 	"rxgains2gtrelnabypa2=1\0"
467 	"rxgains5gelnagaina2=3\0"
468 	"rxgains5gtrisoa2=7\0"
469 	"rxgains5gtrelnabypa2=1\0"
470 	"maxp5ga2=76,76,76,76\0"
471 "pa5ga2=0xff2d,0x144a,0xfd63,0xff35,0x15d7,0xfd3b,0xff35,0x1668,0xfd2f,0xff31,0x1664,0xfd27\0"
472 	"END\0";
473 
474 #endif /* defined(BCMHOSTVARS) */
475 #endif /* !defined(BCMDONGLEHOST) */
476 
477 #if !defined(BCMDONGLEHOST)
478 #if defined(BCMHOSTVARS)
479 static char BCMATTACHDATA(defaultsromvars_wltest)[] =
480 	"macaddr=00:90:4c:f8:00:01\0"
481 	"et0macaddr=00:11:22:33:44:52\0"
482 	"et0phyaddr=30\0"
483 	"et0mdcport=0\0"
484 	"gpio2=robo_reset\0"
485 	"boardvendor=0x14e4\0"
486 	"boardflags=0x210\0"
487 	"boardflags2=0\0"
488 	"boardtype=0x04c3\0"
489 	"boardrev=0x1100\0"
490 	"sromrev=8\0"
491 	"devid=0x432c\0"
492 	"ccode=0\0"
493 	"regrev=0\0"
494 	"aa2g=3\0"
495 	"ag0=2\0"
496 	"ag1=2\0"
497 	"aa5g=3\0"
498 	"aa0=2\0"
499 	"aa1=2\0"
500 	"txchain=3\0"
501 	"rxchain=3\0"
502 	"antswitch=0\0"
503 	"itt2ga0=0x20\0"
504 	"maxp2ga0=0x48\0"
505 	"pa2gw0a0=0xfe9e\0"
506 	"pa2gw1a0=0x15d5\0"
507 	"pa2gw2a0=0xfae9\0"
508 	"itt2ga1=0x20\0"
509 	"maxp2ga1=0x48\0"
510 	"pa2gw0a1=0xfeb3\0"
511 	"pa2gw1a1=0x15c9\0"
512 	"pa2gw2a1=0xfaf7\0"
513 	"tssipos2g=1\0"
514 	"extpagain2g=0\0"
515 	"pdetrange2g=0\0"
516 	"triso2g=3\0"
517 	"antswctl2g=0\0"
518 	"tssipos5g=1\0"
519 	"extpagain5g=0\0"
520 	"pdetrange5g=0\0"
521 	"triso5g=3\0"
522 	"antswctl5g=0\0"
523 	"cck2gpo=0\0"
524 	"ofdm2gpo=0\0"
525 	"mcs2gpo0=0\0"
526 	"mcs2gpo1=0\0"
527 	"mcs2gpo2=0\0"
528 	"mcs2gpo3=0\0"
529 	"mcs2gpo4=0\0"
530 	"mcs2gpo5=0\0"
531 	"mcs2gpo6=0\0"
532 	"mcs2gpo7=0\0"
533 	"cddpo=0\0"
534 	"stbcpo=0\0"
535 	"bw40po=4\0"
536 	"bwduppo=0\0"
537 	"END\0";
538 
539 /**
540  * The contents of this array is a first attempt, is likely incorrect for 43602, needs to be
541  * edited in a later stage.
542  */
543 static char BCMATTACHDATA(defaultsromvars_43602)[] =
544 	"sromrev=11\0"
545 	"boardrev=0x1421\0"
546 	"boardflags=0x10401001\0"
547 	"boardflags2=0x00000002\0"
548 	"boardflags3=0x00000003\0"
549 	"boardtype=0x61b\0"
550 	"subvid=0x14e4\0"
551 	"boardnum=62526\0"
552 	"macaddr=00:90:4c:0d:f4:3e\0"
553 	"ccode=X0\0"
554 	"regrev=15\0"
555 	"aa2g=7\0"
556 	"aa5g=7\0"
557 	"agbg0=71\0"
558 	"agbg1=71\0"
559 	"agbg2=133\0"
560 	"aga0=71\0"
561 	"aga1=133\0"
562 	"aga2=133\0"
563 	"antswitch=0\0"
564 	"tssiposslope2g=1\0"
565 	"epagain2g=0\0"
566 	"pdgain2g=9\0"
567 	"tworangetssi2g=0\0"
568 	"papdcap2g=0\0"
569 	"femctrl=2\0"
570 	"tssiposslope5g=1\0"
571 	"epagain5g=0\0"
572 	"pdgain5g=9\0"
573 	"tworangetssi5g=0\0"
574 	"papdcap5g=0\0"
575 	"gainctrlsph=0\0"
576 	"tempthresh=255\0"
577 	"tempoffset=255\0"
578 	"rawtempsense=0x1ff\0"
579 	"measpower=0x7f\0"
580 	"tempsense_slope=0xff\0"
581 	"tempcorrx=0x3f\0"
582 	"tempsense_option=0x3\0"
583 	"xtalfreq=40000\0"
584 	"phycal_tempdelta=255\0"
585 	"temps_period=15\0"
586 	"temps_hysteresis=15\0"
587 	"measpower1=0x7f\0"
588 	"measpower2=0x7f\0"
589 	"pdoffset2g40ma0=15\0"
590 	"pdoffset2g40ma1=15\0"
591 	"pdoffset2g40ma2=15\0"
592 	"pdoffset2g40mvalid=1\0"
593 	"pdoffset40ma0=9010\0"
594 	"pdoffset40ma1=12834\0"
595 	"pdoffset40ma2=8994\0"
596 	"pdoffset80ma0=16\0"
597 	"pdoffset80ma1=4096\0"
598 	"pdoffset80ma2=0\0"
599 	"subband5gver=0x4\0"
600 	"cckbw202gpo=0\0"
601 	"cckbw20ul2gpo=0\0"
602 	"mcsbw202gpo=2571386880\0"
603 	"mcsbw402gpo=2571386880\0"
604 	"dot11agofdmhrbw202gpo=17408\0"
605 	"ofdmlrbw202gpo=0\0"
606 	"mcsbw205glpo=4001923072\0"
607 	"mcsbw405glpo=4001923072\0"
608 	"mcsbw805glpo=4001923072\0"
609 	"mcsbw1605glpo=0\0"
610 	"mcsbw205gmpo=3431497728\0"
611 	"mcsbw405gmpo=3431497728\0"
612 	"mcsbw805gmpo=3431497728\0"
613 	"mcsbw1605gmpo=0\0"
614 	"mcsbw205ghpo=3431497728\0"
615 	"mcsbw405ghpo=3431497728\0"
616 	"mcsbw805ghpo=3431497728\0"
617 	"mcsbw1605ghpo=0\0"
618 	"mcslr5glpo=0\0"
619 	"mcslr5gmpo=0\0"
620 	"mcslr5ghpo=0\0"
621 	"sb20in40hrpo=0\0"
622 	"sb20in80and160hr5glpo=0\0"
623 	"sb40and80hr5glpo=0\0"
624 	"sb20in80and160hr5gmpo=0\0"
625 	"sb40and80hr5gmpo=0\0"
626 	"sb20in80and160hr5ghpo=0\0"
627 	"sb40and80hr5ghpo=0\0"
628 	"sb20in40lrpo=0\0"
629 	"sb20in80and160lr5glpo=0\0"
630 	"sb40and80lr5glpo=0\0"
631 	"sb20in80and160lr5gmpo=0\0"
632 	"sb40and80lr5gmpo=0\0"
633 	"sb20in80and160lr5ghpo=0\0"
634 	"sb40and80lr5ghpo=0\0"
635 	"dot11agduphrpo=0\0"
636 	"dot11agduplrpo=0\0"
637 	"pcieingress_war=15\0"
638 	"sar2g=18\0"
639 	"sar5g=15\0"
640 	"noiselvl2ga0=31\0"
641 	"noiselvl2ga1=31\0"
642 	"noiselvl2ga2=31\0"
643 	"noiselvl5ga0=31,31,31,31\0"
644 	"noiselvl5ga1=31,31,31,31\0"
645 	"noiselvl5ga2=31,31,31,31\0"
646 	"rxgainerr2ga0=63\0"
647 	"rxgainerr2ga1=31\0"
648 	"rxgainerr2ga2=31\0"
649 	"rxgainerr5ga0=63,63,63,63\0"
650 	"rxgainerr5ga1=31,31,31,31\0"
651 	"rxgainerr5ga2=31,31,31,31\0"
652 	"maxp2ga0=76\0"
653 	"pa2ga0=0xff3c,0x172c,0xfd20\0"
654 	"rxgains5gmelnagaina0=7\0"
655 	"rxgains5gmtrisoa0=15\0"
656 	"rxgains5gmtrelnabypa0=1\0"
657 	"rxgains5ghelnagaina0=7\0"
658 	"rxgains5ghtrisoa0=15\0"
659 	"rxgains5ghtrelnabypa0=1\0"
660 	"rxgains2gelnagaina0=4\0"
661 	"rxgains2gtrisoa0=7\0"
662 	"rxgains2gtrelnabypa0=1\0"
663 	"rxgains5gelnagaina0=3\0"
664 	"rxgains5gtrisoa0=7\0"
665 	"rxgains5gtrelnabypa0=1\0"
666 	"maxp5ga0=76,76,76,76\0"
667 "pa5ga0=0xff3a,0x14d4,0xfd5f,0xff36,0x1626,0xfd2e,0xff42,0x15bd,0xfd47,0xff39,0x15a3,0xfd3d\0"
668 	"maxp2ga1=76\0"
669 	"pa2ga1=0xff2a,0x16b2,0xfd28\0"
670 	"rxgains5gmelnagaina1=7\0"
671 	"rxgains5gmtrisoa1=15\0"
672 	"rxgains5gmtrelnabypa1=1\0"
673 	"rxgains5ghelnagaina1=7\0"
674 	"rxgains5ghtrisoa1=15\0"
675 	"rxgains5ghtrelnabypa1=1\0"
676 	"rxgains2gelnagaina1=3\0"
677 	"rxgains2gtrisoa1=6\0"
678 	"rxgains2gtrelnabypa1=1\0"
679 	"rxgains5gelnagaina1=3\0"
680 	"rxgains5gtrisoa1=6\0"
681 	"rxgains5gtrelnabypa1=1\0"
682 	"maxp5ga1=76,76,76,76\0"
683 "pa5ga1=0xff4e,0x1530,0xfd53,0xff58,0x15b4,0xfd4d,0xff58,0x1671,0xfd2f,0xff55,0x15e2,0xfd46\0"
684 	"maxp2ga2=76\0"
685 	"pa2ga2=0xff3c,0x1736,0xfd1f\0"
686 	"rxgains5gmelnagaina2=7\0"
687 	"rxgains5gmtrisoa2=15\0"
688 	"rxgains5gmtrelnabypa2=1\0"
689 	"rxgains5ghelnagaina2=7\0"
690 	"rxgains5ghtrisoa2=15\0"
691 	"rxgains5ghtrelnabypa2=1\0"
692 	"rxgains2gelnagaina2=4\0"
693 	"rxgains2gtrisoa2=7\0"
694 	"rxgains2gtrelnabypa2=1\0"
695 	"rxgains5gelnagaina2=3\0"
696 	"rxgains5gtrisoa2=7\0"
697 	"rxgains5gtrelnabypa2=1\0"
698 	"maxp5ga2=76,76,76,76\0"
699 "pa5ga2=0xff2d,0x144a,0xfd63,0xff35,0x15d7,0xfd3b,0xff35,0x1668,0xfd2f,0xff31,0x1664,0xfd27\0"
700 	"END\0";
701 
702 /**
703  * The contents of this array is a first attempt, was copied from 4378, needs to be edited in
704  * a later stage.
705  */
706 static char BCMATTACHDATA(defaultsromvars_4378)[] =
707 	"cckdigfilttype=4\0"
708 	"sromrev=11\0"
709 	"boardrev=0x1102\0"
710 	"boardtype=0x0771\0"
711 	"boardflags=0x10481201\0"
712 	"boardflags2=0x00000000\0"
713 	"boardflags3=0x04000080\0"
714 	"macaddr=00:90:4c:12:43:47\0"
715 	"ccode=0\0"
716 	"regrev=0\0"
717 	"antswitch=0\0"
718 	"pdgain5g=0\0"
719 	"pdgain2g=0\0"
720 	"tworangetssi2g=0\0"
721 	"tworangetssi5g=0\0"
722 	"femctrl=16\0"
723 	"vendid=0x14e4\0"
724 	"devid=0x4425\0"
725 	"manfid=0x2d0\0"
726 	"nocrc=1\0"
727 	"btc_params82=0x1a0\0"
728 	"otpimagesize=502\0"
729 	"xtalfreq=37400\0"
730 	"rxgains2gelnagaina0=3\0"
731 	"rxgains2gtrisoa0=7\0"
732 	"rxgains2gtrelnabypa0=1\0"
733 	"rxgains5gelnagaina0=3\0"
734 	"rxgains5gtrisoa0=6\0"
735 	"rxgains5gtrelnabypa0=1\0"
736 	"rxgains5gmelnagaina0=3\0"
737 	"rxgains5gmtrisoa0=6\0"
738 	"rxgains5gmtrelnabypa0=1\0"
739 	"rxgains5ghelnagaina0=3\0"
740 	"rxgains5ghtrisoa0=6\0"
741 	"rxgains5ghtrelnabypa0=1\0"
742 	"rxgains2gelnagaina1=3\0"
743 	"rxgains2gtrisoa1=7\0"
744 	"rxgains2gtrelnabypa1=1\0"
745 	"rxgains5gelnagaina1=3\0"
746 	"rxgains5gtrisoa1=6\0"
747 	"rxgains5gtrelnabypa1=1\0"
748 	"rxgains5gmelnagaina1=3\0"
749 	"rxgains5gmtrisoa1=6\0"
750 	"rxgains5gmtrelnabypa1=1\0"
751 	"rxgains5ghelnagaina1=3\0"
752 	"rxgains5ghtrisoa1=6\0"
753 	"rxgains5ghtrelnabypa1=1\0"
754 	"rxchain=3\0"
755 	"txchain=3\0"
756 	"aa2g=3\0"
757 	"aa5g=3\0"
758 	"agbg0=2\0"
759 	"agbg1=2\0"
760 	"aga0=2\0"
761 	"aga1=2\0"
762 	"tssipos2g=1\0"
763 	"tssipos5g=1\0"
764 	"tempthresh=255\0"
765 	"tempoffset=255\0"
766 	"rawtempsense=0x1ff\0"
767 	"pa2gccka0=-200,7392,-897\0"
768 	"pa2gccka1=-198,7522,-907\0"
769 	"pa2ga0=-174,7035,-838\0"
770 	"pa2ga1=-185,6772,-811\0"
771 	"pa5ga0=-175,7296,-887,-164,7553,-910,-155,7801,-936,-149,7908,-951\0"
772 	"pa5ga1=-155,7675,-925,-148,7851,-940,-152,7930,-954,-143,8121,-969\0"
773 	"pa5gbw4080a0=-178,7872,-959,-173,8107,-986,-165,8398,-1019,-150,8809,-1063\0"
774 	"pa5gbw4080a1=-166,8179,-993,-161,8378,-1015,-165,8402,-1019,-155,8757,-1057\0"
775 	"maxp2ga0=66\0"
776 	"maxp2ga1=66\0"
777 	"maxp5ga0=66,66,66,66\0"
778 	"maxp5ga1=66,66,66,66\0"
779 	"subband5gver=0x4\0"
780 	"paparambwver=3\0"
781 	"cckpwroffset0=0\0"
782 	"cckpwroffset1=0\0"
783 	"pdoffset40ma0=0x0000\0"
784 	"pdoffset80ma0=0xeeee\0"
785 	"pdoffset40ma1=0x0000\0"
786 	"pdoffset80ma1=0xeeee\0"
787 	"cckbw202gpo=0\0"
788 	"cckbw20ul2gpo=0\0"
789 	"mcsbw202gpo=0xEC888222\0"
790 	"mcsbw402gpo=0xEC888222\0"
791 	"dot11agofdmhrbw202gpo=0x6622\0"
792 	"ofdmlrbw202gpo=0x0000\0"
793 	"mcsbw205glpo=0xCA666000\0"
794 	"mcsbw405glpo=0xCA666000\0"
795 	"mcsbw805glpo=0xEA666000\0"
796 	"mcsbw1605glpo=0\0"
797 	"mcsbw205gmpo=0xCA666000\0"
798 	"mcsbw405gmpo=0xCA666000\0"
799 	"mcsbw805gmpo=0xEA666000\0"
800 	"mcsbw1605gmpo=0\0"
801 	"mcsbw205ghpo=0xCA666000\0"
802 	"mcsbw405ghpo=0xCA666000\0"
803 	"mcsbw805ghpo=0xEA666000\0"
804 	"mcsbw1605ghpo=0\0"
805 	"mcslr5glpo=0x0000\0"
806 	"mcslr5gmpo=0x0000\0"
807 	"mcslr5ghpo=0x0000\0"
808 	"sb20in40hrpo=0x0\0"
809 	"sb20in80and160hr5glpo=0x0\0"
810 	"sb40and80hr5glpo=0x0\0"
811 	"sb20in80and160hr5gmpo=0x0\0"
812 	"sb40and80hr5gmpo=0x0\0"
813 	"sb20in80and160hr5ghpo=0x0\0"
814 	"sb40and80hr5ghpo=0x0\0"
815 	"sb20in40lrpo=0x0\0"
816 	"sb20in80and160lr5glpo=0x0\0"
817 	"sb40and80lr5glpo=0x0\0"
818 	"sb20in80and160lr5gmpo=0x0\0"
819 	"sb40and80lr5gmpo=0x0\0"
820 	"sb20in80and160lr5ghpo=0x0\0"
821 	"sb40and80lr5ghpo=0x0\0"
822 	"dot11agduphrpo=0x0\0"
823 	"dot11agduplrpo=0x0\0"
824 	"phycal_tempdelta=15\0"
825 	"temps_period=15\0"
826 	"temps_hysteresis=15\0"
827 	"swctrlmap_2g=0x00000404,0x0a0a0000,0x02020000,0x010a02,0x1fe\0"
828 	"swctrlmapext_2g=0x00000000,0x00000000,0x00000000,0x000000,0x000\0"
829 	"swctrlmap_5g=0x00001010,0x60600000,0x40400000,0x000000,0x0f0\0"
830 	"swctrlmapext_5g=0x00000000,0x00000000,0x00000000,0x000000,0x000\0"
831 	"powoffs2gtna0=1,3,3,1,0,0,1,2,2,2,1,1,0,0\0"
832 	"powoffs2gtna1=-1,1,1,1,0,0,1,2,3,2,2,0,0,0\0"
833 	"END\0";
834 
835 /**
836  * The contents of this array is a first attempt, was copied from 4387, needs to be edited in
837  * a later stage.
838  */
839 static char BCMATTACHDATA(defaultsromvars_4387)[] =
840 	"cckdigfilttype=4\0"
841 	"sromrev=11\0"
842 	"boardrev=0x1102\0"
843 	"boardtype=0x0771\0"
844 	"boardflags=0x10481201\0"
845 	"boardflags2=0x00000000\0"
846 	"boardflags3=0x04000080\0"
847 	"macaddr=00:90:4c:12:43:47\0"
848 	"ccode=0\0"
849 	"regrev=0\0"
850 	"antswitch=0\0"
851 	"pdgain5g=0\0"
852 	"pdgain2g=0\0"
853 	"tworangetssi2g=0\0"
854 	"tworangetssi5g=0\0"
855 	"femctrl=16\0"
856 	"vendid=0x14e4\0"
857 	"devid=0x4425\0"
858 	"manfid=0x2d0\0"
859 	"nocrc=1\0"
860 	"btc_params82=0x1a0\0"
861 	"otpimagesize=502\0"
862 	"xtalfreq=37400\0"
863 	"rxgains2gelnagaina0=3\0"
864 	"rxgains2gtrisoa0=7\0"
865 	"rxgains2gtrelnabypa0=1\0"
866 	"rxgains5gelnagaina0=3\0"
867 	"rxgains5gtrisoa0=6\0"
868 	"rxgains5gtrelnabypa0=1\0"
869 	"rxgains5gmelnagaina0=3\0"
870 	"rxgains5gmtrisoa0=6\0"
871 	"rxgains5gmtrelnabypa0=1\0"
872 	"rxgains5ghelnagaina0=3\0"
873 	"rxgains5ghtrisoa0=6\0"
874 	"rxgains5ghtrelnabypa0=1\0"
875 	"rxgains2gelnagaina1=3\0"
876 	"rxgains2gtrisoa1=7\0"
877 	"rxgains2gtrelnabypa1=1\0"
878 	"rxgains5gelnagaina1=3\0"
879 	"rxgains5gtrisoa1=6\0"
880 	"rxgains5gtrelnabypa1=1\0"
881 	"rxgains5gmelnagaina1=3\0"
882 	"rxgains5gmtrisoa1=6\0"
883 	"rxgains5gmtrelnabypa1=1\0"
884 	"rxgains5ghelnagaina1=3\0"
885 	"rxgains5ghtrisoa1=6\0"
886 	"rxgains5ghtrelnabypa1=1\0"
887 	"rxchain=3\0"
888 	"txchain=3\0"
889 	"aa2g=3\0"
890 	"aa5g=3\0"
891 	"agbg0=2\0"
892 	"agbg1=2\0"
893 	"aga0=2\0"
894 	"aga1=2\0"
895 	"tssipos2g=1\0"
896 	"tssipos5g=1\0"
897 	"tempthresh=255\0"
898 	"tempoffset=255\0"
899 	"rawtempsense=0x1ff\0"
900 	"pa2gccka0=-200,7392,-897\0"
901 	"pa2gccka1=-198,7522,-907\0"
902 	"pa2ga0=-174,7035,-838\0"
903 	"pa2ga1=-185,6772,-811\0"
904 	"pa5ga0=-175,7296,-887,-164,7553,-910,-155,7801,-936,-149,7908,-951\0"
905 	"pa5ga1=-155,7675,-925,-148,7851,-940,-152,7930,-954,-143,8121,-969\0"
906 	"pa5gbw4080a0=-178,7872,-959,-173,8107,-986,-165,8398,-1019,-150,8809,-1063\0"
907 	"pa5gbw4080a1=-166,8179,-993,-161,8378,-1015,-165,8402,-1019,-155,8757,-1057\0"
908 	"maxp2ga0=66\0"
909 	"maxp2ga1=66\0"
910 	"maxp5ga0=66,66,66,66\0"
911 	"maxp5ga1=66,66,66,66\0"
912 	"subband5gver=0x4\0"
913 	"paparambwver=3\0"
914 	"cckpwroffset0=0\0"
915 	"cckpwroffset1=0\0"
916 	"pdoffset40ma0=0x0000\0"
917 	"pdoffset80ma0=0xeeee\0"
918 	"pdoffset40ma1=0x0000\0"
919 	"pdoffset80ma1=0xeeee\0"
920 	"cckbw202gpo=0\0"
921 	"cckbw20ul2gpo=0\0"
922 	"mcsbw202gpo=0xEC888222\0"
923 	"mcsbw402gpo=0xEC888222\0"
924 	"dot11agofdmhrbw202gpo=0x6622\0"
925 	"ofdmlrbw202gpo=0x0000\0"
926 	"mcsbw205glpo=0xCA666000\0"
927 	"mcsbw405glpo=0xCA666000\0"
928 	"mcsbw805glpo=0xEA666000\0"
929 	"mcsbw1605glpo=0\0"
930 	"mcsbw205gmpo=0xCA666000\0"
931 	"mcsbw405gmpo=0xCA666000\0"
932 	"mcsbw805gmpo=0xEA666000\0"
933 	"mcsbw1605gmpo=0\0"
934 	"mcsbw205ghpo=0xCA666000\0"
935 	"mcsbw405ghpo=0xCA666000\0"
936 	"mcsbw805ghpo=0xEA666000\0"
937 	"mcsbw1605ghpo=0\0"
938 	"mcslr5glpo=0x0000\0"
939 	"mcslr5gmpo=0x0000\0"
940 	"mcslr5ghpo=0x0000\0"
941 	"sb20in40hrpo=0x0\0"
942 	"sb20in80and160hr5glpo=0x0\0"
943 	"sb40and80hr5glpo=0x0\0"
944 	"sb20in80and160hr5gmpo=0x0\0"
945 	"sb40and80hr5gmpo=0x0\0"
946 	"sb20in80and160hr5ghpo=0x0\0"
947 	"sb40and80hr5ghpo=0x0\0"
948 	"sb20in40lrpo=0x0\0"
949 	"sb20in80and160lr5glpo=0x0\0"
950 	"sb40and80lr5glpo=0x0\0"
951 	"sb20in80and160lr5gmpo=0x0\0"
952 	"sb40and80lr5gmpo=0x0\0"
953 	"sb20in80and160lr5ghpo=0x0\0"
954 	"sb40and80lr5ghpo=0x0\0"
955 	"dot11agduphrpo=0x0\0"
956 	"dot11agduplrpo=0x0\0"
957 	"phycal_tempdelta=15\0"
958 	"temps_period=15\0"
959 	"temps_hysteresis=15\0"
960 	"swctrlmap_2g=0x00000404,0x0a0a0000,0x02020000,0x010a02,0x1fe\0"
961 	"swctrlmapext_2g=0x00000000,0x00000000,0x00000000,0x000000,0x000\0"
962 	"swctrlmap_5g=0x00001010,0x60600000,0x40400000,0x000000,0x0f0\0"
963 	"swctrlmapext_5g=0x00000000,0x00000000,0x00000000,0x000000,0x000\0"
964 	"powoffs2gtna0=1,3,3,1,0,0,1,2,2,2,1,1,0,0\0"
965 	"powoffs2gtna1=-1,1,1,1,0,0,1,2,3,2,2,0,0,0\0"
966 	"END\0";
967 
968 #endif /* defined(BCMHOSTVARS) */
969 #endif /* !defined(BCMDONGLEHOST) */
970 
971 static bool srvars_inited = FALSE; /* Use OTP/SROM as global variables */
972 
973 #if (!defined(BCMDONGLEHOST) && defined(BCMHOSTVARS))
974 /* It must end with pattern of "END" */
975 static uint
BCMATTACHFN(srom_vars_len)976 BCMATTACHFN(srom_vars_len)(char *vars)
977 {
978 	uint pos = 0;
979 	uint len;
980 	char *s;
981 	char *emark = "END";
982 	uint emark_len = strlen(emark) + 1;
983 
984 	for (s = vars; s && *s;) {
985 
986 		if (strcmp(s, emark) == 0)
987 			break;
988 
989 		len = strlen(s);
990 		s += strlen(s) + 1;
991 		pos += len + 1;
992 		/* BS_ERROR(("len %d vars[pos] %s\n", pos, s)); */
993 		if (pos >= (VARS_MAX - emark_len)) {
994 			return 0;
995 		}
996 	}
997 
998 	return pos + emark_len;	/* include the "END\0" */
999 }
1000 #endif /* BCMHOSTVARS */
1001 
1002 #if !defined(BCMDONGLEHOST)
1003 #ifdef BCMNVRAMVARS
1004 static int
BCMATTACHFN(initvars_nvram_vars)1005 BCMATTACHFN(initvars_nvram_vars)(si_t *sih, osl_t *osh, char **vars, uint *vars_sz)
1006 {
1007 	int ret;
1008 
1009 	ASSERT(vars != NULL && vars_sz != NULL);
1010 
1011 	/* allocate maximum buffer as we don't know big it should be */
1012 	*vars = MALLOC(osh, MAXSZ_NVRAM_VARS);
1013 	if (*vars == NULL) {
1014 		ret = BCME_NOMEM;
1015 		goto fail;
1016 	}
1017 	*vars_sz = MAXSZ_NVRAM_VARS;
1018 
1019 	/* query the name=value pairs */
1020 	if ((ret = nvram_getall(*vars, *vars_sz)) != BCME_OK) {
1021 		goto fail;
1022 	}
1023 
1024 	/* treat empty name=value list as an error so that we can indicate
1025 	 * the condition up throught error code return...
1026 	 */
1027 	if (*vars_sz == 0) {
1028 		ret = BCME_ERROR;
1029 		goto fail;
1030 	}
1031 
1032 	return BCME_OK;
1033 
1034 fail:
1035 	if (*vars != NULL) {
1036 		MFREE(osh, *vars, MAXSZ_NVRAM_VARS);
1037 	}
1038 	*vars = NULL;
1039 	*vars_sz = 0;
1040 	return ret;
1041 }
1042 #endif /* BCMNVRAMVARS */
1043 
1044 /**
1045  * Initialize local vars from the right source for this platform. Called from siutils.c.
1046  *
1047  * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this
1048  *        function set 'vars' to NULL, in that case this function will prematurely return.
1049  *
1050  * Return 0 on success, nonzero on error.
1051  */
1052 int
BCMATTACHFN(srom_var_init)1053 BCMATTACHFN(srom_var_init)(si_t *sih, uint bustype, volatile void *curmap, osl_t *osh,
1054 	char **vars, uint *count)
1055 {
1056 	ASSERT(bustype == BUSTYPE(bustype));
1057 	if (vars == NULL || count == NULL)
1058 		return (0);
1059 
1060 	*vars = NULL;
1061 	*count = 0;
1062 
1063 	switch (BUSTYPE(bustype)) {
1064 	case SI_BUS:
1065 #ifdef BCMPCIEDEV
1066 		if (BCMPCIEDEV_ENAB()) {
1067 			int ret;
1068 
1069 			ret = initvars_cis_pci(sih, osh, curmap, vars, count);
1070 
1071 #ifdef BCMPCIEDEV_SROM_FORMAT
1072 			if (ret)
1073 				ret = initvars_srom_pci(sih, curmap, vars, count);
1074 #endif
1075 			if (ret)
1076 				ret =  initvars_srom_si(sih, osh, curmap, vars, count);
1077 			return ret;
1078 		} else
1079 #endif /* BCMPCIEDEV */
1080 		{
1081 			return initvars_srom_si(sih, osh, curmap, vars, count);
1082 		}
1083 	case PCI_BUS: {
1084 		int ret;
1085 
1086 #ifdef BCMNVRAMVARS
1087 		if ((ret = initvars_nvram_vars(sih, osh, vars, count)) == BCME_OK) {
1088 			return ret;
1089 		} else
1090 #endif
1091 		{
1092 			ASSERT(curmap != NULL);
1093 			if (curmap == NULL)
1094 				return (-1);
1095 
1096 			/* First check for CIS format. if not CIS, try SROM format */
1097 			if ((ret = initvars_cis_pci(sih, osh, curmap, vars, count)))
1098 				return initvars_srom_pci(sih, curmap, vars, count);
1099 			return ret;
1100 		}
1101 	}
1102 
1103 #ifdef BCMSDIO
1104 	case SDIO_BUS:
1105 		return initvars_cis_sdio(sih, osh, vars, count);
1106 #endif /* BCMSDIO */
1107 
1108 #ifdef BCMSPI
1109 	case SPI_BUS:
1110 		return initvars_cis_spi(sih, osh, vars, count);
1111 #endif /* BCMSPI */
1112 
1113 	default:
1114 		ASSERT(0);
1115 	}
1116 	return (-1);
1117 }
1118 #endif /* !defined(BCMDONGLEHOST) */
1119 
1120 /** support only 16-bit word read from srom */
1121 int
srom_read(si_t * sih,uint bustype,volatile void * curmap,osl_t * osh,uint byteoff,uint nbytes,uint16 * buf,bool check_crc)1122 srom_read(si_t *sih, uint bustype, volatile void *curmap, osl_t *osh,
1123           uint byteoff, uint nbytes, uint16 *buf, bool check_crc)
1124 {
1125 	uint i, off, nw;
1126 
1127 	BCM_REFERENCE(i);
1128 
1129 	ASSERT(bustype == BUSTYPE(bustype));
1130 
1131 	/* check input - 16-bit access only */
1132 	if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > SROM_MAX)
1133 		return 1;
1134 
1135 	off = byteoff / 2;
1136 	nw = nbytes / 2;
1137 
1138 #ifdef BCMPCIEDEV
1139 	if ((BUSTYPE(bustype) == SI_BUS) &&
1140 		(BCM43602_CHIP(sih->chip) ||
1141 		(BCM4369_CHIP(sih->chip)) ||
1142 		(BCM4378_CHIP(sih->chip)) ||
1143 		(BCM4387_CHIP(sih->chip)) ||
1144 		(BCM4388_CHIP(sih->chip)) ||
1145 		(BCM4362_CHIP(sih->chip)) ||
1146 		(BCM4385_CHIP(sih->chip)) ||
1147 		(BCM4389_CHIP(sih->chip)) ||
1148 		(BCM4397_CHIP(sih->chip)) ||
1149 
1150 #ifdef UNRELEASEDCHIP
1151 #endif
1152 
1153 	     FALSE)) { /* building firmware for chips with a PCIe interface and internal SI bus */
1154 #else
1155 	if (BUSTYPE(bustype) == PCI_BUS) {
1156 #endif /* BCMPCIEDEV */
1157 		if (!curmap)
1158 			return 1;
1159 
1160 		if (si_is_sprom_available(sih)) {
1161 			volatile uint16 *srom;
1162 
1163 			srom = (volatile uint16 *)srom_offset(sih, curmap);
1164 			if (srom == NULL)
1165 				return 1;
1166 
1167 			if (sprom_read_pci(osh, sih, srom, off, buf, nw, check_crc))
1168 				return 1;
1169 		}
1170 #if !defined(BCMDONGLEHOST) && (defined(BCMNVRAMW) || defined(BCMNVRAMR))
1171 		else if (!((BUSTYPE(bustype) == SI_BUS) &&
1172 			(BCM43602_CHIP(sih->chip) ||
1173 			(BCM4369_CHIP(sih->chip)) ||
1174 			(BCM4362_CHIP(sih->chip)) ||
1175 			(BCM4378_CHIP(sih->chip)) ||
1176 			(BCM4385_CHIP(sih->chip)) ||
1177 			(BCM4389_CHIP(sih->chip)) ||
1178 			(BCM4387_CHIP(sih->chip)) ||
1179 			(BCM4388_CHIP(sih->chip)) ||
1180 			(BCM4397_CHIP(sih->chip)) ||
1181 			0))) {
1182 			if (otp_read_pci(osh, sih, buf, nbytes))
1183 				return 1;
1184 		}
1185 #endif /* !BCMDONGLEHOST && (BCMNVRAMW||BCMNVRAMR) */
1186 #ifdef BCMSDIO
1187 	} else if (BUSTYPE(bustype) == SDIO_BUS) {
1188 		off = byteoff / 2;
1189 		nw = nbytes / 2;
1190 		for (i = 0; i < nw; i++) {
1191 			if (sprom_read_sdio(osh, (uint16)(off + i), (uint16 *)(buf + i)))
1192 				return 1;
1193 		}
1194 #endif /* BCMSDIO */
1195 #ifdef BCMSPI
1196 	} else if (BUSTYPE(bustype) == SPI_BUS) {
1197 		if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, (uint8 *)buf, byteoff + nbytes) != 0)
1198 			return 1;
1199 #endif /* BCMSPI */
1200 	} else if (BUSTYPE(bustype) == SI_BUS) {
1201 		return 1;
1202 	} else {
1203 		return 1;
1204 	}
1205 
1206 	return 0;
1207 }
1208 
1209 #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG)
1210 /** support only 16-bit word write into srom */
1211 int
1212 srom_write(si_t *sih, uint bustype, volatile void *curmap, osl_t *osh,
1213            uint byteoff, uint nbytes, uint16 *buf)
1214 {
1215 	uint i, nw, crc_range;
1216 	uint16 *old, *new;
1217 	uint8 crc;
1218 	volatile uint32 val32;
1219 	int rc = 1;
1220 
1221 	ASSERT(bustype == BUSTYPE(bustype));
1222 
1223 	/* freed in same function */
1224 	old = MALLOC_NOPERSIST(osh, SROM_MAXW * sizeof(uint16));
1225 	new = MALLOC_NOPERSIST(osh, SROM_MAXW * sizeof(uint16));
1226 
1227 	if (old == NULL || new == NULL)
1228 		goto done;
1229 
1230 	/* check input - 16-bit access only. use byteoff 0x55aa to indicate
1231 	 * srclear
1232 	 */
1233 	if ((byteoff != 0x55aa) && ((byteoff & 1) || (nbytes & 1)))
1234 		goto done;
1235 
1236 	if ((byteoff != 0x55aa) && ((byteoff + nbytes) > SROM_MAX))
1237 		goto done;
1238 
1239 	if (FALSE) {
1240 	}
1241 #ifdef BCMSDIO
1242 	else if (BUSTYPE(bustype) == SDIO_BUS) {
1243 		crc_range = SROM_MAX;
1244 	}
1245 #endif
1246 	else {
1247 		crc_range = srom_size(sih, osh);
1248 	}
1249 
1250 	nw = crc_range / 2;
1251 	/* read first small number words from srom, then adjust the length, read all */
1252 	if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE))
1253 		goto done;
1254 
1255 	BS_ERROR(("srom_write: old[SROM4_SIGN] 0x%x, old[SROM8_SIGN] 0x%x\n",
1256 	          old[SROM4_SIGN], old[SROM8_SIGN]));
1257 	/* Deal with blank srom */
1258 	if (old[0] == 0xffff) {
1259 		/* Do nothing to blank srom when it's srclear */
1260 		if (byteoff == 0x55aa) {
1261 			rc = 0;
1262 			goto done;
1263 		}
1264 
1265 		/* see if the input buffer is valid SROM image or not */
1266 		if (buf[SROM11_SIGN] == SROM11_SIGNATURE) {
1267 			BS_ERROR(("srom_write: buf[SROM11_SIGN] 0x%x\n",
1268 				buf[SROM11_SIGN]));
1269 
1270 			/* block invalid buffer size */
1271 			if (nbytes < SROM11_WORDS * 2) {
1272 				rc = BCME_BUFTOOSHORT;
1273 				goto done;
1274 			} else if (nbytes > SROM11_WORDS * 2) {
1275 				rc = BCME_BUFTOOLONG;
1276 				goto done;
1277 			}
1278 
1279 			nw = SROM11_WORDS;
1280 
1281 		} else if (buf[SROM12_SIGN] == SROM12_SIGNATURE) {
1282 			BS_ERROR(("srom_write: buf[SROM12_SIGN] 0x%x\n",
1283 				buf[SROM12_SIGN]));
1284 
1285 			/* block invalid buffer size */
1286 			if (nbytes < SROM12_WORDS * 2) {
1287 				rc = BCME_BUFTOOSHORT;
1288 				goto done;
1289 			} else if (nbytes > SROM12_WORDS * 2) {
1290 				rc = BCME_BUFTOOLONG;
1291 				goto done;
1292 			}
1293 
1294 			nw = SROM12_WORDS;
1295 
1296 		} else if (buf[SROM13_SIGN] == SROM13_SIGNATURE) {
1297 			BS_ERROR(("srom_write: buf[SROM13_SIGN] 0x%x\n",
1298 				buf[SROM13_SIGN]));
1299 
1300 			/* block invalid buffer size */
1301 			if (nbytes < SROM13_WORDS * 2) {
1302 				rc = BCME_BUFTOOSHORT;
1303 				goto done;
1304 			} else if (nbytes > SROM13_WORDS * 2) {
1305 				rc = BCME_BUFTOOLONG;
1306 				goto done;
1307 			}
1308 
1309 			nw = SROM13_WORDS;
1310 
1311 		} else if (buf[SROM16_SIGN] == SROM16_SIGNATURE) {
1312 			BS_ERROR(("srom_write: buf[SROM16_SIGN] 0x%x\n",
1313 				buf[SROM16_SIGN]));
1314 
1315 			/* block invalid buffer size */
1316 			if (nbytes < SROM16_WORDS * 2) {
1317 				rc = BCME_BUFTOOSHORT;
1318 				goto done;
1319 			} else if (nbytes > SROM16_WORDS * 2) {
1320 				rc = BCME_BUFTOOLONG;
1321 				goto done;
1322 			}
1323 
1324 			nw = SROM16_WORDS;
1325 
1326 		} else if (buf[SROM17_SIGN] == SROM17_SIGNATURE) {
1327 			BS_ERROR(("srom_write: buf[SROM17_SIGN] 0x%x\n",
1328 				buf[SROM17_SIGN]));
1329 
1330 			/* block invalid buffer size */
1331 			if (nbytes < SROM17_WORDS * 2) {
1332 				rc = BCME_BUFTOOSHORT;
1333 				goto done;
1334 			} else if (nbytes > SROM17_WORDS * 2) {
1335 				rc = BCME_BUFTOOLONG;
1336 				goto done;
1337 			}
1338 
1339 			nw = SROM17_WORDS;
1340 		} else if (buf[SROM18_SIGN] == SROM18_SIGNATURE) {
1341 			BS_ERROR(("srom_write: buf[SROM18_SIGN] 0x%x\n",
1342 				buf[SROM18_SIGN]));
1343 
1344 			/* block invalid buffer size */
1345 			/* nbytes can be < SROM18 bytes since host limits transfer chunk size
1346 			 * to 1500 Bytes
1347 			 */
1348 			if (nbytes > SROM18_WORDS * 2) {
1349 				rc = BCME_BUFTOOLONG;
1350 				goto done;
1351 			}
1352 
1353 			nw = SROM18_WORDS;
1354 
1355 		} else if (buf[SROM11_SIGN] == SROM15_SIGNATURE) {
1356 			BS_ERROR(("srom_write: buf[SROM15_SIGN] 0x%x\n",
1357 				buf[SROM11_SIGN]));
1358 			 /* nbytes can be < SROM15 bytes since host limits trasnfer chunk size
1359 			 * to 1518 Bytes
1360 			 */
1361 			 if (nbytes > SROM15_WORDS * 2) {
1362 				rc = BCME_BUFTOOLONG;
1363 				goto done;
1364 			}
1365 			nw = SROM15_WORDS;
1366 		} else if ((buf[SROM4_SIGN] == SROM4_SIGNATURE) ||
1367 			(buf[SROM8_SIGN] == SROM4_SIGNATURE)) {
1368 			BS_ERROR(("srom_write: buf[SROM4_SIGN] 0x%x, buf[SROM8_SIGN] 0x%x\n",
1369 				buf[SROM4_SIGN], buf[SROM8_SIGN]));
1370 
1371 			/* block invalid buffer size */
1372 			if (nbytes < SROM4_WORDS * 2) {
1373 				rc = BCME_BUFTOOSHORT;
1374 				goto done;
1375 			} else if (nbytes > SROM4_WORDS * 2) {
1376 				rc = BCME_BUFTOOLONG;
1377 				goto done;
1378 			}
1379 
1380 			nw = SROM4_WORDS;
1381 		} else if (nbytes == SROM_WORDS * 2){ /* the other possible SROM format */
1382 			BS_ERROR(("srom_write: Not SROM4 or SROM8.\n"));
1383 
1384 			nw = SROM_WORDS;
1385 		} else {
1386 			BS_ERROR(("srom_write: Invalid input file signature\n"));
1387 			rc = BCME_BADARG;
1388 			goto done;
1389 		}
1390 		crc_range = nw * 2;
1391 		if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1392 			goto done;
1393 		}
1394 	} else if (old[SROM18_SIGN] == SROM18_SIGNATURE) {
1395 		nw = SROM18_WORDS;
1396 		crc_range = nw * 2;
1397 		if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1398 			goto done;
1399 		}
1400 	} else if (old[SROM17_SIGN] == SROM17_SIGNATURE) {
1401 		nw = SROM17_WORDS;
1402 		crc_range = nw * 2;
1403 		if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1404 			goto done;
1405 		}
1406 	} else if (old[SROM16_SIGN] == SROM16_SIGNATURE) {
1407 		nw = SROM16_WORDS;
1408 		crc_range = nw * 2;
1409 		if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1410 			goto done;
1411 		}
1412 	} else if (old[SROM15_SIGN] == SROM15_SIGNATURE) {
1413 		nw = SROM15_WORDS;
1414 		crc_range = nw * 2;
1415 		if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1416 			goto done;
1417 		}
1418 	} else if (old[SROM13_SIGN] == SROM13_SIGNATURE) {
1419 		nw = SROM13_WORDS;
1420 		crc_range = nw * 2;
1421 		if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1422 			goto done;
1423 		}
1424 	} else if (old[SROM12_SIGN] == SROM12_SIGNATURE) {
1425 		nw = SROM12_WORDS;
1426 		crc_range = nw * 2;
1427 		if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1428 			goto done;
1429 		}
1430 	} else if (old[SROM11_SIGN] == SROM11_SIGNATURE) {
1431 		nw = SROM11_WORDS;
1432 		crc_range = nw * 2;
1433 		if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1434 			goto done;
1435 		}
1436 	} else if ((old[SROM4_SIGN] == SROM4_SIGNATURE) ||
1437 	           (old[SROM8_SIGN] == SROM4_SIGNATURE)) {
1438 		nw = SROM4_WORDS;
1439 		crc_range = nw * 2;
1440 		if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) {
1441 			goto done;
1442 		}
1443 	} else {
1444 		/* Assert that we have already read enough for sromrev 2 */
1445 		ASSERT(crc_range >= SROM_WORDS * 2);
1446 		nw = SROM_WORDS;
1447 		crc_range = nw * 2;
1448 	}
1449 
1450 	if (byteoff == 0x55aa) {
1451 		/* Erase request */
1452 		crc_range = 0;
1453 		memset((void *)new, 0xff, nw * 2);
1454 	} else {
1455 		/* Copy old contents */
1456 		bcopy((void *)old, (void *)new, nw * 2);
1457 		/* make changes */
1458 		bcopy((void *)buf, (void *)&new[byteoff / 2], nbytes);
1459 	}
1460 
1461 	if (crc_range) {
1462 		/* calculate crc */
1463 		htol16_buf(new, crc_range);
1464 		crc = ~hndcrc8((uint8 *)new, crc_range - 1, CRC8_INIT_VALUE);
1465 		ltoh16_buf(new, crc_range);
1466 		new[nw - 1] = (crc << 8) | (new[nw - 1] & 0xff);
1467 	}
1468 
1469 #ifdef BCMPCIEDEV
1470 	if ((BUSTYPE(bustype) == SI_BUS) &&
1471 		(BCM43602_CHIP(sih->chip) ||
1472 		(BCM4369_CHIP(sih->chip)) ||
1473 		(BCM4362_CHIP(sih->chip)) ||
1474 		(BCM4378_CHIP(sih->chip)) ||
1475 		(BCM4387_CHIP(sih->chip)) ||
1476 		(BCM4388_CHIP(sih->chip)) ||
1477 		(BCM4385_CHIP(sih->chip)) ||
1478 		(BCM4389_CHIP(sih->chip)) ||
1479 		(BCM4397_CHIP(sih->chip)) ||
1480 
1481 #ifdef UNRELEASEDCHIP
1482 #endif /* UNRELEASEDCHIP */
1483 
1484 	     FALSE)) {
1485 #else
1486 	if (BUSTYPE(bustype) == PCI_BUS) {
1487 #endif /* BCMPCIEDEV */
1488 		volatile uint16 *srom = NULL;
1489 		volatile void *ccregs = NULL;
1490 		uint32 ccval = 0;
1491 
1492 		if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1493 		    (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1494 		    (CHIPID(sih->chip) == BCM43526_CHIP_ID) ||
1495 		    (CHIPID(sih->chip) == BCM4352_CHIP_ID) ||
1496 		    BCM43602_CHIP(sih->chip)) {
1497 			/* save current control setting */
1498 			ccval = si_chipcontrl_read(sih);
1499 		}
1500 
1501 		if (BCM43602_CHIP(sih->chip) ||
1502 			(((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1503 			(CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1504 			(CHIPID(sih->chip) == BCM4352_CHIP_ID)) &&
1505 			(CHIPREV(sih->chiprev) <= 2))) {
1506 			si_chipcontrl_srom4360(sih, TRUE);
1507 		}
1508 
1509 		if (FALSE) {
1510 			si_srom_clk_set(sih); /* corrects srom clock frequency */
1511 		}
1512 
1513 		/* enable writes to the SPROM */
1514 		if (sih->ccrev > 31) {
1515 			if (BUSTYPE(sih->bustype) == SI_BUS)
1516 				ccregs = (void *)(uintptr)SI_ENUM_BASE(sih);
1517 			else
1518 				ccregs = ((volatile uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET);
1519 			srom = (volatile uint16 *)((volatile uint8 *)ccregs + CC_SROM_OTP);
1520 			(void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WREN, 0, 0);
1521 		} else {
1522 			srom = (volatile uint16 *)
1523 					((volatile uint8 *)curmap + PCI_BAR0_SPROM_OFFSET);
1524 			val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
1525 			val32 |= SPROM_WRITEEN;
1526 			OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32);
1527 		}
1528 		bcm_mdelay(WRITE_ENABLE_DELAY);
1529 		/* write srom */
1530 		for (i = 0; i < nw; i++) {
1531 			if (old[i] != new[i]) {
1532 				if (sih->ccrev > 31) {
1533 					if ((sih->cccaps & CC_CAP_SROM) == 0) {
1534 						/* No srom support in this chip */
1535 						BS_ERROR(("srom_write, invalid srom, skip\n"));
1536 					} else
1537 						(void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRITE,
1538 							i, new[i]);
1539 				} else {
1540 					W_REG(osh, &srom[i], new[i]);
1541 				}
1542 				bcm_mdelay(WRITE_WORD_DELAY);
1543 			}
1544 		}
1545 		/* disable writes to the SPROM */
1546 		if (sih->ccrev > 31) {
1547 			(void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRDIS, 0, 0);
1548 		} else {
1549 			OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 &
1550 			                     ~SPROM_WRITEEN);
1551 		}
1552 
1553 		if (BCM43602_CHIP(sih->chip) ||
1554 		    (CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1555 		    (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1556 		    (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
1557 			/* Restore config after reading SROM */
1558 			si_chipcontrl_restore(sih, ccval);
1559 		}
1560 #ifdef BCMSDIO
1561 	} else if (BUSTYPE(bustype) == SDIO_BUS) {
1562 		/* enable writes to the SPROM */
1563 		if (sprom_cmd_sdio(osh, SBSDIO_SPROM_WEN))
1564 			goto done;
1565 		bcm_mdelay(WRITE_ENABLE_DELAY);
1566 		/* write srom */
1567 		for (i = 0; i < nw; i++) {
1568 			if (old[i] != new[i]) {
1569 				sprom_write_sdio(osh, (uint16)(i), new[i]);
1570 				bcm_mdelay(WRITE_WORD_DELAY);
1571 			}
1572 		}
1573 		/* disable writes to the SPROM */
1574 		if (sprom_cmd_sdio(osh, SBSDIO_SPROM_WDS))
1575 			goto done;
1576 #endif /* BCMSDIO */
1577 	} else if (BUSTYPE(bustype) == SI_BUS) {
1578 		goto done;
1579 	} else {
1580 		goto done;
1581 	}
1582 
1583 	bcm_mdelay(WRITE_ENABLE_DELAY);
1584 	rc = 0;
1585 
1586 done:
1587 	if (old != NULL)
1588 		MFREE(osh, old, SROM_MAXW * sizeof(uint16));
1589 	if (new != NULL)
1590 		MFREE(osh, new, SROM_MAXW * sizeof(uint16));
1591 
1592 	return rc;
1593 }
1594 
1595 /** support only 16-bit word write into srom */
1596 int
1597 srom_write_short(si_t *sih, uint bustype, volatile void *curmap, osl_t *osh,
1598                  uint byteoff, uint16 value)
1599 {
1600 	volatile uint32 val32;
1601 	int rc = 1;
1602 
1603 	ASSERT(bustype == BUSTYPE(bustype));
1604 
1605 	if (byteoff & 1)
1606 		goto done;
1607 
1608 #ifdef BCMPCIEDEV
1609 	if ((BUSTYPE(bustype) == SI_BUS) &&
1610 	    (BCM43602_CHIP(sih->chip) ||
1611 	     FALSE)) {
1612 #else
1613 	if (BUSTYPE(bustype) == PCI_BUS) {
1614 #endif /* BCMPCIEDEV */
1615 		volatile uint16 *srom = NULL;
1616 		volatile void *ccregs = NULL;
1617 		uint32 ccval = 0;
1618 
1619 		if (BCM43602_CHIP(sih->chip) ||
1620 		    (CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1621 		    (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1622 		    (CHIPID(sih->chip) == BCM43526_CHIP_ID) ||
1623 		    (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
1624 			/* save current control setting */
1625 			ccval = si_chipcontrl_read(sih);
1626 		}
1627 
1628 		if (BCM43602_CHIP(sih->chip) ||
1629 			(((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1630 			(CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1631 			(CHIPID(sih->chip) == BCM4352_CHIP_ID)) &&
1632 			(CHIPREV(sih->chiprev) <= 2))) {
1633 			si_chipcontrl_srom4360(sih, TRUE);
1634 		}
1635 
1636 		if (FALSE) {
1637 			si_srom_clk_set(sih); /* corrects srom clock frequency */
1638 		}
1639 
1640 		/* enable writes to the SPROM */
1641 		if (sih->ccrev > 31) {
1642 			if (BUSTYPE(sih->bustype) == SI_BUS)
1643 				ccregs = (void *)(uintptr)SI_ENUM_BASE(sih);
1644 			else
1645 				ccregs = ((volatile uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET);
1646 			srom = (volatile uint16 *)((volatile uint8 *)ccregs + CC_SROM_OTP);
1647 			(void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WREN, 0, 0);
1648 		} else {
1649 			srom = (volatile uint16 *)
1650 					((volatile uint8 *)curmap + PCI_BAR0_SPROM_OFFSET);
1651 			val32 = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
1652 			val32 |= SPROM_WRITEEN;
1653 			OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32);
1654 		}
1655 		bcm_mdelay(WRITE_ENABLE_DELAY);
1656 		/* write srom */
1657 		if (sih->ccrev > 31) {
1658 			if ((sih->cccaps & CC_CAP_SROM) == 0) {
1659 				/* No srom support in this chip */
1660 				BS_ERROR(("srom_write, invalid srom, skip\n"));
1661 			} else
1662 				(void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRITE,
1663 				                   byteoff/2, value);
1664 		} else {
1665 			W_REG(osh, &srom[byteoff/2], value);
1666 		}
1667 		bcm_mdelay(WRITE_WORD_DELAY);
1668 
1669 		/* disable writes to the SPROM */
1670 		if (sih->ccrev > 31) {
1671 			(void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRDIS, 0, 0);
1672 		} else {
1673 			OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 &
1674 			                     ~SPROM_WRITEEN);
1675 		}
1676 
1677 		if (BCM43602_CHIP(sih->chip) ||
1678 		    (CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
1679 		    (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
1680 		    (CHIPID(sih->chip) == BCM43526_CHIP_ID) ||
1681 		    (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
1682 			/* Restore config after reading SROM */
1683 			si_chipcontrl_restore(sih, ccval);
1684 		}
1685 #ifdef BCMSDIO
1686 	} else if (BUSTYPE(bustype) == SDIO_BUS) {
1687 		/* enable writes to the SPROM */
1688 		if (sprom_cmd_sdio(osh, SBSDIO_SPROM_WEN))
1689 			goto done;
1690 		bcm_mdelay(WRITE_ENABLE_DELAY);
1691 		/* write srom */
1692 		sprom_write_sdio(osh, (uint16)(byteoff/2), value);
1693 		bcm_mdelay(WRITE_WORD_DELAY);
1694 
1695 		/* disable writes to the SPROM */
1696 		if (sprom_cmd_sdio(osh, SBSDIO_SPROM_WDS))
1697 			goto done;
1698 #endif /* BCMSDIO */
1699 	} else if (BUSTYPE(bustype) == SI_BUS) {
1700 		goto done;
1701 	} else {
1702 		goto done;
1703 	}
1704 
1705 	bcm_mdelay(WRITE_ENABLE_DELAY);
1706 	rc = 0;
1707 
1708 done:
1709 	return rc;
1710 }
1711 #endif /* defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) */
1712 
1713 /**
1714  * These 'vstr_*' definitions are used to convert from CIS format to a 'NVRAM var=val' format, the
1715  * NVRAM format is used throughout the rest of the firmware.
1716  */
1717 #if !defined(BCMDONGLEHOST)
1718 static const char BCMATTACHDATA(vstr_manf)[] = "manf=%s";
1719 static const char BCMATTACHDATA(vstr_productname)[] = "productname=%s";
1720 static const char BCMATTACHDATA(vstr_manfid)[] = "manfid=0x%x";
1721 static const char BCMATTACHDATA(vstr_prodid)[] = "prodid=0x%x";
1722 #ifdef BCMSDIO
1723 static const char BCMATTACHDATA(vstr_sdmaxspeed)[] = "sdmaxspeed=%d";
1724 static const char BCMATTACHDATA(vstr_sdmaxblk)[][13] =
1725 	{ "sdmaxblk0=%d", "sdmaxblk1=%d", "sdmaxblk2=%d" };
1726 #endif
1727 static const char BCMATTACHDATA(vstr_regwindowsz)[] = "regwindowsz=%d";
1728 static const char BCMATTACHDATA(vstr_sromrev)[] = "sromrev=%d";
1729 static const char BCMATTACHDATA(vstr_chiprev)[] = "chiprev=%d";
1730 static const char BCMATTACHDATA(vstr_subvendid)[] = "subvendid=0x%x";
1731 static const char BCMATTACHDATA(vstr_subdevid)[] = "subdevid=0x%x";
1732 static const char BCMATTACHDATA(vstr_boardrev)[] = "boardrev=0x%x";
1733 static const char BCMATTACHDATA(vstr_aa2g)[] = "aa2g=0x%x";
1734 static const char BCMATTACHDATA(vstr_aa5g)[] = "aa5g=0x%x";
1735 static const char BCMATTACHDATA(vstr_ag)[] = "ag%d=0x%x";
1736 static const char BCMATTACHDATA(vstr_cc)[] = "cc=%d";
1737 static const char BCMATTACHDATA(vstr_opo)[] = "opo=%d";
1738 static const char BCMATTACHDATA(vstr_pa0b)[][9] = { "pa0b0=%d", "pa0b1=%d", "pa0b2=%d" };
1739 static const char BCMATTACHDATA(vstr_pa0b_lo)[][12] =
1740 	{ "pa0b0_lo=%d", "pa0b1_lo=%d", "pa0b2_lo=%d" };
1741 static const char BCMATTACHDATA(vstr_pa0itssit)[] = "pa0itssit=%d";
1742 static const char BCMATTACHDATA(vstr_pa0maxpwr)[] = "pa0maxpwr=%d";
1743 static const char BCMATTACHDATA(vstr_pa1b)[][9] = { "pa1b0=%d", "pa1b1=%d", "pa1b2=%d" };
1744 static const char BCMATTACHDATA(vstr_pa1lob)[][11] =
1745 	{ "pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d" };
1746 static const char BCMATTACHDATA(vstr_pa1hib)[][11] =
1747 	{ "pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d" };
1748 static const char BCMATTACHDATA(vstr_pa1itssit)[] = "pa1itssit=%d";
1749 static const char BCMATTACHDATA(vstr_pa1maxpwr)[] = "pa1maxpwr=%d";
1750 static const char BCMATTACHDATA(vstr_pa1lomaxpwr)[] = "pa1lomaxpwr=%d";
1751 static const char BCMATTACHDATA(vstr_pa1himaxpwr)[] = "pa1himaxpwr=%d";
1752 static const char BCMATTACHDATA(vstr_oem)[] = "oem=%02x%02x%02x%02x%02x%02x%02x%02x";
1753 static const char BCMATTACHDATA(vstr_boardflags)[] = "boardflags=0x%x";
1754 static const char BCMATTACHDATA(vstr_boardflags2)[] = "boardflags2=0x%x";
1755 static const char BCMATTACHDATA(vstr_boardflags3)[] = "boardflags3=0x%x";
1756 static const char BCMATTACHDATA(vstr_boardflags4)[] = "boardflags4=0x%x";
1757 static const char BCMATTACHDATA(vstr_boardflags5)[] = "boardflags5=0x%x";
1758 static const char BCMATTACHDATA(vstr_noccode)[] = "ccode=0x0";
1759 static const char BCMATTACHDATA(vstr_ccode)[] = "ccode=%c%c";
1760 static const char BCMATTACHDATA(vstr_cctl)[] = "cctl=0x%x";
1761 static const char BCMATTACHDATA(vstr_cckpo)[] = "cckpo=0x%x";
1762 static const char BCMATTACHDATA(vstr_ofdmpo)[] = "ofdmpo=0x%x";
1763 static const char BCMATTACHDATA(vstr_rdlid)[] = "rdlid=0x%x";
1764 #ifdef BCM_BOOTLOADER
1765 static const char BCMATTACHDATA(vstr_rdlrndis)[] = "rdlrndis=%d";
1766 static const char BCMATTACHDATA(vstr_rdlrwu)[] = "rdlrwu=%d";
1767 static const char BCMATTACHDATA(vstr_rdlsn)[] = "rdlsn=%d";
1768 #endif /* BCM_BOOTLOADER */
1769 static const char BCMATTACHDATA(vstr_usbfs)[] = "usbfs=%d";
1770 static const char BCMATTACHDATA(vstr_wpsgpio)[] = "wpsgpio=%d";
1771 static const char BCMATTACHDATA(vstr_wpsled)[] = "wpsled=%d";
1772 static const char BCMATTACHDATA(vstr_rssismf2g)[] = "rssismf2g=%d";
1773 static const char BCMATTACHDATA(vstr_rssismc2g)[] = "rssismc2g=%d";
1774 static const char BCMATTACHDATA(vstr_rssisav2g)[] = "rssisav2g=%d";
1775 static const char BCMATTACHDATA(vstr_bxa2g)[] = "bxa2g=%d";
1776 static const char BCMATTACHDATA(vstr_rssismf5g)[] = "rssismf5g=%d";
1777 static const char BCMATTACHDATA(vstr_rssismc5g)[] = "rssismc5g=%d";
1778 static const char BCMATTACHDATA(vstr_rssisav5g)[] = "rssisav5g=%d";
1779 static const char BCMATTACHDATA(vstr_bxa5g)[] = "bxa5g=%d";
1780 static const char BCMATTACHDATA(vstr_tri2g)[] = "tri2g=%d";
1781 static const char BCMATTACHDATA(vstr_tri5gl)[] = "tri5gl=%d";
1782 static const char BCMATTACHDATA(vstr_tri5g)[] = "tri5g=%d";
1783 static const char BCMATTACHDATA(vstr_tri5gh)[] = "tri5gh=%d";
1784 static const char BCMATTACHDATA(vstr_rxpo2g)[] = "rxpo2g=%d";
1785 static const char BCMATTACHDATA(vstr_rxpo5g)[] = "rxpo5g=%d";
1786 static const char BCMATTACHDATA(vstr_boardtype)[] = "boardtype=0x%x";
1787 static const char BCMATTACHDATA(vstr_vendid)[] = "vendid=0x%x";
1788 static const char BCMATTACHDATA(vstr_devid)[] = "devid=0x%x";
1789 static const char BCMATTACHDATA(vstr_xtalfreq)[] = "xtalfreq=%d";
1790 static const char BCMATTACHDATA(vstr_txchain)[] = "txchain=0x%x";
1791 static const char BCMATTACHDATA(vstr_rxchain)[] = "rxchain=0x%x";
1792 static const char BCMATTACHDATA(vstr_elna2g)[] = "elna2g=0x%x";
1793 static const char BCMATTACHDATA(vstr_elna5g)[] = "elna5g=0x%x";
1794 static const char BCMATTACHDATA(vstr_antswitch)[] = "antswitch=0x%x";
1795 static const char BCMATTACHDATA(vstr_regrev)[] = "regrev=0x%x";
1796 static const char BCMATTACHDATA(vstr_antswctl2g)[] = "antswctl2g=0x%x";
1797 static const char BCMATTACHDATA(vstr_triso2g)[] = "triso2g=0x%x";
1798 static const char BCMATTACHDATA(vstr_pdetrange2g)[] = "pdetrange2g=0x%x";
1799 static const char BCMATTACHDATA(vstr_extpagain2g)[] = "extpagain2g=0x%x";
1800 static const char BCMATTACHDATA(vstr_tssipos2g)[] = "tssipos2g=0x%x";
1801 static const char BCMATTACHDATA(vstr_antswctl5g)[] = "antswctl5g=0x%x";
1802 static const char BCMATTACHDATA(vstr_triso5g)[] = "triso5g=0x%x";
1803 static const char BCMATTACHDATA(vstr_pdetrange5g)[] = "pdetrange5g=0x%x";
1804 static const char BCMATTACHDATA(vstr_extpagain5g)[] = "extpagain5g=0x%x";
1805 static const char BCMATTACHDATA(vstr_tssipos5g)[] = "tssipos5g=0x%x";
1806 static const char BCMATTACHDATA(vstr_maxp2ga)[] = "maxp2ga%d=0x%x";
1807 static const char BCMATTACHDATA(vstr_itt2ga0)[] = "itt2ga0=0x%x";
1808 static const char BCMATTACHDATA(vstr_pa)[] = "pa%dgw%da%d=0x%x";
1809 static const char BCMATTACHDATA(vstr_pahl)[] = "pa%dg%cw%da%d=0x%x";
1810 static const char BCMATTACHDATA(vstr_maxp5ga0)[] = "maxp5ga0=0x%x";
1811 static const char BCMATTACHDATA(vstr_itt5ga0)[] = "itt5ga0=0x%x";
1812 static const char BCMATTACHDATA(vstr_maxp5gha0)[] = "maxp5gha0=0x%x";
1813 static const char BCMATTACHDATA(vstr_maxp5gla0)[] = "maxp5gla0=0x%x";
1814 static const char BCMATTACHDATA(vstr_itt2ga1)[] = "itt2ga1=0x%x";
1815 static const char BCMATTACHDATA(vstr_maxp5ga1)[] = "maxp5ga1=0x%x";
1816 static const char BCMATTACHDATA(vstr_itt5ga1)[] = "itt5ga1=0x%x";
1817 static const char BCMATTACHDATA(vstr_maxp5gha1)[] = "maxp5gha1=0x%x";
1818 static const char BCMATTACHDATA(vstr_maxp5gla1)[] = "maxp5gla1=0x%x";
1819 static const char BCMATTACHDATA(vstr_cck2gpo)[] = "cck2gpo=0x%x";
1820 static const char BCMATTACHDATA(vstr_ofdm2gpo)[] = "ofdm2gpo=0x%x";
1821 static const char BCMATTACHDATA(vstr_ofdm5gpo)[] = "ofdm5gpo=0x%x";
1822 static const char BCMATTACHDATA(vstr_ofdm5glpo)[] = "ofdm5glpo=0x%x";
1823 static const char BCMATTACHDATA(vstr_ofdm5ghpo)[] = "ofdm5ghpo=0x%x";
1824 static const char BCMATTACHDATA(vstr_cddpo)[] = "cddpo=0x%x";
1825 static const char BCMATTACHDATA(vstr_stbcpo)[] = "stbcpo=0x%x";
1826 static const char BCMATTACHDATA(vstr_bw40po)[] = "bw40po=0x%x";
1827 static const char BCMATTACHDATA(vstr_bwduppo)[] = "bwduppo=0x%x";
1828 static const char BCMATTACHDATA(vstr_mcspo)[] = "mcs%dgpo%d=0x%x";
1829 static const char BCMATTACHDATA(vstr_mcspohl)[] = "mcs%dg%cpo%d=0x%x";
1830 static const char BCMATTACHDATA(vstr_custom)[] = "customvar%d=0x%x";
1831 static const char BCMATTACHDATA(vstr_cckdigfilttype)[] = "cckdigfilttype=%d";
1832 static const char BCMATTACHDATA(vstr_usbflags)[] = "usbflags=0x%x";
1833 #ifdef BCM_BOOTLOADER
1834 static const char BCMATTACHDATA(vstr_mdio)[] = "mdio%d=0x%%x";
1835 static const char BCMATTACHDATA(vstr_mdioex)[] = "mdioex%d=0x%%x";
1836 static const char BCMATTACHDATA(vstr_brmin)[] = "brmin=0x%x";
1837 static const char BCMATTACHDATA(vstr_brmax)[] = "brmax=0x%x";
1838 static const char BCMATTACHDATA(vstr_pllreg)[] = "pll%d=0x%x";
1839 static const char BCMATTACHDATA(vstr_ccreg)[] = "chipc%d=0x%x";
1840 static const char BCMATTACHDATA(vstr_regctrl)[] = "reg%d=0x%x";
1841 static const char BCMATTACHDATA(vstr_time)[] = "r%dt=0x%x";
1842 static const char BCMATTACHDATA(vstr_depreg)[] = "r%dd=0x%x";
1843 static const char BCMATTACHDATA(vstr_usbpredly)[] = "usbpredly=0x%x";
1844 static const char BCMATTACHDATA(vstr_usbpostdly)[] = "usbpostdly=0x%x";
1845 static const char BCMATTACHDATA(vstr_usbrdy)[] = "usbrdy=0x%x";
1846 static const char BCMATTACHDATA(vstr_hsicphyctrl1)[] = "hsicphyctrl1=0x%x";
1847 static const char BCMATTACHDATA(vstr_hsicphyctrl2)[] = "hsicphyctrl2=0x%x";
1848 static const char BCMATTACHDATA(vstr_usbdevctrl)[] = "usbdevctrl=0x%x";
1849 static const char BCMATTACHDATA(vstr_bldr_reset_timeout)[] = "bldr_to=0x%x";
1850 static const char BCMATTACHDATA(vstr_muxenab)[] = "muxenab=0x%x";
1851 static const char BCMATTACHDATA(vstr_pubkey)[] = "pubkey=%s";
1852 #endif /* BCM_BOOTLOADER */
1853 static const char BCMATTACHDATA(vstr_boardnum)[] = "boardnum=%d";
1854 static const char BCMATTACHDATA(vstr_macaddr)[] = "macaddr=%s";
1855 static const char BCMATTACHDATA(vstr_macaddr2)[] = "macaddr2=%s";
1856 static const char BCMATTACHDATA(vstr_usbepnum)[] = "usbepnum=0x%x";
1857 #ifdef BCMUSBDEV_COMPOSITE
1858 static const char BCMATTACHDATA(vstr_usbdesc_composite)[] = "usbdesc_composite=0x%x";
1859 #endif /* BCMUSBDEV_COMPOSITE */
1860 static const char BCMATTACHDATA(vstr_usbutmi_ctl)[] = "usbutmi_ctl=0x%x";
1861 static const char BCMATTACHDATA(vstr_usbssphy_utmi_ctl0)[] = "usbssphy_utmi_ctl0=0x%x";
1862 static const char BCMATTACHDATA(vstr_usbssphy_utmi_ctl1)[] = "usbssphy_utmi_ctl1=0x%x";
1863 static const char BCMATTACHDATA(vstr_usbssphy_utmi_ctl2)[] = "usbssphy_utmi_ctl2=0x%x";
1864 static const char BCMATTACHDATA(vstr_usbssphy_sleep0)[] = "usbssphy_sleep0=0x%x";
1865 static const char BCMATTACHDATA(vstr_usbssphy_sleep1)[] = "usbssphy_sleep1=0x%x";
1866 static const char BCMATTACHDATA(vstr_usbssphy_sleep2)[] = "usbssphy_sleep2=0x%x";
1867 static const char BCMATTACHDATA(vstr_usbssphy_sleep3)[] = "usbssphy_sleep3=0x%x";
1868 static const char BCMATTACHDATA(vstr_usbssphy_mdio)[] = "usbssmdio%d=0x%x,0x%x,0x%x,0x%x";
1869 static const char BCMATTACHDATA(vstr_usb30phy_noss)[] = "usbnoss=0x%x";
1870 static const char BCMATTACHDATA(vstr_usb30phy_u1u2)[] = "usb30u1u2=0x%x";
1871 static const char BCMATTACHDATA(vstr_usb30phy_regs)[] = "usb30regs%d=0x%x,0x%x,0x%x,0x%x";
1872 
1873 /* Power per rate for SROM V9 */
1874 static const char BCMATTACHDATA(vstr_cckbw202gpo)[][21] =
1875 	{ "cckbw202gpo=0x%x", "cckbw20ul2gpo=0x%x", "cckbw20in802gpo=0x%x" };
1876 static const char BCMATTACHDATA(vstr_legofdmbw202gpo)[][23] =
1877 	{ "legofdmbw202gpo=0x%x", "legofdmbw20ul2gpo=0x%x" };
1878 static const char BCMATTACHDATA(vstr_legofdmbw205gpo)[][24] =
1879 	{ "legofdmbw205glpo=0x%x", "legofdmbw20ul5glpo=0x%x",
1880 	"legofdmbw205gmpo=0x%x", "legofdmbw20ul5gmpo=0x%x",
1881 	"legofdmbw205ghpo=0x%x", "legofdmbw20ul5ghpo=0x%x" };
1882 
1883 static const char BCMATTACHDATA(vstr_mcs2gpo)[][19] =
1884 { "mcsbw202gpo=0x%x", "mcsbw20ul2gpo=0x%x", "mcsbw402gpo=0x%x", "mcsbw802gpo=0x%x" };
1885 
1886 static const char BCMATTACHDATA(vstr_mcs5glpo)[][20] =
1887 	{ "mcsbw205glpo=0x%x", "mcsbw20ul5glpo=0x%x", "mcsbw405glpo=0x%x" };
1888 
1889 static const char BCMATTACHDATA(vstr_mcs5gmpo)[][20] =
1890 	{ "mcsbw205gmpo=0x%x", "mcsbw20ul5gmpo=0x%x", "mcsbw405gmpo=0x%x" };
1891 
1892 static const char BCMATTACHDATA(vstr_mcs5ghpo)[][20] =
1893 	{ "mcsbw205ghpo=0x%x", "mcsbw20ul5ghpo=0x%x", "mcsbw405ghpo=0x%x" };
1894 
1895 static const char BCMATTACHDATA(vstr_mcs32po)[] = "mcs32po=0x%x";
1896 static const char BCMATTACHDATA(vstr_legofdm40duppo)[] = "legofdm40duppo=0x%x";
1897 
1898 /* SROM V11 */
1899 static const char BCMATTACHDATA(vstr_tempthresh)[] = "tempthresh=%d";	/* HNBU_TEMPTHRESH */
1900 static const char BCMATTACHDATA(vstr_temps_period)[] = "temps_period=%d";
1901 static const char BCMATTACHDATA(vstr_temps_hysteresis)[] = "temps_hysteresis=%d";
1902 static const char BCMATTACHDATA(vstr_tempoffset)[] = "tempoffset=%d";
1903 static const char BCMATTACHDATA(vstr_tempsense_slope)[] = "tempsense_slope=%d";
1904 static const char BCMATTACHDATA(vstr_temp_corrx)[] = "tempcorrx=%d";
1905 static const char BCMATTACHDATA(vstr_tempsense_option)[] = "tempsense_option=%d";
1906 static const char BCMATTACHDATA(vstr_phycal_tempdelta)[] = "phycal_tempdelta=%d";
1907 static const char BCMATTACHDATA(vstr_tssiposslopeg)[] = "tssiposslope%dg=%d";	/* HNBU_FEM_CFG */
1908 static const char BCMATTACHDATA(vstr_epagaing)[] = "epagain%dg=%d";
1909 static const char BCMATTACHDATA(vstr_pdgaing)[] = "pdgain%dg=%d";
1910 static const char BCMATTACHDATA(vstr_tworangetssi)[] = "tworangetssi%dg=%d";
1911 static const char BCMATTACHDATA(vstr_papdcap)[] = "papdcap%dg=%d";
1912 static const char BCMATTACHDATA(vstr_femctrl)[] = "femctrl=%d";
1913 static const char BCMATTACHDATA(vstr_gainctrlsph)[] = "gainctrlsph=%d";
1914 static const char BCMATTACHDATA(vstr_subband5gver)[] = "subband5gver=%d";	/* HNBU_ACPA_CX */
1915 static const char BCMATTACHDATA(vstr_pa2ga)[] = "pa2ga%d=0x%x,0x%x,0x%x";
1916 static const char BCMATTACHDATA(vstr_maxp5ga)[] = "maxp5ga%d=0x%x,0x%x,0x%x,0x%x";
1917 static const char BCMATTACHDATA(vstr_pa5ga)[] = "pa5ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,"
1918 	"0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1919 static const char BCMATTACHDATA(vstr_subband6gver)[] = "subband6gver=%d";	/* HNBU_ACPA_CX */
1920 static const char BCMATTACHDATA(vstr_maxp6ga)[] = "maxp6ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1921 static const char BCMATTACHDATA(vstr_pa6ga)[] = "pa6ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,"
1922 	"0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1923 static const char BCMATTACHDATA(vstr_pa2gccka)[] = "pa2gccka%d=0x%x,0x%x,0x%x";
1924 static const char BCMATTACHDATA(vstr_pa5gbw40a)[] = "pa5gbw40a%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,"
1925 	"0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1926 static const char BCMATTACHDATA(vstr_pa5gbw80a)[] = "pa5gbw80a%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,"
1927 	"0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1928 static const char BCMATTACHDATA(vstr_pa5gbw4080a)[] = "pa5gbw4080a%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,"
1929 	"0x%x,0x%x,0x%x,0x%x,0x%x,0x%x";
1930 static const char BCMATTACHDATA(vstr_rxgainsgelnagaina)[] = "rxgains%dgelnagaina%d=%d";
1931 static const char BCMATTACHDATA(vstr_rxgainsgtrisoa)[] = "rxgains%dgtrisoa%d=%d";
1932 static const char BCMATTACHDATA(vstr_rxgainsgtrelnabypa)[] = "rxgains%dgtrelnabypa%d=%d";
1933 static const char BCMATTACHDATA(vstr_rxgainsgxelnagaina)[] = "rxgains%dg%celnagaina%d=%d";
1934 static const char BCMATTACHDATA(vstr_rxgainsgxtrisoa)[] = "rxgains%dg%ctrisoa%d=%d";
1935 static const char BCMATTACHDATA(vstr_rxgainsgxtrelnabypa)[] = "rxgains%dg%ctrelnabypa%d=%d";
1936 static const char BCMATTACHDATA(vstr_measpower)[] = "measpower=0x%x";	/* HNBU_MEAS_PWR */
1937 static const char BCMATTACHDATA(vstr_measpowerX)[] = "measpower%d=0x%x";
1938 static const char BCMATTACHDATA(vstr_pdoffsetma)[] = "pdoffset%dma%d=0x%x";	/* HNBU_PDOFF */
1939 static const char BCMATTACHDATA(vstr_pdoffset2gma)[] = "pdoffset2g%dma%d=0x%x";	/* HNBU_PDOFF_2G */
1940 static const char BCMATTACHDATA(vstr_pdoffset2gmvalid)[] = "pdoffset2g%dmvalid=0x%x";
1941 static const char BCMATTACHDATA(vstr_rawtempsense)[] = "rawtempsense=0x%x";
1942 /* HNBU_ACPPR_2GPO */
1943 static const char BCMATTACHDATA(vstr_dot11agofdmhrbw202gpo)[] = "dot11agofdmhrbw202gpo=0x%x";
1944 static const char BCMATTACHDATA(vstr_ofdmlrbw202gpo)[] = "ofdmlrbw202gpo=0x%x";
1945 static const char BCMATTACHDATA(vstr_mcsbw805gpo)[] = "mcsbw805g%cpo=0x%x"; /* HNBU_ACPPR_5GPO */
1946 static const char BCMATTACHDATA(vstr_mcsbw1605gpo)[] = "mcsbw1605g%cpo=0x%x";
1947 static const char BCMATTACHDATA(vstr_mcsbw80p805gpo)[] = "mcsbw80p805g%cpo=0x%x";
1948 static const char BCMATTACHDATA(vstr_mcsbw80p805g1po)[] = "mcsbw80p805g%c1po=0x%x";
1949 static const char BCMATTACHDATA(vstr_mcsbw1605g1po)[] = "mcsbw1605g%c1po=0x%x";
1950 static const char BCMATTACHDATA(vstr_mcsbw805g1po)[] = "mcsbw805g%c1po=0x%x";
1951 static const char BCMATTACHDATA(vstr_mcsbw405g1po)[] = "mcsbw405g%c1po=0x%x";
1952 static const char BCMATTACHDATA(vstr_mcsbw205g1po)[] = "mcsbw205g%c1po=0x%x";
1953 static const char BCMATTACHDATA(vstr_mcslr5gpo)[] = "mcslr5g%cpo=0x%x";
1954 static const char BCMATTACHDATA(vstr_mcslr5g1po)[] = "mcslr5g%c1po=0x%x";
1955 static const char BCMATTACHDATA(vstr_mcslr5g80p80po)[] = "mcslr5g80p80po=0x%x";
1956 /* HNBU_ACPPR_SBPO */
1957 static const char BCMATTACHDATA(vstr_sb20in40rpo)[] = "sb20in40%crpo=0x%x";
1958 /* HNBU_ACPPR_SBPO */
1959 static const char BCMATTACHDATA(vstr_sb20in40and80rpo)[] = "sb20in40and80%crpo=0x%x";
1960 static const char BCMATTACHDATA(vstr_sb20in80and160r5gpo)[] = "sb20in80and160%cr5g%cpo=0x%x";
1961 static const char BCMATTACHDATA(vstr_sb20in80and160r5g1po)[] = "sb20in80and160%cr5g%c1po=0x%x";
1962 static const char BCMATTACHDATA(vstr_sb2040and80in80p80r5gpo)[] =
1963 	"sb2040and80in80p80%cr5g%cpo=0x%x";
1964 static const char BCMATTACHDATA(vstr_sb2040and80in80p80r5g1po)[] =
1965 	"sb2040and80in80p80%cr5g%c1po=0x%x";
1966 static const char BCMATTACHDATA(vstr_sb20in40dot11agofdm2gpo)[] = "sb20in40dot11agofdm2gpo=0x%x";
1967 static const char BCMATTACHDATA(vstr_sb20in80dot11agofdm2gpo)[] = "sb20in80dot11agofdm2gpo=0x%x";
1968 static const char BCMATTACHDATA(vstr_sb20in40ofdmlrbw202gpo)[] = "sb20in40ofdmlrbw202gpo=0x%x";
1969 static const char BCMATTACHDATA(vstr_sb20in80ofdmlrbw202gpo)[] = "sb20in80ofdmlrbw202gpo=0x%x";
1970 static const char BCMATTACHDATA(vstr_sb20in80p80r5gpo)[] = "sb20in80p80%cr5gpo=0x%x";
1971 static const char BCMATTACHDATA(vstr_sb40and80r5gpo)[] = "sb40and80%cr5g%cpo=0x%x";
1972 static const char BCMATTACHDATA(vstr_sb40and80r5g1po)[] = "sb40and80%cr5g%c1po=0x%x";
1973 static const char BCMATTACHDATA(vstr_dot11agduprpo)[] = "dot11agdup%crpo=0x%x";
1974 static const char BCMATTACHDATA(vstr_dot11agduppo)[] = "dot11agduppo=0x%x";
1975 static const char BCMATTACHDATA(vstr_noiselvl2ga)[] = "noiselvl2ga%d=%d";	/* HNBU_NOISELVL */
1976 static const char BCMATTACHDATA(vstr_noiselvl5ga)[] = "noiselvl5ga%d=%d,%d,%d,%d";
1977 /* HNBU_RXGAIN_ERR */
1978 static const char BCMATTACHDATA(vstr_rxgainerr2ga)[] = "rxgainerr2ga%d=0x%x";
1979 static const char BCMATTACHDATA(vstr_rxgainerr5ga)[] = "rxgainerr5ga%d=0x%x,0x%x,0x%x,0x%x";
1980 static const char BCMATTACHDATA(vstr_agbg)[] = "agbg%d=0x%x";	/* HNBU_AGBGA */
1981 static const char BCMATTACHDATA(vstr_aga)[] = "aga%d=0x%x";
1982 static const char BCMATTACHDATA(vstr_txduty_ofdm)[] = "tx_duty_cycle_ofdm_%d_5g=%d";
1983 static const char BCMATTACHDATA(vstr_txduty_thresh)[] = "tx_duty_cycle_thresh_%d_5g=%d";
1984 static const char BCMATTACHDATA(vstr_paparambwver)[] = "paparambwver=%d";
1985 
1986 static const char BCMATTACHDATA(vstr_uuid)[] = "uuid=%s";
1987 
1988 static const char BCMATTACHDATA(vstr_wowlgpio)[] = "wowl_gpio=%d";
1989 static const char BCMATTACHDATA(vstr_wowlgpiopol)[] = "wowl_gpiopol=%d";
1990 
1991 static const char BCMATTACHDATA(rstr_ag0)[] = "ag0";
1992 static const char BCMATTACHDATA(rstr_sromrev)[] = "sromrev";
1993 
1994 static const char BCMATTACHDATA(vstr_paparamrpcalvars)[][20] =
1995 	{"rpcal2g=0x%x", "rpcal5gb0=0x%x", "rpcal5gb1=0x%x",
1996 	"rpcal5gb2=0x%x", "rpcal5gb3=0x%x"};
1997 
1998 static const char BCMATTACHDATA(vstr_gpdn)[] = "gpdn=0x%x";
1999 
2000 /* SROM V13 PA */
2001 static const char BCMATTACHDATA(vstr_sr13pa2ga)[] = "pa2ga%d=0x%x,0x%x,0x%x,0x%x";
2002 static const char BCMATTACHDATA(vstr_maxp5gba)[] = "maxp5gb%da%d=0x%x";
2003 static const char BCMATTACHDATA(vstr_sr13pa5ga)[] = "pa5ga%d=%s";
2004 static const char BCMATTACHDATA(vstr_sr13pa5gbwa)[] = "pa5g%da%d=%s";
2005 static const char BCMATTACHDATA(vstr_pa2g40a)[] = "pa2g40a%d=0x%x,0x%x,0x%x,0x%x";
2006 
2007 /* RSSI Cal parameters */
2008 static const char BCMATTACHDATA(vstr_rssicalfrqg)[] =
2009 	"rssi_cal_freq_grp_2g=0x%x0x%x0x%x0x%x0x%x0x%x0x%x";
2010 static const char BCMATTACHDATA(vstr_rssidelta2g)[] =
2011 	"rssi_delta_2gb%d=%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d";
2012 static const char BCMATTACHDATA(vstr_rssidelta5g)[] =
2013 	"rssi_delta_5g%s=%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d";
2014 
2015 uint8 patch_pair = 0;
2016 
2017 /* For dongle HW, accept partial calibration parameters */
2018 #if defined(BCMSDIODEV) || defined(BCMUSBDEV) || defined(BCMDONGLEHOST)
2019 #define BCMDONGLECASE(n) case n:
2020 #else
2021 #define BCMDONGLECASE(n)
2022 #endif
2023 
2024 #ifdef BCM_BOOTLOADER
2025 /* The format of the PMUREGS OTP Tuple ->
2026  * 1 byte -> Lower 5 bits has the address of the register
2027  *                 Higher 3 bits has the mode of the register like
2028  *                 PLL, ChipCtrl, RegCtrl, UpDwn or Dependency mask
2029  * 4 bytes -> Value of the register to be updated.
2030  */
2031 #define PMUREGS_MODE_MASK	0xE0
2032 #define PMUREGS_MODE_SHIFT	5
2033 #define PMUREGS_ADDR_MASK	0x1F
2034 #define PMUREGS_TPL_SIZE	5
2035 
2036 enum {
2037 	PMU_PLLREG_MODE,
2038 	PMU_CCREG_MODE,
2039 	PMU_VOLTREG_MODE,
2040 	PMU_RES_TIME_MODE,
2041 	PMU_RESDEPEND_MODE
2042 };
2043 
2044 #define USBREGS_TPL_SIZE	5
2045 enum {
2046 	USB_DEV_CTRL_REG,
2047 	HSIC_PHY_CTRL1_REG,
2048 	HSIC_PHY_CTRL2_REG
2049 };
2050 
2051 #define USBRDY_DLY_TYPE	0x8000	/* Bit indicating if the byte is pre or post delay value */
2052 #define USBRDY_DLY_MASK	0x7FFF	/* Bits indicating the amount of delay */
2053 #define USBRDY_MAXOTP_SIZE	5	/* Max size of the OTP parameter */
2054 
2055 #endif /* BCM_BOOTLOADER */
2056 
2057 static uint
2058 BCMATTACHFN(get_max_cis_size)(si_t *sih)
2059 {
2060 	uint max_cis_size;
2061 	void *oh;
2062 
2063 	max_cis_size = (sih && sih->ccrev >= 49) ? CIS_SIZE_12K : CIS_SIZE;
2064 	if (sih && (oh = otp_init(sih)) != NULL) {
2065 		max_cis_size -= otp_avsbitslen(oh);
2066 	}
2067 	return max_cis_size;
2068 }
2069 
2070 #ifndef BCM_BOOTLOADER
2071 static uint32
2072 BCMATTACHFN(srom_data2value)(uint8 *p, uint8 len)
2073 {
2074 	uint8 pos = 0;
2075 	uint32 value = 0;
2076 
2077 	ASSERT(len <= 4);
2078 
2079 	while (pos < len) {
2080 		value += (p[pos] << (pos * 8));
2081 		pos++;
2082 	}
2083 
2084 	return value;
2085 }
2086 #endif /* BCM_BOOTLOADER */
2087 
2088 /**
2089  * Both SROM and OTP contain variables in 'CIS' format, whereas the rest of the firmware works with
2090  * 'variable/value' string pairs.
2091  */
2092 int
2093 BCMATTACHFN(srom_parsecis)(si_t *sih, osl_t *osh, uint8 *pcis[], uint ciscnt, char **vars,
2094 	uint *count)
2095 {
2096 	char eabuf[32];
2097 	char eabuf2[32];
2098 	char *base;
2099 	varbuf_t b;
2100 	uint8 *cis, tup, tlen, sromrev = 1;
2101 	uint i;
2102 	uint16 j;
2103 #ifndef BCM_BOOTLOADER
2104 	bool ag_init = FALSE;
2105 #endif
2106 	uint32 w32;
2107 	uint funcid;
2108 	uint cisnum;
2109 	int32 boardnum;
2110 	int err;
2111 	bool standard_cis;
2112 	uint max_cis_size;
2113 	uint var_cis_size = 0;
2114 
2115 	ASSERT(count != NULL);
2116 
2117 	if (vars == NULL) {
2118 		ASSERT(0);	/* crash debug images for investigation */
2119 		return BCME_BADARG;
2120 	}
2121 
2122 	boardnum = -1;
2123 
2124 	/* freed in same function */
2125 	max_cis_size = get_max_cis_size(sih);
2126 	var_cis_size = *count + ((max_cis_size + 2u) * ciscnt);
2127 
2128 	ASSERT(var_cis_size <= MAXSZ_NVRAM_VARS);
2129 
2130 	base = MALLOC_NOPERSIST(osh, var_cis_size);
2131 	ASSERT(base != NULL);
2132 	if (!base)
2133 		return -2;
2134 
2135 	varbuf_init(&b, base, var_cis_size);
2136 	bzero(base, var_cis_size);
2137 	/* Append from vars if there's already something inside */
2138 	if (*vars && **vars && (*count >= 3)) {
2139 		/* back off \0 at the end, leaving only one \0 for the last param */
2140 		while (((*vars)[(*count)-1] == '\0') && ((*vars)[(*count)-2] == '\0'))
2141 			(*count)--;
2142 
2143 		bcopy(*vars, base, *count);
2144 		b.buf += *count;
2145 	}
2146 	eabuf[0] = '\0';
2147 	eabuf2[0] = '\0';
2148 	for (cisnum = 0; cisnum < ciscnt; cisnum++) {
2149 		cis = *pcis++;
2150 		i = 0;
2151 		funcid = 0;
2152 		standard_cis = TRUE;
2153 		do {
2154 			if (standard_cis) {
2155 				tup = cis[i++];
2156 				if (tup == CISTPL_NULL || tup == CISTPL_END)
2157 					tlen = 0;
2158 				else
2159 					tlen = cis[i++];
2160 			} else {
2161 				if (cis[i] == CISTPL_NULL || cis[i] == CISTPL_END) {
2162 					tlen = 0;
2163 					tup = cis[i];
2164 				} else {
2165 					tlen = cis[i];
2166 					tup = CISTPL_BRCM_HNBU;
2167 				}
2168 				++i;
2169 			}
2170 			if ((i + tlen) >= max_cis_size)
2171 				break;
2172 
2173 			switch (tup) {
2174 			case CISTPL_VERS_1:
2175 				/* assume the strings are good if the version field checks out */
2176 				if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) {
2177 					varbuf_append(&b, vstr_manf, &cis[i + 2]);
2178 					varbuf_append(&b, vstr_productname,
2179 					              &cis[i + 3 + strlen((char *)&cis[i + 2])]);
2180 					break;
2181 				}
2182 
2183 			case CISTPL_MANFID:
2184 				varbuf_append(&b, vstr_manfid, (cis[i + 1] << 8) + cis[i]);
2185 				varbuf_append(&b, vstr_prodid, (cis[i + 3] << 8) + cis[i + 2]);
2186 				break;
2187 
2188 			case CISTPL_FUNCID:
2189 				funcid = cis[i];
2190 				break;
2191 
2192 			case CISTPL_FUNCE:
2193 				switch (funcid) {
2194 				case CISTPL_FID_SDIO:
2195 #ifdef BCMSDIO
2196 					if (cis[i] == 0) {
2197 						uint8 spd = cis[i + 3];
2198 						static int lbase[] = {
2199 							-1, 10, 12, 13, 15, 20, 25, 30,
2200 							35, 40, 45, 50, 55, 60, 70, 80
2201 						};
2202 						static int mult[] = {
2203 							10, 100, 1000, 10000,
2204 							-1, -1, -1, -1
2205 						};
2206 						ASSERT((mult[spd & 0x7] != -1) &&
2207 						       (lbase[(spd >> 3) & 0x0f]));
2208 						varbuf_append(&b, vstr_sdmaxblk[0],
2209 						              (cis[i + 2] << 8) + cis[i + 1]);
2210 						varbuf_append(&b, vstr_sdmaxspeed,
2211 						              (mult[spd & 0x7] *
2212 						               lbase[(spd >> 3) & 0x0f]));
2213 					} else if (cis[i] == 1) {
2214 						varbuf_append(&b, vstr_sdmaxblk[cisnum],
2215 						              (cis[i + 13] << 8) | cis[i + 12]);
2216 					}
2217 #endif /* BCMSDIO */
2218 					funcid = 0;
2219 					break;
2220 				default:
2221 					/* set macaddr if HNBU_MACADDR not seen yet */
2222 					if (eabuf[0] == '\0' && cis[i] == LAN_NID &&
2223 						!(ETHER_ISNULLADDR(&cis[i + 2])) &&
2224 						!(ETHER_ISMULTI(&cis[i + 2]))) {
2225 						ASSERT(cis[i + 1] == ETHER_ADDR_LEN);
2226 						bcm_ether_ntoa((struct ether_addr *)&cis[i + 2],
2227 						               eabuf);
2228 
2229 						/* set boardnum if HNBU_BOARDNUM not seen yet */
2230 						if (boardnum == -1)
2231 							boardnum = (cis[i + 6] << 8) + cis[i + 7];
2232 					}
2233 					break;
2234 				}
2235 				break;
2236 
2237 			case CISTPL_CFTABLE:
2238 				varbuf_append(&b, vstr_regwindowsz, (cis[i + 7] << 8) | cis[i + 6]);
2239 				break;
2240 
2241 			case CISTPL_BRCM_HNBU:
2242 				switch (cis[i]) {
2243 				case HNBU_SROMREV:
2244 					sromrev = cis[i + 1];
2245 					varbuf_append(&b, vstr_sromrev, sromrev);
2246 					break;
2247 
2248 				case HNBU_XTALFREQ:
2249 					varbuf_append(&b, vstr_xtalfreq,
2250 					              (cis[i + 4] << 24) |
2251 					              (cis[i + 3] << 16) |
2252 					              (cis[i + 2] << 8) |
2253 					              cis[i + 1]);
2254 					break;
2255 
2256 				case HNBU_CHIPID:
2257 					varbuf_append(&b, vstr_vendid, (cis[i + 2] << 8) +
2258 					              cis[i + 1]);
2259 					varbuf_append(&b, vstr_devid, (cis[i + 4] << 8) +
2260 					              cis[i + 3]);
2261 					if (tlen >= 7) {
2262 						varbuf_append(&b, vstr_chiprev,
2263 						              (cis[i + 6] << 8) + cis[i + 5]);
2264 					}
2265 					if (tlen >= 9) {
2266 						varbuf_append(&b, vstr_subvendid,
2267 						              (cis[i + 8] << 8) + cis[i + 7]);
2268 					}
2269 					if (tlen >= 11) {
2270 						varbuf_append(&b, vstr_subdevid,
2271 						              (cis[i + 10] << 8) + cis[i + 9]);
2272 						/* subdevid doubles for boardtype */
2273 						varbuf_append(&b, vstr_boardtype,
2274 						              (cis[i + 10] << 8) + cis[i + 9]);
2275 					}
2276 					break;
2277 
2278 				case HNBU_BOARDNUM:
2279 					boardnum = (cis[i + 2] << 8) + cis[i + 1];
2280 					break;
2281 
2282 				case HNBU_PATCH: {
2283 					char vstr_paddr[16];
2284 					char vstr_pdata[16];
2285 
2286 					/* retrieve the patch pairs
2287 					 * from tlen/6; where 6 is
2288 					 * sizeof(patch addr(2)) +
2289 					 * sizeof(patch data(4)).
2290 					 */
2291 					patch_pair = tlen/6;
2292 
2293 					for (j = 0; j < patch_pair; j++) {
2294 						snprintf(vstr_paddr, sizeof(vstr_paddr),
2295 							rstr_paddr, j);
2296 						snprintf(vstr_pdata, sizeof(vstr_pdata),
2297 							rstr_pdata, j);
2298 
2299 						varbuf_append(&b, vstr_paddr,
2300 							(cis[i + (j*6) + 2] << 8) |
2301 							cis[i + (j*6) + 1]);
2302 
2303 						varbuf_append(&b, vstr_pdata,
2304 							(cis[i + (j*6) + 6] << 24) |
2305 							(cis[i + (j*6) + 5] << 16) |
2306 							(cis[i + (j*6) + 4] << 8) |
2307 							cis[i + (j*6) + 3]);
2308 					}
2309 					break;
2310 				}
2311 
2312 				case HNBU_BOARDREV:
2313 					if (tlen == 2)
2314 						varbuf_append(&b, vstr_boardrev, cis[i + 1]);
2315 					else
2316 						varbuf_append(&b, vstr_boardrev,
2317 							(cis[i + 2] << 8) + cis[i + 1]);
2318 					break;
2319 
2320 				case HNBU_BOARDFLAGS:
2321 					w32 = (cis[i + 2] << 8) + cis[i + 1];
2322 					if (tlen >= 5)
2323 						w32 |= ((cis[i + 4] << 24) + (cis[i + 3] << 16));
2324 					varbuf_append(&b, vstr_boardflags, w32);
2325 
2326 					if (tlen >= 7) {
2327 						w32 = (cis[i + 6] << 8) + cis[i + 5];
2328 						if (tlen >= 9)
2329 							w32 |= ((cis[i + 8] << 24) +
2330 								(cis[i + 7] << 16));
2331 						varbuf_append(&b, vstr_boardflags2, w32);
2332 					}
2333 					if (tlen >= 11) {
2334 						w32 = (cis[i + 10] << 8) + cis[i + 9];
2335 						if (tlen >= 13)
2336 							w32 |= ((cis[i + 12] << 24) +
2337 								(cis[i + 11] << 16));
2338 						varbuf_append(&b, vstr_boardflags3, w32);
2339 					}
2340 					if (tlen >= 15) {
2341 						w32 = (cis[i + 14] << 8) + cis[i + 13];
2342 						if (tlen >= 17)
2343 							w32 |= ((cis[i + 16] << 24) +
2344 								(cis[i + 15] << 16));
2345 						varbuf_append(&b, vstr_boardflags4, w32);
2346 					}
2347 					if (tlen >= 19) {
2348 						w32 = (cis[i + 18] << 8) + cis[i + 17];
2349 						if (tlen >= 21)
2350 							w32 |= ((cis[i + 20] << 24) +
2351 								(cis[i + 19] << 16));
2352 						varbuf_append(&b, vstr_boardflags5, w32);
2353 					}
2354 					break;
2355 
2356 				case HNBU_USBFS:
2357 					varbuf_append(&b, vstr_usbfs, cis[i + 1]);
2358 					break;
2359 
2360 				case HNBU_BOARDTYPE:
2361 					varbuf_append(&b, vstr_boardtype,
2362 					              (cis[i + 2] << 8) + cis[i + 1]);
2363 					break;
2364 
2365 				case HNBU_HNBUCIS:
2366 					/*
2367 					 * what follows is a nonstandard HNBU CIS
2368 					 * that lacks CISTPL_BRCM_HNBU tags
2369 					 *
2370 					 * skip 0xff (end of standard CIS)
2371 					 * after this tuple
2372 					 */
2373 					tlen++;
2374 					standard_cis = FALSE;
2375 					break;
2376 
2377 				case HNBU_USBEPNUM:
2378 					varbuf_append(&b, vstr_usbepnum,
2379 						(cis[i + 2] << 8) | cis[i + 1]);
2380 					break;
2381 
2382 				case HNBU_PATCH_AUTOINC: {
2383 					char vstr_paddr[16];
2384 					char vstr_pdata[16];
2385 					uint32 addr_inc;
2386 					uint8 pcnt;
2387 
2388 					addr_inc = (cis[i + 4] << 24) |
2389 						(cis[i + 3] << 16) |
2390 						(cis[i + 2] << 8) |
2391 						(cis[i + 1]);
2392 
2393 					pcnt = (tlen - 5)/4;
2394 					for (j = 0; j < pcnt; j++) {
2395 						snprintf(vstr_paddr, sizeof(vstr_paddr),
2396 							rstr_paddr, j + patch_pair);
2397 						snprintf(vstr_pdata, sizeof(vstr_pdata),
2398 							rstr_pdata, j + patch_pair);
2399 
2400 						varbuf_append(&b, vstr_paddr, addr_inc);
2401 						varbuf_append(&b, vstr_pdata,
2402 							(cis[i + (j*4) + 8] << 24) |
2403 							(cis[i + (j*4) + 7] << 16) |
2404 							(cis[i + (j*4) + 6] << 8) |
2405 							cis[i + (j*4) + 5]);
2406 						addr_inc += 4;
2407 					}
2408 					patch_pair += pcnt;
2409 					break;
2410 				}
2411 				case HNBU_PATCH2: {
2412 					char vstr_paddr[16];
2413 					char vstr_pdata[16];
2414 
2415 					/* retrieve the patch pairs
2416 					 * from tlen/8; where 8 is
2417 					 * sizeof(patch addr(4)) +
2418 					 * sizeof(patch data(4)).
2419 					 */
2420 					patch_pair = tlen/8;
2421 
2422 					for (j = 0; j < patch_pair; j++) {
2423 						snprintf(vstr_paddr, sizeof(vstr_paddr),
2424 							rstr_paddr, j);
2425 						snprintf(vstr_pdata, sizeof(vstr_pdata),
2426 							rstr_pdata, j);
2427 
2428 						varbuf_append(&b, vstr_paddr,
2429 							(cis[i + (j*8) + 4] << 24) |
2430 							(cis[i + (j*8) + 3] << 16) |
2431 							(cis[i + (j*8) + 2] << 8) |
2432 							cis[i + (j*8) + 1]);
2433 
2434 						varbuf_append(&b, vstr_pdata,
2435 							(cis[i + (j*8) + 8] << 24) |
2436 							(cis[i + (j*8) + 7] << 16) |
2437 							(cis[i + (j*8) + 6] << 8) |
2438 							cis[i + (j*8) + 5]);
2439 					}
2440 					break;
2441 				}
2442 				case HNBU_PATCH_AUTOINC8: {
2443 					char vstr_paddr[16];
2444 					char vstr_pdatah[16];
2445 					char vstr_pdatal[16];
2446 					uint32 addr_inc;
2447 					uint8 pcnt;
2448 
2449 					addr_inc = (cis[i + 4] << 24) |
2450 						(cis[i + 3] << 16) |
2451 						(cis[i + 2] << 8) |
2452 						(cis[i + 1]);
2453 
2454 					pcnt = (tlen - 5)/8;
2455 					for (j = 0; j < pcnt; j++) {
2456 						snprintf(vstr_paddr, sizeof(vstr_paddr),
2457 							rstr_paddr, j + patch_pair);
2458 						snprintf(vstr_pdatah, sizeof(vstr_pdatah),
2459 							rstr_pdatah, j + patch_pair);
2460 						snprintf(vstr_pdatal, sizeof(vstr_pdatal),
2461 							rstr_pdatal, j + patch_pair);
2462 
2463 						varbuf_append(&b, vstr_paddr, addr_inc);
2464 						varbuf_append(&b, vstr_pdatal,
2465 							(cis[i + (j*8) + 8] << 24) |
2466 							(cis[i + (j*8) + 7] << 16) |
2467 							(cis[i + (j*8) + 6] << 8) |
2468 							cis[i + (j*8) + 5]);
2469 						varbuf_append(&b, vstr_pdatah,
2470 							(cis[i + (j*8) + 12] << 24) |
2471 							(cis[i + (j*8) + 11] << 16) |
2472 							(cis[i + (j*8) + 10] << 8) |
2473 							cis[i + (j*8) + 9]);
2474 						addr_inc += 8;
2475 					}
2476 					patch_pair += pcnt;
2477 					break;
2478 				}
2479 				case HNBU_PATCH8: {
2480 					char vstr_paddr[16];
2481 					char vstr_pdatah[16];
2482 					char vstr_pdatal[16];
2483 
2484 					/* retrieve the patch pairs
2485 					 * from tlen/8; where 8 is
2486 					 * sizeof(patch addr(4)) +
2487 					 * sizeof(patch data(4)).
2488 					 */
2489 					patch_pair = tlen/12;
2490 
2491 					for (j = 0; j < patch_pair; j++) {
2492 						snprintf(vstr_paddr, sizeof(vstr_paddr),
2493 							rstr_paddr, j);
2494 						snprintf(vstr_pdatah, sizeof(vstr_pdatah),
2495 							rstr_pdatah, j);
2496 						snprintf(vstr_pdatal, sizeof(vstr_pdatal),
2497 							rstr_pdatal, j);
2498 
2499 						varbuf_append(&b, vstr_paddr,
2500 							(cis[i + (j*12) + 4] << 24) |
2501 							(cis[i + (j*12) + 3] << 16) |
2502 							(cis[i + (j*12) + 2] << 8) |
2503 							cis[i + (j*12) + 1]);
2504 
2505 						varbuf_append(&b, vstr_pdatal,
2506 							(cis[i + (j*12) + 8] << 24) |
2507 							(cis[i + (j*12) + 7] << 16) |
2508 							(cis[i + (j*12) + 6] << 8) |
2509 							cis[i + (j*12) + 5]);
2510 
2511 						varbuf_append(&b, vstr_pdatah,
2512 							(cis[i + (j*12) + 12] << 24) |
2513 							(cis[i + (j*12) + 11] << 16) |
2514 							(cis[i + (j*12) + 10] << 8) |
2515 							cis[i + (j*12) + 9]);
2516 					}
2517 					break;
2518 				}
2519 				case HNBU_USBFLAGS:
2520 					varbuf_append(&b, vstr_usbflags,
2521 					              (cis[i + 4] << 24) |
2522 					              (cis[i + 3] << 16) |
2523 					              (cis[i + 2] << 8) |
2524 					              cis[i + 1]);
2525 					break;
2526 #ifdef BCM_BOOTLOADER
2527 				case HNBU_MDIOEX_REGLIST:
2528 				case HNBU_MDIO_REGLIST: {
2529 					/* Format: addr (8 bits) | val (16 bits) */
2530 					const uint8 msize = 3;
2531 					char mdiostr[24];
2532 					const char *mdiodesc;
2533 					uint8 *st;
2534 
2535 					mdiodesc = (cis[i] == HNBU_MDIO_REGLIST) ?
2536 						vstr_mdio : vstr_mdioex;
2537 
2538 					ASSERT(((tlen - 1) % msize) == 0);
2539 
2540 					st = &cis[i + 1]; /* start of reg list */
2541 					for (j = 0; j < (tlen - 1); j += msize, st += msize) {
2542 						snprintf(mdiostr, sizeof(mdiostr),
2543 							mdiodesc, st[0]);
2544 						varbuf_append(&b, mdiostr, (st[2] << 8) | st[1]);
2545 					}
2546 					break;
2547 				}
2548 				case HNBU_BRMIN:
2549 					varbuf_append(&b, vstr_brmin,
2550 					              (cis[i + 4] << 24) |
2551 					              (cis[i + 3] << 16) |
2552 					              (cis[i + 2] << 8) |
2553 					              cis[i + 1]);
2554 					break;
2555 
2556 				case HNBU_BRMAX:
2557 					varbuf_append(&b, vstr_brmax,
2558 					              (cis[i + 4] << 24) |
2559 					              (cis[i + 3] << 16) |
2560 					              (cis[i + 2] << 8) |
2561 					              cis[i + 1]);
2562 					break;
2563 #endif /* BCM_BOOTLOADER */
2564 
2565 				case HNBU_RDLID:
2566 					varbuf_append(&b, vstr_rdlid,
2567 					              (cis[i + 2] << 8) | cis[i + 1]);
2568 					break;
2569 
2570 				case HNBU_GCI_CCR: {
2571 					/* format:
2572 					 * |0x80|	<== brcm
2573 					 * |len|	<== variable, multiple of 5
2574 					 * |tup|	<== tupletype
2575 					 * |ccreg_ix0|	<== ix of ccreg [1byte]
2576 					 * |ccreg_val0|	<== corr value [4bytes]
2577 					 *	---
2578 					 * Multiple registers are possible. for eg: we
2579 					 *	can specify reg_ix3val3 and reg_ix5val5, etc
2580 					 */
2581 					char vstr_gci_ccreg_entry[16];
2582 					uint8 num_entries = 0;
2583 
2584 					/* retrieve the index-value pairs
2585 					 * from tlen/5; where 5 is
2586 					 * sizeof(ccreg_ix(1)) +
2587 					 * sizeof(ccreg_val(4)).
2588 					 */
2589 					num_entries = tlen/5;
2590 
2591 					for (j = 0; j < num_entries; j++) {
2592 						snprintf(vstr_gci_ccreg_entry,
2593 							sizeof(vstr_gci_ccreg_entry),
2594 							rstr_gci_ccreg_entry,
2595 							cis[i + (j*5) + 1]);
2596 
2597 						varbuf_append(&b, vstr_gci_ccreg_entry,
2598 							(cis[i + (j*5) + 5] << 24) |
2599 							(cis[i + (j*5) + 4] << 16) |
2600 							(cis[i + (j*5) + 3] << 8) |
2601 							cis[i + (j*5) + 2]);
2602 					}
2603 					break;
2604 				}
2605 
2606 #ifdef BCM_BOOTLOADER
2607 				case HNBU_RDLRNDIS:
2608 					varbuf_append(&b, vstr_rdlrndis, cis[i + 1]);
2609 					break;
2610 
2611 				case HNBU_RDLRWU:
2612 					varbuf_append(&b, vstr_rdlrwu, cis[i + 1]);
2613 					break;
2614 
2615 				case HNBU_RDLSN:
2616 					if (tlen >= 5)
2617 						varbuf_append(&b, vstr_rdlsn,
2618 						              (cis[i + 4] << 24) |
2619 						              (cis[i + 3] << 16) |
2620 						              (cis[i + 2] << 8) |
2621 						              cis[i + 1]);
2622 					else
2623 						varbuf_append(&b, vstr_rdlsn,
2624 						              (cis[i + 2] << 8) |
2625 						              cis[i + 1]);
2626 					break;
2627 
2628 				case HNBU_PMUREGS: {
2629 					uint8 offset = 1, mode_addr, mode, addr;
2630 					const char *fmt;
2631 
2632 					do {
2633 						mode_addr = cis[i+offset];
2634 
2635 						mode = (mode_addr & PMUREGS_MODE_MASK)
2636 							>> PMUREGS_MODE_SHIFT;
2637 						addr = mode_addr & PMUREGS_ADDR_MASK;
2638 
2639 						switch (mode) {
2640 						case PMU_PLLREG_MODE:
2641 							fmt = vstr_pllreg;
2642 							break;
2643 						case PMU_CCREG_MODE:
2644 							fmt = vstr_ccreg;
2645 							break;
2646 						case PMU_VOLTREG_MODE:
2647 							fmt = vstr_regctrl;
2648 							break;
2649 						case PMU_RES_TIME_MODE:
2650 							fmt = vstr_time;
2651 							break;
2652 						case PMU_RESDEPEND_MODE:
2653 							fmt = vstr_depreg;
2654 							break;
2655 						default:
2656 							fmt = NULL;
2657 							break;
2658 						}
2659 
2660 						if (fmt != NULL) {
2661 							varbuf_append(&b, fmt, addr,
2662 								(cis[i + offset + 4] << 24) |
2663 								(cis[i + offset + 3] << 16) |
2664 								(cis[i + offset + 2] << 8) |
2665 								cis[i + offset + 1]);
2666 						}
2667 
2668 						offset += PMUREGS_TPL_SIZE;
2669 					} while (offset < tlen);
2670 					break;
2671 				}
2672 
2673 				case HNBU_USBREGS: {
2674 					uint8 offset = 1, usb_reg;
2675 					const char *fmt;
2676 
2677 					do {
2678 						usb_reg = cis[i+offset];
2679 
2680 						switch (usb_reg) {
2681 						case USB_DEV_CTRL_REG:
2682 							fmt = vstr_usbdevctrl;
2683 							break;
2684 						case HSIC_PHY_CTRL1_REG:
2685 							fmt = vstr_hsicphyctrl1;
2686 							break;
2687 						case HSIC_PHY_CTRL2_REG:
2688 							fmt = vstr_hsicphyctrl2;
2689 							break;
2690 						default:
2691 							fmt = NULL;
2692 							break;
2693 						}
2694 
2695 						if (fmt != NULL) {
2696 							varbuf_append(&b, fmt,
2697 								(cis[i + offset + 4] << 24) |
2698 								(cis[i + offset + 3] << 16) |
2699 								(cis[i + offset + 2] << 8) |
2700 								cis[i + offset + 1]);
2701 						}
2702 
2703 						offset += USBREGS_TPL_SIZE;
2704 					} while (offset < tlen);
2705 					break;
2706 				}
2707 
2708 				case HNBU_USBRDY:
2709 					/* The first byte of this tuple indicate if the host
2710 					 * needs to be informed about the readiness of
2711 					 * the HSIC/USB for enumeration on which GPIO should
2712 					 * the device assert this event.
2713 					 */
2714 					varbuf_append(&b, vstr_usbrdy, cis[i + 1]);
2715 
2716 					/* The following fields in this OTP are optional.
2717 					 * The remaining bytes will indicate the delay required
2718 					 * before and/or after the ch_init(). The delay is defined
2719 					 * using 16-bits of this the MSB(bit15 of 15:0) will be
2720 					 * used indicate if the parameter is for Pre or Post delay.
2721 					 */
2722 					for (j = 2; j < USBRDY_MAXOTP_SIZE && j < tlen;
2723 						j += 2) {
2724 						uint16 usb_delay;
2725 
2726 						usb_delay = cis[i + j] | (cis[i + j + 1] << 8);
2727 
2728 						/* The bit-15 of the delay field will indicate the
2729 						 * type of delay (pre or post).
2730 						 */
2731 						if (usb_delay & USBRDY_DLY_TYPE) {
2732 							varbuf_append(&b, vstr_usbpostdly,
2733 							(usb_delay & USBRDY_DLY_MASK));
2734 						} else {
2735 							varbuf_append(&b, vstr_usbpredly,
2736 							(usb_delay & USBRDY_DLY_MASK));
2737 						}
2738 					}
2739 					break;
2740 
2741 				case HNBU_BLDR_TIMEOUT:
2742 					/* The Delay after USBConnect for timeout till dongle
2743 					 * receives get_descriptor request.
2744 					 */
2745 					varbuf_append(&b, vstr_bldr_reset_timeout,
2746 						(cis[i + 1] | (cis[i + 2] << 8)));
2747 					break;
2748 
2749 				case HNBU_MUXENAB:
2750 					varbuf_append(&b, vstr_muxenab, cis[i + 1]);
2751 					break;
2752 				case HNBU_PUBKEY: {
2753 					/* The public key is in binary format in OTP,
2754 					 * convert to string format before appending
2755 					 * buffer string.
2756 					 *  public key(12 bytes) + crc (1byte) = 129
2757 					 */
2758 					unsigned char a[300];
2759 					int k;
2760 
2761 					for (k = 1, j = 0; k < 129; k++)
2762 						j += snprintf((char *)(a + j),
2763 							sizeof(a) - j,
2764 							"%02x", cis[i + k]);
2765 
2766 					a[256] = 0;
2767 
2768 					varbuf_append(&b, vstr_pubkey, a);
2769 					break;
2770 				}
2771 #else
2772 				case HNBU_AA:
2773 					varbuf_append(&b, vstr_aa2g, cis[i + 1]);
2774 					if (tlen >= 3)
2775 						varbuf_append(&b, vstr_aa5g, cis[i + 2]);
2776 					break;
2777 
2778 				case HNBU_AG:
2779 					varbuf_append(&b, vstr_ag, 0, cis[i + 1]);
2780 					if (tlen >= 3)
2781 						varbuf_append(&b, vstr_ag, 1, cis[i + 2]);
2782 					if (tlen >= 4)
2783 						varbuf_append(&b, vstr_ag, 2, cis[i + 3]);
2784 					if (tlen >= 5)
2785 						varbuf_append(&b, vstr_ag, 3, cis[i + 4]);
2786 					ag_init = TRUE;
2787 					break;
2788 
2789 				case HNBU_ANT5G:
2790 					varbuf_append(&b, vstr_aa5g, cis[i + 1]);
2791 					varbuf_append(&b, vstr_ag, 1, cis[i + 2]);
2792 					break;
2793 
2794 				case HNBU_CC:
2795 					ASSERT(sromrev == 1);
2796 					varbuf_append(&b, vstr_cc, cis[i + 1]);
2797 					break;
2798 
2799 				case HNBU_PAPARMS: {
2800 					uint8 pa0_lo_offset = 0;
2801 					switch (tlen) {
2802 					case 2:
2803 						ASSERT(sromrev == 1);
2804 						varbuf_append(&b, vstr_pa0maxpwr, cis[i + 1]);
2805 						break;
2806 					/* case 16:
2807 						ASSERT(sromrev >= 11);
2808 						for (j = 0; j < 3; j++) {
2809 						varbuf_append(&b, vstr_pa0b_lo[j],
2810 								(cis[i + (j * 2) + 11] << 8) +
2811 								cis[i + (j * 2) + 10]);
2812 						}
2813 						 FALLTHROUGH
2814 					*/
2815 					case 10:
2816 					case 16:
2817 						ASSERT(sromrev >= 2);
2818 						varbuf_append(&b, vstr_opo, cis[i + 9]);
2819 						if (tlen >= 13 && pa0_lo_offset == 0)
2820 							pa0_lo_offset = 9;
2821 						/* FALLTHROUGH */
2822 					case 9:
2823 					case 15:
2824 						varbuf_append(&b, vstr_pa0maxpwr, cis[i + 8]);
2825 						if (tlen >= 13 && pa0_lo_offset == 0)
2826 							pa0_lo_offset = 8;
2827 						/* FALLTHROUGH */
2828 					BCMDONGLECASE(8)
2829 					BCMDONGLECASE(14)
2830 						varbuf_append(&b, vstr_pa0itssit, cis[i + 7]);
2831 						varbuf_append(&b, vstr_maxp2ga, 0, cis[i + 7]);
2832 						if (tlen >= 13 && pa0_lo_offset == 0)
2833 							pa0_lo_offset = 7;
2834 						/* FALLTHROUGH */
2835 					BCMDONGLECASE(7)
2836 					BCMDONGLECASE(13)
2837 					        for (j = 0; j < 3; j++) {
2838 							varbuf_append(&b, vstr_pa0b[j],
2839 							              (cis[i + (j * 2) + 2] << 8) +
2840 							              cis[i + (j * 2) + 1]);
2841 						}
2842 						if (tlen >= 13 && pa0_lo_offset == 0)
2843 							pa0_lo_offset = 6;
2844 
2845 						if (tlen >= 13 && pa0_lo_offset != 0) {
2846 							for (j = 0; j < 3; j++) {
2847 								varbuf_append(&b, vstr_pa0b_lo[j],
2848 								 (cis[pa0_lo_offset+i+(j*2)+2]<<8)+
2849 								 cis[pa0_lo_offset+i+(j*2)+1]);
2850 							}
2851 						}
2852 						break;
2853 					default:
2854 						ASSERT((tlen == 2) || (tlen == 9) || (tlen == 10) ||
2855 							(tlen == 15) || (tlen == 16));
2856 						break;
2857 					}
2858 					break;
2859 				}
2860 				case HNBU_PAPARMS5G:
2861 					ASSERT((sromrev == 2) || (sromrev == 3));
2862 					switch (tlen) {
2863 					case 23:
2864 						varbuf_append(&b, vstr_pa1himaxpwr, cis[i + 22]);
2865 						varbuf_append(&b, vstr_pa1lomaxpwr, cis[i + 21]);
2866 						varbuf_append(&b, vstr_pa1maxpwr, cis[i + 20]);
2867 						/* FALLTHROUGH */
2868 					case 20:
2869 						varbuf_append(&b, vstr_pa1itssit, cis[i + 19]);
2870 						/* FALLTHROUGH */
2871 					case 19:
2872 						for (j = 0; j < 3; j++) {
2873 							varbuf_append(&b, vstr_pa1b[j],
2874 							              (cis[i + (j * 2) + 2] << 8) +
2875 							              cis[i + (j * 2) + 1]);
2876 						}
2877 						for (j = 3; j < 6; j++) {
2878 							varbuf_append(&b, vstr_pa1lob[j - 3],
2879 							              (cis[i + (j * 2) + 2] << 8) +
2880 							              cis[i + (j * 2) + 1]);
2881 						}
2882 						for (j = 6; j < 9; j++) {
2883 							varbuf_append(&b, vstr_pa1hib[j - 6],
2884 							              (cis[i + (j * 2) + 2] << 8) +
2885 							              cis[i + (j * 2) + 1]);
2886 						}
2887 						break;
2888 					default:
2889 						ASSERT((tlen == 19) ||
2890 						       (tlen == 20) || (tlen == 23));
2891 						break;
2892 					}
2893 					break;
2894 
2895 				case HNBU_OEM:
2896 					ASSERT(sromrev == 1);
2897 					varbuf_append(&b, vstr_oem,
2898 					              cis[i + 1], cis[i + 2],
2899 					              cis[i + 3], cis[i + 4],
2900 					              cis[i + 5], cis[i + 6],
2901 					              cis[i + 7], cis[i + 8]);
2902 					break;
2903 
2904 				case HNBU_CCODE:
2905 					ASSERT(sromrev > 1);
2906 					if ((cis[i + 1] == 0) || (cis[i + 2] == 0))
2907 						varbuf_append(&b, vstr_noccode);
2908 					else
2909 						varbuf_append(&b, vstr_ccode,
2910 						              cis[i + 1], cis[i + 2]);
2911 					varbuf_append(&b, vstr_cctl, cis[i + 3]);
2912 					break;
2913 
2914 				case HNBU_CCKPO:
2915 					ASSERT(sromrev > 2);
2916 					varbuf_append(&b, vstr_cckpo,
2917 					              (cis[i + 2] << 8) | cis[i + 1]);
2918 					break;
2919 
2920 				case HNBU_OFDMPO:
2921 					ASSERT(sromrev > 2);
2922 					varbuf_append(&b, vstr_ofdmpo,
2923 					              (cis[i + 4] << 24) |
2924 					              (cis[i + 3] << 16) |
2925 					              (cis[i + 2] << 8) |
2926 					              cis[i + 1]);
2927 					break;
2928 
2929 				case HNBU_WPS:
2930 					varbuf_append(&b, vstr_wpsgpio, cis[i + 1]);
2931 					if (tlen >= 3)
2932 						varbuf_append(&b, vstr_wpsled, cis[i + 2]);
2933 					break;
2934 
2935 				case HNBU_RSSISMBXA2G:
2936 					ASSERT(sromrev == 3);
2937 					varbuf_append(&b, vstr_rssismf2g, cis[i + 1] & 0xf);
2938 					varbuf_append(&b, vstr_rssismc2g, (cis[i + 1] >> 4) & 0xf);
2939 					varbuf_append(&b, vstr_rssisav2g, cis[i + 2] & 0x7);
2940 					varbuf_append(&b, vstr_bxa2g, (cis[i + 2] >> 3) & 0x3);
2941 					break;
2942 
2943 				case HNBU_RSSISMBXA5G:
2944 					ASSERT(sromrev == 3);
2945 					varbuf_append(&b, vstr_rssismf5g, cis[i + 1] & 0xf);
2946 					varbuf_append(&b, vstr_rssismc5g, (cis[i + 1] >> 4) & 0xf);
2947 					varbuf_append(&b, vstr_rssisav5g, cis[i + 2] & 0x7);
2948 					varbuf_append(&b, vstr_bxa5g, (cis[i + 2] >> 3) & 0x3);
2949 					break;
2950 
2951 				case HNBU_TRI2G:
2952 					ASSERT(sromrev == 3);
2953 					varbuf_append(&b, vstr_tri2g, cis[i + 1]);
2954 					break;
2955 
2956 				case HNBU_TRI5G:
2957 					ASSERT(sromrev == 3);
2958 					varbuf_append(&b, vstr_tri5gl, cis[i + 1]);
2959 					varbuf_append(&b, vstr_tri5g, cis[i + 2]);
2960 					varbuf_append(&b, vstr_tri5gh, cis[i + 3]);
2961 					break;
2962 
2963 				case HNBU_RXPO2G:
2964 					ASSERT(sromrev == 3);
2965 					varbuf_append(&b, vstr_rxpo2g, cis[i + 1]);
2966 					break;
2967 
2968 				case HNBU_RXPO5G:
2969 					ASSERT(sromrev == 3);
2970 					varbuf_append(&b, vstr_rxpo5g, cis[i + 1]);
2971 					break;
2972 
2973 				case HNBU_MACADDR:
2974 					if (!(ETHER_ISNULLADDR(&cis[i+1])) &&
2975 					    !(ETHER_ISMULTI(&cis[i+1]))) {
2976 						bcm_ether_ntoa((struct ether_addr *)&cis[i + 1],
2977 						               eabuf);
2978 
2979 						/* set boardnum if HNBU_BOARDNUM not seen yet */
2980 						if (boardnum == -1)
2981 							boardnum = (cis[i + 5] << 8) + cis[i + 6];
2982 					}
2983 					break;
2984 
2985 				case HNBU_CHAINSWITCH:
2986 					varbuf_append(&b, vstr_txchain, cis[i + 1]);
2987 					varbuf_append(&b, vstr_rxchain, cis[i + 2]);
2988 					varbuf_append(&b, vstr_antswitch,
2989 					      (cis[i + 4] << 8) + cis[i + 3]);
2990 					break;
2991 
2992 				case HNBU_ELNA2G:
2993 					varbuf_append(&b, vstr_elna2g, cis[i + 1]);
2994 					break;
2995 
2996 				case HNBU_ELNA5G:
2997 					varbuf_append(&b, vstr_elna5g, cis[i + 1]);
2998 					break;
2999 
3000 				case HNBU_REGREV:
3001 					varbuf_append(&b, vstr_regrev,
3002 						srom_data2value(&cis[i + 1], tlen - 1));
3003 					break;
3004 
3005 				case HNBU_FEM: {
3006 					uint16 fem = (cis[i + 2] << 8) + cis[i + 1];
3007 					varbuf_append(&b, vstr_antswctl2g, (fem &
3008 						SROM8_FEM_ANTSWLUT_MASK) >>
3009 						SROM8_FEM_ANTSWLUT_SHIFT);
3010 					varbuf_append(&b, vstr_triso2g, (fem &
3011 						SROM8_FEM_TR_ISO_MASK) >>
3012 						SROM8_FEM_TR_ISO_SHIFT);
3013 					varbuf_append(&b, vstr_pdetrange2g, (fem &
3014 						SROM8_FEM_PDET_RANGE_MASK) >>
3015 						SROM8_FEM_PDET_RANGE_SHIFT);
3016 					varbuf_append(&b, vstr_extpagain2g, (fem &
3017 						SROM8_FEM_EXTPA_GAIN_MASK) >>
3018 						SROM8_FEM_EXTPA_GAIN_SHIFT);
3019 					varbuf_append(&b, vstr_tssipos2g, (fem &
3020 						SROM8_FEM_TSSIPOS_MASK) >>
3021 						SROM8_FEM_TSSIPOS_SHIFT);
3022 					if (tlen < 5) break;
3023 
3024 					fem = (cis[i + 4] << 8) + cis[i + 3];
3025 					varbuf_append(&b, vstr_antswctl5g, (fem &
3026 						SROM8_FEM_ANTSWLUT_MASK) >>
3027 						SROM8_FEM_ANTSWLUT_SHIFT);
3028 					varbuf_append(&b, vstr_triso5g, (fem &
3029 						SROM8_FEM_TR_ISO_MASK) >>
3030 						SROM8_FEM_TR_ISO_SHIFT);
3031 					varbuf_append(&b, vstr_pdetrange5g, (fem &
3032 						SROM8_FEM_PDET_RANGE_MASK) >>
3033 						SROM8_FEM_PDET_RANGE_SHIFT);
3034 					varbuf_append(&b, vstr_extpagain5g, (fem &
3035 						SROM8_FEM_EXTPA_GAIN_MASK) >>
3036 						SROM8_FEM_EXTPA_GAIN_SHIFT);
3037 					varbuf_append(&b, vstr_tssipos5g, (fem &
3038 						SROM8_FEM_TSSIPOS_MASK) >>
3039 						SROM8_FEM_TSSIPOS_SHIFT);
3040 					break;
3041 				}
3042 
3043 				case HNBU_PAPARMS_C0:
3044 					varbuf_append(&b, vstr_maxp2ga, 0, cis[i + 1]);
3045 					varbuf_append(&b, vstr_itt2ga0, cis[i + 2]);
3046 					varbuf_append(&b, vstr_pa, 2, 0, 0,
3047 						(cis[i + 4] << 8) + cis[i + 3]);
3048 					varbuf_append(&b, vstr_pa, 2, 1, 0,
3049 						(cis[i + 6] << 8) + cis[i + 5]);
3050 					varbuf_append(&b, vstr_pa, 2, 2, 0,
3051 						(cis[i + 8] << 8) + cis[i + 7]);
3052 					if (tlen < 31) break;
3053 
3054 					varbuf_append(&b, vstr_maxp5ga0, cis[i + 9]);
3055 					varbuf_append(&b, vstr_itt5ga0, cis[i + 10]);
3056 					varbuf_append(&b, vstr_maxp5gha0, cis[i + 11]);
3057 					varbuf_append(&b, vstr_maxp5gla0, cis[i + 12]);
3058 					varbuf_append(&b, vstr_pa, 5, 0, 0,
3059 						(cis[i + 14] << 8) + cis[i + 13]);
3060 					varbuf_append(&b, vstr_pa, 5, 1, 0,
3061 						(cis[i + 16] << 8) + cis[i + 15]);
3062 					varbuf_append(&b, vstr_pa, 5, 2, 0,
3063 						(cis[i + 18] << 8) + cis[i + 17]);
3064 					varbuf_append(&b, vstr_pahl, 5, 'l', 0, 0,
3065 						(cis[i + 20] << 8) + cis[i + 19]);
3066 					varbuf_append(&b, vstr_pahl, 5, 'l', 1, 0,
3067 						(cis[i + 22] << 8) + cis[i + 21]);
3068 					varbuf_append(&b, vstr_pahl, 5, 'l', 2, 0,
3069 						(cis[i + 24] << 8) + cis[i + 23]);
3070 					varbuf_append(&b, vstr_pahl, 5, 'h', 0, 0,
3071 						(cis[i + 26] << 8) + cis[i + 25]);
3072 					varbuf_append(&b, vstr_pahl, 5, 'h', 1, 0,
3073 						(cis[i + 28] << 8) + cis[i + 27]);
3074 					varbuf_append(&b, vstr_pahl, 5, 'h', 2, 0,
3075 						(cis[i + 30] << 8) + cis[i + 29]);
3076 					break;
3077 
3078 				case HNBU_PAPARMS_C1:
3079 					varbuf_append(&b, vstr_maxp2ga, 1, cis[i + 1]);
3080 					varbuf_append(&b, vstr_itt2ga1, cis[i + 2]);
3081 					varbuf_append(&b, vstr_pa, 2, 0, 1,
3082 						(cis[i + 4] << 8) + cis[i + 3]);
3083 					varbuf_append(&b, vstr_pa, 2, 1, 1,
3084 						(cis[i + 6] << 8) + cis[i + 5]);
3085 					varbuf_append(&b, vstr_pa, 2, 2, 1,
3086 						(cis[i + 8] << 8) + cis[i + 7]);
3087 					if (tlen < 31) break;
3088 
3089 					varbuf_append(&b, vstr_maxp5ga1, cis[i + 9]);
3090 					varbuf_append(&b, vstr_itt5ga1, cis[i + 10]);
3091 					varbuf_append(&b, vstr_maxp5gha1, cis[i + 11]);
3092 					varbuf_append(&b, vstr_maxp5gla1, cis[i + 12]);
3093 					varbuf_append(&b, vstr_pa, 5, 0, 1,
3094 						(cis[i + 14] << 8) + cis[i + 13]);
3095 					varbuf_append(&b, vstr_pa, 5, 1, 1,
3096 						(cis[i + 16] << 8) + cis[i + 15]);
3097 					varbuf_append(&b, vstr_pa, 5, 2, 1,
3098 						(cis[i + 18] << 8) + cis[i + 17]);
3099 					varbuf_append(&b, vstr_pahl, 5, 'l', 0, 1,
3100 						(cis[i + 20] << 8) + cis[i + 19]);
3101 					varbuf_append(&b, vstr_pahl, 5, 'l', 1, 1,
3102 						(cis[i + 22] << 8) + cis[i + 21]);
3103 					varbuf_append(&b, vstr_pahl, 5, 'l', 2, 1,
3104 						(cis[i + 24] << 8) + cis[i + 23]);
3105 					varbuf_append(&b, vstr_pahl, 5, 'h', 0, 1,
3106 						(cis[i + 26] << 8) + cis[i + 25]);
3107 					varbuf_append(&b, vstr_pahl, 5, 'h', 1, 1,
3108 						(cis[i + 28] << 8) + cis[i + 27]);
3109 					varbuf_append(&b, vstr_pahl, 5, 'h', 2, 1,
3110 						(cis[i + 30] << 8) + cis[i + 29]);
3111 					break;
3112 
3113 				case HNBU_PO_CCKOFDM:
3114 					varbuf_append(&b, vstr_cck2gpo,
3115 						(cis[i + 2] << 8) + cis[i + 1]);
3116 					varbuf_append(&b, vstr_ofdm2gpo,
3117 						(cis[i + 6] << 24) + (cis[i + 5] << 16) +
3118 						(cis[i + 4] << 8) + cis[i + 3]);
3119 					if (tlen < 19) break;
3120 
3121 					varbuf_append(&b, vstr_ofdm5gpo,
3122 						(cis[i + 10] << 24) + (cis[i + 9] << 16) +
3123 						(cis[i + 8] << 8) + cis[i + 7]);
3124 					varbuf_append(&b, vstr_ofdm5glpo,
3125 						(cis[i + 14] << 24) + (cis[i + 13] << 16) +
3126 						(cis[i + 12] << 8) + cis[i + 11]);
3127 					varbuf_append(&b, vstr_ofdm5ghpo,
3128 						(cis[i + 18] << 24) + (cis[i + 17] << 16) +
3129 						(cis[i + 16] << 8) + cis[i + 15]);
3130 					break;
3131 
3132 				case HNBU_PO_MCS2G:
3133 					for (j = 0; j <= (tlen/2); j++) {
3134 						varbuf_append(&b, vstr_mcspo, 2, j,
3135 							(cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]);
3136 					}
3137 					break;
3138 
3139 				case HNBU_PO_MCS5GM:
3140 					for (j = 0; j <= (tlen/2); j++) {
3141 						varbuf_append(&b, vstr_mcspo, 5, j,
3142 							(cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]);
3143 					}
3144 					break;
3145 
3146 				case HNBU_PO_MCS5GLH:
3147 					for (j = 0; j <= (tlen/4); j++) {
3148 						varbuf_append(&b, vstr_mcspohl, 5, 'l', j,
3149 							(cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]);
3150 					}
3151 
3152 					for (j = 0; j <= (tlen/4); j++) {
3153 						varbuf_append(&b, vstr_mcspohl, 5, 'h', j,
3154 							(cis[i + ((tlen/2)+2) + 2*j] << 8) +
3155 							cis[i + ((tlen/2)+1) + 2*j]);
3156 					}
3157 
3158 					break;
3159 
3160 				case HNBU_PO_CDD:
3161 					varbuf_append(&b, vstr_cddpo,
3162 					              (cis[i + 2] << 8) + cis[i + 1]);
3163 					break;
3164 
3165 				case HNBU_PO_STBC:
3166 					varbuf_append(&b, vstr_stbcpo,
3167 					              (cis[i + 2] << 8) + cis[i + 1]);
3168 					break;
3169 
3170 				case HNBU_PO_40M:
3171 					varbuf_append(&b, vstr_bw40po,
3172 					              (cis[i + 2] << 8) + cis[i + 1]);
3173 					break;
3174 
3175 				case HNBU_PO_40MDUP:
3176 					varbuf_append(&b, vstr_bwduppo,
3177 					              (cis[i + 2] << 8) + cis[i + 1]);
3178 					break;
3179 
3180 				case HNBU_OFDMPO5G:
3181 					varbuf_append(&b, vstr_ofdm5gpo,
3182 						(cis[i + 4] << 24) + (cis[i + 3] << 16) +
3183 						(cis[i + 2] << 8) + cis[i + 1]);
3184 					varbuf_append(&b, vstr_ofdm5glpo,
3185 						(cis[i + 8] << 24) + (cis[i + 7] << 16) +
3186 						(cis[i + 6] << 8) + cis[i + 5]);
3187 					varbuf_append(&b, vstr_ofdm5ghpo,
3188 						(cis[i + 12] << 24) + (cis[i + 11] << 16) +
3189 						(cis[i + 10] << 8) + cis[i + 9]);
3190 					break;
3191 				/* Power per rate for SROM V9 */
3192 				case HNBU_CCKBW202GPO:
3193 					varbuf_append(&b, vstr_cckbw202gpo[0],
3194 						((cis[i + 2] << 8) + cis[i + 1]));
3195 					if (tlen > 4)
3196 						varbuf_append(&b, vstr_cckbw202gpo[1],
3197 							((cis[i + 4] << 8) + cis[i + 3]));
3198 					if (tlen > 6)
3199 						varbuf_append(&b, vstr_cckbw202gpo[2],
3200 							((cis[i + 6] << 8) + cis[i + 5]));
3201 					break;
3202 
3203 				case HNBU_LEGOFDMBW202GPO:
3204 					varbuf_append(&b, vstr_legofdmbw202gpo[0],
3205 						((cis[i + 4] << 24) + (cis[i + 3] << 16) +
3206 						(cis[i + 2] << 8) + cis[i + 1]));
3207 					if (tlen > 6)  {
3208 						varbuf_append(&b, vstr_legofdmbw202gpo[1],
3209 							((cis[i + 8] << 24) + (cis[i + 7] << 16) +
3210 							(cis[i + 6] << 8) + cis[i + 5]));
3211 					}
3212 					break;
3213 
3214 				case HNBU_LEGOFDMBW205GPO:
3215 					for (j = 0; j < 6; j++) {
3216 						if (tlen < (2 + 4 * j))
3217 							break;
3218 						varbuf_append(&b, vstr_legofdmbw205gpo[j],
3219 							((cis[4 * j + i + 4] << 24)
3220 							+ (cis[4 * j + i + 3] << 16)
3221 							+ (cis[4 * j + i + 2] << 8)
3222 							+ cis[4 * j + i + 1]));
3223 					}
3224 					break;
3225 
3226 				case HNBU_MCS2GPO:
3227 					for (j = 0; j < 4; j++) {
3228 						if (tlen < (2 + 4 * j))
3229 							break;
3230 						varbuf_append(&b, vstr_mcs2gpo[j],
3231 							((cis[4 * j + i + 4] << 24)
3232 							+ (cis[4 * j + i + 3] << 16)
3233 							+ (cis[4 * j + i + 2] << 8)
3234 							+ cis[4 * j + i + 1]));
3235 					}
3236 					break;
3237 
3238 				case HNBU_MCS5GLPO:
3239 					for (j = 0; j < 3; j++) {
3240 						if (tlen < (2 + 4 * j))
3241 							break;
3242 						varbuf_append(&b, vstr_mcs5glpo[j],
3243 							((cis[4 * j + i + 4] << 24)
3244 							+ (cis[4 * j + i + 3] << 16)
3245 							+ (cis[4 * j + i + 2] << 8)
3246 							+ cis[4 * j + i + 1]));
3247 					}
3248 					break;
3249 
3250 				case HNBU_MCS5GMPO:
3251 					for (j = 0; j < 3; j++) {
3252 						if (tlen < (2 + 4 * j))
3253 							break;
3254 						varbuf_append(&b, vstr_mcs5gmpo[j],
3255 							((cis[4 * j + i + 4] << 24)
3256 							+ (cis[4 * j + i + 3] << 16)
3257 							+ (cis[4 * j + i + 2] << 8)
3258 							+ cis[4 * j + i + 1]));
3259 					}
3260 					break;
3261 
3262 				case HNBU_MCS5GHPO:
3263 					for (j = 0; j < 3; j++) {
3264 						if (tlen < (2 + 4 * j))
3265 							break;
3266 						varbuf_append(&b, vstr_mcs5ghpo[j],
3267 							((cis[4 * j + i + 4] << 24)
3268 							+ (cis[4 * j + i + 3] << 16)
3269 							+ (cis[4 * j + i + 2] << 8)
3270 							+ cis[4 * j + i + 1]));
3271 					}
3272 					break;
3273 
3274 				case HNBU_MCS32PO:
3275 					varbuf_append(&b, vstr_mcs32po,
3276 						(cis[i + 2] << 8) + cis[i + 1]);
3277 					break;
3278 
3279 				case HNBU_LEG40DUPPO:
3280 					varbuf_append(&b, vstr_legofdm40duppo,
3281 						(cis[i + 2] << 8) + cis[i + 1]);
3282 					break;
3283 
3284 				case HNBU_CUSTOM1:
3285 					varbuf_append(&b, vstr_custom, 1, ((cis[i + 4] << 24) +
3286 						(cis[i + 3] << 16) + (cis[i + 2] << 8) +
3287 						cis[i + 1]));
3288 					break;
3289 
3290 #if defined(BCMSDIO) || defined(BCMCCISSR3)
3291 				case HNBU_SROM3SWRGN:
3292 					if (tlen >= 73) {
3293 						uint16 srom[35];
3294 						uint8 srev = cis[i + 1 + 70];
3295 						ASSERT(srev == 3);
3296 						/* make tuple value 16-bit aligned and parse it */
3297 						bcopy(&cis[i + 1], srom, sizeof(srom));
3298 						_initvars_srom_pci(srev, srom, SROM3_SWRGN_OFF, &b);
3299 						/* 2.4G antenna gain is included in SROM */
3300 						ag_init = TRUE;
3301 						/* Ethernet MAC address is included in SROM */
3302 						eabuf[0] = 0;
3303 						/* why boardnum is not -1? */
3304 						boardnum = -1;
3305 					}
3306 					/* create extra variables */
3307 					if (tlen >= 75)
3308 						varbuf_append(&b, vstr_vendid,
3309 						              (cis[i + 1 + 73] << 8) +
3310 						              cis[i + 1 + 72]);
3311 					if (tlen >= 77)
3312 						varbuf_append(&b, vstr_devid,
3313 						              (cis[i + 1 + 75] << 8) +
3314 						              cis[i + 1 + 74]);
3315 					if (tlen >= 79)
3316 						varbuf_append(&b, vstr_xtalfreq,
3317 						              (cis[i + 1 + 77] << 8) +
3318 						              cis[i + 1 + 76]);
3319 					break;
3320 #endif	/* BCMSDIO || BCMCCISSR3 */
3321 
3322 				case HNBU_CCKFILTTYPE:
3323 					varbuf_append(&b, vstr_cckdigfilttype,
3324 						(cis[i + 1]));
3325 					break;
3326 
3327 				case HNBU_TEMPTHRESH:
3328 					varbuf_append(&b, vstr_tempthresh,
3329 						(cis[i + 1]));
3330 					/* period in msb nibble */
3331 					varbuf_append(&b, vstr_temps_period,
3332 						(cis[i + 2] & SROM11_TEMPS_PERIOD_MASK) >>
3333 						SROM11_TEMPS_PERIOD_SHIFT);
3334 					/* hysterisis in lsb nibble */
3335 					varbuf_append(&b, vstr_temps_hysteresis,
3336 						(cis[i + 2] & SROM11_TEMPS_HYSTERESIS_MASK) >>
3337 						SROM11_TEMPS_HYSTERESIS_SHIFT);
3338 					if (tlen >= 4) {
3339 						varbuf_append(&b, vstr_tempoffset,
3340 						(cis[i + 3]));
3341 						varbuf_append(&b, vstr_tempsense_slope,
3342 						(cis[i + 4]));
3343 						varbuf_append(&b, vstr_temp_corrx,
3344 						(cis[i + 5] & SROM11_TEMPCORRX_MASK) >>
3345 						SROM11_TEMPCORRX_SHIFT);
3346 						varbuf_append(&b, vstr_tempsense_option,
3347 						(cis[i + 5] & SROM11_TEMPSENSE_OPTION_MASK) >>
3348 						SROM11_TEMPSENSE_OPTION_SHIFT);
3349 						varbuf_append(&b, vstr_phycal_tempdelta,
3350 						(cis[i + 6]));
3351 					}
3352 					break;
3353 
3354 				case HNBU_FEM_CFG: {
3355 					/* fem_cfg1 */
3356 					uint16 fem_cfg = (cis[i + 2] << 8) + cis[i + 1];
3357 					varbuf_append(&b, vstr_femctrl,
3358 						(fem_cfg & SROM11_FEMCTRL_MASK) >>
3359 						SROM11_FEMCTRL_SHIFT);
3360 					varbuf_append(&b, vstr_papdcap, 2,
3361 						(fem_cfg & SROM11_PAPDCAP_MASK) >>
3362 						SROM11_PAPDCAP_SHIFT);
3363 					varbuf_append(&b, vstr_tworangetssi, 2,
3364 						(fem_cfg & SROM11_TWORANGETSSI_MASK) >>
3365 						SROM11_TWORANGETSSI_SHIFT);
3366 					varbuf_append(&b, vstr_pdgaing, 2,
3367 						(fem_cfg & SROM11_PDGAIN_MASK) >>
3368 						SROM11_PDGAIN_SHIFT);
3369 					varbuf_append(&b, vstr_epagaing, 2,
3370 						(fem_cfg & SROM11_EPAGAIN_MASK) >>
3371 						SROM11_EPAGAIN_SHIFT);
3372 					varbuf_append(&b, vstr_tssiposslopeg, 2,
3373 						(fem_cfg & SROM11_TSSIPOSSLOPE_MASK) >>
3374 						SROM11_TSSIPOSSLOPE_SHIFT);
3375 					/* fem_cfg2 */
3376 					fem_cfg = (cis[i + 4] << 8) + cis[i + 3];
3377 					varbuf_append(&b, vstr_gainctrlsph,
3378 						(fem_cfg & SROM11_GAINCTRLSPH_MASK) >>
3379 						SROM11_GAINCTRLSPH_SHIFT);
3380 					varbuf_append(&b, vstr_papdcap, 5,
3381 						(fem_cfg & SROM11_PAPDCAP_MASK) >>
3382 						SROM11_PAPDCAP_SHIFT);
3383 					varbuf_append(&b, vstr_tworangetssi, 5,
3384 						(fem_cfg & SROM11_TWORANGETSSI_MASK) >>
3385 						SROM11_TWORANGETSSI_SHIFT);
3386 					varbuf_append(&b, vstr_pdgaing, 5,
3387 						(fem_cfg & SROM11_PDGAIN_MASK) >>
3388 						SROM11_PDGAIN_SHIFT);
3389 					varbuf_append(&b, vstr_epagaing, 5,
3390 						(fem_cfg & SROM11_EPAGAIN_MASK) >>
3391 						SROM11_EPAGAIN_SHIFT);
3392 					varbuf_append(&b, vstr_tssiposslopeg, 5,
3393 						(fem_cfg & SROM11_TSSIPOSSLOPE_MASK) >>
3394 						SROM11_TSSIPOSSLOPE_SHIFT);
3395 					break;
3396 				}
3397 
3398 				case HNBU_ACPA_C0: {
3399 					const int a = 0;
3400 
3401 #ifndef OTP_SKIP_MAXP_PAPARAMS
3402 					varbuf_append(&b, vstr_subband5gver,
3403 					              (cis[i + 2] << 8) + cis[i + 1]);
3404 					/* maxp2g */
3405 					/* Decoupling this touple to program from NVRAM */
3406 					varbuf_append(&b, vstr_maxp2ga, a,
3407 						(cis[i + 4] << 8) + cis[i + 3]);
3408 #endif /* OTP_SKIP_MAXP_PAPARAMS */
3409 					/* pa2g */
3410 					varbuf_append(&b, vstr_pa2ga, a,
3411 						(cis[i + 6] << 8) + cis[i + 5],
3412 						(cis[i + 8] << 8) + cis[i + 7],
3413 						(cis[i + 10] << 8) + cis[i + 9]);
3414 #ifndef OTP_SKIP_MAXP_PAPARAMS
3415 					/* maxp5g */
3416 					varbuf_append(&b, vstr_maxp5ga, a,
3417 						cis[i + 11],
3418 						cis[i + 12],
3419 						cis[i + 13],
3420 						cis[i + 14]);
3421 #endif /* OTP_SKIP_MAXP_PAPARAMS */
3422 					/* pa5g */
3423 					varbuf_append(&b, vstr_pa5ga, a,
3424 						(cis[i + 16] << 8) + cis[i + 15],
3425 						(cis[i + 18] << 8) + cis[i + 17],
3426 						(cis[i + 20] << 8) + cis[i + 19],
3427 						(cis[i + 22] << 8) + cis[i + 21],
3428 						(cis[i + 24] << 8) + cis[i + 23],
3429 						(cis[i + 26] << 8) + cis[i + 25],
3430 						(cis[i + 28] << 8) + cis[i + 27],
3431 						(cis[i + 30] << 8) + cis[i + 29],
3432 						(cis[i + 32] << 8) + cis[i + 31],
3433 						(cis[i + 34] << 8) + cis[i + 33],
3434 						(cis[i + 36] << 8) + cis[i + 35],
3435 						(cis[i + 38] << 8) + cis[i + 37]);
3436 					break;
3437 				}
3438 
3439 				case HNBU_ACPA_C1: {
3440 					const int a = 1;
3441 
3442 #ifndef OTP_SKIP_MAXP_PAPARAMS
3443 					/* maxp2g */
3444 					/* Decoupling this touple to program from NVRAM */
3445 					varbuf_append(&b, vstr_maxp2ga, a,
3446 						(cis[i + 2] << 8) + cis[i + 1]);
3447 #endif /* OTP_SKIP_MAXP_PAPARAMS */
3448 					/* pa2g */
3449 					varbuf_append(&b, vstr_pa2ga, a,
3450 						(cis[i + 4] << 8) + cis[i + 3],
3451 						(cis[i + 6] << 8) + cis[i + 5],
3452 						(cis[i + 8] << 8) + cis[i + 7]);
3453 #ifndef OTP_SKIP_MAXP_PAPARAMS
3454 					/* maxp5g */
3455 					varbuf_append(&b, vstr_maxp5ga, a,
3456 						cis[i + 9],
3457 						cis[i + 10],
3458 						cis[i + 11],
3459 						cis[i + 12]);
3460 #endif /* OTP_SKIP_MAXP_PAPARAMS */
3461 					/* pa5g */
3462 					varbuf_append(&b, vstr_pa5ga, a,
3463 						(cis[i + 14] << 8) + cis[i + 13],
3464 						(cis[i + 16] << 8) + cis[i + 15],
3465 						(cis[i + 18] << 8) + cis[i + 17],
3466 						(cis[i + 20] << 8) + cis[i + 19],
3467 						(cis[i + 22] << 8) + cis[i + 21],
3468 						(cis[i + 24] << 8) + cis[i + 23],
3469 						(cis[i + 26] << 8) + cis[i + 25],
3470 						(cis[i + 28] << 8) + cis[i + 27],
3471 						(cis[i + 30] << 8) + cis[i + 29],
3472 						(cis[i + 32] << 8) + cis[i + 31],
3473 						(cis[i + 34] << 8) + cis[i + 33],
3474 						(cis[i + 36] << 8) + cis[i + 35]);
3475 					break;
3476 				}
3477 
3478 				case HNBU_ACPA_C2: {
3479 					const int a = 2;
3480 
3481 #ifndef OTP_SKIP_MAXP_PAPARAMS
3482 					/* maxp2g */
3483 					/* Decoupling this touple to program from NVRAM */
3484 					varbuf_append(&b, vstr_maxp2ga, a,
3485 						(cis[i + 2] << 8) + cis[i + 1]);
3486 #endif /* OTP_SKIP_MAXP_PAPARAMS */
3487 					/* pa2g */
3488 					varbuf_append(&b, vstr_pa2ga, a,
3489 						(cis[i + 4] << 8) + cis[i + 3],
3490 						(cis[i + 6] << 8) + cis[i + 5],
3491 						(cis[i + 8] << 8) + cis[i + 7]);
3492 #ifndef OTP_SKIP_MAXP_PAPARAMS
3493 					/* maxp5g */
3494 					varbuf_append(&b, vstr_maxp5ga, a,
3495 						cis[i + 9],
3496 						cis[i + 10],
3497 						cis[i + 11],
3498 						cis[i + 12]);
3499 #endif /* OTP_SKIP_MAXP_PAPARAMS */
3500 					/* pa5g */
3501 					varbuf_append(&b, vstr_pa5ga, a,
3502 						(cis[i + 14] << 8) + cis[i + 13],
3503 						(cis[i + 16] << 8) + cis[i + 15],
3504 						(cis[i + 18] << 8) + cis[i + 17],
3505 						(cis[i + 20] << 8) + cis[i + 19],
3506 						(cis[i + 22] << 8) + cis[i + 21],
3507 						(cis[i + 24] << 8) + cis[i + 23],
3508 						(cis[i + 26] << 8) + cis[i + 25],
3509 						(cis[i + 28] << 8) + cis[i + 27],
3510 						(cis[i + 30] << 8) + cis[i + 29],
3511 						(cis[i + 32] << 8) + cis[i + 31],
3512 						(cis[i + 34] << 8) + cis[i + 33],
3513 						(cis[i + 36] << 8) + cis[i + 35]);
3514 					break;
3515 				}
3516 
3517 				case HNBU_MEAS_PWR:
3518 					varbuf_append(&b, vstr_measpower, cis[i + 1]);
3519 					varbuf_append(&b, vstr_measpowerX, 1, (cis[i + 2]));
3520 					varbuf_append(&b, vstr_measpowerX, 2, (cis[i + 3]));
3521 					varbuf_append(&b, vstr_rawtempsense,
3522 						((cis[i + 5] & 0x1) << 8) + cis[i + 4]);
3523 					break;
3524 
3525 				case HNBU_PDOFF:
3526 					varbuf_append(&b, vstr_pdoffsetma, 40, 0,
3527 					      (cis[i + 2] << 8) + cis[i + 1]);
3528 					varbuf_append(&b, vstr_pdoffsetma, 40, 1,
3529 					      (cis[i + 4] << 8) + cis[i + 3]);
3530 					varbuf_append(&b, vstr_pdoffsetma, 40, 2,
3531 					      (cis[i + 6] << 8) + cis[i + 5]);
3532 					varbuf_append(&b, vstr_pdoffsetma, 80, 0,
3533 					      (cis[i + 8] << 8) + cis[i + 7]);
3534 					varbuf_append(&b, vstr_pdoffsetma, 80, 1,
3535 					      (cis[i + 10] << 8) + cis[i + 9]);
3536 					varbuf_append(&b, vstr_pdoffsetma, 80, 2,
3537 					      (cis[i + 12] << 8) + cis[i + 11]);
3538 					break;
3539 
3540 				case HNBU_ACPPR_2GPO:
3541 					varbuf_append(&b, vstr_dot11agofdmhrbw202gpo,
3542 					              (cis[i + 2] << 8) + cis[i + 1]);
3543 					varbuf_append(&b, vstr_ofdmlrbw202gpo,
3544 					              (cis[i + 4] << 8) + cis[i + 3]);
3545 
3546 					if (tlen < 13) break;
3547 					varbuf_append(&b, vstr_sb20in40dot11agofdm2gpo,
3548 					              (cis[i + 6] << 8) + cis[i + 5]);
3549 					varbuf_append(&b, vstr_sb20in80dot11agofdm2gpo,
3550 					              (cis[i + 8] << 8) + cis[i + 7]);
3551 					varbuf_append(&b, vstr_sb20in40ofdmlrbw202gpo,
3552 					              (cis[i + 10] << 8) + cis[i + 9]);
3553 					varbuf_append(&b, vstr_sb20in80ofdmlrbw202gpo,
3554 					              (cis[i + 12] << 8) + cis[i + 11]);
3555 					break;
3556 
3557 				case HNBU_ACPPR_5GPO:
3558 					varbuf_append(&b, vstr_mcsbw805gpo, 'l',
3559 						(cis[i + 4] << 24) + (cis[i + 3] << 16) +
3560 						(cis[i + 2] << 8) + cis[i + 1]);
3561 					varbuf_append(&b, vstr_mcsbw1605gpo, 'l',
3562 						(cis[i + 8] << 24) + (cis[i + 7] << 16) +
3563 						(cis[i + 6] << 8) + cis[i + 5]);
3564 					varbuf_append(&b, vstr_mcsbw805gpo, 'm',
3565 						(cis[i + 12] << 24) + (cis[i + 11] << 16) +
3566 						(cis[i + 10] << 8) + cis[i + 9]);
3567 					varbuf_append(&b, vstr_mcsbw1605gpo, 'm',
3568 						(cis[i + 16] << 24) + (cis[i + 15] << 16) +
3569 						(cis[i + 14] << 8) + cis[i + 13]);
3570 					varbuf_append(&b, vstr_mcsbw805gpo, 'h',
3571 						(cis[i + 20] << 24) + (cis[i + 19] << 16) +
3572 						(cis[i + 18] << 8) + cis[i + 17]);
3573 					varbuf_append(&b, vstr_mcsbw1605gpo, 'h',
3574 						(cis[i + 24] << 24) + (cis[i + 23] << 16) +
3575 						(cis[i + 22] << 8) + cis[i + 21]);
3576 					varbuf_append(&b, vstr_mcslr5gpo, 'l',
3577 					              (cis[i + 26] << 8) + cis[i + 25]);
3578 					varbuf_append(&b, vstr_mcslr5gpo, 'm',
3579 					              (cis[i + 28] << 8) + cis[i + 27]);
3580 					varbuf_append(&b, vstr_mcslr5gpo, 'h',
3581 					              (cis[i + 30] << 8) + cis[i + 29]);
3582 
3583 					if (tlen < 51) break;
3584 					varbuf_append(&b, vstr_mcsbw80p805gpo, 'l',
3585 						(cis[i + 34] << 24) + (cis[i + 33] << 16) +
3586 						(cis[i + 32] << 8) + cis[i + 31]);
3587 					varbuf_append(&b, vstr_mcsbw80p805gpo, 'm',
3588 						(cis[i + 38] << 24) + (cis[i + 37] << 16) +
3589 						(cis[i + 36] << 8) + cis[i + 35]);
3590 					varbuf_append(&b, vstr_mcsbw80p805gpo, 'h',
3591 						(cis[i + 42] << 24) + (cis[i + 41] << 16) +
3592 						(cis[i + 40] << 8) + cis[i + 39]);
3593 					varbuf_append(&b, vstr_mcsbw80p805g1po, 'x',
3594 						(cis[i + 46] << 24) + (cis[i + 45] << 16) +
3595 						(cis[i + 44] << 8) + cis[i + 43]);
3596 					varbuf_append(&b, vstr_mcslr5g1po, 'x',
3597 					              (cis[i + 48] << 8) + cis[i + 47]);
3598 					varbuf_append(&b, vstr_mcslr5g80p80po,
3599 					              (cis[i + 50] << 8) + cis[i + 49]);
3600 					varbuf_append(&b, vstr_mcsbw805g1po, 'x',
3601 						(cis[i + 54] << 24) + (cis[i + 53] << 16) +
3602 						(cis[i + 52] << 8) + cis[i + 51]);
3603 					varbuf_append(&b, vstr_mcsbw1605g1po, 'x',
3604 						(cis[i + 58] << 24) + (cis[i + 57] << 16) +
3605 						(cis[i + 56] << 8) + cis[i + 55]);
3606 
3607 					break;
3608 
3609 				case HNBU_MCS5Gx1PO:
3610 					varbuf_append(&b, vstr_mcsbw205g1po, 'x',
3611 						(cis[i + 4] << 24) + (cis[i + 3] << 16) +
3612 						(cis[i + 2] << 8) + cis[i + 1]);
3613 					varbuf_append(&b, vstr_mcsbw405g1po, 'x',
3614 						(cis[i + 8] << 24) + (cis[i + 7] << 16) +
3615 						(cis[i + 6] << 8) + cis[i + 5]);
3616 					break;
3617 
3618 				case HNBU_ACPPR_SBPO:
3619 					varbuf_append(&b, vstr_sb20in40rpo, 'h',
3620 					              (cis[i + 2] << 8) + cis[i + 1]);
3621 					varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'l',
3622 					              (cis[i + 4] << 8) + cis[i + 3]);
3623 					varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'l',
3624 					              (cis[i + 6] << 8) + cis[i + 5]);
3625 					varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'm',
3626 					              (cis[i + 8] << 8) + cis[i + 7]);
3627 					varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'm',
3628 					              (cis[i + 10] << 8) + cis[i + 9]);
3629 					varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'h',
3630 					              (cis[i + 12] << 8) + cis[i + 11]);
3631 					varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'h',
3632 					              (cis[i + 14] << 8) + cis[i + 13]);
3633 					varbuf_append(&b, vstr_sb20in40rpo, 'l',
3634 					              (cis[i + 16] << 8) + cis[i + 15]);
3635 					varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'l',
3636 					              (cis[i + 18] << 8) + cis[i + 17]);
3637 					varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'l',
3638 					              (cis[i + 20] << 8) + cis[i + 19]);
3639 					varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'm',
3640 					              (cis[i + 22] << 8) + cis[i + 21]);
3641 					varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'm',
3642 					              (cis[i + 24] << 8) + cis[i + 23]);
3643 					varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'h',
3644 					              (cis[i + 26] << 8) + cis[i + 25]);
3645 					varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'h',
3646 					              (cis[i + 28] << 8) + cis[i + 27]);
3647 					varbuf_append(&b, vstr_dot11agduprpo, 'h',
3648 						(cis[i + 32] << 24) + (cis[i + 31] << 16) +
3649 						(cis[i + 30] << 8) + cis[i + 29]);
3650 					varbuf_append(&b, vstr_dot11agduprpo, 'l',
3651 						(cis[i + 36] << 24) + (cis[i + 35] << 16) +
3652 						(cis[i + 34] << 8) + cis[i + 33]);
3653 
3654 					if (tlen < 49) break;
3655 					varbuf_append(&b, vstr_sb20in40and80rpo, 'h',
3656 						(cis[i + 38] << 8) + cis[i + 37]);
3657 					varbuf_append(&b, vstr_sb20in40and80rpo, 'l',
3658 						(cis[i + 40] << 8) + cis[i + 39]);
3659 					varbuf_append(&b, vstr_sb20in80and160r5g1po, 'h', 'x',
3660 						(cis[i + 42] << 8) + cis[i + 41]);
3661 					varbuf_append(&b, vstr_sb20in80and160r5g1po, 'l', 'x',
3662 						(cis[i + 44] << 8) + cis[i + 43]);
3663 					varbuf_append(&b, vstr_sb40and80r5g1po, 'h', 'x',
3664 						(cis[i + 46] << 8) + cis[i + 45]);
3665 					varbuf_append(&b, vstr_sb40and80r5g1po, 'l', 'x',
3666 						(cis[i + 48] << 8) + cis[i + 47]);
3667 					break;
3668 
3669 				case HNBU_ACPPR_SB8080_PO:
3670 					varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'h', 'l',
3671 						(cis[i + 2] << 8) + cis[i + 1]);
3672 					varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'l', 'l',
3673 						(cis[i + 4] << 8) + cis[i + 3]);
3674 					varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'h', 'm',
3675 						(cis[i + 6] << 8) + cis[i + 5]);
3676 					varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'l', 'm',
3677 						(cis[i + 8] << 8) + cis[i + 7]);
3678 					varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'h', 'h',
3679 						(cis[i + 10] << 8) + cis[i + 9]);
3680 					varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'l', 'h',
3681 						(cis[i + 12] << 8) + cis[i + 11]);
3682 					varbuf_append(&b, vstr_sb2040and80in80p80r5g1po, 'h', 'x',
3683 						(cis[i + 14] << 8) + cis[i + 13]);
3684 					varbuf_append(&b, vstr_sb2040and80in80p80r5g1po, 'l', 'x',
3685 						(cis[i + 16] << 8) + cis[i + 15]);
3686 					varbuf_append(&b, vstr_sb20in80p80r5gpo, 'h',
3687 						(cis[i + 18] << 8) + cis[i + 17]);
3688 					varbuf_append(&b, vstr_sb20in80p80r5gpo, 'l',
3689 						(cis[i + 20] << 8) + cis[i + 19]);
3690 					varbuf_append(&b, vstr_dot11agduppo,
3691 						(cis[i + 22] << 8) + cis[i + 21]);
3692 					break;
3693 
3694 				case HNBU_NOISELVL:
3695 					/* noiselvl2g */
3696 					varbuf_append(&b, vstr_noiselvl2ga, 0,
3697 					              (cis[i + 1] & 0x1f));
3698 					varbuf_append(&b, vstr_noiselvl2ga, 1,
3699 					              (cis[i + 2] & 0x1f));
3700 					varbuf_append(&b, vstr_noiselvl2ga, 2,
3701 					              (cis[i + 3] & 0x1f));
3702 					/* noiselvl5g */
3703 					varbuf_append(&b, vstr_noiselvl5ga, 0,
3704 					              (cis[i + 4] & 0x1f),
3705 					              (cis[i + 5] & 0x1f),
3706 					              (cis[i + 6] & 0x1f),
3707 					              (cis[i + 7] & 0x1f));
3708 					varbuf_append(&b, vstr_noiselvl5ga, 1,
3709 					              (cis[i + 8] & 0x1f),
3710 					              (cis[i + 9] & 0x1f),
3711 					              (cis[i + 10] & 0x1f),
3712 					              (cis[i + 11] & 0x1f));
3713 					varbuf_append(&b, vstr_noiselvl5ga, 2,
3714 					              (cis[i + 12] & 0x1f),
3715 					              (cis[i + 13] & 0x1f),
3716 					              (cis[i + 14] & 0x1f),
3717 					              (cis[i + 15] & 0x1f));
3718 					break;
3719 
3720 				case HNBU_RXGAIN_ERR:
3721 					varbuf_append(&b, vstr_rxgainerr2ga, 0,
3722 					              (cis[i + 1] & 0x3f));
3723 					varbuf_append(&b, vstr_rxgainerr2ga, 1,
3724 					              (cis[i + 2] & 0x1f));
3725 					varbuf_append(&b, vstr_rxgainerr2ga, 2,
3726 					              (cis[i + 3] & 0x1f));
3727 					varbuf_append(&b, vstr_rxgainerr5ga, 0,
3728 					              (cis[i + 4] & 0x3f),
3729 					              (cis[i + 5] & 0x3f),
3730 					              (cis[i + 6] & 0x3f),
3731 					              (cis[i + 7] & 0x3f));
3732 					varbuf_append(&b, vstr_rxgainerr5ga, 1,
3733 					              (cis[i + 8] & 0x1f),
3734 					              (cis[i + 9] & 0x1f),
3735 					              (cis[i + 10] & 0x1f),
3736 					              (cis[i + 11] & 0x1f));
3737 					varbuf_append(&b, vstr_rxgainerr5ga, 2,
3738 					              (cis[i + 12] & 0x1f),
3739 					              (cis[i + 13] & 0x1f),
3740 					              (cis[i + 14] & 0x1f),
3741 					              (cis[i + 15] & 0x1f));
3742 					break;
3743 
3744 				case HNBU_AGBGA:
3745 					varbuf_append(&b, vstr_agbg, 0, cis[i + 1]);
3746 					varbuf_append(&b, vstr_agbg, 1, cis[i + 2]);
3747 					varbuf_append(&b, vstr_agbg, 2, cis[i + 3]);
3748 					varbuf_append(&b, vstr_aga, 0, cis[i + 4]);
3749 					varbuf_append(&b, vstr_aga, 1, cis[i + 5]);
3750 					varbuf_append(&b, vstr_aga, 2, cis[i + 6]);
3751 					break;
3752 
3753 				case HNBU_ACRXGAINS_C0: {
3754 					int a = 0;
3755 
3756 					/* rxgains */
3757 					uint16 rxgains = (cis[i + 2] << 8) + cis[i + 1];
3758 					varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a,
3759 						(rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3760 						SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3761 					varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a,
3762 						(rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3763 						SROM11_RXGAINS5GTRISOA_SHIFT);
3764 					varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a,
3765 						(rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3766 						SROM11_RXGAINS5GELNAGAINA_SHIFT);
3767 					varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a,
3768 						(rxgains & SROM11_RXGAINS2GTRELNABYPA_MASK) >>
3769 						SROM11_RXGAINS2GTRELNABYPA_SHIFT);
3770 					varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a,
3771 						(rxgains & SROM11_RXGAINS2GTRISOA_MASK) >>
3772 						SROM11_RXGAINS2GTRISOA_SHIFT);
3773 					varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a,
3774 						(rxgains & SROM11_RXGAINS2GELNAGAINA_MASK) >>
3775 						SROM11_RXGAINS2GELNAGAINA_SHIFT);
3776 					/* rxgains1 */
3777 					rxgains = (cis[i + 4] << 8) + cis[i + 3];
3778 					varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'h', a,
3779 						(rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3780 						SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3781 					varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'h', a,
3782 						(rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3783 						SROM11_RXGAINS5GTRISOA_SHIFT);
3784 					varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'h', a,
3785 						(rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3786 						SROM11_RXGAINS5GELNAGAINA_SHIFT);
3787 					varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'm', a,
3788 						(rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3789 						SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3790 					varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'm', a,
3791 						(rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3792 						SROM11_RXGAINS5GTRISOA_SHIFT);
3793 					varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'm', a,
3794 						(rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3795 						SROM11_RXGAINS5GELNAGAINA_SHIFT);
3796 					break;
3797 				}
3798 
3799 				case HNBU_ACRXGAINS_C1: {
3800 					int a = 1;
3801 
3802 					/* rxgains */
3803 					uint16 rxgains = (cis[i + 2] << 8) + cis[i + 1];
3804 					varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a,
3805 						(rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3806 						SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3807 					varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a,
3808 						(rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3809 						SROM11_RXGAINS5GTRISOA_SHIFT);
3810 					varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a,
3811 						(rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3812 						SROM11_RXGAINS5GELNAGAINA_SHIFT);
3813 					varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a,
3814 						(rxgains & SROM11_RXGAINS2GTRELNABYPA_MASK) >>
3815 						SROM11_RXGAINS2GTRELNABYPA_SHIFT);
3816 					varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a,
3817 						(rxgains & SROM11_RXGAINS2GTRISOA_MASK) >>
3818 						SROM11_RXGAINS2GTRISOA_SHIFT);
3819 					varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a,
3820 						(rxgains & SROM11_RXGAINS2GELNAGAINA_MASK) >>
3821 						SROM11_RXGAINS2GELNAGAINA_SHIFT);
3822 					/* rxgains1 */
3823 					rxgains = (cis[i + 4] << 8) + cis[i + 3];
3824 					varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'h', a,
3825 						(rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3826 						SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3827 					varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'h', a,
3828 						(rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3829 						SROM11_RXGAINS5GTRISOA_SHIFT);
3830 					varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'h', a,
3831 						(rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3832 						SROM11_RXGAINS5GELNAGAINA_SHIFT);
3833 					varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'm', a,
3834 						(rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3835 						SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3836 					varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'm', a,
3837 						(rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3838 						SROM11_RXGAINS5GTRISOA_SHIFT);
3839 					varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'm', a,
3840 						(rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3841 						SROM11_RXGAINS5GELNAGAINA_SHIFT);
3842 					break;
3843 				}
3844 
3845 				case HNBU_ACRXGAINS_C2: {
3846 					int a = 2;
3847 
3848 					/* rxgains */
3849 					uint16 rxgains = (cis[i + 2] << 8) + cis[i + 1];
3850 					varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a,
3851 						(rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3852 						SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3853 					varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a,
3854 						(rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3855 						SROM11_RXGAINS5GTRISOA_SHIFT);
3856 					varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a,
3857 						(rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3858 						SROM11_RXGAINS5GELNAGAINA_SHIFT);
3859 					varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a,
3860 						(rxgains & SROM11_RXGAINS2GTRELNABYPA_MASK) >>
3861 						SROM11_RXGAINS2GTRELNABYPA_SHIFT);
3862 					varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a,
3863 						(rxgains & SROM11_RXGAINS2GTRISOA_MASK) >>
3864 						SROM11_RXGAINS2GTRISOA_SHIFT);
3865 					varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a,
3866 						(rxgains & SROM11_RXGAINS2GELNAGAINA_MASK) >>
3867 						SROM11_RXGAINS2GELNAGAINA_SHIFT);
3868 					/* rxgains1 */
3869 					rxgains = (cis[i + 4] << 8) + cis[i + 3];
3870 					varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'h', a,
3871 						(rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3872 						SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3873 					varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'h', a,
3874 						(rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3875 						SROM11_RXGAINS5GTRISOA_SHIFT);
3876 					varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'h', a,
3877 						(rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3878 						SROM11_RXGAINS5GELNAGAINA_SHIFT);
3879 					varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'm', a,
3880 						(rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >>
3881 						SROM11_RXGAINS5GTRELNABYPA_SHIFT);
3882 					varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'm', a,
3883 						(rxgains & SROM11_RXGAINS5GTRISOA_MASK) >>
3884 						SROM11_RXGAINS5GTRISOA_SHIFT);
3885 					varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'm', a,
3886 						(rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >>
3887 						SROM11_RXGAINS5GELNAGAINA_SHIFT);
3888 					break;
3889 				}
3890 
3891 				case HNBU_TXDUTY: {
3892 					varbuf_append(&b, vstr_txduty_ofdm, 40,
3893 					              (cis[i + 2] << 8) + cis[i + 1]);
3894 					varbuf_append(&b, vstr_txduty_thresh, 40,
3895 					              (cis[i + 4] << 8) + cis[i + 3]);
3896 					varbuf_append(&b, vstr_txduty_ofdm, 80,
3897 					              (cis[i + 6] << 8) + cis[i + 5]);
3898 					varbuf_append(&b, vstr_txduty_thresh, 80,
3899 					              (cis[i + 8] << 8) + cis[i + 7]);
3900 					break;
3901 				}
3902 
3903 				case HNBU_UUID: {
3904 					/* uuid format 12345678-1234-5678-1234-567812345678 */
3905 
3906 					char uuidstr[37]; /* 32 ids, 4 '-', 1 Null */
3907 
3908 					snprintf(uuidstr, sizeof(uuidstr),
3909 						rstr_uuidstr,
3910 						cis[i + 1], cis[i + 2], cis[i + 3], cis[i + 4],
3911 						cis[i + 5], cis[i + 6], cis[i + 7], cis[i + 8],
3912 						cis[i + 9], cis[i + 10], cis[i + 11], cis[i + 12],
3913 						cis[i + 13], cis[i + 14], cis[i + 15], cis[i + 16]);
3914 
3915 					varbuf_append(&b, vstr_uuid, uuidstr);
3916 					break;
3917 				}
3918 
3919 				case HNBU_WOWLGPIO:
3920 					varbuf_append(&b, vstr_wowlgpio, ((cis[i + 1]) & 0x7F));
3921 					varbuf_append(&b, vstr_wowlgpiopol,
3922 						(((cis[i + 1]) >> 7) & 0x1));
3923 					break;
3924 
3925 #endif /* !BCM_BOOTLOADER */
3926 #ifdef BCMUSBDEV_COMPOSITE
3927 				case HNBU_USBDESC_COMPOSITE:
3928 					varbuf_append(&b, vstr_usbdesc_composite,
3929 						(cis[i + 2] << 8) | cis[i + 1]);
3930 					break;
3931 #endif /* BCMUSBDEV_COMPOSITE */
3932 				case HNBU_USBUTMI_CTL:
3933 					varbuf_append(&b, vstr_usbutmi_ctl,
3934 						(cis[i + 2] << 8) | cis[i + 1]);
3935 					break;
3936 
3937 				case HNBU_USBSSPHY_UTMI_CTL0:
3938 					varbuf_append(&b, vstr_usbssphy_utmi_ctl0,
3939 						(cis[i + 4] << 24) | (cis[i + 3] << 16) |
3940 						(cis[i + 2] << 8) | cis[i + 1]);
3941 					break;
3942 
3943 				case HNBU_USBSSPHY_UTMI_CTL1:
3944 					varbuf_append(&b, vstr_usbssphy_utmi_ctl1,
3945 						(cis[i + 4] << 24) | (cis[i + 3] << 16) |
3946 						(cis[i + 2] << 8) | cis[i + 1]);
3947 					break;
3948 
3949 				case HNBU_USBSSPHY_UTMI_CTL2:
3950 					varbuf_append(&b, vstr_usbssphy_utmi_ctl2,
3951 						(cis[i + 4] << 24) | (cis[i + 3] << 16) |
3952 						(cis[i + 2] << 8) | cis[i + 1]);
3953 					break;
3954 
3955 				case HNBU_USBSSPHY_SLEEP0:
3956 					varbuf_append(&b, vstr_usbssphy_sleep0,
3957 						(cis[i + 2] << 8) | cis[i + 1]);
3958 					break;
3959 
3960 				case HNBU_USBSSPHY_SLEEP1:
3961 					varbuf_append(&b, vstr_usbssphy_sleep1,
3962 						(cis[i + 2] << 8) | cis[i + 1]);
3963 					break;
3964 
3965 				case HNBU_USBSSPHY_SLEEP2:
3966 					varbuf_append(&b, vstr_usbssphy_sleep2,
3967 						(cis[i + 2] << 8) | cis[i + 1]);
3968 					break;
3969 
3970 				case HNBU_USBSSPHY_SLEEP3:
3971 					varbuf_append(&b, vstr_usbssphy_sleep3,
3972 						(cis[i + 2] << 8) | cis[i + 1]);
3973 					break;
3974 				case HNBU_USBSSPHY_MDIO: {
3975 					uint8 setnum;
3976 					uint16 k;
3977 
3978 					setnum = (cis[i + 1])/4;
3979 					if (setnum == 0)
3980 						break;
3981 					for (j = 0; j < setnum; j++) {
3982 						k = j*12;
3983 						varbuf_append(&b, vstr_usbssphy_mdio, j,
3984 						(cis[i+4+k]<<16) | (cis[i+3+k]<<8) | cis[i+2+k],
3985 						(cis[i+7+k]<<16) | (cis[i+6+k]<<8) | cis[i+5+k],
3986 						(cis[i+10+k]<<16) | (cis[i+9+k]<<8) | cis[i+8+k],
3987 						(cis[i+13+k]<<16) | (cis[i+12+k]<<8) | cis[i+11+k]);
3988 					}
3989 					break;
3990 				}
3991 				case HNBU_USB30PHY_NOSS:
3992 					varbuf_append(&b, vstr_usb30phy_noss, cis[i + 1]);
3993 					break;
3994 				case HNBU_USB30PHY_U1U2:
3995 					varbuf_append(&b, vstr_usb30phy_u1u2, cis[i + 1]);
3996 					break;
3997 				case HNBU_USB30PHY_REGS:
3998 					varbuf_append(&b, vstr_usb30phy_regs, 0,
3999 						cis[i+4]|cis[i+3]|cis[i+2]|cis[i+1],
4000 						cis[i+8]|cis[i+7]|cis[i+6]|cis[i+5],
4001 						cis[i+12]|cis[i+11]|cis[i+10]|cis[i+9],
4002 						cis[i+16]|cis[i+15]|cis[i+14]|cis[i+13]);
4003 					varbuf_append(&b, vstr_usb30phy_regs, 1,
4004 						cis[i+20]|cis[i+19]|cis[i+18]|cis[i+17],
4005 						cis[i+24]|cis[i+23]|cis[i+22]|cis[i+21],
4006 						cis[i+28]|cis[i+27]|cis[i+26]|cis[i+25],
4007 						cis[i+32]|cis[i+31]|cis[i+30]|cis[i+29]);
4008 
4009 					break;
4010 
4011 				case HNBU_PDOFF_2G: {
4012 					uint16 pdoff_2g = (cis[i + 2] << 8) + cis[i + 1];
4013 					varbuf_append(&b, vstr_pdoffset2gma, 40, 0,
4014 						(pdoff_2g & SROM11_PDOFF_2G_40M_A0_MASK) >>
4015 						SROM11_PDOFF_2G_40M_A0_SHIFT);
4016 					varbuf_append(&b, vstr_pdoffset2gma, 40, 1,
4017 						(pdoff_2g & SROM11_PDOFF_2G_40M_A1_MASK) >>
4018 						SROM11_PDOFF_2G_40M_A1_SHIFT);
4019 					varbuf_append(&b, vstr_pdoffset2gma, 40, 2,
4020 						(pdoff_2g & SROM11_PDOFF_2G_40M_A2_MASK) >>
4021 						SROM11_PDOFF_2G_40M_A2_SHIFT);
4022 					varbuf_append(&b, vstr_pdoffset2gmvalid, 40,
4023 						(pdoff_2g & SROM11_PDOFF_2G_40M_VALID_MASK) >>
4024 						SROM11_PDOFF_2G_40M_VALID_SHIFT);
4025 					break;
4026 				}
4027 
4028 				case HNBU_ACPA_CCK_C0:
4029 					varbuf_append(&b, vstr_pa2gccka, 0,
4030 					        (cis[i + 2] << 8) + cis[i + 1],
4031 						(cis[i + 4] << 8) + cis[i + 3],
4032 						(cis[i + 6] << 8) + cis[i + 5]);
4033 					break;
4034 
4035 				case HNBU_ACPA_CCK_C1:
4036 					varbuf_append(&b, vstr_pa2gccka, 1,
4037 						(cis[i + 2] << 8) + cis[i + 1],
4038 						(cis[i + 4] << 8) + cis[i + 3],
4039 						(cis[i + 6] << 8) + cis[i + 5]);
4040 					break;
4041 
4042 				case HNBU_ACPA_40:
4043 					varbuf_append(&b, vstr_pa5gbw40a, 0,
4044 					        (cis[i + 2] << 8) + cis[i + 1],
4045 						(cis[i + 4] << 8) + cis[i + 3],
4046 						(cis[i + 6] << 8) + cis[i + 5],
4047 					        (cis[i + 8] << 8) + cis[i + 7],
4048 						(cis[i + 10] << 8) + cis[i + 9],
4049 						(cis[i + 12] << 8) + cis[i + 11],
4050 					        (cis[i + 14] << 8) + cis[i + 13],
4051 						(cis[i + 16] << 8) + cis[i + 15],
4052 						(cis[i + 18] << 8) + cis[i + 17],
4053 					        (cis[i + 20] << 8) + cis[i + 19],
4054 						(cis[i + 22] << 8) + cis[i + 21],
4055 						(cis[i + 24] << 8) + cis[i + 23]);
4056 					break;
4057 
4058 				case HNBU_ACPA_80:
4059 					varbuf_append(&b, vstr_pa5gbw80a, 0,
4060 					        (cis[i + 2] << 8) + cis[i + 1],
4061 						(cis[i + 4] << 8) + cis[i + 3],
4062 						(cis[i + 6] << 8) + cis[i + 5],
4063 					        (cis[i + 8] << 8) + cis[i + 7],
4064 						(cis[i + 10] << 8) + cis[i + 9],
4065 						(cis[i + 12] << 8) + cis[i + 11],
4066 					        (cis[i + 14] << 8) + cis[i + 13],
4067 						(cis[i + 16] << 8) + cis[i + 15],
4068 						(cis[i + 18] << 8) + cis[i + 17],
4069 					        (cis[i + 20] << 8) + cis[i + 19],
4070 						(cis[i + 22] << 8) + cis[i + 21],
4071 						(cis[i + 24] << 8) + cis[i + 23]);
4072 					break;
4073 
4074 				case HNBU_ACPA_4080:
4075 					varbuf_append(&b, vstr_pa5gbw4080a, 0,
4076 					        (cis[i + 2] << 8) + cis[i + 1],
4077 						(cis[i + 4] << 8) + cis[i + 3],
4078 						(cis[i + 6] << 8) + cis[i + 5],
4079 					        (cis[i + 8] << 8) + cis[i + 7],
4080 						(cis[i + 10] << 8) + cis[i + 9],
4081 						(cis[i + 12] << 8) + cis[i + 11],
4082 					        (cis[i + 14] << 8) + cis[i + 13],
4083 						(cis[i + 16] << 8) + cis[i + 15],
4084 						(cis[i + 18] << 8) + cis[i + 17],
4085 					        (cis[i + 20] << 8) + cis[i + 19],
4086 						(cis[i + 22] << 8) + cis[i + 21],
4087 						(cis[i + 24] << 8) + cis[i + 23]);
4088 					varbuf_append(&b, vstr_pa5gbw4080a, 1,
4089 					        (cis[i + 26] << 8) + cis[i + 25],
4090 						(cis[i + 28] << 8) + cis[i + 27],
4091 						(cis[i + 30] << 8) + cis[i + 29],
4092 					        (cis[i + 32] << 8) + cis[i + 31],
4093 						(cis[i + 34] << 8) + cis[i + 33],
4094 						(cis[i + 36] << 8) + cis[i + 35],
4095 					        (cis[i + 38] << 8) + cis[i + 37],
4096 						(cis[i + 40] << 8) + cis[i + 39],
4097 						(cis[i + 42] << 8) + cis[i + 41],
4098 					        (cis[i + 44] << 8) + cis[i + 43],
4099 						(cis[i + 46] << 8) + cis[i + 45],
4100 						(cis[i + 48] << 8) + cis[i + 47]);
4101 					break;
4102 
4103 				case HNBU_ACPA_4X4C0:
4104 				case HNBU_ACPA_4X4C1:
4105 				case HNBU_ACPA_4X4C2:
4106 				case HNBU_ACPA_4X4C3: {
4107 					int core_num = 0;
4108 					uint8 tuple = cis[i];
4109 
4110 					if (tuple == HNBU_ACPA_4X4C1) {
4111 						core_num = 1;
4112 					} else if (tuple == HNBU_ACPA_4X4C2) {
4113 						core_num = 2;
4114 					} else if (tuple == HNBU_ACPA_4X4C3) {
4115 						core_num = 3;
4116 					}
4117 
4118 					varbuf_append(&b, vstr_maxp2ga, core_num, cis[i + 1]);
4119 					/* pa2g */
4120 					varbuf_append(&b, vstr_sr13pa2ga, core_num,
4121 						(cis[i + 3] << 8) + cis[i + 2],
4122 						(cis[i + 5] << 8) + cis[i + 4],
4123 						(cis[i + 7] << 8) + cis[i + 6],
4124 						(cis[i + 9] << 8) + cis[i + 8]);
4125 					/* pa2g40 */
4126 					varbuf_append(&b, vstr_pa2g40a, core_num,
4127 						(cis[i + 11] << 8) + cis[i + 10],
4128 						(cis[i + 13] << 8) + cis[i + 12],
4129 						(cis[i + 15] << 8) + cis[i + 14],
4130 						(cis[i + 17] << 8) + cis[i + 16]);
4131 					for (j = 0; j < 5; j++) {
4132 						varbuf_append(&b, vstr_maxp5gba, j, core_num,
4133 							cis[i + j + 18]);
4134 					}
4135 					break;
4136 				}
4137 
4138 				case HNBU_ACPA_BW20_4X4C0:
4139 				case HNBU_ACPA_BW40_4X4C0:
4140 				case HNBU_ACPA_BW80_4X4C0:
4141 				case HNBU_ACPA_BW20_4X4C1:
4142 				case HNBU_ACPA_BW40_4X4C1:
4143 				case HNBU_ACPA_BW80_4X4C1:
4144 				case HNBU_ACPA_BW20_4X4C2:
4145 				case HNBU_ACPA_BW40_4X4C2:
4146 				case HNBU_ACPA_BW80_4X4C2:
4147 				case HNBU_ACPA_BW20_4X4C3:
4148 				case HNBU_ACPA_BW40_4X4C3:
4149 				case HNBU_ACPA_BW80_4X4C3: {
4150 					int k = 0;
4151 					char pabuf[140]; /* max: 20 '0x????'s + 19 ','s + 1 Null */
4152 					int core_num = 0, buflen = 0;
4153 					uint8 tuple = cis[i];
4154 
4155 					if (tuple == HNBU_ACPA_BW20_4X4C1 ||
4156 						tuple == HNBU_ACPA_BW40_4X4C1 ||
4157 						tuple == HNBU_ACPA_BW80_4X4C1) {
4158 						core_num = 1;
4159 					} else if (tuple == HNBU_ACPA_BW20_4X4C2 ||
4160 						tuple == HNBU_ACPA_BW40_4X4C2 ||
4161 						tuple == HNBU_ACPA_BW80_4X4C2) {
4162 						core_num = 2;
4163 					} else if (tuple == HNBU_ACPA_BW20_4X4C3 ||
4164 						tuple == HNBU_ACPA_BW40_4X4C3 ||
4165 						tuple == HNBU_ACPA_BW80_4X4C3) {
4166 						core_num = 3;
4167 					}
4168 
4169 					buflen = sizeof(pabuf);
4170 					for (j = 0; j < 20; j++) { /* cis[i+1] - cis[i+40] */
4171 						k += snprintf(pabuf+k, buflen-k, rstr_hex,
4172 							((cis[i + (2*j) + 2] << 8) +
4173 							cis[i + (2*j) + 1]));
4174 						if (j < 19) {
4175 							k += snprintf(pabuf+k, buflen-k,
4176 								",");
4177 						}
4178 					}
4179 
4180 					if (tuple == HNBU_ACPA_BW20_4X4C0 ||
4181 						tuple == HNBU_ACPA_BW20_4X4C1 ||
4182 						tuple == HNBU_ACPA_BW20_4X4C2 ||
4183 						tuple == HNBU_ACPA_BW20_4X4C3) {
4184 						varbuf_append(&b, vstr_sr13pa5ga, core_num, pabuf);
4185 					} else {
4186 						int bw = 40;
4187 
4188 						if (tuple == HNBU_ACPA_BW80_4X4C0 ||
4189 							tuple == HNBU_ACPA_BW80_4X4C1 ||
4190 							tuple == HNBU_ACPA_BW80_4X4C2 ||
4191 							tuple == HNBU_ACPA_BW80_4X4C3) {
4192 							bw = 80;
4193 						}
4194 						varbuf_append(&b, vstr_sr13pa5gbwa, bw,
4195 							core_num, pabuf);
4196 					}
4197 					break;
4198 				}
4199 
4200 				case HNBU_RSSI_DELTA_2G_B0:
4201 				case HNBU_RSSI_DELTA_2G_B1:
4202 				case HNBU_RSSI_DELTA_2G_B2:
4203 				case HNBU_RSSI_DELTA_2G_B3:
4204 				case HNBU_RSSI_DELTA_2G_B4: {
4205 					uint8 tuple = cis[i];
4206 					uint8 grp;
4207 					if (tuple  == HNBU_RSSI_DELTA_2G_B0) {
4208 						grp = 0;
4209 					} else if (tuple  == HNBU_RSSI_DELTA_2G_B1) {
4210 						grp = 1;
4211 					} else if (tuple  == HNBU_RSSI_DELTA_2G_B2) {
4212 						grp = 2;
4213 					} else if (tuple  == HNBU_RSSI_DELTA_2G_B3) {
4214 						grp = 3;
4215 					} else {
4216 						grp = 4;
4217 					}
4218 					/* 2G Band Gourp = grp */
4219 					varbuf_append(&b, vstr_rssidelta2g, grp,
4220 						cis[i + 1],  cis[i + 2],
4221 						cis[i + 3],  cis[i + 4],
4222 						cis[i + 5],  cis[i + 6],
4223 						cis[i + 7],  cis[i + 8],
4224 						cis[i + 9],  cis[i + 10],
4225 						cis[i + 11], cis[i + 12],
4226 						cis[i + 13], cis[i + 14],
4227 						cis[i + 15], cis[i + 16]);
4228 					break;
4229 				}
4230 
4231 				case  HNBU_RSSI_CAL_FREQ_GRP_2G:
4232 					/* 2G Band Gourp Defintion */
4233 					varbuf_append(&b, vstr_rssicalfrqg,
4234 						cis[i + 1],  cis[i + 2],
4235 						cis[i + 3],  cis[i + 4],
4236 						cis[i + 5],  cis[i + 6],
4237 						cis[i + 7]);
4238 					break;
4239 
4240 				case HNBU_RSSI_DELTA_5GL:
4241 				case HNBU_RSSI_DELTA_5GML:
4242 				case HNBU_RSSI_DELTA_5GMU:
4243 				case HNBU_RSSI_DELTA_5GH: {
4244 					uint8 tuple = cis[i];
4245 					char *band[] = {"l", "ml", "mu", "h"};
4246 					char *pband;
4247 					if (tuple == HNBU_RSSI_DELTA_5GL) {
4248 						pband = band[0];
4249 					} else if (tuple == HNBU_RSSI_DELTA_5GML) {
4250 						pband = band[1];
4251 					} else if (tuple == HNBU_RSSI_DELTA_5GMU) {
4252 						pband = band[2];
4253 					} else {
4254 						pband = band[3];
4255 					}
4256 					/* 5G Band = band */
4257 					varbuf_append(&b, vstr_rssidelta5g, pband,
4258 						cis[i + 1],  cis[i + 2],
4259 						cis[i + 3],  cis[i + 4],
4260 						cis[i + 5],  cis[i + 6],
4261 						cis[i + 7],  cis[i + 8],
4262 						cis[i + 9],  cis[i + 10],
4263 						cis[i + 11], cis[i + 12],
4264 						cis[i + 13], cis[i + 14],
4265 						cis[i + 15], cis[i + 16],
4266 						cis[i + 17], cis[i + 17],
4267 						cis[i + 19], cis[i + 20],
4268 						cis[i + 21], cis[i + 22],
4269 						cis[i + 9],  cis[i + 24]);
4270 					break;
4271 				}
4272 
4273 				case HNBU_ACPA_6G_C0: {
4274 					const int a = 0;
4275 #ifndef OTP_SKIP_MAXP_PAPARAMS
4276 					varbuf_append(&b, vstr_subband6gver,
4277 						(cis[i + 2] << 8) + cis[i + 1]);
4278 					/* maxp5g */
4279 					varbuf_append(&b, vstr_maxp6ga, a,
4280 						cis[i + 3],
4281 						cis[i + 4],
4282 						cis[i + 5],
4283 						cis[i + 6],
4284 						cis[i + 7],
4285 						cis[i + 8]);
4286 #endif /* OTP_SKIP_MAXP_PAPARAMS */
4287 					/* pa5g */
4288 					varbuf_append(&b, vstr_pa6ga, a,
4289 						(cis[i + 10] << 8) + cis[i + 9],
4290 						(cis[i + 12] << 8) + cis[i + 11],
4291 						(cis[i + 14] << 8) + cis[i + 13],
4292 						(cis[i + 16] << 8) + cis[i + 15],
4293 						(cis[i + 18] << 8) + cis[i + 17],
4294 						(cis[i + 20] << 8) + cis[i + 19],
4295 						(cis[i + 22] << 8) + cis[i + 21],
4296 						(cis[i + 24] << 8) + cis[i + 23],
4297 						(cis[i + 26] << 8) + cis[i + 25],
4298 						(cis[i + 28] << 8) + cis[i + 27],
4299 						(cis[i + 30] << 8) + cis[i + 29],
4300 						(cis[i + 32] << 8) + cis[i + 31],
4301 						(cis[i + 34] << 8) + cis[i + 33],
4302 						(cis[i + 36] << 8) + cis[i + 35],
4303 						(cis[i + 38] << 8) + cis[i + 37],
4304 						(cis[i + 40] << 8) + cis[i + 39],
4305 						(cis[i + 42] << 8) + cis[i + 41],
4306 						(cis[i + 44] << 8) + cis[i + 43]);
4307 					break;
4308 				}
4309 
4310 				case HNBU_ACPA_6G_C1: {
4311 					const int a = 1;
4312 #ifndef OTP_SKIP_MAXP_PAPARAMS
4313 					/* maxp6g */
4314 					varbuf_append(&b, vstr_maxp6ga, a,
4315 						cis[i + 1],
4316 						cis[i + 2],
4317 						cis[i + 3],
4318 						cis[i + 4],
4319 						cis[i + 5],
4320 						cis[i + 6]);
4321 #endif /* OTP_SKIP_MAXP_PAPARAMS */
4322 					/* pa6g */
4323 					varbuf_append(&b, vstr_pa6ga, a,
4324 						(cis[i + 8] << 8) + cis[i + 7],
4325 						(cis[i + 10] << 8) + cis[i + 9],
4326 						(cis[i + 12] << 8) + cis[i + 11],
4327 						(cis[i + 14] << 8) + cis[i + 13],
4328 						(cis[i + 16] << 8) + cis[i + 15],
4329 						(cis[i + 18] << 8) + cis[i + 17],
4330 						(cis[i + 20] << 8) + cis[i + 19],
4331 						(cis[i + 22] << 8) + cis[i + 21],
4332 						(cis[i + 24] << 8) + cis[i + 23],
4333 						(cis[i + 26] << 8) + cis[i + 25],
4334 						(cis[i + 28] << 8) + cis[i + 27],
4335 						(cis[i + 30] << 8) + cis[i + 29],
4336 						(cis[i + 32] << 8) + cis[i + 31],
4337 						(cis[i + 34] << 8) + cis[i + 33],
4338 						(cis[i + 36] << 8) + cis[i + 35],
4339 						(cis[i + 38] << 8) + cis[i + 37],
4340 						(cis[i + 40] << 8) + cis[i + 39],
4341 						(cis[i + 42] << 8) + cis[i + 41]);
4342 					break;
4343 				}
4344 
4345 				case HNBU_ACPA_6G_C2: {
4346 					const int a = 2;
4347 #ifndef OTP_SKIP_MAXP_PAPARAMS
4348 					/* maxp6g */
4349 					varbuf_append(&b, vstr_maxp6ga, a,
4350 						cis[i + 1],
4351 						cis[i + 2],
4352 						cis[i + 3],
4353 						cis[i + 4],
4354 						cis[i + 5],
4355 						cis[i + 6]);
4356 #endif /* OTP_SKIP_MAXP_PAPARAMS */
4357 					/* pa6g */
4358 					varbuf_append(&b, vstr_pa6ga, a,
4359 						(cis[i + 8] << 8) + cis[i + 7],
4360 						(cis[i + 10] << 8) + cis[i + 9],
4361 						(cis[i + 12] << 8) + cis[i + 11],
4362 						(cis[i + 14] << 8) + cis[i + 13],
4363 						(cis[i + 16] << 8) + cis[i + 15],
4364 						(cis[i + 18] << 8) + cis[i + 17],
4365 						(cis[i + 20] << 8) + cis[i + 19],
4366 						(cis[i + 22] << 8) + cis[i + 21],
4367 						(cis[i + 24] << 8) + cis[i + 23],
4368 						(cis[i + 26] << 8) + cis[i + 25],
4369 						(cis[i + 28] << 8) + cis[i + 27],
4370 						(cis[i + 30] << 8) + cis[i + 29],
4371 						(cis[i + 32] << 8) + cis[i + 31],
4372 						(cis[i + 34] << 8) + cis[i + 33],
4373 						(cis[i + 36] << 8) + cis[i + 35],
4374 						(cis[i + 38] << 8) + cis[i + 37],
4375 						(cis[i + 40] << 8) + cis[i + 39],
4376 						(cis[i + 42] << 8) + cis[i + 41]);
4377 					break;
4378 				}
4379 
4380 				case HNBU_SUBBAND5GVER:
4381 					varbuf_append(&b, vstr_subband5gver,
4382 					        (cis[i + 2] << 8) + cis[i + 1]);
4383 					break;
4384 
4385 				case HNBU_PAPARAMBWVER:
4386 					varbuf_append(&b, vstr_paparambwver, cis[i + 1]);
4387 					break;
4388 
4389 				case HNBU_TXBFRPCALS:
4390 				/* note: all 5 rpcal parameters are expected to be */
4391 				/* inside one tuple record, i.e written with one  */
4392 				/* wl wrvar cmd as follows: */
4393 				/* wl wrvar rpcal2g=0x1211 ... rpcal5gb3=0x0  */
4394 					if (tlen != 11 ) { /* sanity check */
4395 						BS_ERROR(("srom_parsecis:incorrect length:%d for"
4396 							" HNBU_TXBFRPCALS tuple\n",
4397 							tlen));
4398 						break;
4399 					}
4400 
4401 					varbuf_append(&b, vstr_paparamrpcalvars[0],
4402 						(cis[i + 1] + (cis[i + 2] << 8)));
4403 					varbuf_append(&b, vstr_paparamrpcalvars[1],
4404 						(cis[i + 3]  +  (cis[i + 4] << 8)));
4405 					varbuf_append(&b, vstr_paparamrpcalvars[2],
4406 						(cis[i + 5]  +  (cis[i + 6] << 8)));
4407 					varbuf_append(&b, vstr_paparamrpcalvars[3],
4408 						(cis[i + 7]  +  (cis[i + 8] << 8)));
4409 					varbuf_append(&b, vstr_paparamrpcalvars[4],
4410 						(cis[i + 9]  +  (cis[i + 10] << 8)));
4411 					break;
4412 
4413 				case HNBU_GPIO_PULL_DOWN:
4414 					varbuf_append(&b, vstr_gpdn,
4415 					              (cis[i + 4] << 24) |
4416 					              (cis[i + 3] << 16) |
4417 					              (cis[i + 2] << 8) |
4418 					              cis[i + 1]);
4419 					break;
4420 
4421 				case HNBU_MACADDR2:
4422 					if (!(ETHER_ISNULLADDR(&cis[i+1])) &&
4423 					    !(ETHER_ISMULTI(&cis[i+1]))) {
4424 						bcm_ether_ntoa((struct ether_addr *)&cis[i + 1],
4425 						               eabuf2);
4426 					}
4427 					break;
4428 				} /* CISTPL_BRCM_HNBU */
4429 				break;
4430 			} /* switch (tup) */
4431 
4432 			i += tlen;
4433 		} while (tup != CISTPL_END);
4434 	}
4435 
4436 	if (boardnum != -1) {
4437 		varbuf_append(&b, vstr_boardnum, boardnum);
4438 	}
4439 
4440 	if (eabuf[0]) {
4441 		varbuf_append(&b, vstr_macaddr, eabuf);
4442 	}
4443 
4444 	if (eabuf2[0]) {
4445 		varbuf_append(&b, vstr_macaddr2, eabuf2);
4446 	}
4447 
4448 #ifndef BCM_BOOTLOADER
4449 	/* if there is no antenna gain field, set default */
4450 	sromrev = (sromrev == 1u) ? (uint8)getintvar(NULL, rstr_sromrev) : sromrev;
4451 	if (sromrev <= 10u && getvar(NULL, rstr_ag0) == NULL && ag_init == FALSE) {
4452 		varbuf_append(&b, vstr_ag, 0, 0xff);
4453 	}
4454 #endif
4455 
4456 	/* final nullbyte terminator */
4457 	ASSERT(b.size >= 1u);
4458 	*b.buf++ = '\0';
4459 
4460 	ASSERT((uint)(b.buf - base) <= var_cis_size);
4461 
4462 	/* initvars_table() MALLOCs, copies and assigns the MALLOCed buffer to '*vars' */
4463 	err = initvars_table(osh, base /* start */, b.buf /* end */, vars, count);
4464 
4465 	MFREE(osh, base, var_cis_size);
4466 	return err;
4467 }
4468 #endif /* !defined(BCMDONGLEHOST) */
4469 
4470 /**
4471  * In chips with chipcommon rev 32 and later, the srom is in chipcommon,
4472  * not in the bus cores.
4473  */
4474 static uint16
4475 srom_cc_cmd(si_t *sih, osl_t *osh, volatile void *ccregs, uint32 cmd, uint wordoff, uint16 data)
4476 {
4477 	chipcregs_t *cc = ccregs;
4478 	uint wait_cnt = 1000;
4479 	uint32 byteoff = 0, sprom_size = 0;
4480 
4481 	BCM_REFERENCE(sih);
4482 	byteoff = wordoff * 2;
4483 
4484 	sprom_size = R_REG(osh, &cc->sromcontrol);
4485 	sprom_size = (sprom_size & SROM_SIZE_MASK) >> SROM_SIZE_SHFT_MASK;
4486 	if (sprom_size == SROM_SIZE_2K)
4487 		sprom_size = 2048;
4488 	else if (sprom_size == SROM_SIZE_512)
4489 		sprom_size = 512;
4490 	else if (sprom_size == SROM_SIZE_128)
4491 		sprom_size = 128;
4492 	if (byteoff >= sprom_size)
4493 		return 0xffff;
4494 
4495 	if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
4496 		if (sih->ccrev >= 59)
4497 			W_REG(osh, &cc->chipcontrol, (byteoff & SROM16K_BANK_SEL_MASK) >>
4498 				SROM16K_BANK_SHFT_MASK);
4499 		W_REG(osh, &cc->sromaddress, (byteoff  & SROM16K_ADDR_SEL_MASK));
4500 		if (cmd == SRC_OP_WRITE)
4501 			W_REG(osh, &cc->sromdata, data);
4502 	}
4503 
4504 	W_REG(osh, &cc->sromcontrol, SRC_START | cmd);
4505 
4506 	while (wait_cnt--) {
4507 		if ((R_REG(osh, &cc->sromcontrol) & SRC_BUSY) == 0)
4508 			break;
4509 	}
4510 
4511 	if (!wait_cnt) {
4512 		BS_ERROR(("srom_cc_cmd: Command 0x%x timed out\n", cmd));
4513 		return 0xffff;
4514 	}
4515 	if (cmd == SRC_OP_READ)
4516 		return (uint16)R_REG(osh, &cc->sromdata);
4517 	else
4518 		return 0xffff;
4519 }
4520 
4521 #define CC_SROM_SHADOW_WSIZE	512	/* 0x800 - 0xC00 */
4522 
4523 /**
4524  * Read in and validate sprom.
4525  * Return 0 on success, nonzero on error.
4526  * Returns success on an SPROM containing only ones, unclear if this is intended.
4527  */
4528 static int
4529 sprom_read_pci(osl_t *osh, si_t *sih, volatile uint16 *sprom, uint wordoff,
4530 	uint16 *buf, uint nwords, bool check_crc)
4531 {
4532 	int err = 0;
4533 	uint i;
4534 	volatile void *ccregs = NULL;
4535 	chipcregs_t *cc = NULL;
4536 	uint32 ccval = 0, sprom_size = 0;
4537 	uint32 sprom_num_words;
4538 
4539 	if (BCM43602_CHIP(sih->chip) ||
4540 	    (CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
4541 	    (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
4542 	    (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
4543 		/* save current control setting */
4544 		ccval = si_chipcontrl_read(sih);
4545 	}
4546 
4547 	if (BCM43602_CHIP(sih->chip) ||
4548 		(((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
4549 		(CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
4550 		(CHIPID(sih->chip) == BCM4352_CHIP_ID)) &&
4551 		(CHIPREV(sih->chiprev) <= 2))) {
4552 		si_chipcontrl_srom4360(sih, TRUE);
4553 	}
4554 
4555 	if (FALSE) {
4556 		si_srom_clk_set(sih); /* corrects srom clock frequency */
4557 	}
4558 
4559 	ccregs = ((volatile uint8 *)sprom - CC_SROM_OTP);
4560 	cc = ccregs;
4561 	sprom_size = R_REG(osh, &cc->sromcontrol);
4562 	sprom_size = (sprom_size & SROM_SIZE_MASK) >> SROM_SIZE_SHFT_MASK;
4563 	if (sprom_size == SROM_SIZE_2K)
4564 		sprom_size = 2048;
4565 	else if (sprom_size == SROM_SIZE_512)
4566 		sprom_size = 512;
4567 	else if (sprom_size == SROM_SIZE_128)
4568 		sprom_size = 128;
4569 	sprom_num_words = sprom_size/2;
4570 
4571 	/* read the sprom */
4572 	for (i = 0; i < nwords; i++) {
4573 		if (sih->ccrev > 31 && ISSIM_ENAB(sih)) {
4574 			/* use indirect since direct is too slow on QT */
4575 			if ((sih->cccaps & CC_CAP_SROM) == 0) {
4576 				err = 1;
4577 				goto error;
4578 			}
4579 
4580 			/* hack to get ccregs */
4581 			ccregs = (volatile void *)((volatile uint8 *)sprom - CC_SROM_OTP);
4582 			buf[i] = srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ, wordoff + i, 0);
4583 
4584 		} else {
4585 			/* Because of the slow emulation we need to read twice in QT */
4586 			if (ISSIM_ENAB(sih)) {
4587 				buf[i] = R_REG(osh, &sprom[wordoff + i]);
4588 			}
4589 
4590 			if ((wordoff + i) >= sprom_num_words) {
4591 				buf[i] = 0xffff;
4592 			} else if ((wordoff + i) >= CC_SROM_SHADOW_WSIZE) {
4593 				/* Srom shadow region in chipcommon is only 512 words
4594 				 * use indirect access for Srom beyond 512 words
4595 				 */
4596 				buf[i] = srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ, wordoff + i, 0);
4597 			} else {
4598 				buf[i] = R_REG(osh, &sprom[wordoff + i]);
4599 			}
4600 		}
4601 		if (i == SROM13_SIGN) {
4602 			if ((buf[SROM13_SIGN] !=  SROM13_SIGNATURE) && (nwords == SROM13_WORDS)) {
4603 				err = 1;
4604 				goto error;
4605 			}
4606 		}
4607 	}
4608 
4609 	/* bypass crc checking for simulation to allow srom hack */
4610 	if (ISSIM_ENAB(sih)) {
4611 		goto error;
4612 	}
4613 
4614 	if (check_crc) {
4615 
4616 		if (buf[0] == 0xffff) {
4617 			/* The hardware thinks that an srom that starts with 0xffff
4618 			 * is blank, regardless of the rest of the content, so declare
4619 			 * it bad.
4620 			 */
4621 			BS_ERROR(("sprom_read_pci: buf[0] = 0x%x, returning bad-crc\n", buf[0]));
4622 			err = 1;
4623 			goto error;
4624 		}
4625 
4626 		/* fixup the endianness so crc8 will pass */
4627 		htol16_buf(buf, nwords * 2);
4628 		if (hndcrc8((uint8 *)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) {
4629 			/* DBG only pci always read srom4 first, then srom8/9 */
4630 			/* BS_ERROR(("sprom_read_pci: bad crc\n")); */
4631 			err = 1;
4632 		}
4633 		/* now correct the endianness of the byte array */
4634 		ltoh16_buf(buf, nwords * 2);
4635 	}
4636 
4637 error:
4638 	if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
4639 	    (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
4640 	    (CHIPID(sih->chip) == BCM4352_CHIP_ID) ||
4641 	    BCM43602_CHIP(sih->chip)) {
4642 		/* Restore config after reading SROM */
4643 		si_chipcontrl_restore(sih, ccval);
4644 	}
4645 
4646 	return err;
4647 }
4648 
4649 #if !defined(BCMDONGLEHOST)
4650 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
4651 static int
4652 BCMSROMATTACHFN(otp_read_pci)(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz)
4653 {
4654 	uint8 *otp;
4655 	uint sz = OTP_SZ_MAX/2; /* size in words */
4656 	int err = 0;
4657 
4658 	if (bufsz > OTP_SZ_MAX) {
4659 		return BCME_ERROR;
4660 	}
4661 
4662 	/* freed in same function */
4663 	if ((otp = MALLOC_NOPERSIST(osh, OTP_SZ_MAX)) == NULL) {
4664 		return BCME_ERROR;
4665 	}
4666 
4667 	bzero(otp, OTP_SZ_MAX);
4668 
4669 	err = otp_read_region(sih, OTP_HW_RGN, (uint16 *)otp, &sz);
4670 
4671 	if (err) {
4672 		MFREE(osh, otp, OTP_SZ_MAX);
4673 		return err;
4674 	}
4675 
4676 	bcopy(otp, buf, bufsz);
4677 
4678 	/* Check CRC */
4679 	if (((uint16 *)otp)[0] == 0xffff) {
4680 		/* The hardware thinks that an srom that starts with 0xffff
4681 		 * is blank, regardless of the rest of the content, so declare
4682 		 * it bad.
4683 		 */
4684 		BS_ERROR(("otp_read_pci: otp[0] = 0x%x, returning bad-crc\n",
4685 		          ((uint16 *)otp)[0]));
4686 		MFREE(osh, otp, OTP_SZ_MAX);
4687 		return 1;
4688 	}
4689 
4690 	/* fixup the endianness so crc8 will pass */
4691 	htol16_buf(otp, OTP_SZ_MAX);
4692 	if (hndcrc8(otp, SROM4_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE &&
4693 		hndcrc8(otp, SROM10_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE &&
4694 		hndcrc8(otp, SROM11_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE &&
4695 		hndcrc8(otp, SROM12_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE &&
4696 		hndcrc8(otp, SROM13_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) {
4697 		BS_ERROR(("otp_read_pci: bad crc\n"));
4698 		err = 1;
4699 	}
4700 
4701 	MFREE(osh, otp, OTP_SZ_MAX);
4702 
4703 	return err;
4704 }
4705 #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */
4706 #endif /* !defined(BCMDONGLEHOST) */
4707 
4708 int
4709 srom_otp_write_region_crc(si_t *sih, uint nbytes, uint16* buf16, bool write)
4710 {
4711 #if defined(WLTEST) || defined(BCMDBG)
4712 	int err = 0, crc = 0;
4713 #if !defined(BCMDONGLEHOST)
4714 	uint8 *buf8;
4715 
4716 	/* Check nbytes is not odd or too big */
4717 	if ((nbytes & 1) || (nbytes > SROM_MAX))
4718 		return 1;
4719 
4720 	/* block invalid buffer size */
4721 	if (nbytes < SROM4_WORDS * 2)
4722 		return BCME_BUFTOOSHORT;
4723 	else if (nbytes > SROM13_WORDS * 2)
4724 		return BCME_BUFTOOLONG;
4725 
4726 	/* Verify signatures */
4727 	if (!((buf16[SROM4_SIGN] == SROM4_SIGNATURE) ||
4728 		(buf16[SROM8_SIGN] == SROM4_SIGNATURE) ||
4729 		(buf16[SROM10_SIGN] == SROM4_SIGNATURE) ||
4730 		(buf16[SROM11_SIGN] == SROM11_SIGNATURE)||
4731 		(buf16[SROM12_SIGN] == SROM12_SIGNATURE)||
4732 		(buf16[SROM13_SIGN] == SROM13_SIGNATURE))) {
4733 		BS_ERROR(("srom_otp_write_region_crc: wrong signature SROM4_SIGN %x SROM8_SIGN %x"
4734 			" SROM10_SIGN %x\n",
4735 			buf16[SROM4_SIGN], buf16[SROM8_SIGN], buf16[SROM10_SIGN]));
4736 		return BCME_ERROR;
4737 	}
4738 
4739 	/* Check CRC */
4740 	if (buf16[0] == 0xffff) {
4741 		/* The hardware thinks that an srom that starts with 0xffff
4742 		 * is blank, regardless of the rest of the content, so declare
4743 		 * it bad.
4744 		 */
4745 		BS_ERROR(("srom_otp_write_region_crc: invalid buf16[0] = 0x%x\n", buf16[0]));
4746 		goto out;
4747 	}
4748 
4749 	buf8 = (uint8*)buf16;
4750 	/* fixup the endianness and then calculate crc */
4751 	htol16_buf(buf8, nbytes);
4752 	crc = ~hndcrc8(buf8, nbytes - 1, CRC8_INIT_VALUE);
4753 	/* now correct the endianness of the byte array */
4754 	ltoh16_buf(buf8, nbytes);
4755 
4756 	if (nbytes == SROM11_WORDS * 2)
4757 		buf16[SROM11_CRCREV] = (crc << 8) | (buf16[SROM11_CRCREV] & 0xff);
4758 	else if (nbytes == SROM12_WORDS * 2)
4759 		buf16[SROM12_CRCREV] = (crc << 8) | (buf16[SROM12_CRCREV] & 0xff);
4760 	else if (nbytes == SROM13_WORDS * 2)
4761 		buf16[SROM13_CRCREV] = (crc << 8) | (buf16[SROM13_CRCREV] & 0xff);
4762 	else if (nbytes == SROM10_WORDS * 2)
4763 		buf16[SROM10_CRCREV] = (crc << 8) | (buf16[SROM10_CRCREV] & 0xff);
4764 	else
4765 		buf16[SROM4_CRCREV] = (crc << 8) | (buf16[SROM4_CRCREV] & 0xff);
4766 
4767 #ifdef BCMNVRAMW
4768 	/* Write the CRC back */
4769 	if (write)
4770 		err = otp_write_region(sih, OTP_HW_RGN, buf16, nbytes/2, 0);
4771 #endif /* BCMNVRAMW */
4772 
4773 out:
4774 #endif /* !defined(BCMDONGLEHOST) */
4775 	return write ? err : crc;
4776 #else
4777 	BCM_REFERENCE(sih);
4778 	BCM_REFERENCE(nbytes);
4779 	BCM_REFERENCE(buf16);
4780 	BCM_REFERENCE(write);
4781 	return 0;
4782 #endif /* WLTEST || BCMDBG */
4783 
4784 }
4785 
4786 #if !defined(BCMDONGLEHOST)
4787 int
4788 BCMATTACHFN(dbushost_initvars_flash)(si_t *sih, osl_t *osh, char **base, uint len)
4789 {
4790 	return initvars_flash(sih, osh, base, len);
4791 }
4792 
4793 /**
4794  * Find variables with <devpath> from flash. 'base' points to the beginning
4795  * of the table upon enter and to the end of the table upon exit when success.
4796  * Return 0 on success, nonzero on error.
4797  */
4798 static int
4799 BCMATTACHFN(initvars_flash)(si_t *sih, osl_t *osh, char **base, uint len)
4800 {
4801 	char *vp = *base;
4802 	char *flash;
4803 	int err;
4804 	char *s;
4805 	uint l, dl, copy_len;
4806 	char devpath[SI_DEVPATH_BUFSZ], devpath_pcie[SI_DEVPATH_BUFSZ];
4807 	char coded_name[SI_DEVPATH_BUFSZ] = {0};
4808 	int path_len, coded_len, devid_len, pcie_path_len;
4809 
4810 	/* allocate memory and read in flash */
4811 	/* freed in same function */
4812 	if (!(flash = MALLOC_NOPERSIST(osh, MAX_NVRAM_SPACE)))
4813 		return BCME_NOMEM;
4814 	if ((err = nvram_getall(flash, MAX_NVRAM_SPACE)))
4815 		goto exit;
4816 
4817 	/* create legacy devpath prefix */
4818 	si_devpath(sih, devpath, sizeof(devpath));
4819 	path_len = strlen(devpath);
4820 
4821 	if (BUSTYPE(sih->bustype) == PCI_BUS) {
4822 		si_devpath_pcie(sih, devpath_pcie, sizeof(devpath_pcie));
4823 		pcie_path_len = strlen(devpath_pcie);
4824 	} else
4825 		pcie_path_len = 0;
4826 
4827 	/* create coded devpath prefix */
4828 	si_coded_devpathvar(sih, coded_name, sizeof(coded_name), "devid");
4829 
4830 	/* coded_name now is 'xx:devid, eat ending 'devid' */
4831 	/* to be 'xx:' */
4832 	devid_len = strlen("devid");
4833 	coded_len = strlen(coded_name);
4834 	if (coded_len > devid_len) {
4835 		coded_name[coded_len - devid_len] = '\0';
4836 		coded_len -= devid_len;
4837 	}
4838 	else
4839 		coded_len = 0;
4840 
4841 	/* grab vars with the <devpath> prefix or <coded_name> previx in name */
4842 	for (s = flash; s && *s; s += l + 1) {
4843 		l = strlen(s);
4844 
4845 		/* skip non-matching variable */
4846 		if (strncmp(s, devpath, path_len) == 0)
4847 			dl = path_len;
4848 		else if (pcie_path_len && strncmp(s, devpath_pcie, pcie_path_len) == 0)
4849 			dl = pcie_path_len;
4850 		else if (coded_len && strncmp(s, coded_name, coded_len) == 0)
4851 			dl = coded_len;
4852 		else
4853 			continue;
4854 
4855 		/* is there enough room to copy? */
4856 		copy_len = l - dl + 1;
4857 		if (len < copy_len) {
4858 			err = BCME_BUFTOOSHORT;
4859 			goto exit;
4860 		}
4861 
4862 		/* no prefix, just the name=value */
4863 		strlcpy(vp, &s[dl], copy_len);
4864 		vp += copy_len;
4865 		len -= copy_len;
4866 	}
4867 
4868 	/* add null string as terminator */
4869 	if (len < 1) {
4870 		err = BCME_BUFTOOSHORT;
4871 		goto exit;
4872 	}
4873 	*vp++ = '\0';
4874 
4875 	*base = vp;
4876 
4877 exit:
4878 	MFREE(osh, flash, MAX_NVRAM_SPACE);
4879 	return err;
4880 }
4881 #endif /* !defined(BCMDONGLEHOST) */
4882 
4883 #if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED) &&	\
4884 	!defined(BCMPCIEDEV_ENABLED)
4885 #if !defined(BCMDONGLEHOST)
4886 /**
4887  * Initialize nonvolatile variable table from flash.
4888  * Return 0 on success, nonzero on error.
4889  */
4890 /* no needs to load the nvram variables from the flash for dongles.
4891  * These variables are mainly for supporting SROM-less devices although
4892  * we can use the same machenism to support configuration of multiple
4893  * cores of the same type.
4894  */
4895 static int
4896 BCMATTACHFN(initvars_flash_si)(si_t *sih, char **vars, uint *count)
4897 {
4898 	osl_t *osh = si_osh(sih);
4899 	char *vp, *base;
4900 	int err;
4901 
4902 	ASSERT(vars != NULL);
4903 	ASSERT(count != NULL);
4904 
4905 	/* freed in same function */
4906 	base = vp = MALLOC_NOPERSIST(osh, MAXSZ_NVRAM_VARS);
4907 	ASSERT(vp != NULL);
4908 	if (!vp)
4909 		return BCME_NOMEM;
4910 
4911 	if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS)) == 0)
4912 		err = initvars_table(osh, base, vp, vars, count);
4913 
4914 	MFREE(osh, base, MAXSZ_NVRAM_VARS);
4915 
4916 	return err;
4917 }
4918 #endif /* !defined(BCMDONGLEHOST) */
4919 #endif	/* !BCMUSBDEV && !BCMSDIODEV */
4920 
4921 #if !defined(BCMDONGLEHOST)
4922 
4923 /** returns position of rightmost bit that was set in caller supplied mask */
4924 static uint
4925 mask_shift(uint16 mask)
4926 {
4927 	uint i;
4928 	for (i = 0; i < (sizeof(mask) << 3); i ++) {
4929 		if (mask & (1 << i))
4930 			return i;
4931 	}
4932 	ASSERT(mask);
4933 	return 0;
4934 }
4935 
4936 static uint
4937 mask_width(uint16 mask)
4938 {
4939 	int i;
4940 	for (i = (sizeof(mask) << 3) - 1; i >= 0; i --) {
4941 		if (mask & (1 << i))
4942 			return (uint)(i - mask_shift(mask) + 1);
4943 	}
4944 	ASSERT(mask);
4945 	return 0;
4946 }
4947 
4948 #ifdef BCMASSERT_SUPPORT
4949 static bool
4950 mask_valid(uint16 mask)
4951 {
4952 	uint shift = mask_shift(mask);
4953 	uint width = mask_width(mask);
4954 	return mask == ((~0 << shift) & ~(~0 << (shift + width)));
4955 }
4956 #endif
4957 #ifdef NVSRCX
4958 void
4959 srom_set_sromvars(char *vars)
4960 {
4961 	if (sromh)
4962 		sromh->_srom_vars = vars;
4963 }
4964 char *
4965 srom_get_sromvars()
4966 {
4967 	if (sromh)
4968 		return sromh->_srom_vars;
4969 	else
4970 		return NULL;
4971 }
4972 
4973 srom_info_t *
4974 srom_info_init(osl_t *osh)
4975 {
4976 	sromh = (srom_info_t *) MALLOC_NOPERSIST(osh, sizeof(srom_info_t));
4977 	if (!sromh)
4978 		return NULL;
4979 	sromh->_srom_vars = NULL;
4980 	sromh->is_caldata_prsnt = FALSE;
4981 	return sromh;
4982 }
4983 #endif /* NVSRCX */
4984 /**
4985  * Parses caller supplied SROM contents into name=value pairs. Global array pci_sromvars[] contains
4986  * the link between a word offset in SROM and the corresponding NVRAM variable name.'srom' points to
4987  * the SROM word array. 'off' specifies the offset of the first word 'srom' points to, which should
4988  * be either 0 or SROM3_SWRG_OFF (full SROM or software region).
4989  */
4990 static void
4991 BCMATTACHFN(_initvars_srom_pci)(uint8 sromrev, uint16 *srom, uint off, varbuf_t *b)
4992 {
4993 	uint16 w;
4994 	uint32 val;
4995 	const sromvar_t *srv;
4996 	uint width;
4997 	uint flags;
4998 	uint32 sr = (1 << sromrev);
4999 	bool in_array = FALSE;
5000 	static char array_temp[256];
5001 	uint array_curr = 0;
5002 	const char* array_name = NULL;
5003 
5004 	varbuf_append(b, "sromrev=%d", sromrev);
5005 #if !defined(SROM15_MEMOPT) && !defined(SROM17_MEMOPT)
5006 	if (sromrev == 15) {
5007 		srv = pci_srom15vars;
5008 	} else if (sromrev == 16) {
5009 		srv = pci_srom16vars;
5010 	} else if (sromrev == 17) {
5011 		srv = pci_srom17vars;
5012 	} else if (sromrev == 18) {
5013 		srv = pci_srom18vars;
5014 	} else {
5015 		srv = pci_sromvars;
5016 	}
5017 #else
5018 #if defined(SROM15_MEMOPT)
5019 	srv = pci_srom15vars;
5020 #endif /* defined(SROM15_MEMOPT) */
5021 #if defined(SROM17_MEMOPT)
5022 	srv = pci_srom17vars;
5023 #endif /* defined(SROM17_MEMOPT) */
5024 #endif /* !defined(SROM15_MEMOPT) && !defined(SROM17_MEMOPT) */
5025 
5026 	for (; srv->name != NULL; srv ++) {
5027 		const char *name;
5028 		static bool in_array2 = FALSE;
5029 		static char array_temp2[256];
5030 		static uint array_curr2 = 0;
5031 		static const char* array_name2 = NULL;
5032 
5033 		if ((srv->revmask & sr) == 0)
5034 		    continue;
5035 
5036 		if (srv->off < off)
5037 			continue;
5038 
5039 		flags = srv->flags;
5040 		name = srv->name;
5041 
5042 		/* This entry is for mfgc only. Don't generate param for it, */
5043 		if (flags & SRFL_NOVAR)
5044 			continue;
5045 
5046 		if (flags & SRFL_ETHADDR) {
5047 			char eabuf[ETHER_ADDR_STR_LEN];
5048 			struct ether_addr ea;
5049 
5050 			ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff;
5051 			ea.octet[1] = srom[srv->off - off] & 0xff;
5052 			ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
5053 			ea.octet[3] = srom[srv->off + 1 - off] & 0xff;
5054 			ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
5055 			ea.octet[5] = srom[srv->off + 2 - off] & 0xff;
5056 			bcm_ether_ntoa(&ea, eabuf);
5057 
5058 			varbuf_append(b, "%s=%s", name, eabuf);
5059 		} else {
5060 			ASSERT(mask_valid(srv->mask));
5061 			ASSERT(mask_width(srv->mask));
5062 
5063 			/* Start of an array */
5064 			if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array2) {
5065 				array_curr2 = 0;
5066 				array_name2 = (const char*)srv->name;
5067 				bzero((void*)array_temp2, sizeof(array_temp2));
5068 				in_array2 = TRUE;
5069 			}
5070 
5071 			w = srom[srv->off - off];
5072 			val = (w & srv->mask) >> mask_shift(srv->mask);
5073 			width = mask_width(srv->mask);
5074 
5075 			while (srv->flags & SRFL_MORE) {
5076 				srv ++;
5077 				ASSERT(srv->name != NULL);
5078 
5079 				if (srv->off == 0 || srv->off < off)
5080 					continue;
5081 
5082 				ASSERT(mask_valid(srv->mask));
5083 				ASSERT(mask_width(srv->mask));
5084 
5085 				w = srom[srv->off - off];
5086 				val += ((w & srv->mask) >> mask_shift(srv->mask)) << width;
5087 				width += mask_width(srv->mask);
5088 			}
5089 
5090 			if ((flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1))
5091 				continue;
5092 
5093 			/* Array support starts in sromrev 10. Skip arrays for sromrev <= 9 */
5094 			if (sromrev <= 9 && srv->flags & SRFL_ARRAY) {
5095 				while (srv->flags & SRFL_ARRAY)
5096 					srv ++;
5097 				srv ++;
5098 			}
5099 
5100 			if (in_array2) {
5101 				int ret;
5102 
5103 				if (flags & SRFL_PRHEX) {
5104 					ret = snprintf(array_temp2 + array_curr2,
5105 						sizeof(array_temp2) - array_curr2, "0x%x,", val);
5106 				} else if ((flags & SRFL_PRSIGN) &&
5107 					(val & (1 << (width - 1)))) {
5108 					ret = snprintf(array_temp2 + array_curr2,
5109 						sizeof(array_temp2) - array_curr2, "%d,",
5110 						(int)(val | (~0 << width)));
5111 				} else {
5112 					ret = snprintf(array_temp2 + array_curr2,
5113 						sizeof(array_temp2) - array_curr2, "%u,", val);
5114 				}
5115 
5116 				if (ret > 0) {
5117 					array_curr2 += ret;
5118 				} else {
5119 					BS_ERROR(("_initvars_srom_pci: array %s parsing error."
5120 						" buffer too short.\n",
5121 						array_name2));
5122 					ASSERT(0);
5123 
5124 					/* buffer too small, skip this param */
5125 					while (srv->flags & SRFL_ARRAY)
5126 						srv ++;
5127 					srv ++;
5128 					in_array2 = FALSE;
5129 					continue;
5130 				}
5131 
5132 				if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */
5133 					/* Remove the last ',' */
5134 					array_temp2[array_curr2-1] = '\0';
5135 					in_array2 = FALSE;
5136 					varbuf_append(b, "%s=%s", array_name2, array_temp2);
5137 				}
5138 			} else if (flags & SRFL_CCODE) {
5139 				if (val == 0)
5140 					varbuf_append(b, "ccode=");
5141 				else
5142 					varbuf_append(b, "ccode=%c%c", (val >> 8), (val & 0xff));
5143 			} else if (flags & SRFL_PRHEX) {
5144 				varbuf_append(b, "%s=0x%x", name, val);
5145 			} else if ((flags & SRFL_PRSIGN) && (val & (1 << (width - 1)))) {
5146 				varbuf_append(b, "%s=%d", name, (int)(val | (~0 << width)));
5147 			} else {
5148 				varbuf_append(b, "%s=%u", name, val);
5149 			}
5150 		}
5151 	}
5152 
5153 	if ((sromrev >= 4) && (sromrev != 16) && (sromrev != 18)) {
5154 		/* Do per-path variables */
5155 		uint p, pb, psz, path_num;
5156 
5157 		if  ((sromrev == 17) || (sromrev == 15)) {
5158 			pb = psz = 0;
5159 			path_num = 0;
5160 			if (sromh)
5161 				sromh->is_caldata_prsnt = TRUE;
5162 		} else if  (sromrev >= 13) {
5163 			pb = SROM13_PATH0;
5164 			psz = SROM13_PATH1 - SROM13_PATH0;
5165 			path_num = MAX_PATH_SROM_13;
5166 		} else if  (sromrev >= 12) {
5167 			pb = SROM12_PATH0;
5168 			psz = SROM12_PATH1 - SROM12_PATH0;
5169 			path_num = MAX_PATH_SROM_12;
5170 		} else if (sromrev >= 11) {
5171 			pb = SROM11_PATH0;
5172 			psz = SROM11_PATH1 - SROM11_PATH0;
5173 			path_num = MAX_PATH_SROM_11;
5174 		} else if (sromrev >= 8) {
5175 			pb = SROM8_PATH0;
5176 			psz = SROM8_PATH1 - SROM8_PATH0;
5177 			path_num = MAX_PATH_SROM;
5178 		} else {
5179 			pb = SROM4_PATH0;
5180 			psz = SROM4_PATH1 - SROM4_PATH0;
5181 			path_num = MAX_PATH_SROM;
5182 		}
5183 
5184 		for (p = 0; p < path_num; p++) {
5185 			for (srv = perpath_pci_sromvars; srv->name != NULL; srv ++) {
5186 
5187 				if ((srv->revmask & sr) == 0)
5188 					continue;
5189 
5190 				if (pb + srv->off < off)
5191 					continue;
5192 
5193 				/* This entry is for mfgc only. Don't generate param for it, */
5194 				if (srv->flags & SRFL_NOVAR)
5195 					continue;
5196 
5197 				/* Start of an array */
5198 				if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array) {
5199 					array_curr = 0;
5200 					array_name = (const char*)srv->name;
5201 					bzero((void*)array_temp, sizeof(array_temp));
5202 					in_array = TRUE;
5203 				}
5204 
5205 				w = srom[pb + srv->off - off];
5206 
5207 				ASSERT(mask_valid(srv->mask));
5208 				val = (w & srv->mask) >> mask_shift(srv->mask);
5209 				width = mask_width(srv->mask);
5210 
5211 				flags = srv->flags;
5212 
5213 				/* Cheating: no per-path var is more than 1 word */
5214 
5215 				if ((srv->flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1))
5216 					continue;
5217 
5218 				if (in_array) {
5219 					int ret;
5220 
5221 					if (flags & SRFL_PRHEX) {
5222 						ret = snprintf(array_temp + array_curr,
5223 						  sizeof(array_temp) - array_curr, "0x%x,", val);
5224 					} else if ((flags & SRFL_PRSIGN) &&
5225 						(val & (1 << (width - 1)))) {
5226 						ret = snprintf(array_temp + array_curr,
5227 							sizeof(array_temp) - array_curr, "%d,",
5228 							(int)(val | (~0 << width)));
5229 					} else {
5230 						ret = snprintf(array_temp + array_curr,
5231 						  sizeof(array_temp) - array_curr, "%u,", val);
5232 					}
5233 
5234 					if (ret > 0) {
5235 						array_curr += ret;
5236 					} else {
5237 						BS_ERROR(
5238 						("_initvars_srom_pci: array %s parsing error."
5239 						" buffer too short.\n",
5240 						array_name));
5241 						ASSERT(0);
5242 
5243 						/* buffer too small, skip this param */
5244 						while (srv->flags & SRFL_ARRAY)
5245 							srv ++;
5246 						srv ++;
5247 						in_array = FALSE;
5248 						continue;
5249 					}
5250 
5251 					if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */
5252 						/* Remove the last ',' */
5253 						array_temp[array_curr-1] = '\0';
5254 						in_array = FALSE;
5255 						varbuf_append(b, "%s%d=%s",
5256 							array_name, p, array_temp);
5257 					}
5258 				} else if (srv->flags & SRFL_PRHEX)
5259 					varbuf_append(b, "%s%d=0x%x", srv->name, p, val);
5260 				else
5261 					varbuf_append(b, "%s%d=%d", srv->name, p, val);
5262 			}
5263 			if (sromrev >= 13 && (p == (MAX_PATH_SROM_13 - 2))) {
5264 				psz = SROM13_PATH3 - SROM13_PATH2;
5265 			}
5266 			pb += psz;
5267 		}
5268 	} /* per path variables */
5269 } /* _initvars_srom_pci */
5270 
5271 int
5272 BCMATTACHFN(get_srom_pci_caldata_size)(uint32 sromrev)
5273 {
5274 	uint32 caldata_size;
5275 
5276 	switch (sromrev) {
5277 		case 15:
5278 			caldata_size = (SROM15_CALDATA_WORDS * 2);
5279 			break;
5280 		case 17:
5281 			caldata_size = (SROM17_CALDATA_WORDS * 2);
5282 			break;
5283 		default:
5284 			caldata_size = 0;
5285 			break;
5286 	}
5287 	return caldata_size;
5288 }
5289 
5290 uint32
5291 BCMATTACHFN(get_srom_size)(uint32 sromrev)
5292 {
5293 	uint32 size;
5294 
5295 	switch (sromrev) {
5296 		case 15:
5297 			size = (SROM15_WORDS * 2);
5298 			break;
5299 		case 17:
5300 			size = (SROM17_WORDS * 2);
5301 			break;
5302 		default:
5303 			size = 0;
5304 			break;
5305 	}
5306 	return size;
5307 }
5308 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
5309 
5310 int
5311 BCMATTACHFN(_initvars_srom_pci_caldata)(si_t *sih, uint16 *srom, uint32 sromrev)
5312 {
5313 	int err = BCME_ERROR;
5314 
5315 	if (sromh && (!sromh->is_caldata_prsnt)) {
5316 		return err;
5317 	}
5318 
5319 	if (si_is_sprom_available(sih)) {
5320 		uint32 caldata_size;
5321 
5322 		caldata_size = get_srom_pci_caldata_size(sromrev);
5323 		memcpy(srom, caldata_array, caldata_size);
5324 		err = BCME_OK;
5325 	}
5326 	return err;
5327 }
5328 #endif /* defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) */
5329 /**
5330  * Initialize nonvolatile variable table from sprom, or OTP when SPROM is not available, or
5331  * optionally a set of 'defaultsromvars' (compiled-in) variables when both OTP and SPROM bear no
5332  * contents.
5333  *
5334  * On success, a buffer containing var/val pairs is allocated and returned in params vars and count.
5335  *
5336  * Return 0 on success, nonzero on error.
5337  */
5338 static int
5339 BCMATTACHFN(initvars_srom_pci)(si_t *sih, volatile void *curmap, char **vars, uint *count)
5340 {
5341 	uint16 *srom;
5342 	volatile uint16 *sromwindow;
5343 	uint8 sromrev = 0;
5344 	uint32 sr;
5345 	varbuf_t b;
5346 	char *vp, *base = NULL;
5347 	osl_t *osh = si_osh(sih);
5348 	bool flash = FALSE;
5349 	int err = 0;
5350 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
5351 	uint16 cal_wordoffset;
5352 #endif
5353 
5354 	/*
5355 	 * Apply CRC over SROM content regardless SROM is present or not, and use variable
5356 	 * <devpath>sromrev's existance in flash to decide if we should return an error when CRC
5357 	 * fails or read SROM variables from flash.
5358 	 */
5359 
5360 	/* freed in same function */
5361 	srom = MALLOC_NOPERSIST(osh, SROM_MAX);
5362 	ASSERT(srom != NULL);
5363 	if (!srom)
5364 		return -2;
5365 
5366 	sromwindow = (volatile uint16 *)srom_offset(sih, curmap);
5367 	if (si_is_sprom_available(sih)) {
5368 		err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM_SIGN_MINWORDS + 1, FALSE);
5369 		if (err == 0) {
5370 			if (srom[SROM18_SIGN] == SROM18_SIGNATURE) {
5371 				err = sprom_read_pci(osh, sih, sromwindow,
5372 						0, srom, SROM18_WORDS, TRUE);
5373 				sromrev = srom[SROM18_CRCREV] & 0xff;
5374 			} else if (srom[SROM17_SIGN] == SROM17_SIGNATURE) {
5375 				err = sprom_read_pci(osh, sih, sromwindow,
5376 						0, srom, SROM17_WORDS, TRUE);
5377 				sromrev = srom[SROM17_CRCREV] & 0xff;
5378 			} else if (srom[SROM16_SIGN] == SROM16_SIGNATURE) {
5379 				err = sprom_read_pci(osh, sih, sromwindow,
5380 						0, srom, SROM16_WORDS, TRUE);
5381 				sromrev = srom[SROM16_CRCREV] & 0xff;
5382 			} else if (srom[SROM15_SIGN] == SROM15_SIGNATURE) { /* srom 15  */
5383 				err = sprom_read_pci(osh, sih, sromwindow,
5384 						0, srom, SROM15_WORDS, TRUE);
5385 				sromrev = srom[SROM15_CRCREV] & 0xff;
5386 			} else if (srom[SROM11_SIGN] == SROM13_SIGNATURE) {
5387 				err = sprom_read_pci(osh, sih, sromwindow,
5388 						0, srom, SROM13_WORDS, TRUE);
5389 				sromrev = srom[SROM13_CRCREV] & 0xff;
5390 			} else if (srom[SROM11_SIGN] == SROM12_SIGNATURE) {
5391 				err = sprom_read_pci(osh, sih, sromwindow,
5392 						0, srom, SROM12_WORDS, TRUE);
5393 				sromrev = srom[SROM12_CRCREV] & 0xff;
5394 			} else if (srom[SROM11_SIGN] == SROM11_SIGNATURE) {
5395 				err = sprom_read_pci(osh, sih, sromwindow,
5396 						0, srom, SROM11_WORDS, TRUE);
5397 				sromrev = srom[SROM11_CRCREV] & 0xff;
5398 			} else  if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || /* srom 4  */
5399 				(srom[SROM8_SIGN] == SROM4_SIGNATURE)) { /* srom 8,9  */
5400 				err = sprom_read_pci(osh, sih, sromwindow,
5401 						0, srom, SROM4_WORDS, TRUE);
5402 				sromrev = srom[SROM4_CRCREV] & 0xff;
5403 			} else {
5404 				err = sprom_read_pci(osh, sih, sromwindow, 0,
5405 						srom, SROM_WORDS, TRUE);
5406 				if (err == 0) {
5407 					/* srom is good and is rev < 4 */
5408 					/* top word of sprom contains version and crc8 */
5409 					sromrev = srom[SROM_CRCREV] & 0xff;
5410 					/* bcm4401 sroms misprogrammed */
5411 					if (sromrev == 0x10)
5412 						sromrev = 1;
5413 				}
5414 			}
5415 			if (err)
5416 				BS_ERROR(("srom read failed\n"));
5417 		}
5418 		else
5419 			BS_ERROR(("srom read failed\n"));
5420 	}
5421 
5422 #if defined(BCMNVRAMW) || defined(BCMNVRAMR)
5423 	/* Use OTP if SPROM not available */
5424 	else if ((err = otp_read_pci(osh, sih, srom, SROM_MAX)) == 0) {
5425 		/* OTP only contain SROM rev8/rev9/rev10/Rev11 for now */
5426 
5427 		if (srom[SROM13_SIGN] == SROM13_SIGNATURE)
5428 			sromrev = srom[SROM13_CRCREV] & 0xff;
5429 		else if (srom[SROM12_SIGN] == SROM12_SIGNATURE)
5430 			sromrev = srom[SROM12_CRCREV] & 0xff;
5431 		else if (srom[SROM11_SIGN] == SROM11_SIGNATURE)
5432 			sromrev = srom[SROM11_CRCREV] & 0xff;
5433 		else if (srom[SROM10_SIGN] == SROM10_SIGNATURE)
5434 			sromrev = srom[SROM10_CRCREV] & 0xff;
5435 		else
5436 			sromrev = srom[SROM4_CRCREV] & 0xff;
5437 	}
5438 #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */
5439 	else {
5440 		err = 1;
5441 		BS_ERROR(("Neither SPROM nor OTP has valid image\n"));
5442 	}
5443 
5444 	BS_ERROR(("srom rev:%d\n", sromrev));
5445 
5446 	/* We want internal/wltest driver to come up with default sromvars so we can
5447 	 * program a blank SPROM/OTP.
5448 	 */
5449 	if (err || sromrev == 0) {
5450 		char *value;
5451 #if defined(BCMHOSTVARS)
5452 		uint32 val;
5453 #endif
5454 
5455 		if ((value = si_getdevpathvar(sih, "sromrev"))) {
5456 			sromrev = (uint8)bcm_strtoul(value, NULL, 0);
5457 			flash = TRUE;
5458 			goto varscont;
5459 		}
5460 
5461 		BS_ERROR(("initvars_srom_pci, SROM CRC Error\n"));
5462 
5463 #if !defined(DONGLEBUILD) || defined(BCMPCIEDEV_SROM_FORMAT)
5464 		/* NIC build or PCIe FD using SROM format shouldn't load driver
5465 		 * default when external nvram exists.
5466 		 */
5467 		if ((value = getvar(NULL, "sromrev"))) {
5468 			BS_ERROR(("initvars_srom_pci, Using external nvram\n"));
5469 			err = 0;
5470 			goto errout;
5471 		}
5472 #endif /* !DONGLEBUILD || BCMPCIEDEV_SROM_FORMAT */
5473 
5474 #if defined(BCMHOSTVARS)
5475 		/*
5476 		 * CRC failed on srom, so if the device is using OTP
5477 		 * and if OTP is not programmed use the default variables.
5478 		 * for 4311 A1 there is no signature to indicate that OTP is
5479 		 * programmed, so can't really verify the OTP is unprogrammed
5480 		 * or a bad OTP.
5481 		*/
5482 		val = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32));
5483 		if ((si_is_sprom_available(sih) && srom[0] == 0xffff) ||
5484 #ifdef BCMQT
5485 			(si_is_sprom_available(sih) && sromrev == 0) ||
5486 #endif
5487 			(val & SPROM_OTPIN_USE)) {
5488 			vp = base = mfgsromvars;
5489 
5490 			/* For windows internal/wltest driver, a .nvm file with default
5491 			 * nvram parameters is downloaded from the file system (in src/wl/sys:
5492 			 * wl_readconfigdata()).
5493 			 * Only when we cannot download default vars from the file system, use
5494 			 * defaultsromvars_wltest as default
5495 			 */
5496 			if (defvarslen == 0) {
5497 				BS_ERROR(("No nvm file, use generic default (for programming"
5498 					" SPROM/OTP only)\n"));
5499 
5500 				if (BCM43602_CHIP(sih->chip)) {
5501 					defvarslen = srom_vars_len(defaultsromvars_43602);
5502 					bcopy(defaultsromvars_43602, vp, defvarslen);
5503 				} else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
5504 				           (CHIPID(sih->chip) == BCM4352_CHIP_ID)) {
5505 					defvarslen = srom_vars_len(defaultsromvars_4360);
5506 					bcopy(defaultsromvars_4360, vp, defvarslen);
5507 				} else if (BCM4378_CHIP(sih->chip)) {
5508 					defvarslen = srom_vars_len(defaultsromvars_4378);
5509 					bcopy(defaultsromvars_4378, vp, defvarslen);
5510 				} else if (BCM4387_CHIP(sih->chip)) {
5511 					defvarslen = srom_vars_len(defaultsromvars_4387);
5512 					bcopy(defaultsromvars_4387, vp, defvarslen);
5513 				} else {
5514 					defvarslen = srom_vars_len(defaultsromvars_wltest);
5515 					bcopy(defaultsromvars_wltest, vp, defvarslen);
5516 				}
5517 			} else {
5518 				BS_ERROR(("Use nvm file as default\n"));
5519 			}
5520 
5521 			vp += defvarslen;
5522 			/* add final null terminator */
5523 			*vp++ = '\0';
5524 
5525 			BS_ERROR(("Used %d bytes of defaultsromvars\n", defvarslen));
5526 			goto varsdone;
5527 
5528 		} else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
5529 			(CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
5530 			(CHIPID(sih->chip) == BCM4352_CHIP_ID) ||
5531 			BCM43602_CHIP(sih->chip)) {
5532 
5533 			base = vp = mfgsromvars;
5534 
5535 			if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) ||
5536 			    (CHIPID(sih->chip) == BCM43460_CHIP_ID) ||
5537 			    (CHIPID(sih->chip) == BCM4352_CHIP_ID) ||
5538 			    BCM43602_CHIP(sih->chip))
5539 				BS_ERROR(("4360 BOOT w/o SPROM or OTP\n"));
5540 			else
5541 				BS_ERROR(("BOOT w/o SPROM or OTP\n"));
5542 
5543 			if (defvarslen == 0) {
5544 				if (BCM43602_CHIP(sih->chip)) {
5545 					defvarslen = srom_vars_len(defaultsromvars_43602);
5546 					bcopy(defaultsromvars_43602, vp, defvarslen);
5547 				} else if ((sih->chip == BCM4360_CHIP_ID) ||
5548 						(sih->chip == BCM4352_CHIP_ID)) {
5549 					defvarslen = srom_vars_len(defaultsromvars_4360);
5550 					bcopy(defaultsromvars_4360, vp, defvarslen);
5551 				} else {
5552 					defvarslen = srom_vars_len(defaultsromvars_4331);
5553 					bcopy(defaultsromvars_4331, vp, defvarslen);
5554 				}
5555 			}
5556 			vp += defvarslen;
5557 			*vp++ = '\0';
5558 			goto varsdone;
5559 		} else
5560 #endif /* defined(BCMHOSTVARS) */
5561 		{
5562 			err = -1;
5563 			goto errout;
5564 		}
5565 	}
5566 #if defined(BCM_ONE_NVRAM_SRC)
5567 	/* Discard hostvars if SROM parsing is successful, so only one nvram source
5568 	 * will be used.
5569 	 * Routers use combined srom/host nvram so shouldn't define BCM_ONE_NVRAM_SRC.
5570 	 */
5571 	else {
5572 		nvram_exit((void *)sih); /* free up global vars */
5573 	}
5574 #endif /* BCM_ONE_NVRAM_SRC */
5575 
5576 varscont:
5577 	/* Bitmask for the sromrev */
5578 	sr = 1 << sromrev;
5579 
5580 	/* srom version check: Current valid versions are:
5581 	  * 1-5, 8-11, 12, 13, 15, 16, 17, 18 SROM_MAXREV
5582 	  * This is a bit mask of all valid SROM versions.
5583 	  */
5584 	if ((sr & 0x7bf3e) == 0) {
5585 		BS_ERROR(("Invalid SROM rev %d\n", sromrev));
5586 		err = -2;
5587 		goto errout;
5588 	}
5589 
5590 	ASSERT(vars != NULL);
5591 	ASSERT(count != NULL);
5592 
5593 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
5594 	srom_sromrev = sromrev;
5595 #endif /* defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) */
5596 
5597 	/* freed in same function */
5598 	base = vp = MALLOC_NOPERSIST(osh, MAXSZ_NVRAM_VARS);
5599 	ASSERT(vp != NULL);
5600 	if (!vp) {
5601 		err = -2;
5602 		goto errout;
5603 	}
5604 
5605 	/* read variables from flash */
5606 	if (flash) {
5607 		if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS)))
5608 			goto errout;
5609 		goto varsdone;
5610 	}
5611 
5612 	varbuf_init(&b, base, MAXSZ_NVRAM_VARS);
5613 
5614 	/* parse SROM into name=value pairs. */
5615 	_initvars_srom_pci(sromrev, srom, 0, &b);
5616 
5617 	/* final nullbyte terminator */
5618 	ASSERT(b.size >= 1);
5619 	vp = b.buf;
5620 	*vp++ = '\0';
5621 
5622 	ASSERT((vp - base) <= MAXSZ_NVRAM_VARS);
5623 
5624 varsdone:
5625 	err = initvars_table(osh, base, vp, vars, count); /* allocates buffer in 'vars' */
5626 
5627 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
5628 	if (sromrev == 18) {
5629 		int caldata_wordoffset = srom[SROM18_CALDATA_OFFSET_LOC] / 2;
5630 
5631 		if ((caldata_wordoffset != 0) &&
5632 			(caldata_wordoffset + SROM_CALDATA_WORDS < SROM18_WORDS)) {
5633 			memcpy(caldata_array, srom + caldata_wordoffset, SROM18_CALDATA_WORDS * 2);
5634 			is_caldata_prsnt = TRUE;
5635 		}
5636 	} else if (sromrev == 16) {
5637 		int caldata_wordoffset = srom[SROM16_CALDATA_OFFSET_LOC] / 2;
5638 
5639 		if ((caldata_wordoffset != 0) &&
5640 			(caldata_wordoffset + SROM_CALDATA_WORDS < SROM16_WORDS)) {
5641 			memcpy(caldata_array, srom + caldata_wordoffset, SROM_CALDATA_WORDS * 2);
5642 			is_caldata_prsnt = TRUE;
5643 		}
5644 	}
5645 #endif /* defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) */
5646 
5647 #ifdef NVSRCX
5648 	if (sromrev != 0)
5649 		nvram_append((void *)sih, *vars, *count, VARBUF_PRIO_SROM);
5650 #endif
5651 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
5652 	if ((sromrev == 15) || (sromrev == 17)) {
5653 		uint32 caldata_size = get_srom_pci_caldata_size(sromrev);
5654 
5655 		cal_wordoffset = getintvar(NULL, "caldata_offset")/2;
5656 		memcpy(caldata_array, srom + cal_wordoffset, caldata_size);
5657 	}
5658 #endif
5659 errout:
5660 #if defined(BCMHOSTVARS)
5661 	if (base && (base != mfgsromvars))
5662 #else
5663 	if (base)
5664 #endif /* defined(BCMHOSTVARS) */
5665 		MFREE(osh, base, MAXSZ_NVRAM_VARS);
5666 
5667 	MFREE(osh, srom, SROM_MAX);
5668 	return err;
5669 }
5670 
5671 /**
5672  * initvars_cis_pci() parses OTP CIS. This is specifically for PCIe full dongle that has SROM
5673  * header plus CIS tuples programmed in OTP.
5674  * Return error if the content is not in CIS format or OTP is not present.
5675  */
5676 static int
5677 BCMATTACHFN(initvars_cis_pci)(si_t *sih, osl_t *osh, volatile void *curmap,
5678 	char **vars, uint *count)
5679 {
5680 	uint wsz = 0, sz = 0, base_len = 0;
5681 	void *oh = NULL;
5682 	int rc = BCME_OK;
5683 	uint16 *cisbuf = NULL;
5684 	uint8 *cis = NULL;
5685 #if defined (BCMHOSTVARS)
5686 	char *vp = NULL;
5687 #endif /* BCMHOSTVARS */
5688 	char *base = NULL;
5689 	bool wasup;
5690 	uint32 min_res_mask = 0;
5691 	BCM_REFERENCE(curmap);
5692 
5693 	/* Bail out if we've dealt with OTP/SPROM before! */
5694 	if (srvars_inited)
5695 		goto exit;
5696 
5697 	/* Turn on OTP if it's not already on */
5698 	if (!(wasup = si_is_otp_powered(sih)))
5699 		si_otp_power(sih, TRUE, &min_res_mask);
5700 
5701 	if (si_cis_source(sih) != CIS_OTP)
5702 		rc = BCME_NOTFOUND;
5703 	else if ((oh = otp_init(sih)) == NULL)
5704 		rc = BCME_ERROR;
5705 	else if (!(((BUSCORETYPE(sih->buscoretype) == PCIE2_CORE_ID) || otp_newcis(oh)) &&
5706 		(otp_status(oh) & OTPS_GUP_HW))) {
5707 		/* OTP bit CIS format (507) not used by pcie core - only needed for sdio core */
5708 		rc = BCME_NOTFOUND;
5709 	} else if ((sz = otp_size(oh)) != 0) {
5710 		if ((cisbuf = (uint16*)MALLOC_NOPERSIST(osh, sz))) {
5711 			/* otp_size() returns bytes, not words. */
5712 			wsz = sz >> 1;
5713 			/* for 4389b0 (CCREV-70) sw region is before the hw region */
5714 			if (CCREV(sih->ccrev) == 70) {
5715 				rc = otp_read_region(sih, OTP_SW_RGN, cisbuf, &wsz);
5716 				cis = (uint8*)cisbuf;
5717 			} else {
5718 				rc = otp_read_region(sih, OTP_HW_RGN, cisbuf, &wsz);
5719 				/* Bypass the HW header and signature */
5720 				cis = (uint8*)(cisbuf + (otp_pcie_hwhdr_sz(sih) / 2));
5721 			}
5722 			BS_ERROR(("initvars_cis_pci: Parsing CIS in OTP.\n"));
5723 		} else
5724 			rc = BCME_NOMEM;
5725 	}
5726 
5727 	/* Restore original OTP state */
5728 	if (!wasup)
5729 		si_otp_power(sih, FALSE, &min_res_mask);
5730 
5731 	if (rc != BCME_OK) {
5732 		BS_ERROR(("initvars_cis_pci: Not CIS format\n"));
5733 		goto exit;
5734 	}
5735 
5736 #if defined (BCMHOSTVARS)
5737 	if (defvarslen) {
5738 		vp = mfgsromvars;
5739 		vp += defvarslen;
5740 
5741 		/* allocates buffer in 'vars' */
5742 		rc = initvars_table(osh, mfgsromvars, vp, &base, &base_len);
5743 		if (rc)
5744 			goto exit;
5745 
5746 		*vars = base;
5747 		*count = base_len;
5748 
5749 		BS_ERROR(("initvars_cis_pci external nvram %d bytes\n", defvarslen));
5750 	}
5751 
5752 #endif /* BCMHOSTVARS */
5753 
5754 	/* Parse the CIS and allocate a(nother) buffer in 'vars' */
5755 	rc = srom_parsecis(sih, osh, &cis, SROM_CIS_SINGLE, vars, count);
5756 
5757 	srvars_inited = TRUE;
5758 exit:
5759 	/* Clean up */
5760 	if (base)
5761 		MFREE(osh, base, base_len);
5762 	if (cisbuf)
5763 		MFREE(osh, cisbuf, sz);
5764 
5765 	/* return OK so the driver will load & use defaults if bad srom/otp */
5766 	return rc;
5767 }
5768 #endif /* !defined(BCMDONGLEHOST) */
5769 
5770 #ifdef BCMSDIO
5771 #if !defined(BCMDONGLEHOST)
5772 /**
5773  * Read the SDIO cis and call parsecis to allocate and initialize the NVRAM vars buffer.
5774  * Return 0 on success, nonzero on error.
5775  */
5776 static int
5777 BCMATTACHFN(initvars_cis_sdio)(si_t *sih, osl_t *osh, char **vars, uint *count)
5778 {
5779 	uint8 *cis[SBSDIO_NUM_FUNCTION + 1];
5780 	uint fn, numfn;
5781 	int rc = 0;
5782 
5783 	/* Using MALLOC here causes the Windows driver to crash Needs Investigating */
5784 #ifdef NDIS
5785 	uint8 cisd[SBSDIO_NUM_FUNCTION + 1][SBSDIO_CIS_SIZE_LIMIT];
5786 #endif
5787 
5788 	numfn = bcmsdh_query_iofnum(NULL);
5789 	ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
5790 
5791 	for (fn = 0; fn <= numfn; fn++) {
5792 #ifdef NDIS
5793 		cis[fn] = (uint8*)cisd[fn];
5794 #else
5795 		/* freed in same function */
5796 		if ((cis[fn] = MALLOC_NOPERSIST(osh, SBSDIO_CIS_SIZE_LIMIT)) == NULL) {
5797 			rc = -1;
5798 			break;
5799 		}
5800 #endif /* NDIS */
5801 
5802 		bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT);
5803 
5804 		if (bcmsdh_cis_read(NULL, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT) != 0) {
5805 #ifdef NDIS
5806 			/* nothing to do */
5807 #else
5808 			MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
5809 #endif
5810 			rc = -2;
5811 			break;
5812 		}
5813 	}
5814 
5815 	if (!rc)
5816 		rc = srom_parsecis(sih, osh, cis, fn, vars, count);
5817 
5818 #ifdef NDIS
5819 	/* nothing to do here */
5820 #else
5821 	while (fn-- > 0)
5822 		MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
5823 #endif
5824 
5825 	return (rc);
5826 }
5827 #endif /* !defined(BCMDONGLEHOST) */
5828 
5829 /** set SDIO sprom command register */
5830 static int
5831 BCMATTACHFN(sprom_cmd_sdio)(osl_t *osh, uint8 cmd)
5832 {
5833 	uint8 status = 0;
5834 	uint wait_cnt = 1000;
5835 
5836 	/* write sprom command register */
5837 	bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, cmd, NULL);
5838 
5839 	/* wait status */
5840 	while (wait_cnt--) {
5841 		status = bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, NULL);
5842 		if (status & SBSDIO_SPROM_DONE)
5843 			return 0;
5844 	}
5845 
5846 	return 1;
5847 }
5848 
5849 /** read a word from the SDIO srom */
5850 static int
5851 sprom_read_sdio(osl_t *osh, uint16 addr, uint16 *data)
5852 {
5853 	uint8 addr_l, addr_h, data_l, data_h;
5854 
5855 	addr_l = (uint8)((addr * 2) & 0xff);
5856 	addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
5857 
5858 	/* set address */
5859 	bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_HIGH, addr_h, NULL);
5860 	bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_LOW, addr_l, NULL);
5861 
5862 	/* do read */
5863 	if (sprom_cmd_sdio(osh, SBSDIO_SPROM_READ))
5864 		return 1;
5865 
5866 	/* read data */
5867 	data_h = bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_HIGH, NULL);
5868 	data_l = bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_LOW, NULL);
5869 
5870 	*data = (data_h << 8) | data_l;
5871 	return 0;
5872 }
5873 
5874 #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG)
5875 /** write a word to the SDIO srom */
5876 static int
5877 sprom_write_sdio(osl_t *osh, uint16 addr, uint16 data)
5878 {
5879 	uint8 addr_l, addr_h, data_l, data_h;
5880 
5881 	addr_l = (uint8)((addr * 2) & 0xff);
5882 	addr_h = (uint8)(((addr * 2) >> 8) & 0xff);
5883 	data_l = (uint8)(data & 0xff);
5884 	data_h = (uint8)((data >> 8) & 0xff);
5885 
5886 	/* set address */
5887 	bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_HIGH, addr_h, NULL);
5888 	bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_LOW, addr_l, NULL);
5889 
5890 	/* write data */
5891 	bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_HIGH, data_h, NULL);
5892 	bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_LOW, data_l, NULL);
5893 
5894 	/* do write */
5895 	return sprom_cmd_sdio(osh, SBSDIO_SPROM_WRITE);
5896 }
5897 #endif /* defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) */
5898 #endif /* BCMSDIO */
5899 
5900 #if !defined(BCMDONGLEHOST)
5901 #ifdef BCMSPI
5902 /**
5903  * Read the SPI cis and call parsecis to allocate and initialize the NVRAM vars buffer.
5904  * Return 0 on success, nonzero on error.
5905  */
5906 static int
5907 BCMATTACHFN(initvars_cis_spi)(si_t *sih, osl_t *osh, char **vars, uint *count)
5908 {
5909 	uint8 *cis;
5910 	int rc;
5911 
5912 	/* Using MALLOC here causes the Windows driver to crash Needs Investigating */
5913 #ifdef NDIS
5914 	uint8 cisd[SBSDIO_CIS_SIZE_LIMIT];
5915 	cis = (uint8*)cisd;
5916 #else
5917 	/* freed in same function */
5918 	if ((cis = MALLOC_NOPERSIST(osh, SBSDIO_CIS_SIZE_LIMIT)) == NULL) {
5919 		return -1;
5920 	}
5921 #endif /* NDIS */
5922 
5923 	bzero(cis, SBSDIO_CIS_SIZE_LIMIT);
5924 
5925 	if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, cis, SBSDIO_CIS_SIZE_LIMIT) != 0) {
5926 #ifdef NDIS
5927 		/* nothing to do */
5928 #else
5929 		MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT);
5930 #endif /* NDIS */
5931 		return -2;
5932 	}
5933 
5934 	rc = srom_parsecis(sih, osh, &cis, SDIO_FUNC_1, vars, count);
5935 
5936 #ifdef NDIS
5937 	/* nothing to do here */
5938 #else
5939 	MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT);
5940 #endif
5941 
5942 	return (rc);
5943 }
5944 #endif /* BCMSPI */
5945 #endif /* !defined(BCMDONGLEHOST) */
5946 
5947 /** Return sprom size in 16-bit words */
5948 uint
5949 srom_size(si_t *sih, osl_t *osh)
5950 {
5951 	uint size = (SROM16_SIGN + 1) * 2;	/* must big enough for SROM16 */
5952 	return size;
5953 }
5954 
5955 /**
5956  * initvars are different for BCMUSBDEV and BCMSDIODEV.  This is OK when supporting both at
5957  * the same time, but only because all of the code is in attach functions and not in ROM.
5958  */
5959 
5960 #if defined(BCMUSBDEV_ENABLED)
5961 #ifdef BCM_DONGLEVARS
5962 /*** reads a CIS structure (so not an SROM-MAP structure) from either OTP or SROM */
5963 static int
5964 BCMATTACHFN(initvars_srom_si_bl)(si_t *sih, osl_t *osh, volatile void *curmap,
5965 	char **vars, uint *varsz)
5966 {
5967 	int sel = 0;		/* where to read srom/cis: 0 - none, 1 - otp, 2 - sprom */
5968 	uint sz = 0;		/* srom size in bytes */
5969 	void *oh = NULL;
5970 	int rc = BCME_OK;
5971 	uint16 prio = VARBUF_PRIO_INVALID;
5972 
5973 	if ((oh = otp_init(sih)) != NULL && (otp_status(oh) & OTPS_GUP_SW)) {
5974 		/* Access OTP if it is present, powered on, and programmed */
5975 		sz = otp_size(oh);
5976 		sel = 1;
5977 	} else if ((sz = srom_size(sih, osh)) != 0) {
5978 		/* Access the SPROM if it is present */
5979 		sz <<= 1;
5980 		sel = 2;
5981 	}
5982 
5983 	/* Read CIS in OTP/SPROM */
5984 	if (sel != 0) {
5985 		uint16 *srom;
5986 		uint8 *body = NULL;
5987 		uint otpsz = sz;
5988 
5989 		ASSERT(sz);
5990 
5991 		/* Allocate memory */
5992 		if ((srom = (uint16 *)MALLOC(osh, sz)) == NULL)
5993 			return BCME_NOMEM;
5994 
5995 		/* Read CIS */
5996 		switch (sel) {
5997 		case 1:
5998 			rc = otp_read_region(sih, OTP_SW_RGN, srom, &otpsz);
5999 			sz = otpsz;
6000 			body = (uint8 *)srom;
6001 			prio = VARBUF_PRIO_OTP;
6002 			break;
6003 		case 2:
6004 			rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, srom, TRUE);
6005 			/* sprom has 8 byte h/w header */
6006 			body = (uint8 *)srom + SBSDIO_SPROM_CIS_OFFSET;
6007 			prio = VARBUF_PRIO_SROM;
6008 			break;
6009 		default:
6010 			/* impossible to come here */
6011 			ASSERT(0);
6012 			break;
6013 		}
6014 
6015 		/* Parse CIS */
6016 		if (rc == BCME_OK) {
6017 			/* each word is in host endian */
6018 			htol16_buf((uint8 *)srom, sz);
6019 			ASSERT(body);
6020 			rc = srom_parsecis(sih, osh, &body, SROM_CIS_SINGLE, vars, varsz);
6021 		}
6022 
6023 		MFREE(osh, srom, sz);	/* Clean up */
6024 
6025 		/* Make SROM variables global */
6026 		if (rc == BCME_OK) {
6027 			nvram_append((void *)sih, *vars, *varsz, prio);
6028 			DONGLE_STORE_VARS_OTP_PTR(*vars);
6029 		}
6030 	}
6031 
6032 	return BCME_OK;
6033 }
6034 #endif	/* #ifdef BCM_DONGLEVARS */
6035 
6036 /**
6037  * initvars_srom_si() is defined multiple times in this file. This is the 1st variant for chips with
6038  * an active USB interface. It is called only for bus types SI_BUS, and only for CIS
6039  * format in SPROM and/or OTP. Reads OTP or SPROM (bootloader only) and appends parsed contents to
6040  * caller supplied var/value pairs.
6041  */
6042 static int
6043 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap,
6044 	char **vars, uint *varsz)
6045 {
6046 
6047 #if defined(BCM_DONGLEVARS)
6048 	BCM_REFERENCE(osh);
6049 	BCM_REFERENCE(sih);
6050 	BCM_REFERENCE(curmap);
6051 #endif
6052 
6053 	/* Bail out if we've dealt with OTP/SPROM before! */
6054 	if (srvars_inited)
6055 		goto exit;
6056 
6057 #ifdef BCM_DONGLEVARS	/* this flag should be defined for usb bootloader, to read OTP or SROM */
6058 	if (BCME_OK != initvars_srom_si_bl(sih, osh, curmap, vars, varsz)) /* CIS format only */
6059 		return BCME_ERROR;
6060 #endif
6061 
6062 	/* update static local var to skip for next call */
6063 	srvars_inited = TRUE;
6064 
6065 exit:
6066 	/* Tell the caller there is no individual SROM variables */
6067 	*vars = NULL;
6068 	*varsz = 0;
6069 
6070 	/* return OK so the driver will load & use defaults if bad srom/otp */
6071 	return BCME_OK;
6072 }
6073 
6074 #elif defined(BCMSDIODEV_ENABLED)
6075 
6076 #ifdef BCM_DONGLEVARS
6077 static uint8 BCMATTACHDATA(defcis4369)[] = { 0x20, 0x4, 0xd0, 0x2, 0x64, 0x43, 0xff, 0xff };
6078 static uint8 BCMATTACHDATA(defcis43012)[] = { 0x20, 0x4, 0xd0, 0x2, 0x04, 0xA8, 0xff, 0xff };
6079 static uint8 BCMATTACHDATA(defcis43013)[] = { 0x20, 0x4, 0xd0, 0x2, 0x05, 0xA8, 0xff, 0xff };
6080 static uint8 BCMATTACHDATA(defcis43014)[] = { 0x20, 0x4, 0xd0, 0x2, 0x06, 0xA8, 0xff, 0xff };
6081 static uint8 BCMATTACHDATA(defcis4362)[] = { 0x20, 0x4, 0xd0, 0x2, 0x62, 0x43, 0xff, 0xff };
6082 static uint8 BCMATTACHDATA(defcis4378)[] = { 0x20, 0x4, 0xd0, 0x2, 0x78, 0x43, 0xff, 0xff };
6083 static uint8 BCMATTACHDATA(defcis4385)[] = { 0x20, 0x4, 0xd0, 0x2, 0x85, 0x43, 0xff, 0xff };
6084 static uint8 BCMATTACHDATA(defcis4387)[] = { 0x20, 0x4, 0xd0, 0x2, 0x78, 0x43, 0xff, 0xff };
6085 static uint8 BCMATTACHDATA(defcis4388)[] = { 0x20, 0x4, 0xd0, 0x2, 0x88, 0x43, 0xff, 0xff };
6086 static uint8 BCMATTACHDATA(defcis4389)[] = { 0x20, 0x4, 0xd0, 0x2, 0x89, 0x43, 0xff, 0xff };
6087 static uint8 BCMATTACHDATA(defcis4397)[] = { 0x20, 0x4, 0xd0, 0x2, 0x97, 0x43, 0xff, 0xff };
6088 
6089 /**
6090  * initvars_srom_si() is defined multiple times in this file. This is the 2nd variant for chips with
6091  * an active SDIOd interface using DONGLEVARS
6092  */
6093 static int
6094 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap,
6095 	char **vars, uint *varsz)
6096 {
6097 	int cis_src;
6098 	uint msz = 0;
6099 	uint sz = 0;
6100 	void *oh = NULL;
6101 	int rc = BCME_OK;
6102 	bool	new_cisformat = FALSE;
6103 
6104 	uint16 *cisbuf = NULL;
6105 
6106 	/* # sdiod fns + common + extra */
6107 	uint8 *cis[SBSDIO_NUM_FUNCTION + 2] = { 0 };
6108 
6109 	uint ciss = 0;
6110 	uint8 *defcis;
6111 	uint hdrsz;
6112 	uint16 prio = VARBUF_PRIO_INVALID;
6113 
6114 #if defined(BCMSDIODEV_ENABLED) && defined(ATE_BUILD)
6115 	if (si_chipcap_sdio_ate_only(sih)) {
6116 		BS_ERROR(("ATE BUILD: skip cis based var init\n"));
6117 		goto exit;
6118 	}
6119 #endif /* BCMSDIODEV_ENABLED && ATE_BUILD */
6120 
6121 	/* Bail out if we've dealt with OTP/SPROM before! */
6122 	if (srvars_inited)
6123 		goto exit;
6124 
6125 	/* Initialize default and cis format count */
6126 	switch (CHIPID(sih->chip)) {
6127 	case BCM4369_CHIP_GRPID: ciss = 1; defcis = defcis4369; hdrsz = 4; break;
6128 	case BCM4378_CHIP_GRPID: ciss = 1; defcis = defcis4378; hdrsz = 4; break;
6129 	case BCM4385_CHIP_GRPID: ciss = 1; defcis = defcis4385; hdrsz = 4; break;
6130 	case BCM4387_CHIP_GRPID: ciss = 1; defcis = defcis4387; hdrsz = 4; break;
6131 	case BCM4388_CHIP_GRPID: ciss = 1; defcis = defcis4388; hdrsz = 4; break;
6132 	case BCM4389_CHIP_GRPID: ciss = 1; defcis = defcis4389; hdrsz = 4; break;
6133 	case BCM4397_CHIP_GRPID: ciss = 1; defcis = defcis4397; hdrsz = 4; break;
6134 	case BCM43012_CHIP_ID: ciss = 1; defcis = defcis43012; hdrsz = 4; break;
6135 	case BCM43013_CHIP_ID: ciss = 1; defcis = defcis43013; hdrsz = 4; break;
6136 	case BCM43014_CHIP_ID: ciss = 1; defcis = defcis43014; hdrsz = 4; break;
6137 	case BCM4362_CHIP_GRPID: ciss = 1; defcis = defcis4362; hdrsz = 4; break;
6138 	default:
6139 		BS_ERROR(("initvars_srom_si: Unknown chip 0x%04x\n", CHIPID(sih->chip)));
6140 		return BCME_ERROR;
6141 	}
6142 	if (sih->ccrev >= 36) {
6143 		uint32 otplayout;
6144 		if (AOB_ENAB(sih)) {
6145 			otplayout = si_corereg(sih, si_findcoreidx(sih, GCI_CORE_ID, 0),
6146 			 OFFSETOF(gciregs_t, otplayout), 0, 0);
6147 		} else {
6148 			otplayout = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, otplayout),
6149 			 0, 0);
6150 		}
6151 		if (otplayout & OTP_CISFORMAT_NEW) {
6152 			ciss = 1;
6153 			hdrsz = 2;
6154 			new_cisformat = TRUE;
6155 		}
6156 		else {
6157 			ciss = 3;
6158 			hdrsz = 12;
6159 		}
6160 	}
6161 
6162 	cis_src = si_cis_source(sih);
6163 	switch (cis_src) {
6164 	case CIS_SROM:
6165 		sz = srom_size(sih, osh) << 1;
6166 		prio = VARBUF_PRIO_SROM;
6167 		break;
6168 	case CIS_OTP:
6169 		/* Note that for *this* type of OTP -- which otp_read_region()
6170 		 * can operate on -- otp_size() returns bytes, not words.
6171 		 */
6172 		if (((oh = otp_init(sih)) != NULL) && (otp_status(oh) & OTPS_GUP_HW))
6173 			sz = otp_size(oh);
6174 		prio = VARBUF_PRIO_OTP;
6175 		break;
6176 	}
6177 
6178 	if (sz != 0) {
6179 		/* freed in same function */
6180 		if ((cisbuf = (uint16*)MALLOC_NOPERSIST(osh, sz)) == NULL)
6181 			return BCME_NOMEM;
6182 		msz = sz;
6183 
6184 		switch (cis_src) {
6185 		case CIS_SROM:
6186 			rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, cisbuf, FALSE);
6187 			break;
6188 		case CIS_OTP:
6189 			sz >>= 1;
6190 			rc = otp_read_region(sih, OTP_HW_RGN, cisbuf, &sz);
6191 			sz <<= 1;
6192 			break;
6193 		}
6194 
6195 		ASSERT(sz > hdrsz);
6196 		if (rc == BCME_OK) {
6197 			if ((cisbuf[0] == 0xffff) || (cisbuf[0] == 0)) {
6198 				MFREE(osh, cisbuf, msz);
6199 			} else if (new_cisformat) {
6200 				cis[0] = (uint8*)(cisbuf + hdrsz);
6201 			} else {
6202 				cis[0] = (uint8*)cisbuf + hdrsz;
6203 				cis[1] = (uint8*)cisbuf + hdrsz +
6204 				        (cisbuf[1] >> 8) + ((cisbuf[2] & 0x00ff) << 8) -
6205 				        SBSDIO_CIS_BASE_COMMON;
6206 				cis[2] = (uint8*)cisbuf + hdrsz +
6207 				        cisbuf[3] - SBSDIO_CIS_BASE_COMMON;
6208 				cis[3] = (uint8*)cisbuf + hdrsz +
6209 				        cisbuf[4] - SBSDIO_CIS_BASE_COMMON;
6210 				ASSERT((cis[1] >= cis[0]) && (cis[1] < (uint8*)cisbuf + sz));
6211 				ASSERT((cis[2] >= cis[0]) && (cis[2] < (uint8*)cisbuf + sz));
6212 				ASSERT(((cis[3] >= cis[0]) && (cis[3] < (uint8*)cisbuf + sz)) ||
6213 				        (ciss <= 3));
6214 			}
6215 		}
6216 	}
6217 
6218 	/* Use default if strapped to, or strapped source empty */
6219 	if (cisbuf == NULL) {
6220 		ciss = 1;
6221 		cis[0] = defcis;
6222 	}
6223 
6224 	/* Parse the CIS */
6225 	if (rc == BCME_OK) {
6226 		if ((rc = srom_parsecis(sih, osh, cis, ciss, vars, varsz)) == BCME_OK) {
6227 			nvram_append((void *)sih, *vars, *varsz, prio);
6228 			DONGLE_STORE_VARS_OTP_PTR(*vars);
6229 		}
6230 	}
6231 
6232 	/* Clean up */
6233 	if (cisbuf != NULL)
6234 		MFREE(osh, cisbuf, msz);
6235 
6236 	srvars_inited = TRUE;
6237 exit:
6238 	/* Tell the caller there is no individual SROM variables */
6239 	*vars = NULL;
6240 	*varsz = 0;
6241 
6242 	/* return OK so the driver will load & use defaults if bad srom/otp */
6243 	return BCME_OK;
6244 } /* initvars_srom_si */
6245 #else /* BCM_DONGLEVARS */
6246 
6247 /**
6248  * initvars_srom_si() is defined multiple times in this file. This is the variant for chips with an
6249  * active SDIOd interface but without BCM_DONGLEVARS
6250  */
6251 static int
6252 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap,
6253 	char **vars, uint *varsz)
6254 {
6255 	*vars = NULL;
6256 	*varsz = 0;
6257 	return BCME_OK;
6258 }
6259 #endif /* BCM_DONGLEVARS */
6260 
6261 #elif defined(BCMPCIEDEV_ENABLED)
6262 
6263 /**
6264  * initvars_srom_si() is defined multiple times in this file. This is the variant for chips with an
6265  * active PCIe interface *and* that use OTP for NVRAM storage.
6266  *
6267  * On success, a buffer containing var/val values has been allocated in parameter 'vars'.
6268  * put an ifdef where if the host wants the dongle wants to parse sprom or not
6269  */
6270 static int
6271 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap,
6272 	char **vars, uint *varsz)
6273 {
6274 #ifdef BCM_DONGLEVARS
6275 	void *oh = NULL;
6276 	uint8 *cis;
6277 	uint sz = 0;
6278 	int rc;
6279 
6280 	if (si_cis_source(sih) !=  CIS_OTP)
6281 		return BCME_OK;
6282 
6283 	if (((oh = otp_init(sih)) != NULL) && (otp_status(oh) & OTPS_GUP_HW))
6284 		sz = otp_size(oh);
6285 	if (sz == 0)
6286 		return BCME_OK;
6287 
6288 	if ((cis = MALLOC(osh, sz)) == NULL)
6289 		return BCME_NOMEM;
6290 	sz >>= 1;
6291 	rc = otp_read_region(sih, OTP_HW_RGN, (uint16 *)cis, &sz);
6292 	sz <<= 1;
6293 
6294 	/* account for the Hardware header */
6295 	if (sz == 128)
6296 		return BCME_OK;
6297 
6298 	cis += 128;
6299 
6300 	/* need to find a better way to identify sprom format content and ignore parse */
6301 	if (*(uint16 *)cis == SROM11_SIGNATURE) {
6302 		return BCME_OK;
6303 	}
6304 
6305 	if ((rc = srom_parsecis(sih, osh, &cis, SROM_CIS_SINGLE, vars, varsz)) == BCME_OK)
6306 		nvram_append((void *)sih, *vars, *varsz, VARBUF_PRIO_OTP);
6307 
6308 	return rc;
6309 #else /* BCM_DONGLEVARS */
6310 	*vars = NULL;
6311 	*varsz = 0;
6312 	return BCME_OK;
6313 #endif /* BCM_DONGLEVARS */
6314 }
6315 #else /* !BCMUSBDEV && !BCMSDIODEV  && !BCMPCIEDEV */
6316 
6317 #ifndef BCMDONGLEHOST
6318 
6319 /**
6320  * initvars_srom_si() is defined multiple times in this file. This is the variant for:
6321  * !BCMDONGLEHOST && !BCMUSBDEV && !BCMSDIODEV && !BCMPCIEDEV
6322  * So this function is defined for PCI (not PCIe) builds that are also non DHD builds.
6323  * On success, a buffer containing var/val values has been allocated in parameter 'vars'.
6324  */
6325 static int
6326 BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap,
6327 	char **vars, uint *varsz)
6328 {
6329 	/* Search flash nvram section for srom variables */
6330 	BCM_REFERENCE(osh);
6331 	BCM_REFERENCE(curmap);
6332 	return initvars_flash_si(sih, vars, varsz);
6333 } /* initvars_srom_si */
6334 #endif /* !BCMDONGLEHOST */
6335 #endif	/* !BCMUSBDEV && !BCMSDIODEV  && !BCMPCIEDEV */
6336 
6337 void
6338 BCMATTACHFN(srom_var_deinit)(si_t *sih)
6339 {
6340 	BCM_REFERENCE(sih);
6341 
6342 	srvars_inited = FALSE;
6343 }
6344 
6345 #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL)
6346 bool
6347 BCMATTACHFN(srom_caldata_prsnt)(si_t *sih)
6348 {
6349 	return is_caldata_prsnt;
6350 }
6351 
6352 int
6353 BCMATTACHFN(srom_get_caldata)(si_t *sih, uint16 *srom)
6354 {
6355 	if (!is_caldata_prsnt) {
6356 		return BCME_ERROR;
6357 	}
6358 	if (srom_sromrev == 18) {
6359 		memcpy(srom, caldata_array, SROM18_CALDATA_WORDS * 2);
6360 	} else {
6361 		memcpy(srom, caldata_array, SROM_CALDATA_WORDS * 2);
6362 	}
6363 	return BCME_OK;
6364 }
6365 #endif /* defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) */
6366