2 * Routines to access SPROM and to parse SROM/CIS variables.
4 * Copyright 2007, Broadcom Corporation
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
19 #include <bcmendian.h>
30 #define BS_ERROR(args) printf args
32 #define BS_ERROR(args)
35 #define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
36 #define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
40 char *buf
; /* pointer to current position */
41 unsigned int size
; /* current (residual) size in bytes */
44 static int initvars_srom_sb (sb_t
* sbh
, osl_t
* osh
, void *curmap
,
45 char **vars
, uint
* count
);
46 static void _initvars_srom_pci (uint8 sromrev
, uint16
* srom
, uint off
,
48 static int initvars_srom_pci (sb_t
* sbh
, void *curmap
, char **vars
,
50 static int initvars_cis_pcmcia (sb_t
* sbh
, osl_t
* osh
, char **vars
,
52 #if !defined(BCMUSBDEV) && !defined(BCMSDIODEV)
53 static int initvars_flash_sb (sb_t
* sbh
, char **vars
, uint
* count
);
54 #endif /* !BCMUSBDEV && !BCMSDIODEV */
55 static int sprom_cmd_pcmcia (osl_t
* osh
, uint8 cmd
);
56 static int sprom_read_pcmcia (osl_t
* osh
, uint16 addr
, uint16
* data
);
57 static int sprom_write_pcmcia (osl_t
* osh
, uint16 addr
, uint16 data
);
58 static int sprom_read_pci (osl_t
* osh
, uint16
* sprom
, uint wordoff
,
59 uint16
* buf
, uint nwords
, bool check_crc
);
61 static int initvars_table (osl_t
* osh
, char *start
, char *end
, char **vars
,
63 static int initvars_flash (sb_t
* sbh
, osl_t
* osh
, char **vp
, uint len
);
66 static int get_sb_pcmcia_srom (sb_t
* sbh
, osl_t
* osh
, uint8
* pcmregs
,
67 uint boff
, uint16
* srom
, uint bsz
);
68 static int set_sb_pcmcia_srom (sb_t
* sbh
, osl_t
* osh
, uint8
* pcmregs
,
69 uint boff
, uint16
* srom
, uint bsz
);
70 static uint
srom_size (sb_t
* sbh
, osl_t
* osh
);
71 #endif /* def BCMUSBDEV */
73 /* Initialization of varbuf structure */
75 varbuf_init (varbuf_t
* b
, char *buf
, uint size
)
81 /* append a null terminated var=value string */
83 varbuf_append (varbuf_t
* b
, const char *fmt
, ...)
92 r
= vsnprintf (b
->buf
, b
->size
, fmt
, ap
);
95 /* C99 snprintf behavior returns r >= size on overflow,
96 * others return -1 on overflow.
97 * All return -1 on format error.
98 * We need to leave room for 2 null terminations, one for the current var
99 * string, and one for final null of the var table. So check that the
100 * strlen written, r, leaves room for 2 chars.
102 if ((r
== -1) || (r
> (int) (b
->size
- 2)))
108 /* skip over this string's null termination */
117 * Initialize local vars from the right source for this platform.
118 * Return 0 on success, nonzero on error.
121 BCMINITFN (srom_var_init
) (sb_t
* sbh
, uint bustype
, void *curmap
,
122 osl_t
* osh
, char **vars
, uint
* count
)
124 ASSERT (bustype
== BUSTYPE (bustype
));
125 if (vars
== NULL
|| count
== NULL
)
131 switch (BUSTYPE (bustype
))
135 return initvars_srom_sb (sbh
, osh
, curmap
, vars
, count
);
138 ASSERT (curmap
); /* can not be NULL */
139 return initvars_srom_pci (sbh
, curmap
, vars
, count
);
142 return initvars_cis_pcmcia (sbh
, osh
, vars
, count
);
151 /* support only 16-bit word read from srom */
153 srom_read (sb_t
* sbh
, uint bustype
, void *curmap
, osl_t
* osh
,
154 uint byteoff
, uint nbytes
, uint16
* buf
)
159 ASSERT (bustype
== BUSTYPE (bustype
));
161 /* check input - 16-bit access only */
162 if (byteoff
& 1 || nbytes
& 1 || (byteoff
+ nbytes
) > (SPROM_SIZE
* 2))
168 if (BUSTYPE (bustype
) == PCI_BUS
)
172 srom
= (uchar
*) curmap
+ PCI_BAR0_SPROM_OFFSET
;
173 if (sprom_read_pci (osh
, srom
, off
, buf
, nw
, FALSE
))
176 else if (BUSTYPE (bustype
) == PCMCIA_BUS
)
178 for (i
= 0; i
< nw
; i
++)
180 if (sprom_read_pcmcia
181 (osh
, (uint16
) (off
+ i
), (uint16
*) (buf
+ i
)))
185 else if (BUSTYPE (bustype
) == SB_BUS
)
188 if (SPROMBUS
== PCMCIA_BUS
)
195 origidx
= sb_coreidx (sbh
);
196 regs
= sb_setcore (sbh
, SB_PCMCIA
, 0);
197 ASSERT (regs
!= NULL
);
199 if (!(wasup
= sb_iscoreup (sbh
)))
200 sb_core_reset (sbh
, 0, 0);
202 rc
= get_sb_pcmcia_srom (sbh
, osh
, regs
, byteoff
, buf
, nbytes
);
205 sb_core_disable (sbh
, 0);
207 sb_setcoreidx (sbh
, origidx
);
210 #endif /* def BCMUSBDEV */
222 /* support only 16-bit word write into srom */
224 srom_write (sb_t
* sbh
, uint bustype
, void *curmap
, osl_t
* osh
,
225 uint byteoff
, uint nbytes
, uint16
* buf
)
228 uint i
, nw
, crc_range
;
229 uint16 image
[SPROM_SIZE
];
231 volatile uint32 val32
;
233 ASSERT (bustype
== BUSTYPE (bustype
));
235 /* check input - 16-bit access only */
236 if ((byteoff
& 1) || (nbytes
& 1))
239 if (byteoff
== 0x55aa)
243 memset ((void *) image
, 0xff, nbytes
);
246 else if ((byteoff
== 0) &&
247 ((nbytes
== SPROM_SIZE
* 2) ||
248 (nbytes
== (SPROM_CRC_RANGE
* 2)) ||
249 (nbytes
== (SROM4_WORDS
* 2))))
251 /* Are we writing the whole thing at once? */
253 bcopy ((void *) buf
, (void *) image
, nbytes
);
258 if ((byteoff
+ nbytes
) > (SPROM_SIZE
* 2))
261 if (BUSTYPE (bustype
) == PCMCIA_BUS
)
263 crc_range
= SPROM_SIZE
* 2;
267 crc_range
= SPROM_CRC_RANGE
* 2; /* Tentative */
271 /* read first 64 words from srom */
272 if (srom_read (sbh
, bustype
, curmap
, osh
, 0, crc_range
, image
))
274 if (image
[SROM4_SIGN
] == SROM4_SIGNATURE
)
278 if (srom_read (sbh
, bustype
, curmap
, osh
, 0, crc_range
, image
))
282 bcopy ((void *) buf
, (void *) &image
[byteoff
/ 2], nbytes
);
288 htol16_buf (image
, crc_range
);
289 crc
= ~hndcrc8 ((uint8
*) image
, crc_range
- 1, 0xff);
290 ltoh16_buf (image
, crc_range
);
291 image
[nw
- 1] = (crc
<< 8) | (image
[nw
- 1] & 0xff);
294 if (BUSTYPE (bustype
) == PCI_BUS
)
296 srom
= (uint16
*) ((uchar
*) curmap
+ PCI_BAR0_SPROM_OFFSET
);
297 /* enable writes to the SPROM */
298 val32
= OSL_PCI_READ_CONFIG (osh
, PCI_SPROM_CONTROL
, sizeof (uint32
));
299 val32
|= SPROM_WRITEEN
;
300 OSL_PCI_WRITE_CONFIG (osh
, PCI_SPROM_CONTROL
, sizeof (uint32
), val32
);
301 bcm_mdelay (WRITE_ENABLE_DELAY
);
303 for (i
= 0; i
< nw
; i
++)
305 W_REG (osh
, &srom
[i
], image
[i
]);
306 bcm_mdelay (WRITE_WORD_DELAY
);
308 /* disable writes to the SPROM */
309 OSL_PCI_WRITE_CONFIG (osh
, PCI_SPROM_CONTROL
, sizeof (uint32
), val32
&
312 else if (BUSTYPE (bustype
) == PCMCIA_BUS
)
314 /* enable writes to the SPROM */
315 if (sprom_cmd_pcmcia (osh
, SROM_WEN
))
317 bcm_mdelay (WRITE_ENABLE_DELAY
);
319 for (i
= 0; i
< nw
; i
++)
321 sprom_write_pcmcia (osh
, (uint16
) (i
), image
[i
]);
322 bcm_mdelay (WRITE_WORD_DELAY
);
324 /* disable writes to the SPROM */
325 if (sprom_cmd_pcmcia (osh
, SROM_WDS
))
328 else if (BUSTYPE (bustype
) == SB_BUS
)
331 if (SPROMBUS
== PCMCIA_BUS
)
338 origidx
= sb_coreidx (sbh
);
339 regs
= sb_setcore (sbh
, SB_PCMCIA
, 0);
340 ASSERT (regs
!= NULL
);
342 if (!(wasup
= sb_iscoreup (sbh
)))
343 sb_core_reset (sbh
, 0, 0);
345 rc
= set_sb_pcmcia_srom (sbh
, osh
, regs
, byteoff
, buf
, nbytes
);
348 sb_core_disable (sbh
, 0);
350 sb_setcoreidx (sbh
, origidx
);
353 #endif /* def BCMUSBDEV */
361 bcm_mdelay (WRITE_ENABLE_DELAY
);
366 #define SB_PCMCIA_READ(osh, regs, fcr) \
367 R_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2)
368 #define SB_PCMCIA_WRITE(osh, regs, fcr, v) \
369 W_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2, v)
371 /* set PCMCIA srom command register */
373 srom_cmd_sb_pcmcia (osl_t
* osh
, uint8
* pcmregs
, uint8 cmd
)
378 /* write srom command register */
379 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_CS
, cmd
);
382 while (++wait_cnt
< 1000000)
384 status
= SB_PCMCIA_READ (osh
, pcmregs
, SROM_CS
);
385 if (status
& SROM_DONE
)
390 BS_ERROR (("sr_cmd: Give up after %d tries, stat = 0x%x\n", wait_cnt
,
395 /* read a word from the PCMCIA srom over SB */
397 srom_read_sb_pcmcia (osl_t
* osh
, uint8
* pcmregs
, uint16 addr
, uint16
* data
)
399 uint8 addr_l
, addr_h
, data_l
, data_h
;
401 addr_l
= (uint8
) ((addr
* 2) & 0xff);
402 addr_h
= (uint8
) (((addr
* 2) >> 8) & 0xff);
405 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_ADDRH
, addr_h
);
406 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_ADDRL
, addr_l
);
409 if (srom_cmd_sb_pcmcia (osh
, pcmregs
, SROM_READ
))
413 data_h
= SB_PCMCIA_READ (osh
, pcmregs
, SROM_DATAH
);
414 data_l
= SB_PCMCIA_READ (osh
, pcmregs
, SROM_DATAL
);
415 *data
= ((uint16
) data_h
<< 8) | data_l
;
420 /* write a word to the PCMCIA srom over SB */
422 srom_write_sb_pcmcia (osl_t
* osh
, uint8
* pcmregs
, uint16 addr
, uint16 data
)
424 uint8 addr_l
, addr_h
, data_l
, data_h
;
427 addr_l
= (uint8
) ((addr
* 2) & 0xff);
428 addr_h
= (uint8
) (((addr
* 2) >> 8) & 0xff);
431 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_ADDRH
, addr_h
);
432 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_ADDRL
, addr_l
);
434 data_l
= (uint8
) (data
& 0xff);
435 data_h
= (uint8
) ((data
>> 8) & 0xff);
438 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_DATAH
, data_h
);
439 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_DATAL
, data_l
);
442 rc
= srom_cmd_sb_pcmcia (osh
, pcmregs
, SROM_WRITE
);
448 * Read the srom for the pcmcia-srom over sb case.
449 * Return 0 on success, nonzero on error.
452 get_sb_pcmcia_srom (sb_t
* sbh
, osl_t
* osh
, uint8
* pcmregs
,
453 uint boff
, uint16
* srom
, uint bsz
)
455 uint i
, nw
, woff
, wsz
;
458 /* read must be at word boundary */
459 ASSERT ((boff
& 1) == 0 && (bsz
& 1) == 0);
461 /* read sprom size and validate the parms */
462 if ((nw
= srom_size (sbh
, osh
)) == 0)
464 BS_ERROR (("get_sb_pcmcia_srom: sprom size unknown\n"));
468 if (boff
+ bsz
> 2 * nw
)
470 BS_ERROR (("get_sb_pcmcia_srom: sprom size exceeded\n"));
475 /* read in sprom contents */
476 for (woff
= boff
/ 2, wsz
= bsz
/ 2, i
= 0;
477 woff
< nw
&& i
< wsz
; woff
++, i
++)
479 if (srom_read_sb_pcmcia (osh
, pcmregs
, (uint16
) woff
, &srom
[i
]))
481 BS_ERROR (("get_sb_pcmcia_srom: sprom read failed\n"));
492 * Write the srom for the pcmcia-srom over sb case.
493 * Return 0 on success, nonzero on error.
496 set_sb_pcmcia_srom (sb_t
* sbh
, osl_t
* osh
, uint8
* pcmregs
,
497 uint boff
, uint16
* srom
, uint bsz
)
499 uint i
, nw
, woff
, wsz
;
504 /* write must be at word boundary */
505 ASSERT ((boff
& 1) == 0 && (bsz
& 1) == 0);
507 /* read sprom size and validate the parms */
508 if ((nw
= srom_size (sbh
, osh
)) == 0)
510 BS_ERROR (("set_sb_pcmcia_srom: sprom size unknown\n"));
514 if (boff
+ bsz
> 2 * nw
)
516 BS_ERROR (("set_sb_pcmcia_srom: sprom size exceeded\n"));
522 if (srom_cmd_sb_pcmcia (osh
, pcmregs
, SROM_WEN
))
524 BS_ERROR (("set_sb_pcmcia_srom: sprom wen failed\n"));
529 /* write buffer to sprom */
530 for (woff
= boff
/ 2, wsz
= bsz
/ 2, i
= 0;
531 woff
< nw
&& i
< wsz
; woff
++, i
++)
533 if (srom_write_sb_pcmcia (osh
, pcmregs
, (uint16
) woff
, srom
[i
]))
535 BS_ERROR (("set_sb_pcmcia_srom: sprom write failed\n"));
543 for (woff
= 0; woff
< nw
; woff
++)
545 if (srom_read_sb_pcmcia (osh
, pcmregs
, (uint16
) woff
, &word
))
547 BS_ERROR (("set_sb_pcmcia_srom: sprom fix crc read failed\n"));
551 word
= htol16 (word
);
552 crc
= hndcrc8 ((uint8
*) & word
, woff
!= nw
- 1 ? 2 : 1, crc
);
554 word
= (~crc
<< 8) + (ltoh16 (word
) & 0xff);
555 if (srom_write_sb_pcmcia (osh
, pcmregs
, (uint16
) (woff
- 1), word
))
557 BS_ERROR (("set_sb_pcmcia_srom: sprom fix crc write failed\n"));
563 if (srom_cmd_sb_pcmcia (osh
, pcmregs
, SROM_WDS
))
565 BS_ERROR (("set_sb_pcmcia_srom: sprom wds failed\n"));
573 #endif /* def BCMUSBDEV */
576 srom_parsecis (osl_t
* osh
, uint8
* pcis
[], uint ciscnt
, char **vars
,
582 uint8
*cis
, tup
, tlen
, sromrev
= 1;
585 bool ag_init
= FALSE
;
594 base
= MALLOC (osh
, MAXSZ_NVRAM_VARS
);
599 varbuf_init (&b
, base
, MAXSZ_NVRAM_VARS
);
602 for (cisnum
= 0; cisnum
< ciscnt
; cisnum
++)
611 if ((i
+ tlen
) >= CIS_SIZE
)
617 /* assume the strings are good if the version field checks out */
618 if (((cis
[i
+ 1] << 8) + cis
[i
]) >= 0x0008)
620 varbuf_append (&b
, "manf=%s", &cis
[i
+ 2]);
621 varbuf_append (&b
, "productname=%s",
622 &cis
[i
+ 3 + strlen ((char *) &cis
[i
+ 2])]);
627 varbuf_append (&b
, "manfid=0x%x", (cis
[i
+ 1] << 8) + cis
[i
]);
628 varbuf_append (&b
, "prodid=0x%x",
629 (cis
[i
+ 3] << 8) + cis
[i
+ 2]);
640 /* set macaddr if HNBU_MACADDR not seen yet */
641 if (eabuf
[0] == '\0' && cis
[i
] == LAN_NID
)
643 ASSERT (cis
[i
+ 1] == ETHER_ADDR_LEN
);
644 bcm_ether_ntoa ((struct ether_addr
*) &cis
[i
+ 2],
647 /* set boardnum if HNBU_BOARDNUM not seen yet */
649 boardnum
= (cis
[i
+ 6] << 8) + cis
[i
+ 7];
655 varbuf_append (&b
, "regwindowsz=%d",
656 (cis
[i
+ 7] << 8) | cis
[i
+ 6]);
659 case CISTPL_BRCM_HNBU
:
663 sromrev
= cis
[i
+ 1];
664 varbuf_append (&b
, "sromrev=%d", sromrev
);
668 varbuf_append (&b
, "vendid=0x%x", (cis
[i
+ 2] << 8) +
670 varbuf_append (&b
, "devid=0x%x", (cis
[i
+ 4] << 8) +
674 varbuf_append (&b
, "chiprev=%d",
675 (cis
[i
+ 6] << 8) + cis
[i
+ 5]);
679 varbuf_append (&b
, "subvendid=0x%x",
680 (cis
[i
+ 8] << 8) + cis
[i
+ 7]);
684 varbuf_append (&b
, "subdevid=0x%x",
685 (cis
[i
+ 10] << 8) + cis
[i
+ 9]);
686 /* subdevid doubles for boardtype */
687 varbuf_append (&b
, "boardtype=0x%x",
688 (cis
[i
+ 10] << 8) + cis
[i
+ 9]);
693 varbuf_append (&b
, "boardrev=0x%x", cis
[i
+ 1]);
697 varbuf_append (&b
, "aa2g=%d", cis
[i
+ 1]);
701 varbuf_append (&b
, "ag0=%d", cis
[i
+ 1]);
706 varbuf_append (&b
, "aa5g=%d", cis
[i
+ 1]);
707 varbuf_append (&b
, "ag1=%d", cis
[i
+ 2]);
711 ASSERT (sromrev
== 1);
712 varbuf_append (&b
, "cc=%d", cis
[i
+ 1]);
718 ASSERT (sromrev
== 1);
719 varbuf_append (&b
, "pa0maxpwr=%d", cis
[i
+ 1]);
725 ASSERT (sromrev
>= 2);
726 varbuf_append (&b
, "opo=%d", cis
[i
+ 9]);
731 for (j
= 0; j
< 3; j
++)
733 varbuf_append (&b
, "pa0b%d=%d", j
,
734 (cis
[i
+ (j
* 2) + 2] << 8) +
735 cis
[i
+ (j
* 2) + 1]);
737 varbuf_append (&b
, "pa0itssit=%d", cis
[i
+ 7]);
738 varbuf_append (&b
, "pa0maxpwr=%d", cis
[i
+ 8]);
745 ASSERT ((sromrev
== 2) || (sromrev
== 3));
746 for (j
= 0; j
< 3; j
++)
748 varbuf_append (&b
, "pa1b%d=%d", j
,
749 (cis
[i
+ (j
* 2) + 2] << 8) +
750 cis
[i
+ (j
* 2) + 1]);
752 for (j
= 3; j
< 6; j
++)
754 varbuf_append (&b
, "pa1lob%d=%d", j
- 3,
755 (cis
[i
+ (j
* 2) + 2] << 8) +
756 cis
[i
+ (j
* 2) + 1]);
758 for (j
= 6; j
< 9; j
++)
760 varbuf_append (&b
, "pa1hib%d=%d", j
- 6,
761 (cis
[i
+ (j
* 2) + 2] << 8) +
762 cis
[i
+ (j
* 2) + 1]);
764 varbuf_append (&b
, "pa1itssit=%d", cis
[i
+ 19]);
765 varbuf_append (&b
, "pa1maxpwr=%d", cis
[i
+ 20]);
766 varbuf_append (&b
, "pa1lomaxpwr=%d", cis
[i
+ 21]);
767 varbuf_append (&b
, "pa1himaxpwr=%d", cis
[i
+ 22]);
771 ASSERT (sromrev
== 1);
772 varbuf_append (&b
, "oem=%02x%02x%02x%02x%02x%02x%02x%02x",
773 cis
[i
+ 1], cis
[i
+ 2],
774 cis
[i
+ 3], cis
[i
+ 4],
775 cis
[i
+ 5], cis
[i
+ 6],
776 cis
[i
+ 7], cis
[i
+ 8]);
779 case HNBU_BOARDFLAGS
:
780 w32
= (cis
[i
+ 2] << 8) + cis
[i
+ 1];
782 w32
|= (cis
[i
+ 4] << 24) + (cis
[i
+ 3] << 16);
783 varbuf_append (&b
, "boardflags=0x%x", w32
);
787 if (cis
[i
+ 1] != 0xff)
789 varbuf_append (&b
, "ledbh0=%d", cis
[i
+ 1]);
791 if (cis
[i
+ 2] != 0xff)
793 varbuf_append (&b
, "ledbh1=%d", cis
[i
+ 2]);
795 if (cis
[i
+ 3] != 0xff)
797 varbuf_append (&b
, "ledbh2=%d", cis
[i
+ 3]);
799 if (cis
[i
+ 4] != 0xff)
801 varbuf_append (&b
, "ledbh3=%d", cis
[i
+ 4]);
806 ASSERT (sromrev
> 1);
807 if ((cis
[i
+ 1] == 0) || (cis
[i
+ 2] == 0))
808 varbuf_append (&b
, "ccode=");
810 varbuf_append (&b
, "ccode=%c%c", cis
[i
+ 1], cis
[i
+ 2]);
811 varbuf_append (&b
, "cctl=0x%x", cis
[i
+ 3]);
815 ASSERT (sromrev
> 2);
816 varbuf_append (&b
, "cckpo=0x%x",
817 (cis
[i
+ 2] << 8) | cis
[i
+ 1]);
821 ASSERT (sromrev
> 2);
822 varbuf_append (&b
, "ofdmpo=0x%x",
825 (cis
[i
+ 2] << 8) | cis
[i
+ 1]);
829 varbuf_append (&b
, "rdlid=0x%x",
830 (cis
[i
+ 2] << 8) | cis
[i
+ 1]);
834 varbuf_append (&b
, "rdlrndis=%d", cis
[i
+ 1]);
838 varbuf_append (&b
, "rdlrwu=%d", cis
[i
+ 1]);
842 varbuf_append (&b
, "rdlsn=%d",
843 (cis
[i
+ 2] << 8) | cis
[i
+ 1]);
847 varbuf_append (&b
, "xtalfreq=%d",
850 (cis
[i
+ 2] << 8) | cis
[i
+ 1]);
853 case HNBU_RSSISMBXA2G
:
854 ASSERT (sromrev
== 3);
855 varbuf_append (&b
, "rssismf2g=%d", cis
[i
+ 1] & 0xf);
856 varbuf_append (&b
, "rssismc2g=%d", (cis
[i
+ 1] >> 4) & 0xf);
857 varbuf_append (&b
, "rssisav2g=%d", cis
[i
+ 2] & 0x7);
858 varbuf_append (&b
, "bxa2g=%d", (cis
[i
+ 2] >> 3) & 0x3);
861 case HNBU_RSSISMBXA5G
:
862 ASSERT (sromrev
== 3);
863 varbuf_append (&b
, "rssismf5g=%d", cis
[i
+ 1] & 0xf);
864 varbuf_append (&b
, "rssismc5g=%d", (cis
[i
+ 1] >> 4) & 0xf);
865 varbuf_append (&b
, "rssisav5g=%d", cis
[i
+ 2] & 0x7);
866 varbuf_append (&b
, "bxa5g=%d", (cis
[i
+ 2] >> 3) & 0x3);
870 ASSERT (sromrev
== 3);
871 varbuf_append (&b
, "tri2g=%d", cis
[i
+ 1]);
875 ASSERT (sromrev
== 3);
876 varbuf_append (&b
, "tri5gl=%d", cis
[i
+ 1]);
877 varbuf_append (&b
, "tri5g=%d", cis
[i
+ 2]);
878 varbuf_append (&b
, "tri5gh=%d", cis
[i
+ 3]);
882 ASSERT (sromrev
== 3);
883 varbuf_append (&b
, "rxpo2g=%d", cis
[i
+ 1]);
887 ASSERT (sromrev
== 3);
888 varbuf_append (&b
, "rxpo5g=%d", cis
[i
+ 1]);
892 boardnum
= (cis
[i
+ 2] << 8) + cis
[i
+ 1];
896 bcm_ether_ntoa ((struct ether_addr
*) &cis
[i
+ 1], eabuf
);
900 varbuf_append (&b
, "boardtype=0x%x",
901 (cis
[i
+ 2] << 8) + cis
[i
+ 1]);
904 #if defined(BCMCCISSR3)
905 case HNBU_SROM3SWRGN
:
908 uint8 srev
= cis
[i
+ 1 + 70];
910 /* make tuple value 16-bit aligned and parse it */
911 bcopy (&cis
[i
+ 1], srom
, sizeof (srom
));
912 _initvars_srom_pci (srev
, srom
, SROM3_SWRGN_OFF
, &b
);
913 /* create extra variables */
914 varbuf_append (&b
, "vendid=0x%x",
915 (cis
[i
+ 1 + 73] << 8) + cis
[i
+ 1 + 72]);
916 varbuf_append (&b
, "devid=0x%x",
917 (cis
[i
+ 1 + 75] << 8) + cis
[i
+ 1 + 74]);
918 varbuf_append (&b
, "xtalfreq=%d",
919 (cis
[i
+ 1 + 77] << 8) + cis
[i
+ 1 + 76]);
920 /* 2.4G antenna gain is included in SROM */
922 /* Ethernet MAC address is included in SROM */
933 while (tup
!= CISTPL_END
);
938 varbuf_append (&b
, "boardnum=%d", boardnum
);
943 varbuf_append (&b
, "macaddr=%s", eabuf
);
946 /* if there is no antenna gain field, set default */
947 if (ag_init
== FALSE
)
949 varbuf_append (&b
, "ag0=%d", 0xff);
952 /* final nullbyte terminator */
953 ASSERT (b
.size
>= 1);
955 varsize
= (uint
) (b
.buf
- base
);
956 ASSERT (varsize
< MAXSZ_NVRAM_VARS
);
957 if (varsize
< MAXSZ_NVRAM_VARS
)
960 new_buf
= (char *) MALLOC (osh
, varsize
);
964 bcopy (base
, new_buf
, varsize
);
965 MFREE (osh
, base
, MAXSZ_NVRAM_VARS
);
977 /* set PCMCIA sprom command register */
979 sprom_cmd_pcmcia (osl_t
* osh
, uint8 cmd
)
982 uint wait_cnt
= 1000;
984 /* write sprom command register */
985 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_CS
, &cmd
, 1);
990 OSL_PCMCIA_READ_ATTR (osh
, SROM_CS
, &status
, 1);
991 if (status
& SROM_DONE
)
998 /* read a word from the PCMCIA srom */
1000 sprom_read_pcmcia (osl_t
* osh
, uint16 addr
, uint16
* data
)
1002 uint8 addr_l
, addr_h
, data_l
, data_h
;
1004 addr_l
= (uint8
) ((addr
* 2) & 0xff);
1005 addr_h
= (uint8
) (((addr
* 2) >> 8) & 0xff);
1008 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_ADDRH
, &addr_h
, 1);
1009 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_ADDRL
, &addr_l
, 1);
1012 if (sprom_cmd_pcmcia (osh
, SROM_READ
))
1016 data_h
= data_l
= 0;
1017 OSL_PCMCIA_READ_ATTR (osh
, SROM_DATAH
, &data_h
, 1);
1018 OSL_PCMCIA_READ_ATTR (osh
, SROM_DATAL
, &data_l
, 1);
1020 *data
= (data_h
<< 8) | data_l
;
1024 /* write a word to the PCMCIA srom */
1026 sprom_write_pcmcia (osl_t
* osh
, uint16 addr
, uint16 data
)
1028 uint8 addr_l
, addr_h
, data_l
, data_h
;
1030 addr_l
= (uint8
) ((addr
* 2) & 0xff);
1031 addr_h
= (uint8
) (((addr
* 2) >> 8) & 0xff);
1032 data_l
= (uint8
) (data
& 0xff);
1033 data_h
= (uint8
) ((data
>> 8) & 0xff);
1036 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_ADDRH
, &addr_h
, 1);
1037 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_ADDRL
, &addr_l
, 1);
1040 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_DATAH
, &data_h
, 1);
1041 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_DATAL
, &data_l
, 1);
1044 return sprom_cmd_pcmcia (osh
, SROM_WRITE
);
1048 * Read in and validate sprom.
1049 * Return 0 on success, nonzero on error.
1052 sprom_read_pci (osl_t
* osh
, uint16
* sprom
, uint wordoff
, uint16
* buf
,
1053 uint nwords
, bool check_crc
)
1058 /* read the sprom */
1059 for (i
= 0; i
< nwords
; i
++)
1062 buf
[i
] = R_REG (osh
, &sprom
[wordoff
+ i
]);
1064 buf
[i
] = R_REG (osh
, &sprom
[wordoff
+ i
]);
1069 if (buf
[0] == 0xffff)
1071 /* The hardware thinks that an srom that starts with 0xffff
1072 * is blank, regardless of the rest of the content, so declare
1075 BS_ERROR (("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__
,
1080 /* fixup the endianness so crc8 will pass */
1081 htol16_buf (buf
, nwords
* 2);
1082 if (hndcrc8 ((uint8
*) buf
, nwords
* 2, 0xff) != 0x9f)
1084 /* now correct the endianness of the byte array */
1085 ltoh16_buf (buf
, nwords
* 2);
1092 * Create variable table from memory.
1093 * Return 0 on success, nonzero on error.
1096 BCMINITFN (initvars_table
) (osl_t
* osh
, char *start
, char *end
, char **vars
,
1099 int c
= (int) (end
- start
);
1101 /* do it only when there is more than just the null string */
1104 char *vp
= MALLOC (osh
, c
);
1108 bcopy (start
, vp
, c
);
1122 * Find variables with <devpath> from flash. 'base' points to the beginning
1123 * of the table upon enter and to the end of the table upon exit when success.
1124 * Return 0 on success, nonzero on error.
1127 initvars_flash (sb_t
* sbh
, osl_t
* osh
, char **base
, uint len
)
1133 uint l
, dl
, copy_len
;
1134 char devpath
[SB_DEVPATH_BUFSZ
];
1136 /* allocate memory and read in flash */
1137 if (!(flash
= MALLOC (osh
, NVRAM_SPACE
)))
1139 if ((err
= nvram_getall (flash
, NVRAM_SPACE
)))
1142 sb_devpath (sbh
, devpath
, sizeof (devpath
));
1144 /* grab vars with the <devpath> prefix in name */
1145 dl
= strlen (devpath
);
1146 for (s
= flash
; s
&& *s
; s
+= l
+ 1)
1150 /* skip non-matching variable */
1151 if (strncmp (s
, devpath
, dl
))
1154 /* is there enough room to copy? */
1155 copy_len
= l
- dl
+ 1;
1158 err
= BCME_BUFTOOSHORT
;
1162 /* no prefix, just the name=value */
1163 strncpy (vp
, &s
[dl
], copy_len
);
1168 /* add null string as terminator */
1171 err
= BCME_BUFTOOSHORT
;
1178 exit
:MFREE (osh
, flash
, NVRAM_SPACE
);
1182 #if !defined(BCMUSBDEV) && !defined(BCMSDIODEV)
1184 * Initialize nonvolatile variable table from flash.
1185 * Return 0 on success, nonzero on error.
1188 initvars_flash_sb (sb_t
* sbh
, char **vars
, uint
* count
)
1190 osl_t
*osh
= sb_osh (sbh
);
1197 base
= vp
= MALLOC (osh
, MAXSZ_NVRAM_VARS
);
1202 if ((err
= initvars_flash (sbh
, osh
, &vp
, MAXSZ_NVRAM_VARS
)) == 0)
1203 err
= initvars_table (osh
, base
, vp
, vars
, count
);
1205 MFREE (osh
, base
, MAXSZ_NVRAM_VARS
);
1209 #endif /* !BCMUSBDEV && !BCMSDIODEV */
1212 char mfgsromvars
[256];
1213 char *defaultsromvars
= "il0macaddr=00:11:22:33:44:51\0"
1214 "et0macaddr=00:11:22:33:44:52\0"
1215 "et1macaddr=00:11:22:33:44:53\0"
1216 "boardtype=0xffff\0"
1217 "boardrev=0x10\0" "boardflags=8\0" "sromrev=2\0" "aa2g=3\0" "\0";
1218 #define MFGSROM_DEFVARSLEN 149 /* default srom len */
1219 #endif /* WL_TEST */
1222 * Initialize nonvolatile variable table from sprom.
1223 * Return 0 on success, nonzero on error.
1235 #define SRFL_MORE 1 /* value continues as described by the next entry */
1236 #define SRFL_NOFFS 2 /* value bits can't be all one's */
1237 #define SRFL_PRHEX 4 /* value is in hexdecimal format */
1238 #define SRFL_PRSIGN 8 /* value is in signed decimal format */
1239 #define SRFL_CCODE 0x10 /* value is in country code format */
1240 #define SRFL_ETHADDR 0x20 /* value is an Ethernet address */
1241 #define SRFL_LEDDC 0x40 /* value is an LED duty cycle */
1244 * - Ethernet address spins across 3 consective words
1247 * - Add multiple entries next to each other if a value spins across multiple words
1248 * (even multiple fields in the same word) with each entry except the last having
1249 * it's SRFL_MORE bit set.
1250 * - Ethernet address entry does not follow above rule and must not have SRFL_MORE
1251 * bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
1252 * - The last entry's name field must be NULL to indicate the end of the table. Other
1253 * entries must have non-NULL name.
1256 static const sromvar_t pci_sromvars
[] = {
1257 {"boardrev", 0x0000000e, SRFL_PRHEX
, SROM_AABREV
, SROM_BR_MASK
},
1258 {"boardrev", 0x000000f0, SRFL_PRHEX
, SROM4_BREV
, 0xffff},
1259 {"boardrev", 0xffffff00, SRFL_PRHEX
, SROM8_BREV
, 0xffff},
1260 {"boardflags", 0x00000002, SRFL_PRHEX
, SROM_BFL
, 0xffff},
1261 {"boardflags", 0x00000004, SRFL_PRHEX
| SRFL_MORE
, SROM_BFL
, 0xffff},
1262 {"", 0, 0, SROM_BFL2
, 0xffff},
1263 {"boardflags", 0x00000008, SRFL_PRHEX
| SRFL_MORE
, SROM_BFL
, 0xffff},
1264 {"", 0, 0, SROM3_BFL2
, 0xffff},
1265 {"boardflags", 0x00000010, SRFL_PRHEX
| SRFL_MORE
, SROM4_BFL0
, 0xffff},
1266 {"", 0, 0, SROM4_BFL1
, 0xffff},
1267 {"boardflags", 0x000000e0, SRFL_PRHEX
| SRFL_MORE
, SROM5_BFL0
, 0xffff},
1268 {"", 0, 0, SROM5_BFL1
, 0xffff},
1269 {"boardflags", 0xffffff00, SRFL_PRHEX
| SRFL_MORE
, SROM8_BFL0
, 0xffff},
1270 {"", 0, 0, SROM8_BFL1
, 0xffff},
1271 {"boardflags2", 0x00000010, SRFL_PRHEX
| SRFL_MORE
, SROM4_BFL2
, 0xffff},
1272 {"", 0, 0, SROM4_BFL3
, 0xffff},
1273 {"boardflags2", 0x000000e0, SRFL_PRHEX
| SRFL_MORE
, SROM5_BFL2
, 0xffff},
1274 {"", 0, 0, SROM5_BFL3
, 0xffff},
1275 {"boardflags2", 0xffffff00, SRFL_PRHEX
| SRFL_MORE
, SROM8_BFL2
, 0xffff},
1276 {"", 0, 0, SROM8_BFL3
, 0xffff},
1277 {"boardtype", 0xfffffffc, SRFL_PRHEX
, SROM_SSID
, 0xffff},
1278 {"boardnum", 0x00000006, 0, SROM_MACLO_IL0
, 0xffff},
1279 {"boardnum", 0x00000008, 0, SROM3_MACLO
, 0xffff},
1280 {"boardnum", 0x00000010, 0, SROM4_MACLO
, 0xffff},
1281 {"boardnum", 0x000000e0, 0, SROM5_MACLO
, 0xffff},
1282 {"boardnum", 0xffffff00, 0, SROM8_MACLO
, 0xffff},
1283 {"cc", 0x00000002, 0, SROM_AABREV
, SROM_CC_MASK
},
1284 {"regrev", 0x00000008, 0, SROM_OPO
, 0xff00},
1285 {"regrev", 0x00000010, 0, SROM4_REGREV
, 0xff},
1286 {"regrev", 0x000000e0, 0, SROM5_REGREV
, 0xff},
1287 {"regrev", 0xffffff00, 0, SROM8_REGREV
, 0xff},
1288 {"ledbh0", 0x0000000e, SRFL_NOFFS
, SROM_LEDBH10
, 0xff},
1289 {"ledbh1", 0x0000000e, SRFL_NOFFS
, SROM_LEDBH10
, 0xff00},
1290 {"ledbh2", 0x0000000e, SRFL_NOFFS
, SROM_LEDBH32
, 0xff},
1291 {"ledbh3", 0x0000000e, SRFL_NOFFS
, SROM_LEDBH32
, 0xff00},
1292 {"ledbh0", 0x00000010, SRFL_NOFFS
, SROM4_LEDBH10
, 0xff},
1293 {"ledbh1", 0x00000010, SRFL_NOFFS
, SROM4_LEDBH10
, 0xff00},
1294 {"ledbh2", 0x00000010, SRFL_NOFFS
, SROM4_LEDBH32
, 0xff},
1295 {"ledbh3", 0x00000010, SRFL_NOFFS
, SROM4_LEDBH32
, 0xff00},
1296 {"ledbh0", 0x000000e0, SRFL_NOFFS
, SROM5_LEDBH10
, 0xff},
1297 {"ledbh1", 0x000000e0, SRFL_NOFFS
, SROM5_LEDBH10
, 0xff00},
1298 {"ledbh2", 0x000000e0, SRFL_NOFFS
, SROM5_LEDBH32
, 0xff},
1299 {"ledbh3", 0x000000e0, SRFL_NOFFS
, SROM5_LEDBH32
, 0xff00},
1300 {"ledbh0", 0xffffff00, SRFL_NOFFS
, SROM8_LEDBH10
, 0xff},
1301 {"ledbh1", 0xffffff00, SRFL_NOFFS
, SROM8_LEDBH10
, 0xff00},
1302 {"ledbh2", 0xffffff00, SRFL_NOFFS
, SROM8_LEDBH32
, 0xff},
1303 {"ledbh3", 0xffffff00, SRFL_NOFFS
, SROM8_LEDBH32
, 0xff00},
1304 {"pa0b0", 0x0000000e, SRFL_PRHEX
, SROM_WL0PAB0
, 0xffff},
1305 {"pa0b1", 0x0000000e, SRFL_PRHEX
, SROM_WL0PAB1
, 0xffff},
1306 {"pa0b2", 0x0000000e, SRFL_PRHEX
, SROM_WL0PAB2
, 0xffff},
1307 {"pa0itssit", 0x0000000e, 0, SROM_ITT
, 0xff},
1308 {"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP
, 0xff},
1309 {"pa0b0", 0xffffff00, SRFL_PRHEX
, SROM8_W0_PAB0
, 0xffff},
1310 {"pa0b1", 0xffffff00, SRFL_PRHEX
, SROM8_W0_PAB1
, 0xffff},
1311 {"pa0b2", 0xffffff00, SRFL_PRHEX
, SROM8_W0_PAB2
, 0xffff},
1312 {"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP
, 0xff00},
1313 {"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP
, 0xff},
1314 {"opo", 0x0000000c, 0, SROM_OPO
, 0xff},
1315 {"opo", 0xffffff00, 0, SROM8_2G_OFDMPO
, 0xff},
1316 {"aa2g", 0x0000000e, 0, SROM_AABREV
, SROM_AA0_MASK
},
1317 {"aa2g", 0x000000f0, 0, SROM4_AA
, 0xff},
1318 {"aa2g", 0xffffff00, 0, SROM8_AA
, 0xff},
1319 {"aa5g", 0x0000000e, 0, SROM_AABREV
, SROM_AA1_MASK
},
1320 {"aa5g", 0x000000f0, 0, SROM4_AA
, 0xff00},
1321 {"aa5g", 0xffffff00, 0, SROM8_AA
, 0xff00},
1322 {"ag0", 0x0000000e, 0, SROM_AG10
, 0xff},
1323 {"ag1", 0x0000000e, 0, SROM_AG10
, 0xff00},
1324 {"ag0", 0x000000f0, 0, SROM4_AG10
, 0xff},
1325 {"ag1", 0x000000f0, 0, SROM4_AG10
, 0xff00},
1326 {"ag2", 0x000000f0, 0, SROM4_AG32
, 0xff},
1327 {"ag3", 0x000000f0, 0, SROM4_AG32
, 0xff00},
1328 {"ag0", 0xffffff00, 0, SROM8_AG10
, 0xff},
1329 {"ag1", 0xffffff00, 0, SROM8_AG10
, 0xff00},
1330 {"ag2", 0xffffff00, 0, SROM8_AG32
, 0xff},
1331 {"ag3", 0xffffff00, 0, SROM8_AG32
, 0xff00},
1332 {"pa1b0", 0x0000000e, SRFL_PRHEX
, SROM_WL1PAB0
, 0xffff},
1333 {"pa1b1", 0x0000000e, SRFL_PRHEX
, SROM_WL1PAB1
, 0xffff},
1334 {"pa1b2", 0x0000000e, SRFL_PRHEX
, SROM_WL1PAB2
, 0xffff},
1335 {"pa1lob0", 0x0000000c, SRFL_PRHEX
, SROM_WL1LPAB0
, 0xffff},
1336 {"pa1lob1", 0x0000000c, SRFL_PRHEX
, SROM_WL1LPAB1
, 0xffff},
1337 {"pa1lob2", 0x0000000c, SRFL_PRHEX
, SROM_WL1LPAB2
, 0xffff},
1338 {"pa1hib0", 0x0000000c, SRFL_PRHEX
, SROM_WL1HPAB0
, 0xffff},
1339 {"pa1hib1", 0x0000000c, SRFL_PRHEX
, SROM_WL1HPAB1
, 0xffff},
1340 {"pa1hib2", 0x0000000c, SRFL_PRHEX
, SROM_WL1HPAB2
, 0xffff},
1341 {"pa1itssit", 0x0000000e, 0, SROM_ITT
, 0xff00},
1342 {"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP
, 0xff00},
1343 {"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP
, 0xff00},
1344 {"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP
, 0xff},
1345 {"pa1b0", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB0
, 0xffff},
1346 {"pa1b1", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB1
, 0xffff},
1347 {"pa1b2", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB2
, 0xffff},
1348 {"pa1lob0", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB0_LC
, 0xffff},
1349 {"pa1lob1", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB1_LC
, 0xffff},
1350 {"pa1lob2", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB2_LC
, 0xffff},
1351 {"pa1hib0", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB0_HC
, 0xffff},
1352 {"pa1hib1", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB1_HC
, 0xffff},
1353 {"pa1hib2", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB2_HC
, 0xffff},
1354 {"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP
, 0xff00},
1355 {"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP
, 0xff},
1356 {"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC
, 0xff00},
1357 {"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC
, 0xff},
1358 {"bxa2g", 0x00000008, 0, SROM_BXARSSI2G
, 0x1800},
1359 {"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G
, 0x0700},
1360 {"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G
, 0x00f0},
1361 {"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G
, 0x000f},
1362 {"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G
, 0x1800},
1363 {"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G
, 0x0700},
1364 {"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G
, 0x00f0},
1365 {"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G
, 0x000f},
1366 {"bxa5g", 0x00000008, 0, SROM_BXARSSI5G
, 0x1800},
1367 {"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G
, 0x0700},
1368 {"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G
, 0x00f0},
1369 {"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G
, 0x000f},
1370 {"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G
, 0x1800},
1371 {"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G
, 0x0700},
1372 {"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G
, 0x00f0},
1373 {"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G
, 0x000f},
1374 {"tri2g", 0x00000008, 0, SROM_TRI52G
, 0xff},
1375 {"tri5g", 0x00000008, 0, SROM_TRI52G
, 0xff00},
1376 {"tri5gl", 0x00000008, 0, SROM_TRI5GHL
, 0xff},
1377 {"tri5gh", 0x00000008, 0, SROM_TRI5GHL
, 0xff00},
1378 {"tri2g", 0xffffff00, 0, SROM8_TRI52G
, 0xff},
1379 {"tri5g", 0xffffff00, 0, SROM8_TRI52G
, 0xff00},
1380 {"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL
, 0xff},
1381 {"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL
, 0xff00},
1382 {"rxpo2g", 0x00000008, SRFL_PRSIGN
, SROM_RXPO52G
, 0xff},
1383 {"rxpo5g", 0x00000008, SRFL_PRSIGN
, SROM_RXPO52G
, 0xff00},
1384 {"rxpo2g", 0xffffff00, SRFL_PRSIGN
, SROM8_RXPO52G
, 0xff},
1385 {"rxpo5g", 0xffffff00, SRFL_PRSIGN
, SROM8_RXPO52G
, 0xff00},
1386 {"txchain", 0x000000f0, SRFL_NOFFS
, SROM4_TXRXC
, SROM4_TXCHAIN_MASK
},
1387 {"rxchain", 0x000000f0, SRFL_NOFFS
, SROM4_TXRXC
, SROM4_RXCHAIN_MASK
},
1388 {"antswitch", 0x000000f0, SRFL_NOFFS
, SROM4_TXRXC
, SROM4_SWITCH_MASK
},
1389 {"txchain", 0xffffff00, SRFL_NOFFS
, SROM8_TXRXC
, SROM4_TXCHAIN_MASK
},
1390 {"rxchain", 0xffffff00, SRFL_NOFFS
, SROM8_TXRXC
, SROM4_RXCHAIN_MASK
},
1391 {"antswitch", 0xffffff00, SRFL_NOFFS
, SROM8_TXRXC
, SROM4_SWITCH_MASK
},
1392 {"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G
, 0xff},
1393 {"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G
, 0xff00},
1394 {"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G
+ 1, 0xff},
1395 {"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G
+ 1, 0xff00},
1396 {"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G
, 0xff},
1397 {"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G
, 0xff00},
1398 {"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G
+ 1, 0xff},
1399 {"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G
+ 1, 0xff00},
1400 {"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL
, 0xff},
1401 {"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL
, 0xff00},
1402 {"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL
+ 1, 0xff},
1403 {"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL
+ 1, 0xff00},
1404 {"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH
, 0xff},
1405 {"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH
, 0xff00},
1406 {"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH
+ 1, 0xff},
1407 {"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH
+ 1, 0xff00},
1408 {"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO
, 0xffff},
1409 {"cck2gpo", 0xffffff00, 0, SROM8_2G_CCKPO
, 0xffff},
1410 {"ofdm2gpo", 0x000000f0, SRFL_MORE
, SROM4_2G_OFDMPO
, 0xffff},
1411 {"", 0, 0, SROM4_2G_OFDMPO
+ 1, 0xffff},
1412 {"ofdm5gpo", 0x000000f0, SRFL_MORE
, SROM4_5G_OFDMPO
, 0xffff},
1413 {"", 0, 0, SROM4_5G_OFDMPO
+ 1, 0xffff},
1414 {"ofdm5glpo", 0x000000f0, SRFL_MORE
, SROM4_5GL_OFDMPO
, 0xffff},
1415 {"", 0, 0, SROM4_5GL_OFDMPO
+ 1, 0xffff},
1416 {"ofdm5ghpo", 0x000000f0, SRFL_MORE
, SROM4_5GH_OFDMPO
, 0xffff},
1417 {"", 0, 0, SROM4_5GH_OFDMPO
+ 1, 0xffff},
1418 {"ofdm2gpo", 0xffffff00, SRFL_MORE
, SROM8_2G_OFDMPO
, 0xffff},
1419 {"", 0, 0, SROM8_2G_OFDMPO
+ 1, 0xffff},
1420 {"ofdm5gpo", 0xffffff00, SRFL_MORE
, SROM8_5G_OFDMPO
, 0xffff},
1421 {"", 0, 0, SROM8_5G_OFDMPO
+ 1, 0xffff},
1422 {"ofdm5glpo", 0xffffff00, SRFL_MORE
, SROM8_5GL_OFDMPO
, 0xffff},
1423 {"", 0, 0, SROM8_5GL_OFDMPO
+ 1, 0xffff},
1424 {"ofdm5ghpo", 0xffffff00, SRFL_MORE
, SROM8_5GH_OFDMPO
, 0xffff},
1425 {"", 0, 0, SROM8_5GH_OFDMPO
+ 1, 0xffff},
1426 {"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO
, 0xffff},
1427 {"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO
+ 1, 0xffff},
1428 {"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO
+ 2, 0xffff},
1429 {"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO
+ 3, 0xffff},
1430 {"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO
+ 4, 0xffff},
1431 {"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO
+ 5, 0xffff},
1432 {"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO
+ 6, 0xffff},
1433 {"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO
+ 7, 0xffff},
1434 {"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO
, 0xffff},
1435 {"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO
+ 1, 0xffff},
1436 {"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO
+ 2, 0xffff},
1437 {"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO
+ 3, 0xffff},
1438 {"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO
+ 4, 0xffff},
1439 {"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO
+ 5, 0xffff},
1440 {"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO
+ 6, 0xffff},
1441 {"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO
+ 7, 0xffff},
1442 {"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO
, 0xffff},
1443 {"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 1, 0xffff},
1444 {"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 2, 0xffff},
1445 {"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 3, 0xffff},
1446 {"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 4, 0xffff},
1447 {"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 5, 0xffff},
1448 {"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 6, 0xffff},
1449 {"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 7, 0xffff},
1450 {"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO
, 0xffff},
1451 {"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 1, 0xffff},
1452 {"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 2, 0xffff},
1453 {"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 3, 0xffff},
1454 {"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 4, 0xffff},
1455 {"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 5, 0xffff},
1456 {"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 6, 0xffff},
1457 {"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 7, 0xffff},
1458 {"mcs2gpo0", 0xffffff00, 0, SROM8_2G_MCSPO
, 0xffff},
1459 {"mcs2gpo1", 0xffffff00, 0, SROM8_2G_MCSPO
+ 1, 0xffff},
1460 {"mcs2gpo2", 0xffffff00, 0, SROM8_2G_MCSPO
+ 2, 0xffff},
1461 {"mcs2gpo3", 0xffffff00, 0, SROM8_2G_MCSPO
+ 3, 0xffff},
1462 {"mcs2gpo4", 0xffffff00, 0, SROM8_2G_MCSPO
+ 4, 0xffff},
1463 {"mcs2gpo5", 0xffffff00, 0, SROM8_2G_MCSPO
+ 5, 0xffff},
1464 {"mcs2gpo6", 0xffffff00, 0, SROM8_2G_MCSPO
+ 6, 0xffff},
1465 {"mcs2gpo7", 0xffffff00, 0, SROM8_2G_MCSPO
+ 7, 0xffff},
1466 {"mcs5gpo0", 0xffffff00, 0, SROM8_5G_MCSPO
, 0xffff},
1467 {"mcs5gpo1", 0xffffff00, 0, SROM8_5G_MCSPO
+ 1, 0xffff},
1468 {"mcs5gpo2", 0xffffff00, 0, SROM8_5G_MCSPO
+ 2, 0xffff},
1469 {"mcs5gpo3", 0xffffff00, 0, SROM8_5G_MCSPO
+ 3, 0xffff},
1470 {"mcs5gpo4", 0xffffff00, 0, SROM8_5G_MCSPO
+ 4, 0xffff},
1471 {"mcs5gpo5", 0xffffff00, 0, SROM8_5G_MCSPO
+ 5, 0xffff},
1472 {"mcs5gpo6", 0xffffff00, 0, SROM8_5G_MCSPO
+ 6, 0xffff},
1473 {"mcs5gpo7", 0xffffff00, 0, SROM8_5G_MCSPO
+ 7, 0xffff},
1474 {"mcs5glpo0", 0xffffff00, 0, SROM8_5GL_MCSPO
, 0xffff},
1475 {"mcs5glpo1", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 1, 0xffff},
1476 {"mcs5glpo2", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 2, 0xffff},
1477 {"mcs5glpo3", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 3, 0xffff},
1478 {"mcs5glpo4", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 4, 0xffff},
1479 {"mcs5glpo5", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 5, 0xffff},
1480 {"mcs5glpo6", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 6, 0xffff},
1481 {"mcs5glpo7", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 7, 0xffff},
1482 {"mcs5ghpo0", 0xffffff00, 0, SROM8_5GH_MCSPO
, 0xffff},
1483 {"mcs5ghpo1", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 1, 0xffff},
1484 {"mcs5ghpo2", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 2, 0xffff},
1485 {"mcs5ghpo3", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 3, 0xffff},
1486 {"mcs5ghpo4", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 4, 0xffff},
1487 {"mcs5ghpo5", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 5, 0xffff},
1488 {"mcs5ghpo6", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 6, 0xffff},
1489 {"mcs5ghpo7", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 7, 0xffff},
1490 {"cddpo", 0x000000f0, 0, SROM4_CDDPO
, 0xffff},
1491 {"stbcpo", 0x000000f0, 0, SROM4_STBCPO
, 0xffff},
1492 {"bw40po", 0x000000f0, 0, SROM4_BW40PO
, 0xffff},
1493 {"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO
, 0xffff},
1494 {"cddpo", 0xffffff00, 0, SROM8_CDDPO
, 0xffff},
1495 {"stbcpo", 0xffffff00, 0, SROM8_STBCPO
, 0xffff},
1496 {"bw40po", 0xffffff00, 0, SROM8_BW40PO
, 0xffff},
1497 {"bwduppo", 0xffffff00, 0, SROM8_BWDUPPO
, 0xffff},
1498 {"ccode", 0x0000000f, SRFL_CCODE
, SROM_CCODE
, 0xffff},
1499 {"ccode", 0x00000010, SRFL_CCODE
, SROM4_CCODE
, 0xffff},
1500 {"ccode", 0x000000e0, SRFL_CCODE
, SROM5_CCODE
, 0xffff},
1501 {"ccode", 0xffffff00, SRFL_CCODE
, SROM8_CCODE
, 0xffff},
1502 {"macaddr", 0xffffff00, SRFL_ETHADDR
, SROM8_MACHI
, 0xffff},
1503 {"macaddr", 0x000000e0, SRFL_ETHADDR
, SROM5_MACHI
, 0xffff},
1504 {"macaddr", 0x00000010, SRFL_ETHADDR
, SROM4_MACHI
, 0xffff},
1505 {"macaddr", 0x00000008, SRFL_ETHADDR
, SROM3_MACHI
, 0xffff},
1506 {"il0macaddr", 0x00000007, SRFL_ETHADDR
, SROM_MACHI_IL0
, 0xffff},
1507 {"et1macaddr", 0x00000007, SRFL_ETHADDR
, SROM_MACHI_ET1
, 0xffff},
1508 {"leddc", 0xffffff00, SRFL_NOFFS
| SRFL_LEDDC
, SROM8_LEDDC
, 0xffff},
1509 {"leddc", 0x000000e0, SRFL_NOFFS
| SRFL_LEDDC
, SROM5_LEDDC
, 0xffff},
1510 {"leddc", 0x00000010, SRFL_NOFFS
| SRFL_LEDDC
, SROM4_LEDDC
, 0xffff},
1511 {"leddc", 0x00000008, SRFL_NOFFS
| SRFL_LEDDC
, SROM3_LEDDC
, 0xffff},
1515 static const sromvar_t perpath_pci_sromvars
[] = {
1516 {"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP
, 0xff},
1517 {"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP
, 0xff00},
1518 {"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP
, 0xff00},
1519 {"pa2gw0a", 0x000000f0, SRFL_PRHEX
, SROM4_2G_PA
, 0xffff},
1520 {"pa2gw1a", 0x000000f0, SRFL_PRHEX
, SROM4_2G_PA
+ 1, 0xffff},
1521 {"pa2gw2a", 0x000000f0, SRFL_PRHEX
, SROM4_2G_PA
+ 2, 0xffff},
1522 {"pa2gw3a", 0x000000f0, SRFL_PRHEX
, SROM4_2G_PA
+ 3, 0xffff},
1523 {"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP
, 0xff},
1524 {"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP
, 0xff},
1525 {"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP
, 0xff00},
1526 {"pa5gw0a", 0x000000f0, SRFL_PRHEX
, SROM4_5G_PA
, 0xffff},
1527 {"pa5gw1a", 0x000000f0, SRFL_PRHEX
, SROM4_5G_PA
+ 1, 0xffff},
1528 {"pa5gw2a", 0x000000f0, SRFL_PRHEX
, SROM4_5G_PA
+ 2, 0xffff},
1529 {"pa5gw3a", 0x000000f0, SRFL_PRHEX
, SROM4_5G_PA
+ 3, 0xffff},
1530 {"pa5glw0a", 0x000000f0, SRFL_PRHEX
, SROM4_5GL_PA
, 0xffff},
1531 {"pa5glw1a", 0x000000f0, SRFL_PRHEX
, SROM4_5GL_PA
+ 1, 0xffff},
1532 {"pa5glw2a", 0x000000f0, SRFL_PRHEX
, SROM4_5GL_PA
+ 2, 0xffff},
1533 {"pa5glw3a", 0x000000f0, SRFL_PRHEX
, SROM4_5GL_PA
+ 3, 0xffff},
1534 {"pa5ghw0a", 0x000000f0, SRFL_PRHEX
, SROM4_5GH_PA
, 0xffff},
1535 {"pa5ghw1a", 0x000000f0, SRFL_PRHEX
, SROM4_5GH_PA
+ 1, 0xffff},
1536 {"pa5ghw2a", 0x000000f0, SRFL_PRHEX
, SROM4_5GH_PA
+ 2, 0xffff},
1537 {"pa5ghw3a", 0x000000f0, SRFL_PRHEX
, SROM4_5GH_PA
+ 3, 0xffff},
1538 {"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP
, 0xff},
1539 {"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP
, 0xff00},
1540 {"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP
, 0xff00},
1541 {"pa2gw0a", 0xffffff00, SRFL_PRHEX
, SROM8_2G_PA
, 0xffff},
1542 {"pa2gw1a", 0xffffff00, SRFL_PRHEX
, SROM8_2G_PA
+ 1, 0xffff},
1543 {"pa2gw2a", 0xffffff00, SRFL_PRHEX
, SROM8_2G_PA
+ 2, 0xffff},
1544 {"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP
, 0xff},
1545 {"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP
, 0xff},
1546 {"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP
, 0xff00},
1547 {"pa5gw0a", 0xffffff00, SRFL_PRHEX
, SROM8_5G_PA
, 0xffff},
1548 {"pa5gw1a", 0xffffff00, SRFL_PRHEX
, SROM8_5G_PA
+ 1, 0xffff},
1549 {"pa5gw2a", 0xffffff00, SRFL_PRHEX
, SROM8_5G_PA
+ 2, 0xffff},
1550 {"pa5glw0a", 0xffffff00, SRFL_PRHEX
, SROM8_5GL_PA
, 0xffff},
1551 {"pa5glw1a", 0xffffff00, SRFL_PRHEX
, SROM8_5GL_PA
+ 1, 0xffff},
1552 {"pa5glw2a", 0xffffff00, SRFL_PRHEX
, SROM8_5GL_PA
+ 2, 0xffff},
1553 {"pa5ghw0a", 0xffffff00, SRFL_PRHEX
, SROM8_5GH_PA
, 0xffff},
1554 {"pa5ghw1a", 0xffffff00, SRFL_PRHEX
, SROM8_5GH_PA
+ 1, 0xffff},
1555 {"pa5ghw2a", 0xffffff00, SRFL_PRHEX
, SROM8_5GH_PA
+ 2, 0xffff},
1559 /* Parse SROM and create name=value pairs. 'srom' points to
1560 * the SROM word array. 'off' specifies the offset of the
1561 * first word 'srom' points to, which should be either 0 or
1562 * SROM3_SWRG_OFF (full SROM or software region).
1566 mask_shift (uint16 mask
)
1569 for (i
= 0; i
< (sizeof (mask
) << 3); i
++)
1571 if (mask
& (1 << i
))
1579 mask_width (uint16 mask
)
1582 for (i
= (sizeof (mask
) << 3) - 1; i
>= 0; i
--)
1584 if (mask
& (1 << i
))
1585 return (uint
) (i
- mask_shift (mask
) + 1);
1591 #ifdef BCMDBG_ASSERT
1593 mask_valid (uint16 mask
)
1595 uint shift
= mask_shift (mask
);
1596 uint width
= mask_width (mask
);
1597 return mask
== ((~0 << shift
) & ~(~0 << (shift
+ width
)));
1602 _initvars_srom_pci (uint8 sromrev
, uint16
* srom
, uint off
, varbuf_t
* b
)
1606 const sromvar_t
*srv
;
1609 uint32 sr
= (1 << sromrev
);
1611 varbuf_append (b
, "sromrev=%d", sromrev
);
1613 for (srv
= pci_sromvars
; srv
->name
!= NULL
; srv
++)
1617 if ((srv
->revmask
& sr
) == 0)
1626 if (flags
& SRFL_ETHADDR
)
1628 char eabuf
[ETHER_ADDR_STR_LEN
];
1629 struct ether_addr ea
;
1631 ea
.octet
[0] = (srom
[srv
->off
- off
] >> 8) & 0xff;
1632 ea
.octet
[1] = srom
[srv
->off
- off
] & 0xff;
1633 ea
.octet
[2] = (srom
[srv
->off
+ 1 - off
] >> 8) & 0xff;
1634 ea
.octet
[3] = srom
[srv
->off
+ 1 - off
] & 0xff;
1635 ea
.octet
[4] = (srom
[srv
->off
+ 2 - off
] >> 8) & 0xff;
1636 ea
.octet
[5] = srom
[srv
->off
+ 2 - off
] & 0xff;
1637 bcm_ether_ntoa (&ea
, eabuf
);
1639 varbuf_append (b
, "%s=%s", name
, eabuf
);
1643 ASSERT (mask_valid (srv
->mask
));
1644 ASSERT (mask_width (srv
->mask
));
1646 w
= srom
[srv
->off
- off
];
1647 val
= (w
& srv
->mask
) >> mask_shift (srv
->mask
);
1648 width
= mask_width (srv
->mask
);
1650 while (srv
->flags
& SRFL_MORE
)
1655 if (srv
->off
== 0 || srv
->off
< off
)
1658 ASSERT (mask_valid (srv
->mask
));
1659 ASSERT (mask_width (srv
->mask
));
1661 w
= srom
[srv
->off
- off
];
1662 val
+= ((w
& srv
->mask
) >> mask_shift (srv
->mask
)) << width
;
1663 width
+= mask_width (srv
->mask
);
1666 if ((flags
& SRFL_NOFFS
) && ((int) val
== (1 << width
) - 1))
1669 if (flags
& SRFL_CCODE
)
1672 varbuf_append (b
, "ccode=");
1674 varbuf_append (b
, "ccode=%c%c", (val
>> 8), (val
& 0xff));
1676 /* LED Powersave duty cycle has to be scaled:
1677 *(oncount >> 24) (offcount >> 8)
1679 else if (flags
& SRFL_LEDDC
)
1681 uint32 w32
= (((val
>> 8) & 0xff) << 24) | /* oncount */
1682 (((val
& 0xff)) << 8); /* offcount */
1683 varbuf_append (b
, "leddc=%d", w32
);
1685 else if (flags
& SRFL_PRHEX
)
1686 varbuf_append (b
, "%s=0x%x", name
, val
);
1687 else if ((flags
& SRFL_PRSIGN
) && (val
& (1 << (width
- 1))))
1688 varbuf_append (b
, "%s=%d", name
, (int) (val
| (~0 << width
)));
1690 varbuf_append (b
, "%s=%u", name
, val
);
1696 /* Do per-path variables */
1702 psz
= SROM8_PATH1
- SROM8_PATH0
;
1707 psz
= SROM4_PATH1
- SROM4_PATH0
;
1710 for (p
= 0; p
< MAX_PATH
; p
++)
1712 for (srv
= perpath_pci_sromvars
; srv
->name
!= NULL
; srv
++)
1714 if ((srv
->revmask
& sr
) == 0)
1717 if (pb
+ srv
->off
< off
)
1720 w
= srom
[pb
+ srv
->off
- off
];
1721 ASSERT (mask_valid (srv
->mask
));
1722 val
= (w
& srv
->mask
) >> mask_shift (srv
->mask
);
1723 width
= mask_width (srv
->mask
);
1725 /* Cheating: no per-path var is more than 1 word */
1727 if ((srv
->flags
& SRFL_NOFFS
)
1728 && ((int) val
== (1 << width
) - 1))
1731 if (srv
->flags
& SRFL_PRHEX
)
1732 varbuf_append (b
, "%s%d=0x%x", srv
->name
, p
, val
);
1734 varbuf_append (b
, "%s%d=%d", srv
->name
, p
, val
);
1742 initvars_srom_pci (sb_t
* sbh
, void *curmap
, char **vars
, uint
* count
)
1748 char *vp
, *base
= NULL
;
1749 osl_t
*osh
= sb_osh (sbh
);
1755 * Apply CRC over SROM content regardless SROM is present or not,
1756 * and use variable <devpath>sromrev's existance in flash to decide
1757 * if we should return an error when CRC fails or read SROM variables
1760 srom
= MALLOC (osh
, SROM_MAX
);
1766 sprom_read_pci (osh
, (void *) ((int8
*) curmap
+ PCI_BAR0_SPROM_OFFSET
),
1767 0, srom
, SROM_WORDS
, TRUE
);
1769 if ((srom
[SROM4_SIGN
] == SROM4_SIGNATURE
) ||
1770 ((sbh
->buscoretype
== SB_PCIE
) && (sbh
->buscorerev
>= 6)))
1772 /* sromrev >= 4, read more */
1774 sprom_read_pci (osh
,
1775 (void *) ((int8
*) curmap
+ PCI_BAR0_SPROM_OFFSET
), 0,
1776 srom
, SROM4_WORDS
, TRUE
);
1777 sromrev
= srom
[SROM4_CRCREV
] & 0xff;
1781 /* srom is good and is rev < 4 */
1782 /* top word of sprom contains version and crc8 */
1783 sromrev
= srom
[SROM_CRCREV
] & 0xff;
1784 /* bcm4401 sroms misprogrammed */
1785 if (sromrev
== 0x10)
1794 BS_ERROR (("SROM Crc Error, so see if we could use a default\n"));
1795 val
= OSL_PCI_READ_CONFIG (osh
, PCI_SPROM_CONTROL
, sizeof (uint32
));
1796 if (val
& SPROM_OTPIN_USE
)
1798 BS_ERROR (("srom crc failed with OTP, use default vars....\n"));
1799 vp
= base
= mfgsromvars
;
1800 if (sb_chip (sbh
) == BCM4311_CHIP_ID
)
1802 const char *devid
= "devid=0x4311";
1803 const size_t devid_strlen
= strlen (devid
);
1804 BS_ERROR (("setting the devid to be 4311\n"));
1805 bcopy (devid
, vp
, devid_strlen
+ 1);
1806 vp
+= devid_strlen
+ 1;
1808 bcopy (defaultsromvars
, vp
, MFGSROM_DEFVARSLEN
);
1809 vp
+= MFGSROM_DEFVARSLEN
;
1815 BS_ERROR (("srom crc failed with SPROM....\n"));
1816 if (!(value
= sb_getdevpathvar (sbh
, "sromrev")))
1821 sromrev
= (uint8
) simple_strtoul (value
, NULL
, 0);
1828 /* Bitmask for the sromrev */
1831 /* srom version check
1832 * Current valid versions: 1, 2, 3, 4, 5, 8
1834 if ((sr
& 0x13e) == 0)
1843 base
= vp
= MALLOC (osh
, MAXSZ_NVRAM_VARS
);
1851 /* read variables from flash */
1854 if ((err
= initvars_flash (sbh
, osh
, &vp
, MAXSZ_NVRAM_VARS
)))
1859 varbuf_init (&b
, base
, MAXSZ_NVRAM_VARS
);
1861 /* parse SROM into name=value pairs. */
1862 _initvars_srom_pci (sromrev
, srom
, 0, &b
);
1864 /* final nullbyte terminator */
1865 ASSERT (b
.size
>= 1);
1869 ASSERT ((vp
- base
) <= MAXSZ_NVRAM_VARS
);
1872 err
= initvars_table (osh
, base
, vp
, vars
, count
);
1876 if (base
&& (base
!= mfgsromvars
))
1880 MFREE (osh
, base
, MAXSZ_NVRAM_VARS
);
1882 MFREE (osh
, srom
, SROM_MAX
);
1887 * Read the cis and call parsecis to initialize the vars.
1888 * Return 0 on success, nonzero on error.
1891 initvars_cis_pcmcia (sb_t
* sbh
, osl_t
* osh
, char **vars
, uint
* count
)
1897 data_sz
= (sb_pcmciarev (sbh
) == 1) ? (SPROM_SIZE
* 2) : CIS_SIZE
;
1899 if ((cis
= MALLOC (osh
, data_sz
)) == NULL
)
1902 if (sb_pcmciarev (sbh
) == 1)
1905 (sbh
, PCMCIA_BUS
, (void *) NULL
, osh
, 0, data_sz
, (uint16
*) cis
))
1907 MFREE (osh
, cis
, data_sz
);
1910 /* fix up endianess for 16-bit data vs 8-bit parsing */
1911 htol16_buf ((uint16
*) cis
, data_sz
);
1914 OSL_PCMCIA_READ_ATTR (osh
, 0, cis
, data_sz
);
1916 rc
= srom_parsecis (osh
, &cis
, 1, vars
, count
);
1918 MFREE (osh
, cis
, data_sz
);
1925 BCMINITFN (initvars_srom_sb
) (sb_t
* sbh
, osl_t
* osh
, void *curmap
,
1926 char **vars
, uint
* varsz
)
1928 #if defined(BCMSDIODEV)
1929 /* CIS is read and supplied by the host */
1931 #elif defined(BCMUSBDEV)
1932 static bool srvars
= FALSE
; /* Use OTP/SPROM as global variables */
1934 int sel
= 0; /* where to read the srom. 0 - nowhere, 1 - otp, 2 - sprom */
1935 uint sz
= 0; /* srom size in bytes */
1939 /* Bail out if we've dealt with OTP/SPROM before! */
1943 #if defined(BCM4328)
1944 if (sbh
->chip
== BCM4328_CHIP_ID
)
1946 /* Access the SPROM if it is present */
1947 if ((sz
= srom_size (sbh
, osh
)) != 0)
1954 #if defined(BCM4325)
1955 if (sbh
->chip
== BCM4325_CHIP_ID
)
1957 uint32 cst
= sbh
->chipst
& CST4325_SPROM_OTP_SEL_MASK
;
1959 /* Access OTP if it is present, powered on, and programmed */
1960 if ((oh
= otp_init (sbh
)) != NULL
&& (otp_status (oh
) & OTPS_GUP_SW
))
1965 /* Access the SPROM if it is present and allow to be accessed */
1966 else if ((cst
== CST4325_OTP_PWRDN
|| cst
== CST4325_SPROM_SEL
) &&
1967 (sz
= srom_size (sbh
, osh
)) != 0)
1973 #endif /* BCM4325 */
1975 /* Read CIS in OTP/SPROM */
1983 /* Allocate memory */
1984 if ((srom
= (uint16
*) MALLOC (osh
, sz
)) == NULL
)
1991 rc
= otp_read_region (oh
, OTP_SW_RGN
, srom
, sz
);
1992 body
= (uint8
*) srom
;
1995 rc
= srom_read (sbh
, SB_BUS
, curmap
, osh
, 0, sz
, srom
);
1996 /* sprom has 8 byte h/w header */
1997 body
= (uint8
*) srom
+ SBSDIO_SPROM_CIS_OFFSET
;
2000 /* impossible to come here */
2008 uint i
, tpls
= 0xffffffff;
2009 /* # sdiod fns + common + extra */
2010 uint8
*cis
[SBSDIO_NUM_FUNCTION
+ 2];
2013 /* each word is in host endian */
2014 htol16_buf ((uint8
*) srom
, sz
);
2018 /* count cis tuple chains */
2019 for (i
= 0; i
< sz
&& ciss
< ARRAYSIZE (cis
) && tpls
!= 0; i
++)
2021 cis
[ciss
++] = &body
[i
];
2022 for (tpls
= 0; i
< sz
- 1; tpls
++)
2024 if (body
[i
++] == CISTPL_END
)
2030 /* call parser routine only when there are tuple chains */
2032 rc
= srom_parsecis (osh
, cis
, ciss
, vars
, varsz
);
2036 MFREE (osh
, srom
, sz
);
2038 /* Make SROM variables global */
2041 rc
= nvram_append ((void *) sbh
, *vars
, *varsz
);
2044 /* Tell the caller there is no individual SROM variables */
2051 #else /* !BCMUSBDEV && !BCMSDIODEV */
2052 /* Search flash nvram section for srom variables */
2053 return initvars_flash_sb (sbh
, vars
, varsz
);
2054 #endif /* !BCMUSBDEV && !BCMSDIODEV */
2058 /* Return sprom size in 16-bit words */
2060 srom_size (sb_t
* sbh
, osl_t
* osh
)
2063 if (SPROMBUS
== PCMCIA_BUS
)
2066 sdpcmd_regs_t
*pcmregs
;
2069 origidx
= sb_coreidx (sbh
);
2070 pcmregs
= sb_setcore (sbh
, SB_PCMCIA
, 0);
2073 if (!(wasup
= sb_iscoreup (sbh
)))
2074 sb_core_reset (sbh
, 0, 0);
2076 /* not worry about earlier core revs */
2077 if (sb_corerev (sbh
) < 8)
2080 /* SPROM is accessible only in PCMCIA mode unless there is SDIO clock */
2081 if (!(R_REG (osh
, &pcmregs
->corestatus
) & CS_PCMCIAMODE
))
2084 switch (SB_PCMCIA_READ (osh
, pcmregs
, SROM_INFO
) & SRI_SZ_MASK
)
2087 size
= 256; /* SROM_INFO == 1 means 4kbit */
2090 size
= 1024; /* SROM_INFO == 2 means 16kbit */
2098 sb_core_disable (sbh
, 0);
2100 sb_setcoreidx (sbh
, origidx
);
2104 #endif /* def BCMUSBDEV */