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.
20 #include <bcmendian.h>
31 #define BS_ERROR(args) printf args
33 #define BS_ERROR(args)
36 #define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */
37 #define WRITE_WORD_DELAY 20 /* 20 ms between each word write */
41 char *buf
; /* pointer to current position */
42 unsigned int size
; /* current (residual) size in bytes */
45 static int initvars_srom_sb (sb_t
* sbh
, osl_t
* osh
, void *curmap
,
46 char **vars
, uint
* count
);
47 static void _initvars_srom_pci (uint8 sromrev
, uint16
* srom
, uint off
,
49 static int initvars_srom_pci (sb_t
* sbh
, void *curmap
, char **vars
,
51 static int initvars_cis_pcmcia (sb_t
* sbh
, osl_t
* osh
, char **vars
,
53 #if !defined(BCMUSBDEV) && !defined(BCMSDIODEV)
54 static int initvars_flash_sb (sb_t
* sbh
, char **vars
, uint
* count
);
55 #endif /* !BCMUSBDEV && !BCMSDIODEV */
56 static int sprom_cmd_pcmcia (osl_t
* osh
, uint8 cmd
);
57 static int sprom_read_pcmcia (osl_t
* osh
, uint16 addr
, uint16
* data
);
58 static int sprom_write_pcmcia (osl_t
* osh
, uint16 addr
, uint16 data
);
59 static int sprom_read_pci (osl_t
* osh
, uint16
* sprom
, uint wordoff
,
60 uint16
* buf
, uint nwords
, bool check_crc
);
62 static int initvars_table (osl_t
* osh
, char *start
, char *end
, char **vars
,
64 static int initvars_flash (sb_t
* sbh
, osl_t
* osh
, char **vp
, uint len
);
67 static int get_sb_pcmcia_srom (sb_t
* sbh
, osl_t
* osh
, uint8
* pcmregs
,
68 uint boff
, uint16
* srom
, uint bsz
);
69 static int set_sb_pcmcia_srom (sb_t
* sbh
, osl_t
* osh
, uint8
* pcmregs
,
70 uint boff
, uint16
* srom
, uint bsz
);
71 static uint
srom_size (sb_t
* sbh
, osl_t
* osh
);
72 #endif /* def BCMUSBDEV */
74 /* Initialization of varbuf structure */
76 varbuf_init (varbuf_t
* b
, char *buf
, uint size
)
82 /* append a null terminated var=value string */
84 varbuf_append (varbuf_t
* b
, const char *fmt
, ...)
93 r
= vsnprintf (b
->buf
, b
->size
, fmt
, ap
);
96 /* C99 snprintf behavior returns r >= size on overflow,
97 * others return -1 on overflow.
98 * All return -1 on format error.
99 * We need to leave room for 2 null terminations, one for the current var
100 * string, and one for final null of the var table. So check that the
101 * strlen written, r, leaves room for 2 chars.
103 if ((r
== -1) || (r
> (int) (b
->size
- 2)))
109 /* skip over this string's null termination */
118 * Initialize local vars from the right source for this platform.
119 * Return 0 on success, nonzero on error.
122 BCMINITFN (srom_var_init
) (sb_t
* sbh
, uint bustype
, void *curmap
,
123 osl_t
* osh
, char **vars
, uint
* count
)
125 ASSERT (bustype
== BUSTYPE (bustype
));
126 if (vars
== NULL
|| count
== NULL
)
132 switch (BUSTYPE (bustype
))
136 return initvars_srom_sb (sbh
, osh
, curmap
, vars
, count
);
139 ASSERT (curmap
); /* can not be NULL */
140 return initvars_srom_pci (sbh
, curmap
, vars
, count
);
143 return initvars_cis_pcmcia (sbh
, osh
, vars
, count
);
152 /* support only 16-bit word read from srom */
154 srom_read (sb_t
* sbh
, uint bustype
, void *curmap
, osl_t
* osh
,
155 uint byteoff
, uint nbytes
, uint16
* buf
)
160 ASSERT (bustype
== BUSTYPE (bustype
));
162 /* check input - 16-bit access only */
163 if (byteoff
& 1 || nbytes
& 1 || (byteoff
+ nbytes
) > (SPROM_SIZE
* 2))
169 if (BUSTYPE (bustype
) == PCI_BUS
)
173 srom
= (uchar
*) curmap
+ PCI_BAR0_SPROM_OFFSET
;
174 if (sprom_read_pci (osh
, srom
, off
, buf
, nw
, FALSE
))
177 else if (BUSTYPE (bustype
) == PCMCIA_BUS
)
179 for (i
= 0; i
< nw
; i
++)
181 if (sprom_read_pcmcia
182 (osh
, (uint16
) (off
+ i
), (uint16
*) (buf
+ i
)))
186 else if (BUSTYPE (bustype
) == SB_BUS
)
189 if (SPROMBUS
== PCMCIA_BUS
)
196 origidx
= sb_coreidx (sbh
);
197 regs
= sb_setcore (sbh
, SB_PCMCIA
, 0);
198 ASSERT (regs
!= NULL
);
200 if (!(wasup
= sb_iscoreup (sbh
)))
201 sb_core_reset (sbh
, 0, 0);
203 rc
= get_sb_pcmcia_srom (sbh
, osh
, regs
, byteoff
, buf
, nbytes
);
206 sb_core_disable (sbh
, 0);
208 sb_setcoreidx (sbh
, origidx
);
211 #endif /* def BCMUSBDEV */
223 /* support only 16-bit word write into srom */
225 srom_write (sb_t
* sbh
, uint bustype
, void *curmap
, osl_t
* osh
,
226 uint byteoff
, uint nbytes
, uint16
* buf
)
229 uint i
, nw
, crc_range
;
230 uint16 image
[SPROM_SIZE
];
232 volatile uint32 val32
;
234 ASSERT (bustype
== BUSTYPE (bustype
));
236 /* check input - 16-bit access only */
237 if ((byteoff
& 1) || (nbytes
& 1))
240 if (byteoff
== 0x55aa)
244 memset ((void *) image
, 0xff, nbytes
);
247 else if ((byteoff
== 0) &&
248 ((nbytes
== SPROM_SIZE
* 2) ||
249 (nbytes
== (SPROM_CRC_RANGE
* 2)) ||
250 (nbytes
== (SROM4_WORDS
* 2))))
252 /* Are we writing the whole thing at once? */
254 bcopy ((void *) buf
, (void *) image
, nbytes
);
259 if ((byteoff
+ nbytes
) > (SPROM_SIZE
* 2))
262 if (BUSTYPE (bustype
) == PCMCIA_BUS
)
264 crc_range
= SPROM_SIZE
* 2;
268 crc_range
= SPROM_CRC_RANGE
* 2; /* Tentative */
272 /* read first 64 words from srom */
273 if (srom_read (sbh
, bustype
, curmap
, osh
, 0, crc_range
, image
))
275 if (image
[SROM4_SIGN
] == SROM4_SIGNATURE
)
279 if (srom_read (sbh
, bustype
, curmap
, osh
, 0, crc_range
, image
))
283 bcopy ((void *) buf
, (void *) &image
[byteoff
/ 2], nbytes
);
289 htol16_buf (image
, crc_range
);
290 crc
= ~hndcrc8 ((uint8
*) image
, crc_range
- 1, 0xff);
291 ltoh16_buf (image
, crc_range
);
292 image
[nw
- 1] = (crc
<< 8) | (image
[nw
- 1] & 0xff);
295 if (BUSTYPE (bustype
) == PCI_BUS
)
297 srom
= (uint16
*) ((uchar
*) curmap
+ PCI_BAR0_SPROM_OFFSET
);
298 /* enable writes to the SPROM */
299 val32
= OSL_PCI_READ_CONFIG (osh
, PCI_SPROM_CONTROL
, sizeof (uint32
));
300 val32
|= SPROM_WRITEEN
;
301 OSL_PCI_WRITE_CONFIG (osh
, PCI_SPROM_CONTROL
, sizeof (uint32
), val32
);
302 bcm_mdelay (WRITE_ENABLE_DELAY
);
304 for (i
= 0; i
< nw
; i
++)
306 W_REG (osh
, &srom
[i
], image
[i
]);
307 bcm_mdelay (WRITE_WORD_DELAY
);
309 /* disable writes to the SPROM */
310 OSL_PCI_WRITE_CONFIG (osh
, PCI_SPROM_CONTROL
, sizeof (uint32
), val32
&
313 else if (BUSTYPE (bustype
) == PCMCIA_BUS
)
315 /* enable writes to the SPROM */
316 if (sprom_cmd_pcmcia (osh
, SROM_WEN
))
318 bcm_mdelay (WRITE_ENABLE_DELAY
);
320 for (i
= 0; i
< nw
; i
++)
322 sprom_write_pcmcia (osh
, (uint16
) (i
), image
[i
]);
323 bcm_mdelay (WRITE_WORD_DELAY
);
325 /* disable writes to the SPROM */
326 if (sprom_cmd_pcmcia (osh
, SROM_WDS
))
329 else if (BUSTYPE (bustype
) == SB_BUS
)
332 if (SPROMBUS
== PCMCIA_BUS
)
339 origidx
= sb_coreidx (sbh
);
340 regs
= sb_setcore (sbh
, SB_PCMCIA
, 0);
341 ASSERT (regs
!= NULL
);
343 if (!(wasup
= sb_iscoreup (sbh
)))
344 sb_core_reset (sbh
, 0, 0);
346 rc
= set_sb_pcmcia_srom (sbh
, osh
, regs
, byteoff
, buf
, nbytes
);
349 sb_core_disable (sbh
, 0);
351 sb_setcoreidx (sbh
, origidx
);
354 #endif /* def BCMUSBDEV */
362 bcm_mdelay (WRITE_ENABLE_DELAY
);
367 #define SB_PCMCIA_READ(osh, regs, fcr) \
368 R_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2)
369 #define SB_PCMCIA_WRITE(osh, regs, fcr, v) \
370 W_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2, v)
372 /* set PCMCIA srom command register */
374 srom_cmd_sb_pcmcia (osl_t
* osh
, uint8
* pcmregs
, uint8 cmd
)
379 /* write srom command register */
380 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_CS
, cmd
);
383 while (++wait_cnt
< 1000000)
385 status
= SB_PCMCIA_READ (osh
, pcmregs
, SROM_CS
);
386 if (status
& SROM_DONE
)
391 BS_ERROR (("sr_cmd: Give up after %d tries, stat = 0x%x\n", wait_cnt
,
396 /* read a word from the PCMCIA srom over SB */
398 srom_read_sb_pcmcia (osl_t
* osh
, uint8
* pcmregs
, uint16 addr
, uint16
* data
)
400 uint8 addr_l
, addr_h
, data_l
, data_h
;
402 addr_l
= (uint8
) ((addr
* 2) & 0xff);
403 addr_h
= (uint8
) (((addr
* 2) >> 8) & 0xff);
406 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_ADDRH
, addr_h
);
407 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_ADDRL
, addr_l
);
410 if (srom_cmd_sb_pcmcia (osh
, pcmregs
, SROM_READ
))
414 data_h
= SB_PCMCIA_READ (osh
, pcmregs
, SROM_DATAH
);
415 data_l
= SB_PCMCIA_READ (osh
, pcmregs
, SROM_DATAL
);
416 *data
= ((uint16
) data_h
<< 8) | data_l
;
421 /* write a word to the PCMCIA srom over SB */
423 srom_write_sb_pcmcia (osl_t
* osh
, uint8
* pcmregs
, uint16 addr
, uint16 data
)
425 uint8 addr_l
, addr_h
, data_l
, data_h
;
428 addr_l
= (uint8
) ((addr
* 2) & 0xff);
429 addr_h
= (uint8
) (((addr
* 2) >> 8) & 0xff);
432 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_ADDRH
, addr_h
);
433 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_ADDRL
, addr_l
);
435 data_l
= (uint8
) (data
& 0xff);
436 data_h
= (uint8
) ((data
>> 8) & 0xff);
439 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_DATAH
, data_h
);
440 SB_PCMCIA_WRITE (osh
, pcmregs
, SROM_DATAL
, data_l
);
443 rc
= srom_cmd_sb_pcmcia (osh
, pcmregs
, SROM_WRITE
);
449 * Read the srom for the pcmcia-srom over sb case.
450 * Return 0 on success, nonzero on error.
453 get_sb_pcmcia_srom (sb_t
* sbh
, osl_t
* osh
, uint8
* pcmregs
,
454 uint boff
, uint16
* srom
, uint bsz
)
456 uint i
, nw
, woff
, wsz
;
459 /* read must be at word boundary */
460 ASSERT ((boff
& 1) == 0 && (bsz
& 1) == 0);
462 /* read sprom size and validate the parms */
463 if ((nw
= srom_size (sbh
, osh
)) == 0)
465 BS_ERROR (("get_sb_pcmcia_srom: sprom size unknown\n"));
469 if (boff
+ bsz
> 2 * nw
)
471 BS_ERROR (("get_sb_pcmcia_srom: sprom size exceeded\n"));
476 /* read in sprom contents */
477 for (woff
= boff
/ 2, wsz
= bsz
/ 2, i
= 0;
478 woff
< nw
&& i
< wsz
; woff
++, i
++)
480 if (srom_read_sb_pcmcia (osh
, pcmregs
, (uint16
) woff
, &srom
[i
]))
482 BS_ERROR (("get_sb_pcmcia_srom: sprom read failed\n"));
493 * Write the srom for the pcmcia-srom over sb case.
494 * Return 0 on success, nonzero on error.
497 set_sb_pcmcia_srom (sb_t
* sbh
, osl_t
* osh
, uint8
* pcmregs
,
498 uint boff
, uint16
* srom
, uint bsz
)
500 uint i
, nw
, woff
, wsz
;
505 /* write must be at word boundary */
506 ASSERT ((boff
& 1) == 0 && (bsz
& 1) == 0);
508 /* read sprom size and validate the parms */
509 if ((nw
= srom_size (sbh
, osh
)) == 0)
511 BS_ERROR (("set_sb_pcmcia_srom: sprom size unknown\n"));
515 if (boff
+ bsz
> 2 * nw
)
517 BS_ERROR (("set_sb_pcmcia_srom: sprom size exceeded\n"));
523 if (srom_cmd_sb_pcmcia (osh
, pcmregs
, SROM_WEN
))
525 BS_ERROR (("set_sb_pcmcia_srom: sprom wen failed\n"));
530 /* write buffer to sprom */
531 for (woff
= boff
/ 2, wsz
= bsz
/ 2, i
= 0;
532 woff
< nw
&& i
< wsz
; woff
++, i
++)
534 if (srom_write_sb_pcmcia (osh
, pcmregs
, (uint16
) woff
, srom
[i
]))
536 BS_ERROR (("set_sb_pcmcia_srom: sprom write failed\n"));
544 for (woff
= 0; woff
< nw
; woff
++)
546 if (srom_read_sb_pcmcia (osh
, pcmregs
, (uint16
) woff
, &word
))
548 BS_ERROR (("set_sb_pcmcia_srom: sprom fix crc read failed\n"));
552 word
= htol16 (word
);
553 crc
= hndcrc8 ((uint8
*) & word
, woff
!= nw
- 1 ? 2 : 1, crc
);
555 word
= (~crc
<< 8) + (ltoh16 (word
) & 0xff);
556 if (srom_write_sb_pcmcia (osh
, pcmregs
, (uint16
) (woff
- 1), word
))
558 BS_ERROR (("set_sb_pcmcia_srom: sprom fix crc write failed\n"));
564 if (srom_cmd_sb_pcmcia (osh
, pcmregs
, SROM_WDS
))
566 BS_ERROR (("set_sb_pcmcia_srom: sprom wds failed\n"));
574 #endif /* def BCMUSBDEV */
577 srom_parsecis (osl_t
* osh
, uint8
* pcis
[], uint ciscnt
, char **vars
,
583 uint8
*cis
, tup
, tlen
, sromrev
= 1;
586 bool ag_init
= FALSE
;
595 base
= MALLOC (osh
, MAXSZ_NVRAM_VARS
);
600 varbuf_init (&b
, base
, MAXSZ_NVRAM_VARS
);
603 for (cisnum
= 0; cisnum
< ciscnt
; cisnum
++)
612 if ((i
+ tlen
) >= CIS_SIZE
)
618 /* assume the strings are good if the version field checks out */
619 if (((cis
[i
+ 1] << 8) + cis
[i
]) >= 0x0008)
621 varbuf_append (&b
, "manf=%s", &cis
[i
+ 2]);
622 varbuf_append (&b
, "productname=%s",
623 &cis
[i
+ 3 + strlen ((char *) &cis
[i
+ 2])]);
628 varbuf_append (&b
, "manfid=0x%x", (cis
[i
+ 1] << 8) + cis
[i
]);
629 varbuf_append (&b
, "prodid=0x%x",
630 (cis
[i
+ 3] << 8) + cis
[i
+ 2]);
641 /* set macaddr if HNBU_MACADDR not seen yet */
642 if (eabuf
[0] == '\0' && cis
[i
] == LAN_NID
)
644 ASSERT (cis
[i
+ 1] == ETHER_ADDR_LEN
);
645 bcm_ether_ntoa ((struct ether_addr
*) &cis
[i
+ 2],
648 /* set boardnum if HNBU_BOARDNUM not seen yet */
650 boardnum
= (cis
[i
+ 6] << 8) + cis
[i
+ 7];
656 varbuf_append (&b
, "regwindowsz=%d",
657 (cis
[i
+ 7] << 8) | cis
[i
+ 6]);
660 case CISTPL_BRCM_HNBU
:
664 sromrev
= cis
[i
+ 1];
665 varbuf_append (&b
, "sromrev=%d", sromrev
);
669 varbuf_append (&b
, "vendid=0x%x", (cis
[i
+ 2] << 8) +
671 varbuf_append (&b
, "devid=0x%x", (cis
[i
+ 4] << 8) +
675 varbuf_append (&b
, "chiprev=%d",
676 (cis
[i
+ 6] << 8) + cis
[i
+ 5]);
680 varbuf_append (&b
, "subvendid=0x%x",
681 (cis
[i
+ 8] << 8) + cis
[i
+ 7]);
685 varbuf_append (&b
, "subdevid=0x%x",
686 (cis
[i
+ 10] << 8) + cis
[i
+ 9]);
687 /* subdevid doubles for boardtype */
688 varbuf_append (&b
, "boardtype=0x%x",
689 (cis
[i
+ 10] << 8) + cis
[i
+ 9]);
694 varbuf_append (&b
, "boardrev=0x%x", cis
[i
+ 1]);
698 varbuf_append (&b
, "aa2g=%d", cis
[i
+ 1]);
702 varbuf_append (&b
, "ag0=%d", cis
[i
+ 1]);
707 varbuf_append (&b
, "aa5g=%d", cis
[i
+ 1]);
708 varbuf_append (&b
, "ag1=%d", cis
[i
+ 2]);
712 ASSERT (sromrev
== 1);
713 varbuf_append (&b
, "cc=%d", cis
[i
+ 1]);
719 ASSERT (sromrev
== 1);
720 varbuf_append (&b
, "pa0maxpwr=%d", cis
[i
+ 1]);
726 ASSERT (sromrev
>= 2);
727 varbuf_append (&b
, "opo=%d", cis
[i
+ 9]);
732 for (j
= 0; j
< 3; j
++)
734 varbuf_append (&b
, "pa0b%d=%d", j
,
735 (cis
[i
+ (j
* 2) + 2] << 8) +
736 cis
[i
+ (j
* 2) + 1]);
738 varbuf_append (&b
, "pa0itssit=%d", cis
[i
+ 7]);
739 varbuf_append (&b
, "pa0maxpwr=%d", cis
[i
+ 8]);
746 ASSERT ((sromrev
== 2) || (sromrev
== 3));
747 for (j
= 0; j
< 3; j
++)
749 varbuf_append (&b
, "pa1b%d=%d", j
,
750 (cis
[i
+ (j
* 2) + 2] << 8) +
751 cis
[i
+ (j
* 2) + 1]);
753 for (j
= 3; j
< 6; j
++)
755 varbuf_append (&b
, "pa1lob%d=%d", j
- 3,
756 (cis
[i
+ (j
* 2) + 2] << 8) +
757 cis
[i
+ (j
* 2) + 1]);
759 for (j
= 6; j
< 9; j
++)
761 varbuf_append (&b
, "pa1hib%d=%d", j
- 6,
762 (cis
[i
+ (j
* 2) + 2] << 8) +
763 cis
[i
+ (j
* 2) + 1]);
765 varbuf_append (&b
, "pa1itssit=%d", cis
[i
+ 19]);
766 varbuf_append (&b
, "pa1maxpwr=%d", cis
[i
+ 20]);
767 varbuf_append (&b
, "pa1lomaxpwr=%d", cis
[i
+ 21]);
768 varbuf_append (&b
, "pa1himaxpwr=%d", cis
[i
+ 22]);
772 ASSERT (sromrev
== 1);
773 varbuf_append (&b
, "oem=%02x%02x%02x%02x%02x%02x%02x%02x",
774 cis
[i
+ 1], cis
[i
+ 2],
775 cis
[i
+ 3], cis
[i
+ 4],
776 cis
[i
+ 5], cis
[i
+ 6],
777 cis
[i
+ 7], cis
[i
+ 8]);
780 case HNBU_BOARDFLAGS
:
781 w32
= (cis
[i
+ 2] << 8) + cis
[i
+ 1];
783 w32
|= (cis
[i
+ 4] << 24) + (cis
[i
+ 3] << 16);
784 varbuf_append (&b
, "boardflags=0x%x", w32
);
788 if (cis
[i
+ 1] != 0xff)
790 varbuf_append (&b
, "ledbh0=%d", cis
[i
+ 1]);
792 if (cis
[i
+ 2] != 0xff)
794 varbuf_append (&b
, "ledbh1=%d", cis
[i
+ 2]);
796 if (cis
[i
+ 3] != 0xff)
798 varbuf_append (&b
, "ledbh2=%d", cis
[i
+ 3]);
800 if (cis
[i
+ 4] != 0xff)
802 varbuf_append (&b
, "ledbh3=%d", cis
[i
+ 4]);
807 ASSERT (sromrev
> 1);
808 if ((cis
[i
+ 1] == 0) || (cis
[i
+ 2] == 0))
809 varbuf_append (&b
, "ccode=");
811 varbuf_append (&b
, "ccode=%c%c", cis
[i
+ 1], cis
[i
+ 2]);
812 varbuf_append (&b
, "cctl=0x%x", cis
[i
+ 3]);
816 ASSERT (sromrev
> 2);
817 varbuf_append (&b
, "cckpo=0x%x",
818 (cis
[i
+ 2] << 8) | cis
[i
+ 1]);
822 ASSERT (sromrev
> 2);
823 varbuf_append (&b
, "ofdmpo=0x%x",
826 (cis
[i
+ 2] << 8) | cis
[i
+ 1]);
830 varbuf_append (&b
, "rdlid=0x%x",
831 (cis
[i
+ 2] << 8) | cis
[i
+ 1]);
835 varbuf_append (&b
, "rdlrndis=%d", cis
[i
+ 1]);
839 varbuf_append (&b
, "rdlrwu=%d", cis
[i
+ 1]);
843 varbuf_append (&b
, "rdlsn=%d",
844 (cis
[i
+ 2] << 8) | cis
[i
+ 1]);
848 varbuf_append (&b
, "xtalfreq=%d",
851 (cis
[i
+ 2] << 8) | cis
[i
+ 1]);
854 case HNBU_RSSISMBXA2G
:
855 ASSERT (sromrev
== 3);
856 varbuf_append (&b
, "rssismf2g=%d", cis
[i
+ 1] & 0xf);
857 varbuf_append (&b
, "rssismc2g=%d", (cis
[i
+ 1] >> 4) & 0xf);
858 varbuf_append (&b
, "rssisav2g=%d", cis
[i
+ 2] & 0x7);
859 varbuf_append (&b
, "bxa2g=%d", (cis
[i
+ 2] >> 3) & 0x3);
862 case HNBU_RSSISMBXA5G
:
863 ASSERT (sromrev
== 3);
864 varbuf_append (&b
, "rssismf5g=%d", cis
[i
+ 1] & 0xf);
865 varbuf_append (&b
, "rssismc5g=%d", (cis
[i
+ 1] >> 4) & 0xf);
866 varbuf_append (&b
, "rssisav5g=%d", cis
[i
+ 2] & 0x7);
867 varbuf_append (&b
, "bxa5g=%d", (cis
[i
+ 2] >> 3) & 0x3);
871 ASSERT (sromrev
== 3);
872 varbuf_append (&b
, "tri2g=%d", cis
[i
+ 1]);
876 ASSERT (sromrev
== 3);
877 varbuf_append (&b
, "tri5gl=%d", cis
[i
+ 1]);
878 varbuf_append (&b
, "tri5g=%d", cis
[i
+ 2]);
879 varbuf_append (&b
, "tri5gh=%d", cis
[i
+ 3]);
883 ASSERT (sromrev
== 3);
884 varbuf_append (&b
, "rxpo2g=%d", cis
[i
+ 1]);
888 ASSERT (sromrev
== 3);
889 varbuf_append (&b
, "rxpo5g=%d", cis
[i
+ 1]);
893 boardnum
= (cis
[i
+ 2] << 8) + cis
[i
+ 1];
897 bcm_ether_ntoa ((struct ether_addr
*) &cis
[i
+ 1], eabuf
);
901 varbuf_append (&b
, "boardtype=0x%x",
902 (cis
[i
+ 2] << 8) + cis
[i
+ 1]);
905 #if defined(BCMCCISSR3)
906 case HNBU_SROM3SWRGN
:
909 uint8 srev
= cis
[i
+ 1 + 70];
911 /* make tuple value 16-bit aligned and parse it */
912 bcopy (&cis
[i
+ 1], srom
, sizeof (srom
));
913 _initvars_srom_pci (srev
, srom
, SROM3_SWRGN_OFF
, &b
);
914 /* create extra variables */
915 varbuf_append (&b
, "vendid=0x%x",
916 (cis
[i
+ 1 + 73] << 8) + cis
[i
+ 1 + 72]);
917 varbuf_append (&b
, "devid=0x%x",
918 (cis
[i
+ 1 + 75] << 8) + cis
[i
+ 1 + 74]);
919 varbuf_append (&b
, "xtalfreq=%d",
920 (cis
[i
+ 1 + 77] << 8) + cis
[i
+ 1 + 76]);
921 /* 2.4G antenna gain is included in SROM */
923 /* Ethernet MAC address is included in SROM */
934 while (tup
!= CISTPL_END
);
939 varbuf_append (&b
, "boardnum=%d", boardnum
);
944 varbuf_append (&b
, "macaddr=%s", eabuf
);
947 /* if there is no antenna gain field, set default */
948 if (ag_init
== FALSE
)
950 varbuf_append (&b
, "ag0=%d", 0xff);
953 /* final nullbyte terminator */
954 ASSERT (b
.size
>= 1);
956 varsize
= (uint
) (b
.buf
- base
);
957 ASSERT (varsize
< MAXSZ_NVRAM_VARS
);
958 if (varsize
< MAXSZ_NVRAM_VARS
)
961 new_buf
= (char *) MALLOC (osh
, varsize
);
965 bcopy (base
, new_buf
, varsize
);
966 MFREE (osh
, base
, MAXSZ_NVRAM_VARS
);
978 /* set PCMCIA sprom command register */
980 sprom_cmd_pcmcia (osl_t
* osh
, uint8 cmd
)
983 uint wait_cnt
= 1000;
985 /* write sprom command register */
986 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_CS
, &cmd
, 1);
991 OSL_PCMCIA_READ_ATTR (osh
, SROM_CS
, &status
, 1);
992 if (status
& SROM_DONE
)
999 /* read a word from the PCMCIA srom */
1001 sprom_read_pcmcia (osl_t
* osh
, uint16 addr
, uint16
* data
)
1003 uint8 addr_l
, addr_h
, data_l
, data_h
;
1005 addr_l
= (uint8
) ((addr
* 2) & 0xff);
1006 addr_h
= (uint8
) (((addr
* 2) >> 8) & 0xff);
1009 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_ADDRH
, &addr_h
, 1);
1010 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_ADDRL
, &addr_l
, 1);
1013 if (sprom_cmd_pcmcia (osh
, SROM_READ
))
1017 data_h
= data_l
= 0;
1018 OSL_PCMCIA_READ_ATTR (osh
, SROM_DATAH
, &data_h
, 1);
1019 OSL_PCMCIA_READ_ATTR (osh
, SROM_DATAL
, &data_l
, 1);
1021 *data
= (data_h
<< 8) | data_l
;
1025 /* write a word to the PCMCIA srom */
1027 sprom_write_pcmcia (osl_t
* osh
, uint16 addr
, uint16 data
)
1029 uint8 addr_l
, addr_h
, data_l
, data_h
;
1031 addr_l
= (uint8
) ((addr
* 2) & 0xff);
1032 addr_h
= (uint8
) (((addr
* 2) >> 8) & 0xff);
1033 data_l
= (uint8
) (data
& 0xff);
1034 data_h
= (uint8
) ((data
>> 8) & 0xff);
1037 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_ADDRH
, &addr_h
, 1);
1038 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_ADDRL
, &addr_l
, 1);
1041 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_DATAH
, &data_h
, 1);
1042 OSL_PCMCIA_WRITE_ATTR (osh
, SROM_DATAL
, &data_l
, 1);
1045 return sprom_cmd_pcmcia (osh
, SROM_WRITE
);
1049 * Read in and validate sprom.
1050 * Return 0 on success, nonzero on error.
1053 sprom_read_pci (osl_t
* osh
, uint16
* sprom
, uint wordoff
, uint16
* buf
,
1054 uint nwords
, bool check_crc
)
1059 /* read the sprom */
1060 for (i
= 0; i
< nwords
; i
++)
1063 buf
[i
] = R_REG (osh
, &sprom
[wordoff
+ i
]);
1065 buf
[i
] = R_REG (osh
, &sprom
[wordoff
+ i
]);
1070 if (buf
[0] == 0xffff)
1072 /* The hardware thinks that an srom that starts with 0xffff
1073 * is blank, regardless of the rest of the content, so declare
1076 BS_ERROR (("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__
,
1081 /* fixup the endianness so crc8 will pass */
1082 htol16_buf (buf
, nwords
* 2);
1083 if (hndcrc8 ((uint8
*) buf
, nwords
* 2, 0xff) != 0x9f)
1085 /* now correct the endianness of the byte array */
1086 ltoh16_buf (buf
, nwords
* 2);
1093 * Create variable table from memory.
1094 * Return 0 on success, nonzero on error.
1097 BCMINITFN (initvars_table
) (osl_t
* osh
, char *start
, char *end
, char **vars
,
1100 int c
= (int) (end
- start
);
1102 /* do it only when there is more than just the null string */
1105 char *vp
= MALLOC (osh
, c
);
1109 bcopy (start
, vp
, c
);
1123 * Find variables with <devpath> from flash. 'base' points to the beginning
1124 * of the table upon enter and to the end of the table upon exit when success.
1125 * Return 0 on success, nonzero on error.
1128 initvars_flash (sb_t
* sbh
, osl_t
* osh
, char **base
, uint len
)
1134 uint l
, dl
, copy_len
;
1135 char devpath
[SB_DEVPATH_BUFSZ
];
1137 /* allocate memory and read in flash */
1138 if (!(flash
= MALLOC (osh
, NVRAM_SPACE
)))
1140 if ((err
= nvram_getall (flash
, NVRAM_SPACE
)))
1143 sb_devpath (sbh
, devpath
, sizeof (devpath
));
1145 /* grab vars with the <devpath> prefix in name */
1146 dl
= strlen (devpath
);
1147 for (s
= flash
; s
&& *s
; s
+= l
+ 1)
1151 /* skip non-matching variable */
1152 if (strncmp (s
, devpath
, dl
))
1155 /* is there enough room to copy? */
1156 copy_len
= l
- dl
+ 1;
1159 err
= BCME_BUFTOOSHORT
;
1163 /* no prefix, just the name=value */
1164 strncpy (vp
, &s
[dl
], copy_len
);
1169 /* add null string as terminator */
1172 err
= BCME_BUFTOOSHORT
;
1179 exit
:MFREE (osh
, flash
, NVRAM_SPACE
);
1183 #if !defined(BCMUSBDEV) && !defined(BCMSDIODEV)
1185 * Initialize nonvolatile variable table from flash.
1186 * Return 0 on success, nonzero on error.
1189 initvars_flash_sb (sb_t
* sbh
, char **vars
, uint
* count
)
1191 osl_t
*osh
= sb_osh (sbh
);
1198 base
= vp
= MALLOC (osh
, MAXSZ_NVRAM_VARS
);
1203 if ((err
= initvars_flash (sbh
, osh
, &vp
, MAXSZ_NVRAM_VARS
)) == 0)
1204 err
= initvars_table (osh
, base
, vp
, vars
, count
);
1206 MFREE (osh
, base
, MAXSZ_NVRAM_VARS
);
1210 #endif /* !BCMUSBDEV && !BCMSDIODEV */
1213 char mfgsromvars
[256];
1214 char *defaultsromvars
= "il0macaddr=00:11:22:33:44:51\0"
1215 "et0macaddr=00:11:22:33:44:52\0"
1216 "et1macaddr=00:11:22:33:44:53\0"
1217 "boardtype=0xffff\0"
1218 "boardrev=0x10\0" "boardflags=8\0" "sromrev=2\0" "aa2g=3\0" "\0";
1219 #define MFGSROM_DEFVARSLEN 149 /* default srom len */
1220 #endif /* WL_TEST */
1223 * Initialize nonvolatile variable table from sprom.
1224 * Return 0 on success, nonzero on error.
1236 #define SRFL_MORE 1 /* value continues as described by the next entry */
1237 #define SRFL_NOFFS 2 /* value bits can't be all one's */
1238 #define SRFL_PRHEX 4 /* value is in hexdecimal format */
1239 #define SRFL_PRSIGN 8 /* value is in signed decimal format */
1240 #define SRFL_CCODE 0x10 /* value is in country code format */
1241 #define SRFL_ETHADDR 0x20 /* value is an Ethernet address */
1242 #define SRFL_LEDDC 0x40 /* value is an LED duty cycle */
1245 * - Ethernet address spins across 3 consective words
1248 * - Add multiple entries next to each other if a value spins across multiple words
1249 * (even multiple fields in the same word) with each entry except the last having
1250 * it's SRFL_MORE bit set.
1251 * - Ethernet address entry does not follow above rule and must not have SRFL_MORE
1252 * bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
1253 * - The last entry's name field must be NULL to indicate the end of the table. Other
1254 * entries must have non-NULL name.
1257 static const sromvar_t pci_sromvars
[] = {
1258 {"boardrev", 0x0000000e, SRFL_PRHEX
, SROM_AABREV
, SROM_BR_MASK
},
1259 {"boardrev", 0x000000f0, SRFL_PRHEX
, SROM4_BREV
, 0xffff},
1260 {"boardrev", 0xffffff00, SRFL_PRHEX
, SROM8_BREV
, 0xffff},
1261 {"boardflags", 0x00000002, SRFL_PRHEX
, SROM_BFL
, 0xffff},
1262 {"boardflags", 0x00000004, SRFL_PRHEX
| SRFL_MORE
, SROM_BFL
, 0xffff},
1263 {"", 0, 0, SROM_BFL2
, 0xffff},
1264 {"boardflags", 0x00000008, SRFL_PRHEX
| SRFL_MORE
, SROM_BFL
, 0xffff},
1265 {"", 0, 0, SROM3_BFL2
, 0xffff},
1266 {"boardflags", 0x00000010, SRFL_PRHEX
| SRFL_MORE
, SROM4_BFL0
, 0xffff},
1267 {"", 0, 0, SROM4_BFL1
, 0xffff},
1268 {"boardflags", 0x000000e0, SRFL_PRHEX
| SRFL_MORE
, SROM5_BFL0
, 0xffff},
1269 {"", 0, 0, SROM5_BFL1
, 0xffff},
1270 {"boardflags", 0xffffff00, SRFL_PRHEX
| SRFL_MORE
, SROM8_BFL0
, 0xffff},
1271 {"", 0, 0, SROM8_BFL1
, 0xffff},
1272 {"boardflags2", 0x00000010, SRFL_PRHEX
| SRFL_MORE
, SROM4_BFL2
, 0xffff},
1273 {"", 0, 0, SROM4_BFL3
, 0xffff},
1274 {"boardflags2", 0x000000e0, SRFL_PRHEX
| SRFL_MORE
, SROM5_BFL2
, 0xffff},
1275 {"", 0, 0, SROM5_BFL3
, 0xffff},
1276 {"boardflags2", 0xffffff00, SRFL_PRHEX
| SRFL_MORE
, SROM8_BFL2
, 0xffff},
1277 {"", 0, 0, SROM8_BFL3
, 0xffff},
1278 {"boardtype", 0xfffffffc, SRFL_PRHEX
, SROM_SSID
, 0xffff},
1279 {"boardnum", 0x00000006, 0, SROM_MACLO_IL0
, 0xffff},
1280 {"boardnum", 0x00000008, 0, SROM3_MACLO
, 0xffff},
1281 {"boardnum", 0x00000010, 0, SROM4_MACLO
, 0xffff},
1282 {"boardnum", 0x000000e0, 0, SROM5_MACLO
, 0xffff},
1283 {"boardnum", 0xffffff00, 0, SROM8_MACLO
, 0xffff},
1284 {"cc", 0x00000002, 0, SROM_AABREV
, SROM_CC_MASK
},
1285 {"regrev", 0x00000008, 0, SROM_OPO
, 0xff00},
1286 {"regrev", 0x00000010, 0, SROM4_REGREV
, 0xff},
1287 {"regrev", 0x000000e0, 0, SROM5_REGREV
, 0xff},
1288 {"regrev", 0xffffff00, 0, SROM8_REGREV
, 0xff},
1289 {"ledbh0", 0x0000000e, SRFL_NOFFS
, SROM_LEDBH10
, 0xff},
1290 {"ledbh1", 0x0000000e, SRFL_NOFFS
, SROM_LEDBH10
, 0xff00},
1291 {"ledbh2", 0x0000000e, SRFL_NOFFS
, SROM_LEDBH32
, 0xff},
1292 {"ledbh3", 0x0000000e, SRFL_NOFFS
, SROM_LEDBH32
, 0xff00},
1293 {"ledbh0", 0x00000010, SRFL_NOFFS
, SROM4_LEDBH10
, 0xff},
1294 {"ledbh1", 0x00000010, SRFL_NOFFS
, SROM4_LEDBH10
, 0xff00},
1295 {"ledbh2", 0x00000010, SRFL_NOFFS
, SROM4_LEDBH32
, 0xff},
1296 {"ledbh3", 0x00000010, SRFL_NOFFS
, SROM4_LEDBH32
, 0xff00},
1297 {"ledbh0", 0x000000e0, SRFL_NOFFS
, SROM5_LEDBH10
, 0xff},
1298 {"ledbh1", 0x000000e0, SRFL_NOFFS
, SROM5_LEDBH10
, 0xff00},
1299 {"ledbh2", 0x000000e0, SRFL_NOFFS
, SROM5_LEDBH32
, 0xff},
1300 {"ledbh3", 0x000000e0, SRFL_NOFFS
, SROM5_LEDBH32
, 0xff00},
1301 {"ledbh0", 0xffffff00, SRFL_NOFFS
, SROM8_LEDBH10
, 0xff},
1302 {"ledbh1", 0xffffff00, SRFL_NOFFS
, SROM8_LEDBH10
, 0xff00},
1303 {"ledbh2", 0xffffff00, SRFL_NOFFS
, SROM8_LEDBH32
, 0xff},
1304 {"ledbh3", 0xffffff00, SRFL_NOFFS
, SROM8_LEDBH32
, 0xff00},
1305 {"pa0b0", 0x0000000e, SRFL_PRHEX
, SROM_WL0PAB0
, 0xffff},
1306 {"pa0b1", 0x0000000e, SRFL_PRHEX
, SROM_WL0PAB1
, 0xffff},
1307 {"pa0b2", 0x0000000e, SRFL_PRHEX
, SROM_WL0PAB2
, 0xffff},
1308 {"pa0itssit", 0x0000000e, 0, SROM_ITT
, 0xff},
1309 {"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP
, 0xff},
1310 {"pa0b0", 0xffffff00, SRFL_PRHEX
, SROM8_W0_PAB0
, 0xffff},
1311 {"pa0b1", 0xffffff00, SRFL_PRHEX
, SROM8_W0_PAB1
, 0xffff},
1312 {"pa0b2", 0xffffff00, SRFL_PRHEX
, SROM8_W0_PAB2
, 0xffff},
1313 {"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP
, 0xff00},
1314 {"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP
, 0xff},
1315 {"opo", 0x0000000c, 0, SROM_OPO
, 0xff},
1316 {"opo", 0xffffff00, 0, SROM8_2G_OFDMPO
, 0xff},
1317 {"aa2g", 0x0000000e, 0, SROM_AABREV
, SROM_AA0_MASK
},
1318 {"aa2g", 0x000000f0, 0, SROM4_AA
, 0xff},
1319 {"aa2g", 0xffffff00, 0, SROM8_AA
, 0xff},
1320 {"aa5g", 0x0000000e, 0, SROM_AABREV
, SROM_AA1_MASK
},
1321 {"aa5g", 0x000000f0, 0, SROM4_AA
, 0xff00},
1322 {"aa5g", 0xffffff00, 0, SROM8_AA
, 0xff00},
1323 {"ag0", 0x0000000e, 0, SROM_AG10
, 0xff},
1324 {"ag1", 0x0000000e, 0, SROM_AG10
, 0xff00},
1325 {"ag0", 0x000000f0, 0, SROM4_AG10
, 0xff},
1326 {"ag1", 0x000000f0, 0, SROM4_AG10
, 0xff00},
1327 {"ag2", 0x000000f0, 0, SROM4_AG32
, 0xff},
1328 {"ag3", 0x000000f0, 0, SROM4_AG32
, 0xff00},
1329 {"ag0", 0xffffff00, 0, SROM8_AG10
, 0xff},
1330 {"ag1", 0xffffff00, 0, SROM8_AG10
, 0xff00},
1331 {"ag2", 0xffffff00, 0, SROM8_AG32
, 0xff},
1332 {"ag3", 0xffffff00, 0, SROM8_AG32
, 0xff00},
1333 {"pa1b0", 0x0000000e, SRFL_PRHEX
, SROM_WL1PAB0
, 0xffff},
1334 {"pa1b1", 0x0000000e, SRFL_PRHEX
, SROM_WL1PAB1
, 0xffff},
1335 {"pa1b2", 0x0000000e, SRFL_PRHEX
, SROM_WL1PAB2
, 0xffff},
1336 {"pa1lob0", 0x0000000c, SRFL_PRHEX
, SROM_WL1LPAB0
, 0xffff},
1337 {"pa1lob1", 0x0000000c, SRFL_PRHEX
, SROM_WL1LPAB1
, 0xffff},
1338 {"pa1lob2", 0x0000000c, SRFL_PRHEX
, SROM_WL1LPAB2
, 0xffff},
1339 {"pa1hib0", 0x0000000c, SRFL_PRHEX
, SROM_WL1HPAB0
, 0xffff},
1340 {"pa1hib1", 0x0000000c, SRFL_PRHEX
, SROM_WL1HPAB1
, 0xffff},
1341 {"pa1hib2", 0x0000000c, SRFL_PRHEX
, SROM_WL1HPAB2
, 0xffff},
1342 {"pa1itssit", 0x0000000e, 0, SROM_ITT
, 0xff00},
1343 {"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP
, 0xff00},
1344 {"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP
, 0xff00},
1345 {"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP
, 0xff},
1346 {"pa1b0", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB0
, 0xffff},
1347 {"pa1b1", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB1
, 0xffff},
1348 {"pa1b2", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB2
, 0xffff},
1349 {"pa1lob0", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB0_LC
, 0xffff},
1350 {"pa1lob1", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB1_LC
, 0xffff},
1351 {"pa1lob2", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB2_LC
, 0xffff},
1352 {"pa1hib0", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB0_HC
, 0xffff},
1353 {"pa1hib1", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB1_HC
, 0xffff},
1354 {"pa1hib2", 0xffffff00, SRFL_PRHEX
, SROM8_W1_PAB2_HC
, 0xffff},
1355 {"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP
, 0xff00},
1356 {"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP
, 0xff},
1357 {"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC
, 0xff00},
1358 {"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC
, 0xff},
1359 {"bxa2g", 0x00000008, 0, SROM_BXARSSI2G
, 0x1800},
1360 {"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G
, 0x0700},
1361 {"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G
, 0x00f0},
1362 {"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G
, 0x000f},
1363 {"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G
, 0x1800},
1364 {"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G
, 0x0700},
1365 {"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G
, 0x00f0},
1366 {"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G
, 0x000f},
1367 {"bxa5g", 0x00000008, 0, SROM_BXARSSI5G
, 0x1800},
1368 {"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G
, 0x0700},
1369 {"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G
, 0x00f0},
1370 {"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G
, 0x000f},
1371 {"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G
, 0x1800},
1372 {"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G
, 0x0700},
1373 {"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G
, 0x00f0},
1374 {"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G
, 0x000f},
1375 {"tri2g", 0x00000008, 0, SROM_TRI52G
, 0xff},
1376 {"tri5g", 0x00000008, 0, SROM_TRI52G
, 0xff00},
1377 {"tri5gl", 0x00000008, 0, SROM_TRI5GHL
, 0xff},
1378 {"tri5gh", 0x00000008, 0, SROM_TRI5GHL
, 0xff00},
1379 {"tri2g", 0xffffff00, 0, SROM8_TRI52G
, 0xff},
1380 {"tri5g", 0xffffff00, 0, SROM8_TRI52G
, 0xff00},
1381 {"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL
, 0xff},
1382 {"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL
, 0xff00},
1383 {"rxpo2g", 0x00000008, SRFL_PRSIGN
, SROM_RXPO52G
, 0xff},
1384 {"rxpo5g", 0x00000008, SRFL_PRSIGN
, SROM_RXPO52G
, 0xff00},
1385 {"rxpo2g", 0xffffff00, SRFL_PRSIGN
, SROM8_RXPO52G
, 0xff},
1386 {"rxpo5g", 0xffffff00, SRFL_PRSIGN
, SROM8_RXPO52G
, 0xff00},
1387 {"txchain", 0x000000f0, SRFL_NOFFS
, SROM4_TXRXC
, SROM4_TXCHAIN_MASK
},
1388 {"rxchain", 0x000000f0, SRFL_NOFFS
, SROM4_TXRXC
, SROM4_RXCHAIN_MASK
},
1389 {"antswitch", 0x000000f0, SRFL_NOFFS
, SROM4_TXRXC
, SROM4_SWITCH_MASK
},
1390 {"txchain", 0xffffff00, SRFL_NOFFS
, SROM8_TXRXC
, SROM4_TXCHAIN_MASK
},
1391 {"rxchain", 0xffffff00, SRFL_NOFFS
, SROM8_TXRXC
, SROM4_RXCHAIN_MASK
},
1392 {"antswitch", 0xffffff00, SRFL_NOFFS
, SROM8_TXRXC
, SROM4_SWITCH_MASK
},
1393 {"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G
, 0xff},
1394 {"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G
, 0xff00},
1395 {"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G
+ 1, 0xff},
1396 {"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G
+ 1, 0xff00},
1397 {"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G
, 0xff},
1398 {"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G
, 0xff00},
1399 {"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G
+ 1, 0xff},
1400 {"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G
+ 1, 0xff00},
1401 {"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL
, 0xff},
1402 {"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL
, 0xff00},
1403 {"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL
+ 1, 0xff},
1404 {"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL
+ 1, 0xff00},
1405 {"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH
, 0xff},
1406 {"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH
, 0xff00},
1407 {"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH
+ 1, 0xff},
1408 {"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH
+ 1, 0xff00},
1409 {"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO
, 0xffff},
1410 {"cck2gpo", 0xffffff00, 0, SROM8_2G_CCKPO
, 0xffff},
1411 {"ofdm2gpo", 0x000000f0, SRFL_MORE
, SROM4_2G_OFDMPO
, 0xffff},
1412 {"", 0, 0, SROM4_2G_OFDMPO
+ 1, 0xffff},
1413 {"ofdm5gpo", 0x000000f0, SRFL_MORE
, SROM4_5G_OFDMPO
, 0xffff},
1414 {"", 0, 0, SROM4_5G_OFDMPO
+ 1, 0xffff},
1415 {"ofdm5glpo", 0x000000f0, SRFL_MORE
, SROM4_5GL_OFDMPO
, 0xffff},
1416 {"", 0, 0, SROM4_5GL_OFDMPO
+ 1, 0xffff},
1417 {"ofdm5ghpo", 0x000000f0, SRFL_MORE
, SROM4_5GH_OFDMPO
, 0xffff},
1418 {"", 0, 0, SROM4_5GH_OFDMPO
+ 1, 0xffff},
1419 {"ofdm2gpo", 0xffffff00, SRFL_MORE
, SROM8_2G_OFDMPO
, 0xffff},
1420 {"", 0, 0, SROM8_2G_OFDMPO
+ 1, 0xffff},
1421 {"ofdm5gpo", 0xffffff00, SRFL_MORE
, SROM8_5G_OFDMPO
, 0xffff},
1422 {"", 0, 0, SROM8_5G_OFDMPO
+ 1, 0xffff},
1423 {"ofdm5glpo", 0xffffff00, SRFL_MORE
, SROM8_5GL_OFDMPO
, 0xffff},
1424 {"", 0, 0, SROM8_5GL_OFDMPO
+ 1, 0xffff},
1425 {"ofdm5ghpo", 0xffffff00, SRFL_MORE
, SROM8_5GH_OFDMPO
, 0xffff},
1426 {"", 0, 0, SROM8_5GH_OFDMPO
+ 1, 0xffff},
1427 {"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO
, 0xffff},
1428 {"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO
+ 1, 0xffff},
1429 {"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO
+ 2, 0xffff},
1430 {"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO
+ 3, 0xffff},
1431 {"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO
+ 4, 0xffff},
1432 {"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO
+ 5, 0xffff},
1433 {"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO
+ 6, 0xffff},
1434 {"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO
+ 7, 0xffff},
1435 {"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO
, 0xffff},
1436 {"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO
+ 1, 0xffff},
1437 {"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO
+ 2, 0xffff},
1438 {"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO
+ 3, 0xffff},
1439 {"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO
+ 4, 0xffff},
1440 {"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO
+ 5, 0xffff},
1441 {"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO
+ 6, 0xffff},
1442 {"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO
+ 7, 0xffff},
1443 {"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO
, 0xffff},
1444 {"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 1, 0xffff},
1445 {"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 2, 0xffff},
1446 {"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 3, 0xffff},
1447 {"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 4, 0xffff},
1448 {"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 5, 0xffff},
1449 {"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 6, 0xffff},
1450 {"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO
+ 7, 0xffff},
1451 {"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO
, 0xffff},
1452 {"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 1, 0xffff},
1453 {"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 2, 0xffff},
1454 {"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 3, 0xffff},
1455 {"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 4, 0xffff},
1456 {"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 5, 0xffff},
1457 {"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 6, 0xffff},
1458 {"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO
+ 7, 0xffff},
1459 {"mcs2gpo0", 0xffffff00, 0, SROM8_2G_MCSPO
, 0xffff},
1460 {"mcs2gpo1", 0xffffff00, 0, SROM8_2G_MCSPO
+ 1, 0xffff},
1461 {"mcs2gpo2", 0xffffff00, 0, SROM8_2G_MCSPO
+ 2, 0xffff},
1462 {"mcs2gpo3", 0xffffff00, 0, SROM8_2G_MCSPO
+ 3, 0xffff},
1463 {"mcs2gpo4", 0xffffff00, 0, SROM8_2G_MCSPO
+ 4, 0xffff},
1464 {"mcs2gpo5", 0xffffff00, 0, SROM8_2G_MCSPO
+ 5, 0xffff},
1465 {"mcs2gpo6", 0xffffff00, 0, SROM8_2G_MCSPO
+ 6, 0xffff},
1466 {"mcs2gpo7", 0xffffff00, 0, SROM8_2G_MCSPO
+ 7, 0xffff},
1467 {"mcs5gpo0", 0xffffff00, 0, SROM8_5G_MCSPO
, 0xffff},
1468 {"mcs5gpo1", 0xffffff00, 0, SROM8_5G_MCSPO
+ 1, 0xffff},
1469 {"mcs5gpo2", 0xffffff00, 0, SROM8_5G_MCSPO
+ 2, 0xffff},
1470 {"mcs5gpo3", 0xffffff00, 0, SROM8_5G_MCSPO
+ 3, 0xffff},
1471 {"mcs5gpo4", 0xffffff00, 0, SROM8_5G_MCSPO
+ 4, 0xffff},
1472 {"mcs5gpo5", 0xffffff00, 0, SROM8_5G_MCSPO
+ 5, 0xffff},
1473 {"mcs5gpo6", 0xffffff00, 0, SROM8_5G_MCSPO
+ 6, 0xffff},
1474 {"mcs5gpo7", 0xffffff00, 0, SROM8_5G_MCSPO
+ 7, 0xffff},
1475 {"mcs5glpo0", 0xffffff00, 0, SROM8_5GL_MCSPO
, 0xffff},
1476 {"mcs5glpo1", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 1, 0xffff},
1477 {"mcs5glpo2", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 2, 0xffff},
1478 {"mcs5glpo3", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 3, 0xffff},
1479 {"mcs5glpo4", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 4, 0xffff},
1480 {"mcs5glpo5", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 5, 0xffff},
1481 {"mcs5glpo6", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 6, 0xffff},
1482 {"mcs5glpo7", 0xffffff00, 0, SROM8_5GL_MCSPO
+ 7, 0xffff},
1483 {"mcs5ghpo0", 0xffffff00, 0, SROM8_5GH_MCSPO
, 0xffff},
1484 {"mcs5ghpo1", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 1, 0xffff},
1485 {"mcs5ghpo2", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 2, 0xffff},
1486 {"mcs5ghpo3", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 3, 0xffff},
1487 {"mcs5ghpo4", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 4, 0xffff},
1488 {"mcs5ghpo5", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 5, 0xffff},
1489 {"mcs5ghpo6", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 6, 0xffff},
1490 {"mcs5ghpo7", 0xffffff00, 0, SROM8_5GH_MCSPO
+ 7, 0xffff},
1491 {"cddpo", 0x000000f0, 0, SROM4_CDDPO
, 0xffff},
1492 {"stbcpo", 0x000000f0, 0, SROM4_STBCPO
, 0xffff},
1493 {"bw40po", 0x000000f0, 0, SROM4_BW40PO
, 0xffff},
1494 {"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO
, 0xffff},
1495 {"cddpo", 0xffffff00, 0, SROM8_CDDPO
, 0xffff},
1496 {"stbcpo", 0xffffff00, 0, SROM8_STBCPO
, 0xffff},
1497 {"bw40po", 0xffffff00, 0, SROM8_BW40PO
, 0xffff},
1498 {"bwduppo", 0xffffff00, 0, SROM8_BWDUPPO
, 0xffff},
1499 {"ccode", 0x0000000f, SRFL_CCODE
, SROM_CCODE
, 0xffff},
1500 {"ccode", 0x00000010, SRFL_CCODE
, SROM4_CCODE
, 0xffff},
1501 {"ccode", 0x000000e0, SRFL_CCODE
, SROM5_CCODE
, 0xffff},
1502 {"ccode", 0xffffff00, SRFL_CCODE
, SROM8_CCODE
, 0xffff},
1503 {"macaddr", 0xffffff00, SRFL_ETHADDR
, SROM8_MACHI
, 0xffff},
1504 {"macaddr", 0x000000e0, SRFL_ETHADDR
, SROM5_MACHI
, 0xffff},
1505 {"macaddr", 0x00000010, SRFL_ETHADDR
, SROM4_MACHI
, 0xffff},
1506 {"macaddr", 0x00000008, SRFL_ETHADDR
, SROM3_MACHI
, 0xffff},
1507 {"il0macaddr", 0x00000007, SRFL_ETHADDR
, SROM_MACHI_IL0
, 0xffff},
1508 {"et1macaddr", 0x00000007, SRFL_ETHADDR
, SROM_MACHI_ET1
, 0xffff},
1509 {"leddc", 0xffffff00, SRFL_NOFFS
| SRFL_LEDDC
, SROM8_LEDDC
, 0xffff},
1510 {"leddc", 0x000000e0, SRFL_NOFFS
| SRFL_LEDDC
, SROM5_LEDDC
, 0xffff},
1511 {"leddc", 0x00000010, SRFL_NOFFS
| SRFL_LEDDC
, SROM4_LEDDC
, 0xffff},
1512 {"leddc", 0x00000008, SRFL_NOFFS
| SRFL_LEDDC
, SROM3_LEDDC
, 0xffff},
1516 static const sromvar_t perpath_pci_sromvars
[] = {
1517 {"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP
, 0xff},
1518 {"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP
, 0xff00},
1519 {"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP
, 0xff00},
1520 {"pa2gw0a", 0x000000f0, SRFL_PRHEX
, SROM4_2G_PA
, 0xffff},
1521 {"pa2gw1a", 0x000000f0, SRFL_PRHEX
, SROM4_2G_PA
+ 1, 0xffff},
1522 {"pa2gw2a", 0x000000f0, SRFL_PRHEX
, SROM4_2G_PA
+ 2, 0xffff},
1523 {"pa2gw3a", 0x000000f0, SRFL_PRHEX
, SROM4_2G_PA
+ 3, 0xffff},
1524 {"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP
, 0xff},
1525 {"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP
, 0xff},
1526 {"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP
, 0xff00},
1527 {"pa5gw0a", 0x000000f0, SRFL_PRHEX
, SROM4_5G_PA
, 0xffff},
1528 {"pa5gw1a", 0x000000f0, SRFL_PRHEX
, SROM4_5G_PA
+ 1, 0xffff},
1529 {"pa5gw2a", 0x000000f0, SRFL_PRHEX
, SROM4_5G_PA
+ 2, 0xffff},
1530 {"pa5gw3a", 0x000000f0, SRFL_PRHEX
, SROM4_5G_PA
+ 3, 0xffff},
1531 {"pa5glw0a", 0x000000f0, SRFL_PRHEX
, SROM4_5GL_PA
, 0xffff},
1532 {"pa5glw1a", 0x000000f0, SRFL_PRHEX
, SROM4_5GL_PA
+ 1, 0xffff},
1533 {"pa5glw2a", 0x000000f0, SRFL_PRHEX
, SROM4_5GL_PA
+ 2, 0xffff},
1534 {"pa5glw3a", 0x000000f0, SRFL_PRHEX
, SROM4_5GL_PA
+ 3, 0xffff},
1535 {"pa5ghw0a", 0x000000f0, SRFL_PRHEX
, SROM4_5GH_PA
, 0xffff},
1536 {"pa5ghw1a", 0x000000f0, SRFL_PRHEX
, SROM4_5GH_PA
+ 1, 0xffff},
1537 {"pa5ghw2a", 0x000000f0, SRFL_PRHEX
, SROM4_5GH_PA
+ 2, 0xffff},
1538 {"pa5ghw3a", 0x000000f0, SRFL_PRHEX
, SROM4_5GH_PA
+ 3, 0xffff},
1539 {"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP
, 0xff},
1540 {"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP
, 0xff00},
1541 {"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP
, 0xff00},
1542 {"pa2gw0a", 0xffffff00, SRFL_PRHEX
, SROM8_2G_PA
, 0xffff},
1543 {"pa2gw1a", 0xffffff00, SRFL_PRHEX
, SROM8_2G_PA
+ 1, 0xffff},
1544 {"pa2gw2a", 0xffffff00, SRFL_PRHEX
, SROM8_2G_PA
+ 2, 0xffff},
1545 {"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP
, 0xff},
1546 {"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP
, 0xff},
1547 {"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP
, 0xff00},
1548 {"pa5gw0a", 0xffffff00, SRFL_PRHEX
, SROM8_5G_PA
, 0xffff},
1549 {"pa5gw1a", 0xffffff00, SRFL_PRHEX
, SROM8_5G_PA
+ 1, 0xffff},
1550 {"pa5gw2a", 0xffffff00, SRFL_PRHEX
, SROM8_5G_PA
+ 2, 0xffff},
1551 {"pa5glw0a", 0xffffff00, SRFL_PRHEX
, SROM8_5GL_PA
, 0xffff},
1552 {"pa5glw1a", 0xffffff00, SRFL_PRHEX
, SROM8_5GL_PA
+ 1, 0xffff},
1553 {"pa5glw2a", 0xffffff00, SRFL_PRHEX
, SROM8_5GL_PA
+ 2, 0xffff},
1554 {"pa5ghw0a", 0xffffff00, SRFL_PRHEX
, SROM8_5GH_PA
, 0xffff},
1555 {"pa5ghw1a", 0xffffff00, SRFL_PRHEX
, SROM8_5GH_PA
+ 1, 0xffff},
1556 {"pa5ghw2a", 0xffffff00, SRFL_PRHEX
, SROM8_5GH_PA
+ 2, 0xffff},
1560 /* Parse SROM and create name=value pairs. 'srom' points to
1561 * the SROM word array. 'off' specifies the offset of the
1562 * first word 'srom' points to, which should be either 0 or
1563 * SROM3_SWRG_OFF (full SROM or software region).
1567 mask_shift (uint16 mask
)
1570 for (i
= 0; i
< (sizeof (mask
) << 3); i
++)
1572 if (mask
& (1 << i
))
1580 mask_width (uint16 mask
)
1583 for (i
= (sizeof (mask
) << 3) - 1; i
>= 0; i
--)
1585 if (mask
& (1 << i
))
1586 return (uint
) (i
- mask_shift (mask
) + 1);
1592 #ifdef BCMDBG_ASSERT
1594 mask_valid (uint16 mask
)
1596 uint shift
= mask_shift (mask
);
1597 uint width
= mask_width (mask
);
1598 return mask
== ((~0 << shift
) & ~(~0 << (shift
+ width
)));
1603 _initvars_srom_pci (uint8 sromrev
, uint16
* srom
, uint off
, varbuf_t
* b
)
1607 const sromvar_t
*srv
;
1610 uint32 sr
= (1 << sromrev
);
1612 varbuf_append (b
, "sromrev=%d", sromrev
);
1614 for (srv
= pci_sromvars
; srv
->name
!= NULL
; srv
++)
1618 if ((srv
->revmask
& sr
) == 0)
1627 if (flags
& SRFL_ETHADDR
)
1629 char eabuf
[ETHER_ADDR_STR_LEN
];
1630 struct ether_addr ea
;
1632 ea
.octet
[0] = (srom
[srv
->off
- off
] >> 8) & 0xff;
1633 ea
.octet
[1] = srom
[srv
->off
- off
] & 0xff;
1634 ea
.octet
[2] = (srom
[srv
->off
+ 1 - off
] >> 8) & 0xff;
1635 ea
.octet
[3] = srom
[srv
->off
+ 1 - off
] & 0xff;
1636 ea
.octet
[4] = (srom
[srv
->off
+ 2 - off
] >> 8) & 0xff;
1637 ea
.octet
[5] = srom
[srv
->off
+ 2 - off
] & 0xff;
1638 bcm_ether_ntoa (&ea
, eabuf
);
1640 varbuf_append (b
, "%s=%s", name
, eabuf
);
1644 ASSERT (mask_valid (srv
->mask
));
1645 ASSERT (mask_width (srv
->mask
));
1647 w
= srom
[srv
->off
- off
];
1648 val
= (w
& srv
->mask
) >> mask_shift (srv
->mask
);
1649 width
= mask_width (srv
->mask
);
1651 while (srv
->flags
& SRFL_MORE
)
1656 if (srv
->off
== 0 || srv
->off
< off
)
1659 ASSERT (mask_valid (srv
->mask
));
1660 ASSERT (mask_width (srv
->mask
));
1662 w
= srom
[srv
->off
- off
];
1663 val
+= ((w
& srv
->mask
) >> mask_shift (srv
->mask
)) << width
;
1664 width
+= mask_width (srv
->mask
);
1667 if ((flags
& SRFL_NOFFS
) && ((int) val
== (1 << width
) - 1))
1670 if (flags
& SRFL_CCODE
)
1673 varbuf_append (b
, "ccode=");
1675 varbuf_append (b
, "ccode=%c%c", (val
>> 8), (val
& 0xff));
1677 /* LED Powersave duty cycle has to be scaled:
1678 *(oncount >> 24) (offcount >> 8)
1680 else if (flags
& SRFL_LEDDC
)
1682 uint32 w32
= (((val
>> 8) & 0xff) << 24) | /* oncount */
1683 (((val
& 0xff)) << 8); /* offcount */
1684 varbuf_append (b
, "leddc=%d", w32
);
1686 else if (flags
& SRFL_PRHEX
)
1687 varbuf_append (b
, "%s=0x%x", name
, val
);
1688 else if ((flags
& SRFL_PRSIGN
) && (val
& (1 << (width
- 1))))
1689 varbuf_append (b
, "%s=%d", name
, (int) (val
| (~0 << width
)));
1691 varbuf_append (b
, "%s=%u", name
, val
);
1697 /* Do per-path variables */
1703 psz
= SROM8_PATH1
- SROM8_PATH0
;
1708 psz
= SROM4_PATH1
- SROM4_PATH0
;
1711 for (p
= 0; p
< MAX_PATH
; p
++)
1713 for (srv
= perpath_pci_sromvars
; srv
->name
!= NULL
; srv
++)
1715 if ((srv
->revmask
& sr
) == 0)
1718 if (pb
+ srv
->off
< off
)
1721 w
= srom
[pb
+ srv
->off
- off
];
1722 ASSERT (mask_valid (srv
->mask
));
1723 val
= (w
& srv
->mask
) >> mask_shift (srv
->mask
);
1724 width
= mask_width (srv
->mask
);
1726 /* Cheating: no per-path var is more than 1 word */
1728 if ((srv
->flags
& SRFL_NOFFS
)
1729 && ((int) val
== (1 << width
) - 1))
1732 if (srv
->flags
& SRFL_PRHEX
)
1733 varbuf_append (b
, "%s%d=0x%x", srv
->name
, p
, val
);
1735 varbuf_append (b
, "%s%d=%d", srv
->name
, p
, val
);
1743 initvars_srom_pci (sb_t
* sbh
, void *curmap
, char **vars
, uint
* count
)
1749 char *vp
, *base
= NULL
;
1750 osl_t
*osh
= sb_osh (sbh
);
1756 * Apply CRC over SROM content regardless SROM is present or not,
1757 * and use variable <devpath>sromrev's existance in flash to decide
1758 * if we should return an error when CRC fails or read SROM variables
1761 srom
= MALLOC (osh
, SROM_MAX
);
1767 sprom_read_pci (osh
, (void *) ((int8
*) curmap
+ PCI_BAR0_SPROM_OFFSET
),
1768 0, srom
, SROM_WORDS
, TRUE
);
1770 if ((srom
[SROM4_SIGN
] == SROM4_SIGNATURE
) ||
1771 ((sbh
->buscoretype
== SB_PCIE
) && (sbh
->buscorerev
>= 6)))
1773 /* sromrev >= 4, read more */
1775 sprom_read_pci (osh
,
1776 (void *) ((int8
*) curmap
+ PCI_BAR0_SPROM_OFFSET
), 0,
1777 srom
, SROM4_WORDS
, TRUE
);
1778 sromrev
= srom
[SROM4_CRCREV
] & 0xff;
1782 /* srom is good and is rev < 4 */
1783 /* top word of sprom contains version and crc8 */
1784 sromrev
= srom
[SROM_CRCREV
] & 0xff;
1785 /* bcm4401 sroms misprogrammed */
1786 if (sromrev
== 0x10)
1795 BS_ERROR (("SROM Crc Error, so see if we could use a default\n"));
1796 val
= OSL_PCI_READ_CONFIG (osh
, PCI_SPROM_CONTROL
, sizeof (uint32
));
1797 if (val
& SPROM_OTPIN_USE
)
1799 BS_ERROR (("srom crc failed with OTP, use default vars....\n"));
1800 vp
= base
= mfgsromvars
;
1801 if (sb_chip (sbh
) == BCM4311_CHIP_ID
)
1803 const char *devid
= "devid=0x4311";
1804 const size_t devid_strlen
= strlen (devid
);
1805 BS_ERROR (("setting the devid to be 4311\n"));
1806 bcopy (devid
, vp
, devid_strlen
+ 1);
1807 vp
+= devid_strlen
+ 1;
1809 bcopy (defaultsromvars
, vp
, MFGSROM_DEFVARSLEN
);
1810 vp
+= MFGSROM_DEFVARSLEN
;
1816 BS_ERROR (("srom crc failed with SPROM....\n"));
1817 if (!(value
= sb_getdevpathvar (sbh
, "sromrev")))
1822 sromrev
= (uint8
) simple_strtoul (value
, NULL
, 0);
1829 /* Bitmask for the sromrev */
1832 /* srom version check
1833 * Current valid versions: 1, 2, 3, 4, 5, 8
1835 if ((sr
& 0x13e) == 0)
1844 base
= vp
= MALLOC (osh
, MAXSZ_NVRAM_VARS
);
1852 /* read variables from flash */
1855 if ((err
= initvars_flash (sbh
, osh
, &vp
, MAXSZ_NVRAM_VARS
)))
1860 varbuf_init (&b
, base
, MAXSZ_NVRAM_VARS
);
1862 /* parse SROM into name=value pairs. */
1863 _initvars_srom_pci (sromrev
, srom
, 0, &b
);
1865 /* final nullbyte terminator */
1866 ASSERT (b
.size
>= 1);
1870 ASSERT ((vp
- base
) <= MAXSZ_NVRAM_VARS
);
1873 err
= initvars_table (osh
, base
, vp
, vars
, count
);
1877 if (base
&& (base
!= mfgsromvars
))
1881 MFREE (osh
, base
, MAXSZ_NVRAM_VARS
);
1883 MFREE (osh
, srom
, SROM_MAX
);
1888 * Read the cis and call parsecis to initialize the vars.
1889 * Return 0 on success, nonzero on error.
1892 initvars_cis_pcmcia (sb_t
* sbh
, osl_t
* osh
, char **vars
, uint
* count
)
1898 data_sz
= (sb_pcmciarev (sbh
) == 1) ? (SPROM_SIZE
* 2) : CIS_SIZE
;
1900 if ((cis
= MALLOC (osh
, data_sz
)) == NULL
)
1903 if (sb_pcmciarev (sbh
) == 1)
1906 (sbh
, PCMCIA_BUS
, (void *) NULL
, osh
, 0, data_sz
, (uint16
*) cis
))
1908 MFREE (osh
, cis
, data_sz
);
1911 /* fix up endianess for 16-bit data vs 8-bit parsing */
1912 htol16_buf ((uint16
*) cis
, data_sz
);
1915 OSL_PCMCIA_READ_ATTR (osh
, 0, cis
, data_sz
);
1917 rc
= srom_parsecis (osh
, &cis
, 1, vars
, count
);
1919 MFREE (osh
, cis
, data_sz
);
1926 BCMINITFN (initvars_srom_sb
) (sb_t
* sbh
, osl_t
* osh
, void *curmap
,
1927 char **vars
, uint
* varsz
)
1929 #if defined(BCMSDIODEV)
1930 /* CIS is read and supplied by the host */
1932 #elif defined(BCMUSBDEV)
1933 static bool srvars
= FALSE
; /* Use OTP/SPROM as global variables */
1935 int sel
= 0; /* where to read the srom. 0 - nowhere, 1 - otp, 2 - sprom */
1936 uint sz
= 0; /* srom size in bytes */
1940 /* Bail out if we've dealt with OTP/SPROM before! */
1944 #if defined(BCM4328)
1945 if (sbh
->chip
== BCM4328_CHIP_ID
)
1947 /* Access the SPROM if it is present */
1948 if ((sz
= srom_size (sbh
, osh
)) != 0)
1955 #if defined(BCM4325)
1956 if (sbh
->chip
== BCM4325_CHIP_ID
)
1958 uint32 cst
= sbh
->chipst
& CST4325_SPROM_OTP_SEL_MASK
;
1960 /* Access OTP if it is present, powered on, and programmed */
1961 if ((oh
= otp_init (sbh
)) != NULL
&& (otp_status (oh
) & OTPS_GUP_SW
))
1966 /* Access the SPROM if it is present and allow to be accessed */
1967 else if ((cst
== CST4325_OTP_PWRDN
|| cst
== CST4325_SPROM_SEL
) &&
1968 (sz
= srom_size (sbh
, osh
)) != 0)
1974 #endif /* BCM4325 */
1976 /* Read CIS in OTP/SPROM */
1984 /* Allocate memory */
1985 if ((srom
= (uint16
*) MALLOC (osh
, sz
)) == NULL
)
1992 rc
= otp_read_region (oh
, OTP_SW_RGN
, srom
, sz
);
1993 body
= (uint8
*) srom
;
1996 rc
= srom_read (sbh
, SB_BUS
, curmap
, osh
, 0, sz
, srom
);
1997 /* sprom has 8 byte h/w header */
1998 body
= (uint8
*) srom
+ SBSDIO_SPROM_CIS_OFFSET
;
2001 /* impossible to come here */
2009 uint i
, tpls
= 0xffffffff;
2010 /* # sdiod fns + common + extra */
2011 uint8
*cis
[SBSDIO_NUM_FUNCTION
+ 2];
2014 /* each word is in host endian */
2015 htol16_buf ((uint8
*) srom
, sz
);
2019 /* count cis tuple chains */
2020 for (i
= 0; i
< sz
&& ciss
< ARRAYSIZE (cis
) && tpls
!= 0; i
++)
2022 cis
[ciss
++] = &body
[i
];
2023 for (tpls
= 0; i
< sz
- 1; tpls
++)
2025 if (body
[i
++] == CISTPL_END
)
2031 /* call parser routine only when there are tuple chains */
2033 rc
= srom_parsecis (osh
, cis
, ciss
, vars
, varsz
);
2037 MFREE (osh
, srom
, sz
);
2039 /* Make SROM variables global */
2042 rc
= nvram_append ((void *) sbh
, *vars
, *varsz
);
2045 /* Tell the caller there is no individual SROM variables */
2052 #else /* !BCMUSBDEV && !BCMSDIODEV */
2053 /* Search flash nvram section for srom variables */
2054 return initvars_flash_sb (sbh
, vars
, varsz
);
2055 #endif /* !BCMUSBDEV && !BCMSDIODEV */
2059 /* Return sprom size in 16-bit words */
2061 srom_size (sb_t
* sbh
, osl_t
* osh
)
2064 if (SPROMBUS
== PCMCIA_BUS
)
2067 sdpcmd_regs_t
*pcmregs
;
2070 origidx
= sb_coreidx (sbh
);
2071 pcmregs
= sb_setcore (sbh
, SB_PCMCIA
, 0);
2074 if (!(wasup
= sb_iscoreup (sbh
)))
2075 sb_core_reset (sbh
, 0, 0);
2077 /* not worry about earlier core revs */
2078 if (sb_corerev (sbh
) < 8)
2081 /* SPROM is accessible only in PCMCIA mode unless there is SDIO clock */
2082 if (!(R_REG (osh
, &pcmregs
->corestatus
) & CS_PCMCIAMODE
))
2085 switch (SB_PCMCIA_READ (osh
, pcmregs
, SROM_INFO
) & SRI_SZ_MASK
)
2088 size
= 256; /* SROM_INFO == 1 means 4kbit */
2091 size
= 1024; /* SROM_INFO == 2 means 16kbit */
2099 sb_core_disable (sbh
, 0);
2101 sb_setcoreidx (sbh
, origidx
);
2105 #endif /* def BCMUSBDEV */