diff options
Diffstat (limited to 'target/linux/brcm-2.4/files/arch/mips/bcm947xx/bcmsrom.c')
-rw-r--r-- | target/linux/brcm-2.4/files/arch/mips/bcm947xx/bcmsrom.c | 2104 |
1 files changed, 0 insertions, 2104 deletions
diff --git a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/bcmsrom.c b/target/linux/brcm-2.4/files/arch/mips/bcm947xx/bcmsrom.c deleted file mode 100644 index 4cf73b5af8..0000000000 --- a/target/linux/brcm-2.4/files/arch/mips/bcm947xx/bcmsrom.c +++ /dev/null @@ -1,2104 +0,0 @@ -/* - * Routines to access SPROM and to parse SROM/CIS variables. - * - * Copyright 2007, Broadcom Corporation - * All Rights Reserved. - * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. - */ - -#include <typedefs.h> -#include <bcmdefs.h> -#include <osl.h> -#include <stdarg.h> -#include <sbchipc.h> -#include <bcmdevs.h> -#include <bcmendian.h> -#include <sbpcmcia.h> -#include <pcicfg.h> -#include <sbconfig.h> -#include <sbutils.h> -#include <bcmsrom.h> -#include <bcmnvram.h> -#include "utils.h" - -/* debug/trace */ -#if defined(WLTEST) -#define BS_ERROR(args) printf args -#else -#define BS_ERROR(args) -#endif - -#define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */ -#define WRITE_WORD_DELAY 20 /* 20 ms between each word write */ - -typedef struct varbuf -{ - char *buf; /* pointer to current position */ - unsigned int size; /* current (residual) size in bytes */ -} varbuf_t; - -static int initvars_srom_sb (sb_t * sbh, osl_t * osh, void *curmap, - char **vars, uint * count); -static void _initvars_srom_pci (uint8 sromrev, uint16 * srom, uint off, - varbuf_t * b); -static int initvars_srom_pci (sb_t * sbh, void *curmap, char **vars, - uint * count); -static int initvars_cis_pcmcia (sb_t * sbh, osl_t * osh, char **vars, - uint * count); -#if !defined(BCMUSBDEV) && !defined(BCMSDIODEV) -static int initvars_flash_sb (sb_t * sbh, char **vars, uint * count); -#endif /* !BCMUSBDEV && !BCMSDIODEV */ -static int sprom_cmd_pcmcia (osl_t * osh, uint8 cmd); -static int sprom_read_pcmcia (osl_t * osh, uint16 addr, uint16 * data); -static int sprom_write_pcmcia (osl_t * osh, uint16 addr, uint16 data); -static int sprom_read_pci (osl_t * osh, uint16 * sprom, uint wordoff, - uint16 * buf, uint nwords, bool check_crc); - -static int initvars_table (osl_t * osh, char *start, char *end, char **vars, - uint * count); -static int initvars_flash (sb_t * sbh, osl_t * osh, char **vp, uint len); - -#ifdef BCMUSBDEV -static int get_sb_pcmcia_srom (sb_t * sbh, osl_t * osh, uint8 * pcmregs, - uint boff, uint16 * srom, uint bsz); -static int set_sb_pcmcia_srom (sb_t * sbh, osl_t * osh, uint8 * pcmregs, - uint boff, uint16 * srom, uint bsz); -static uint srom_size (sb_t * sbh, osl_t * osh); -#endif /* def BCMUSBDEV */ - -/* Initialization of varbuf structure */ -static void -varbuf_init (varbuf_t * b, char *buf, uint size) -{ - b->size = size; - b->buf = buf; -} - -/* append a null terminated var=value string */ -static int -varbuf_append (varbuf_t * b, const char *fmt, ...) -{ - va_list ap; - int r; - - if (b->size < 2) - return 0; - - va_start (ap, fmt); - r = vsnprintf (b->buf, b->size, fmt, ap); - va_end (ap); - - /* C99 snprintf behavior returns r >= size on overflow, - * others return -1 on overflow. - * All return -1 on format error. - * We need to leave room for 2 null terminations, one for the current var - * string, and one for final null of the var table. So check that the - * strlen written, r, leaves room for 2 chars. - */ - if ((r == -1) || (r > (int) (b->size - 2))) - { - b->size = 0; - return 0; - } - - /* skip over this string's null termination */ - r++; - b->size -= r; - b->buf += r; - - return r; -} - -/* - * Initialize local vars from the right source for this platform. - * Return 0 on success, nonzero on error. - */ -int -BCMINITFN (srom_var_init) (sb_t * sbh, uint bustype, void *curmap, - osl_t * osh, char **vars, uint * count) -{ - ASSERT (bustype == BUSTYPE (bustype)); - if (vars == NULL || count == NULL) - return (0); - - *vars = NULL; - *count = 0; - - switch (BUSTYPE (bustype)) - { - case SB_BUS: - case JTAG_BUS: - return initvars_srom_sb (sbh, osh, curmap, vars, count); - - case PCI_BUS: - ASSERT (curmap); /* can not be NULL */ - return initvars_srom_pci (sbh, curmap, vars, count); - - case PCMCIA_BUS: - return initvars_cis_pcmcia (sbh, osh, vars, count); - - - default: - ASSERT (0); - } - return (-1); -} - -/* support only 16-bit word read from srom */ -int -srom_read (sb_t * sbh, uint bustype, void *curmap, osl_t * osh, - uint byteoff, uint nbytes, uint16 * buf) -{ - void *srom; - uint i, off, nw; - - ASSERT (bustype == BUSTYPE (bustype)); - - /* check input - 16-bit access only */ - if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > (SPROM_SIZE * 2)) - return 1; - - off = byteoff / 2; - nw = nbytes / 2; - - if (BUSTYPE (bustype) == PCI_BUS) - { - if (!curmap) - return 1; - srom = (uchar *) curmap + PCI_BAR0_SPROM_OFFSET; - if (sprom_read_pci (osh, srom, off, buf, nw, FALSE)) - return 1; - } - else if (BUSTYPE (bustype) == PCMCIA_BUS) - { - for (i = 0; i < nw; i++) - { - if (sprom_read_pcmcia - (osh, (uint16) (off + i), (uint16 *) (buf + i))) - return 1; - } - } - else if (BUSTYPE (bustype) == SB_BUS) - { -#ifdef BCMUSBDEV - if (SPROMBUS == PCMCIA_BUS) - { - uint origidx; - void *regs; - int rc; - bool wasup; - - origidx = sb_coreidx (sbh); - regs = sb_setcore (sbh, SB_PCMCIA, 0); - ASSERT (regs != NULL); - - if (!(wasup = sb_iscoreup (sbh))) - sb_core_reset (sbh, 0, 0); - - rc = get_sb_pcmcia_srom (sbh, osh, regs, byteoff, buf, nbytes); - - if (!wasup) - sb_core_disable (sbh, 0); - - sb_setcoreidx (sbh, origidx); - return rc; - } -#endif /* def BCMUSBDEV */ - - return 1; - } - else - { - return 1; - } - - return 0; -} - -/* support only 16-bit word write into srom */ -int -srom_write (sb_t * sbh, uint bustype, void *curmap, osl_t * osh, - uint byteoff, uint nbytes, uint16 * buf) -{ - uint16 *srom; - uint i, nw, crc_range; - uint16 image[SPROM_SIZE]; - uint8 crc; - volatile uint32 val32; - - ASSERT (bustype == BUSTYPE (bustype)); - - /* check input - 16-bit access only */ - if ((byteoff & 1) || (nbytes & 1)) - return 1; - - if (byteoff == 0x55aa) - { - /* Erase request */ - crc_range = 0; - memset ((void *) image, 0xff, nbytes); - nw = nbytes / 2; - } - else if ((byteoff == 0) && - ((nbytes == SPROM_SIZE * 2) || - (nbytes == (SPROM_CRC_RANGE * 2)) || - (nbytes == (SROM4_WORDS * 2)))) - { - /* Are we writing the whole thing at once? */ - crc_range = nbytes; - bcopy ((void *) buf, (void *) image, nbytes); - nw = nbytes / 2; - } - else - { - if ((byteoff + nbytes) > (SPROM_SIZE * 2)) - return 1; - - if (BUSTYPE (bustype) == PCMCIA_BUS) - { - crc_range = SPROM_SIZE * 2; - } - else - { - crc_range = SPROM_CRC_RANGE * 2; /* Tentative */ - } - - nw = crc_range / 2; - /* read first 64 words from srom */ - if (srom_read (sbh, bustype, curmap, osh, 0, crc_range, image)) - return 1; - if (image[SROM4_SIGN] == SROM4_SIGNATURE) - { - nw = SROM4_WORDS; - crc_range = nw * 2; - if (srom_read (sbh, bustype, curmap, osh, 0, crc_range, image)) - return 1; - } - /* make changes */ - bcopy ((void *) buf, (void *) &image[byteoff / 2], nbytes); - } - - if (crc_range) - { - /* calculate crc */ - htol16_buf (image, crc_range); - crc = ~hndcrc8 ((uint8 *) image, crc_range - 1, 0xff); - ltoh16_buf (image, crc_range); - image[nw - 1] = (crc << 8) | (image[nw - 1] & 0xff); - } - - if (BUSTYPE (bustype) == PCI_BUS) - { - srom = (uint16 *) ((uchar *) curmap + PCI_BAR0_SPROM_OFFSET); - /* enable writes to the SPROM */ - val32 = OSL_PCI_READ_CONFIG (osh, PCI_SPROM_CONTROL, sizeof (uint32)); - val32 |= SPROM_WRITEEN; - OSL_PCI_WRITE_CONFIG (osh, PCI_SPROM_CONTROL, sizeof (uint32), val32); - bcm_mdelay (WRITE_ENABLE_DELAY); - /* write srom */ - for (i = 0; i < nw; i++) - { - W_REG (osh, &srom[i], image[i]); - bcm_mdelay (WRITE_WORD_DELAY); - } - /* disable writes to the SPROM */ - OSL_PCI_WRITE_CONFIG (osh, PCI_SPROM_CONTROL, sizeof (uint32), val32 & - ~SPROM_WRITEEN); - } - else if (BUSTYPE (bustype) == PCMCIA_BUS) - { - /* enable writes to the SPROM */ - if (sprom_cmd_pcmcia (osh, SROM_WEN)) - return 1; - bcm_mdelay (WRITE_ENABLE_DELAY); - /* write srom */ - for (i = 0; i < nw; i++) - { - sprom_write_pcmcia (osh, (uint16) (i), image[i]); - bcm_mdelay (WRITE_WORD_DELAY); - } - /* disable writes to the SPROM */ - if (sprom_cmd_pcmcia (osh, SROM_WDS)) - return 1; - } - else if (BUSTYPE (bustype) == SB_BUS) - { -#ifdef BCMUSBDEV - if (SPROMBUS == PCMCIA_BUS) - { - uint origidx; - void *regs; - int rc; - bool wasup; - - origidx = sb_coreidx (sbh); - regs = sb_setcore (sbh, SB_PCMCIA, 0); - ASSERT (regs != NULL); - - if (!(wasup = sb_iscoreup (sbh))) - sb_core_reset (sbh, 0, 0); - - rc = set_sb_pcmcia_srom (sbh, osh, regs, byteoff, buf, nbytes); - - if (!wasup) - sb_core_disable (sbh, 0); - - sb_setcoreidx (sbh, origidx); - return rc; - } -#endif /* def BCMUSBDEV */ - return 1; - } - else - { - return 1; - } - - bcm_mdelay (WRITE_ENABLE_DELAY); - return 0; -} - -#ifdef BCMUSBDEV -#define SB_PCMCIA_READ(osh, regs, fcr) \ - R_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2) -#define SB_PCMCIA_WRITE(osh, regs, fcr, v) \ - W_REG(osh, (volatile uint8 *)(regs) + 0x600 + (fcr) - 0x700 / 2, v) - -/* set PCMCIA srom command register */ -static int -srom_cmd_sb_pcmcia (osl_t * osh, uint8 * pcmregs, uint8 cmd) -{ - uint8 status = 0; - uint wait_cnt = 0; - - /* write srom command register */ - SB_PCMCIA_WRITE (osh, pcmregs, SROM_CS, cmd); - - /* wait status */ - while (++wait_cnt < 1000000) - { - status = SB_PCMCIA_READ (osh, pcmregs, SROM_CS); - if (status & SROM_DONE) - return 0; - OSL_DELAY (1); - } - - BS_ERROR (("sr_cmd: Give up after %d tries, stat = 0x%x\n", wait_cnt, - status)); - return 1; -} - -/* read a word from the PCMCIA srom over SB */ -static int -srom_read_sb_pcmcia (osl_t * osh, uint8 * pcmregs, uint16 addr, uint16 * data) -{ - uint8 addr_l, addr_h, data_l, data_h; - - addr_l = (uint8) ((addr * 2) & 0xff); - addr_h = (uint8) (((addr * 2) >> 8) & 0xff); - - /* set address */ - SB_PCMCIA_WRITE (osh, pcmregs, SROM_ADDRH, addr_h); - SB_PCMCIA_WRITE (osh, pcmregs, SROM_ADDRL, addr_l); - - /* do read */ - if (srom_cmd_sb_pcmcia (osh, pcmregs, SROM_READ)) - return 1; - - /* read data */ - data_h = SB_PCMCIA_READ (osh, pcmregs, SROM_DATAH); - data_l = SB_PCMCIA_READ (osh, pcmregs, SROM_DATAL); - *data = ((uint16) data_h << 8) | data_l; - - return 0; -} - -/* write a word to the PCMCIA srom over SB */ -static int -srom_write_sb_pcmcia (osl_t * osh, uint8 * pcmregs, uint16 addr, uint16 data) -{ - uint8 addr_l, addr_h, data_l, data_h; - int rc; - - addr_l = (uint8) ((addr * 2) & 0xff); - addr_h = (uint8) (((addr * 2) >> 8) & 0xff); - - /* set address */ - SB_PCMCIA_WRITE (osh, pcmregs, SROM_ADDRH, addr_h); - SB_PCMCIA_WRITE (osh, pcmregs, SROM_ADDRL, addr_l); - - data_l = (uint8) (data & 0xff); - data_h = (uint8) ((data >> 8) & 0xff); - - /* write data */ - SB_PCMCIA_WRITE (osh, pcmregs, SROM_DATAH, data_h); - SB_PCMCIA_WRITE (osh, pcmregs, SROM_DATAL, data_l); - - /* do write */ - rc = srom_cmd_sb_pcmcia (osh, pcmregs, SROM_WRITE); - OSL_DELAY (20000); - return rc; -} - -/* - * Read the srom for the pcmcia-srom over sb case. - * Return 0 on success, nonzero on error. - */ -static int -get_sb_pcmcia_srom (sb_t * sbh, osl_t * osh, uint8 * pcmregs, - uint boff, uint16 * srom, uint bsz) -{ - uint i, nw, woff, wsz; - int err = 0; - - /* read must be at word boundary */ - ASSERT ((boff & 1) == 0 && (bsz & 1) == 0); - - /* read sprom size and validate the parms */ - if ((nw = srom_size (sbh, osh)) == 0) - { - BS_ERROR (("get_sb_pcmcia_srom: sprom size unknown\n")); - err = -1; - goto out; - } - if (boff + bsz > 2 * nw) - { - BS_ERROR (("get_sb_pcmcia_srom: sprom size exceeded\n")); - err = -2; - goto out; - } - - /* read in sprom contents */ - for (woff = boff / 2, wsz = bsz / 2, i = 0; - woff < nw && i < wsz; woff++, i++) - { - if (srom_read_sb_pcmcia (osh, pcmregs, (uint16) woff, &srom[i])) - { - BS_ERROR (("get_sb_pcmcia_srom: sprom read failed\n")); - err = -3; - goto out; - } - } - -out: - return err; -} - -/* - * Write the srom for the pcmcia-srom over sb case. - * Return 0 on success, nonzero on error. - */ -static int -set_sb_pcmcia_srom (sb_t * sbh, osl_t * osh, uint8 * pcmregs, - uint boff, uint16 * srom, uint bsz) -{ - uint i, nw, woff, wsz; - uint16 word; - uint8 crc; - int err = 0; - - /* write must be at word boundary */ - ASSERT ((boff & 1) == 0 && (bsz & 1) == 0); - - /* read sprom size and validate the parms */ - if ((nw = srom_size (sbh, osh)) == 0) - { - BS_ERROR (("set_sb_pcmcia_srom: sprom size unknown\n")); - err = -1; - goto out; - } - if (boff + bsz > 2 * nw) - { - BS_ERROR (("set_sb_pcmcia_srom: sprom size exceeded\n")); - err = -2; - goto out; - } - - /* enable write */ - if (srom_cmd_sb_pcmcia (osh, pcmregs, SROM_WEN)) - { - BS_ERROR (("set_sb_pcmcia_srom: sprom wen failed\n")); - err = -3; - goto out; - } - - /* write buffer to sprom */ - for (woff = boff / 2, wsz = bsz / 2, i = 0; - woff < nw && i < wsz; woff++, i++) - { - if (srom_write_sb_pcmcia (osh, pcmregs, (uint16) woff, srom[i])) - { - BS_ERROR (("set_sb_pcmcia_srom: sprom write failed\n")); - err = -4; - goto out; - } - } - - /* fix crc */ - crc = 0xff; - for (woff = 0; woff < nw; woff++) - { - if (srom_read_sb_pcmcia (osh, pcmregs, (uint16) woff, &word)) - { - BS_ERROR (("set_sb_pcmcia_srom: sprom fix crc read failed\n")); - err = -5; - goto out; - } - word = htol16 (word); - crc = hndcrc8 ((uint8 *) & word, woff != nw - 1 ? 2 : 1, crc); - } - word = (~crc << 8) + (ltoh16 (word) & 0xff); - if (srom_write_sb_pcmcia (osh, pcmregs, (uint16) (woff - 1), word)) - { - BS_ERROR (("set_sb_pcmcia_srom: sprom fix crc write failed\n")); - err = -6; - goto out; - } - - /* disable write */ - if (srom_cmd_sb_pcmcia (osh, pcmregs, SROM_WDS)) - { - BS_ERROR (("set_sb_pcmcia_srom: sprom wds failed\n")); - err = -7; - goto out; - } - -out: - return err; -} -#endif /* def BCMUSBDEV */ - -int -srom_parsecis (osl_t * osh, uint8 * pcis[], uint ciscnt, char **vars, - uint * count) -{ - char eabuf[32]; - char *base; - varbuf_t b; - uint8 *cis, tup, tlen, sromrev = 1; - int i, j; - uint varsize; - bool ag_init = FALSE; - uint32 w32; - uint funcid; - uint cisnum; - int32 boardnum = -1; - - ASSERT (vars); - ASSERT (count); - - base = MALLOC (osh, MAXSZ_NVRAM_VARS); - ASSERT (base); - if (!base) - return -2; - - varbuf_init (&b, base, MAXSZ_NVRAM_VARS); - - eabuf[0] = '\0'; - for (cisnum = 0; cisnum < ciscnt; cisnum++) - { - cis = *pcis++; - i = 0; - funcid = 0; - do - { - tup = cis[i++]; - tlen = cis[i++]; - if ((i + tlen) >= CIS_SIZE) - break; - - switch (tup) - { - case CISTPL_VERS_1: - /* assume the strings are good if the version field checks out */ - if (((cis[i + 1] << 8) + cis[i]) >= 0x0008) - { - varbuf_append (&b, "manf=%s", &cis[i + 2]); - varbuf_append (&b, "productname=%s", - &cis[i + 3 + strlen ((char *) &cis[i + 2])]); - break; - } - - case CISTPL_MANFID: - varbuf_append (&b, "manfid=0x%x", (cis[i + 1] << 8) + cis[i]); - varbuf_append (&b, "prodid=0x%x", - (cis[i + 3] << 8) + cis[i + 2]); - break; - - case CISTPL_FUNCID: - funcid = cis[i]; - break; - - case CISTPL_FUNCE: - switch (funcid) - { - default: - /* set macaddr if HNBU_MACADDR not seen yet */ - if (eabuf[0] == '\0' && cis[i] == LAN_NID) - { - ASSERT (cis[i + 1] == ETHER_ADDR_LEN); - bcm_ether_ntoa ((struct ether_addr *) &cis[i + 2], - eabuf); - } - /* set boardnum if HNBU_BOARDNUM not seen yet */ - if (boardnum == -1) - boardnum = (cis[i + 6] << 8) + cis[i + 7]; - break; - } - break; - - case CISTPL_CFTABLE: - varbuf_append (&b, "regwindowsz=%d", - (cis[i + 7] << 8) | cis[i + 6]); - break; - - case CISTPL_BRCM_HNBU: - switch (cis[i]) - { - case HNBU_SROMREV: - sromrev = cis[i + 1]; - varbuf_append (&b, "sromrev=%d", sromrev); - break; - - case HNBU_CHIPID: - varbuf_append (&b, "vendid=0x%x", (cis[i + 2] << 8) + - cis[i + 1]); - varbuf_append (&b, "devid=0x%x", (cis[i + 4] << 8) + - cis[i + 3]); - if (tlen >= 7) - { - varbuf_append (&b, "chiprev=%d", - (cis[i + 6] << 8) + cis[i + 5]); - } - if (tlen >= 9) - { - varbuf_append (&b, "subvendid=0x%x", - (cis[i + 8] << 8) + cis[i + 7]); - } - if (tlen >= 11) - { - varbuf_append (&b, "subdevid=0x%x", - (cis[i + 10] << 8) + cis[i + 9]); - /* subdevid doubles for boardtype */ - varbuf_append (&b, "boardtype=0x%x", - (cis[i + 10] << 8) + cis[i + 9]); - } - break; - - case HNBU_BOARDREV: - varbuf_append (&b, "boardrev=0x%x", cis[i + 1]); - break; - - case HNBU_AA: - varbuf_append (&b, "aa2g=%d", cis[i + 1]); - break; - - case HNBU_AG: - varbuf_append (&b, "ag0=%d", cis[i + 1]); - ag_init = TRUE; - break; - - case HNBU_ANT5G: - varbuf_append (&b, "aa5g=%d", cis[i + 1]); - varbuf_append (&b, "ag1=%d", cis[i + 2]); - break; - - case HNBU_CC: - ASSERT (sromrev == 1); - varbuf_append (&b, "cc=%d", cis[i + 1]); - break; - - case HNBU_PAPARMS: - if (tlen == 2) - { - ASSERT (sromrev == 1); - varbuf_append (&b, "pa0maxpwr=%d", cis[i + 1]); - } - else if (tlen >= 9) - { - if (tlen == 10) - { - ASSERT (sromrev >= 2); - varbuf_append (&b, "opo=%d", cis[i + 9]); - } - else - ASSERT (tlen == 9); - - for (j = 0; j < 3; j++) - { - varbuf_append (&b, "pa0b%d=%d", j, - (cis[i + (j * 2) + 2] << 8) + - cis[i + (j * 2) + 1]); - } - varbuf_append (&b, "pa0itssit=%d", cis[i + 7]); - varbuf_append (&b, "pa0maxpwr=%d", cis[i + 8]); - } - else - ASSERT (tlen >= 9); - break; - - case HNBU_PAPARMS5G: - ASSERT ((sromrev == 2) || (sromrev == 3)); - for (j = 0; j < 3; j++) - { - varbuf_append (&b, "pa1b%d=%d", j, - (cis[i + (j * 2) + 2] << 8) + - cis[i + (j * 2) + 1]); - } - for (j = 3; j < 6; j++) - { - varbuf_append (&b, "pa1lob%d=%d", j - 3, - (cis[i + (j * 2) + 2] << 8) + - cis[i + (j * 2) + 1]); - } - for (j = 6; j < 9; j++) - { - varbuf_append (&b, "pa1hib%d=%d", j - 6, - (cis[i + (j * 2) + 2] << 8) + - cis[i + (j * 2) + 1]); - } - varbuf_append (&b, "pa1itssit=%d", cis[i + 19]); - varbuf_append (&b, "pa1maxpwr=%d", cis[i + 20]); - varbuf_append (&b, "pa1lomaxpwr=%d", cis[i + 21]); - varbuf_append (&b, "pa1himaxpwr=%d", cis[i + 22]); - break; - - case HNBU_OEM: - ASSERT (sromrev == 1); - varbuf_append (&b, "oem=%02x%02x%02x%02x%02x%02x%02x%02x", - cis[i + 1], cis[i + 2], - cis[i + 3], cis[i + 4], - cis[i + 5], cis[i + 6], - cis[i + 7], cis[i + 8]); - break; - - case HNBU_BOARDFLAGS: - w32 = (cis[i + 2] << 8) + cis[i + 1]; - if (tlen == 5) - w32 |= (cis[i + 4] << 24) + (cis[i + 3] << 16); - varbuf_append (&b, "boardflags=0x%x", w32); - break; - - case HNBU_LEDS: - if (cis[i + 1] != 0xff) - { - varbuf_append (&b, "ledbh0=%d", cis[i + 1]); - } - if (cis[i + 2] != 0xff) - { - varbuf_append (&b, "ledbh1=%d", cis[i + 2]); - } - if (cis[i + 3] != 0xff) - { - varbuf_append (&b, "ledbh2=%d", cis[i + 3]); - } - if (cis[i + 4] != 0xff) - { - varbuf_append (&b, "ledbh3=%d", cis[i + 4]); - } - break; - - case HNBU_CCODE: - ASSERT (sromrev > 1); - if ((cis[i + 1] == 0) || (cis[i + 2] == 0)) - varbuf_append (&b, "ccode="); - else - varbuf_append (&b, "ccode=%c%c", cis[i + 1], cis[i + 2]); - varbuf_append (&b, "cctl=0x%x", cis[i + 3]); - break; - - case HNBU_CCKPO: - ASSERT (sromrev > 2); - varbuf_append (&b, "cckpo=0x%x", - (cis[i + 2] << 8) | cis[i + 1]); - break; - - case HNBU_OFDMPO: - ASSERT (sromrev > 2); - varbuf_append (&b, "ofdmpo=0x%x", - (cis[i + 4] << 24) | - (cis[i + 3] << 16) | - (cis[i + 2] << 8) | cis[i + 1]); - break; - - case HNBU_RDLID: - varbuf_append (&b, "rdlid=0x%x", - (cis[i + 2] << 8) | cis[i + 1]); - break; - - case HNBU_RDLRNDIS: - varbuf_append (&b, "rdlrndis=%d", cis[i + 1]); - break; - - case HNBU_RDLRWU: - varbuf_append (&b, "rdlrwu=%d", cis[i + 1]); - break; - - case HNBU_RDLSN: - varbuf_append (&b, "rdlsn=%d", - (cis[i + 2] << 8) | cis[i + 1]); - break; - - case HNBU_XTALFREQ: - varbuf_append (&b, "xtalfreq=%d", - (cis[i + 4] << 24) | - (cis[i + 3] << 16) | - (cis[i + 2] << 8) | cis[i + 1]); - break; - - case HNBU_RSSISMBXA2G: - ASSERT (sromrev == 3); - varbuf_append (&b, "rssismf2g=%d", cis[i + 1] & 0xf); - varbuf_append (&b, "rssismc2g=%d", (cis[i + 1] >> 4) & 0xf); - varbuf_append (&b, "rssisav2g=%d", cis[i + 2] & 0x7); - varbuf_append (&b, "bxa2g=%d", (cis[i + 2] >> 3) & 0x3); - break; - - case HNBU_RSSISMBXA5G: - ASSERT (sromrev == 3); - varbuf_append (&b, "rssismf5g=%d", cis[i + 1] & 0xf); - varbuf_append (&b, "rssismc5g=%d", (cis[i + 1] >> 4) & 0xf); - varbuf_append (&b, "rssisav5g=%d", cis[i + 2] & 0x7); - varbuf_append (&b, "bxa5g=%d", (cis[i + 2] >> 3) & 0x3); - break; - - case HNBU_TRI2G: - ASSERT (sromrev == 3); - varbuf_append (&b, "tri2g=%d", cis[i + 1]); - break; - - case HNBU_TRI5G: - ASSERT (sromrev == 3); - varbuf_append (&b, "tri5gl=%d", cis[i + 1]); - varbuf_append (&b, "tri5g=%d", cis[i + 2]); - varbuf_append (&b, "tri5gh=%d", cis[i + 3]); - break; - - case HNBU_RXPO2G: - ASSERT (sromrev == 3); - varbuf_append (&b, "rxpo2g=%d", cis[i + 1]); - break; - - case HNBU_RXPO5G: - ASSERT (sromrev == 3); - varbuf_append (&b, "rxpo5g=%d", cis[i + 1]); - break; - - case HNBU_BOARDNUM: - boardnum = (cis[i + 2] << 8) + cis[i + 1]; - break; - - case HNBU_MACADDR: - bcm_ether_ntoa ((struct ether_addr *) &cis[i + 1], eabuf); - break; - - case HNBU_BOARDTYPE: - varbuf_append (&b, "boardtype=0x%x", - (cis[i + 2] << 8) + cis[i + 1]); - break; - -#if defined(BCMCCISSR3) - case HNBU_SROM3SWRGN: - { - uint16 srom[35]; - uint8 srev = cis[i + 1 + 70]; - ASSERT (srev == 3); - /* make tuple value 16-bit aligned and parse it */ - bcopy (&cis[i + 1], srom, sizeof (srom)); - _initvars_srom_pci (srev, srom, SROM3_SWRGN_OFF, &b); - /* create extra variables */ - varbuf_append (&b, "vendid=0x%x", - (cis[i + 1 + 73] << 8) + cis[i + 1 + 72]); - varbuf_append (&b, "devid=0x%x", - (cis[i + 1 + 75] << 8) + cis[i + 1 + 74]); - varbuf_append (&b, "xtalfreq=%d", - (cis[i + 1 + 77] << 8) + cis[i + 1 + 76]); - /* 2.4G antenna gain is included in SROM */ - ag_init = TRUE; - /* Ethernet MAC address is included in SROM */ - eabuf[0] = 0; - boardnum = -1; - break; - } -#endif - } - break; - } - i += tlen; - } - while (tup != CISTPL_END); - } - - if (boardnum != -1) - { - varbuf_append (&b, "boardnum=%d", boardnum); - } - - if (eabuf[0]) - { - varbuf_append (&b, "macaddr=%s", eabuf); - } - - /* if there is no antenna gain field, set default */ - if (ag_init == FALSE) - { - varbuf_append (&b, "ag0=%d", 0xff); - } - - /* final nullbyte terminator */ - ASSERT (b.size >= 1); - *b.buf++ = '\0'; - varsize = (uint) (b.buf - base); - ASSERT (varsize < MAXSZ_NVRAM_VARS); - if (varsize < MAXSZ_NVRAM_VARS) - { - char *new_buf; - new_buf = (char *) MALLOC (osh, varsize); - ASSERT (new_buf); - if (new_buf) - { - bcopy (base, new_buf, varsize); - MFREE (osh, base, MAXSZ_NVRAM_VARS); - base = new_buf; - } - } - - *vars = base; - *count = varsize; - - return (0); -} - - -/* set PCMCIA sprom command register */ -static int -sprom_cmd_pcmcia (osl_t * osh, uint8 cmd) -{ - uint8 status = 0; - uint wait_cnt = 1000; - - /* write sprom command register */ - OSL_PCMCIA_WRITE_ATTR (osh, SROM_CS, &cmd, 1); - - /* wait status */ - while (wait_cnt--) - { - OSL_PCMCIA_READ_ATTR (osh, SROM_CS, &status, 1); - if (status & SROM_DONE) - return 0; - } - - return 1; -} - -/* read a word from the PCMCIA srom */ -static int -sprom_read_pcmcia (osl_t * osh, uint16 addr, uint16 * data) -{ - uint8 addr_l, addr_h, data_l, data_h; - - addr_l = (uint8) ((addr * 2) & 0xff); - addr_h = (uint8) (((addr * 2) >> 8) & 0xff); - - /* set address */ - OSL_PCMCIA_WRITE_ATTR (osh, SROM_ADDRH, &addr_h, 1); - OSL_PCMCIA_WRITE_ATTR (osh, SROM_ADDRL, &addr_l, 1); - - /* do read */ - if (sprom_cmd_pcmcia (osh, SROM_READ)) - return 1; - - /* read data */ - data_h = data_l = 0; - OSL_PCMCIA_READ_ATTR (osh, SROM_DATAH, &data_h, 1); - OSL_PCMCIA_READ_ATTR (osh, SROM_DATAL, &data_l, 1); - - *data = (data_h << 8) | data_l; - return 0; -} - -/* write a word to the PCMCIA srom */ -static int -sprom_write_pcmcia (osl_t * osh, uint16 addr, uint16 data) -{ - uint8 addr_l, addr_h, data_l, data_h; - - addr_l = (uint8) ((addr * 2) & 0xff); - addr_h = (uint8) (((addr * 2) >> 8) & 0xff); - data_l = (uint8) (data & 0xff); - data_h = (uint8) ((data >> 8) & 0xff); - - /* set address */ - OSL_PCMCIA_WRITE_ATTR (osh, SROM_ADDRH, &addr_h, 1); - OSL_PCMCIA_WRITE_ATTR (osh, SROM_ADDRL, &addr_l, 1); - - /* write data */ - OSL_PCMCIA_WRITE_ATTR (osh, SROM_DATAH, &data_h, 1); - OSL_PCMCIA_WRITE_ATTR (osh, SROM_DATAL, &data_l, 1); - - /* do write */ - return sprom_cmd_pcmcia (osh, SROM_WRITE); -} - -/* - * Read in and validate sprom. - * Return 0 on success, nonzero on error. - */ -static int -sprom_read_pci (osl_t * osh, uint16 * sprom, uint wordoff, uint16 * buf, - uint nwords, bool check_crc) -{ - int err = 0; - uint i; - - /* read the sprom */ - for (i = 0; i < nwords; i++) - { -#ifdef BCMQT - buf[i] = R_REG (osh, &sprom[wordoff + i]); -#endif - buf[i] = R_REG (osh, &sprom[wordoff + i]); - } - - if (check_crc) - { - if (buf[0] == 0xffff) - { - /* The hardware thinks that an srom that starts with 0xffff - * is blank, regardless of the rest of the content, so declare - * it bad. - */ - BS_ERROR (("%s: buf[0] = 0x%x, returning bad-crc\n", __FUNCTION__, - buf[0])); - return 1; - } - - /* fixup the endianness so crc8 will pass */ - htol16_buf (buf, nwords * 2); - if (hndcrc8 ((uint8 *) buf, nwords * 2, 0xff) != 0x9f) - err = 1; - /* now correct the endianness of the byte array */ - ltoh16_buf (buf, nwords * 2); - } - - return err; -} - -/* -* Create variable table from memory. -* Return 0 on success, nonzero on error. -*/ -static int -BCMINITFN (initvars_table) (osl_t * osh, char *start, char *end, char **vars, - uint * count) -{ - int c = (int) (end - start); - - /* do it only when there is more than just the null string */ - if (c > 1) - { - char *vp = MALLOC (osh, c); - ASSERT (vp); - if (!vp) - return BCME_NOMEM; - bcopy (start, vp, c); - *vars = vp; - *count = c; - } - else - { - *vars = NULL; - *count = 0; - } - - return 0; -} - -/* - * Find variables with <devpath> from flash. 'base' points to the beginning - * of the table upon enter and to the end of the table upon exit when success. - * Return 0 on success, nonzero on error. - */ -static int -initvars_flash (sb_t * sbh, osl_t * osh, char **base, uint len) -{ - char *vp = *base; - char *flash; - int err; - char *s; - uint l, dl, copy_len; - char devpath[SB_DEVPATH_BUFSZ]; - - /* allocate memory and read in flash */ - if (!(flash = MALLOC (osh, NVRAM_SPACE))) - return BCME_NOMEM; - if ((err = nvram_getall (flash, NVRAM_SPACE))) - goto exit; - - sb_devpath (sbh, devpath, sizeof (devpath)); - - /* grab vars with the <devpath> prefix in name */ - dl = strlen (devpath); - for (s = flash; s && *s; s += l + 1) - { - l = strlen (s); - - /* skip non-matching variable */ - if (strncmp (s, devpath, dl)) - continue; - - /* is there enough room to copy? */ - copy_len = l - dl + 1; - if (len < copy_len) - { - err = BCME_BUFTOOSHORT; - goto exit; - } - - /* no prefix, just the name=value */ - strncpy (vp, &s[dl], copy_len); - vp += copy_len; - len -= copy_len; - } - - /* add null string as terminator */ - if (len < 1) - { - err = BCME_BUFTOOSHORT; - goto exit; - } - *vp++ = '\0'; - - *base = vp; - -exit:MFREE (osh, flash, NVRAM_SPACE); - return err; -} - -#if !defined(BCMUSBDEV) && !defined(BCMSDIODEV) -/* - * Initialize nonvolatile variable table from flash. - * Return 0 on success, nonzero on error. - */ -static int -initvars_flash_sb (sb_t * sbh, char **vars, uint * count) -{ - osl_t *osh = sb_osh (sbh); - char *vp, *base; - int err; - - ASSERT (vars); - ASSERT (count); - - base = vp = MALLOC (osh, MAXSZ_NVRAM_VARS); - ASSERT (vp); - if (!vp) - return BCME_NOMEM; - - if ((err = initvars_flash (sbh, osh, &vp, MAXSZ_NVRAM_VARS)) == 0) - err = initvars_table (osh, base, vp, vars, count); - - MFREE (osh, base, MAXSZ_NVRAM_VARS); - - return err; -} -#endif /* !BCMUSBDEV && !BCMSDIODEV */ - -#ifdef WLTEST -char mfgsromvars[256]; -char *defaultsromvars = "il0macaddr=00:11:22:33:44:51\0" - "et0macaddr=00:11:22:33:44:52\0" - "et1macaddr=00:11:22:33:44:53\0" - "boardtype=0xffff\0" - "boardrev=0x10\0" "boardflags=8\0" "sromrev=2\0" "aa2g=3\0" "\0"; -#define MFGSROM_DEFVARSLEN 149 /* default srom len */ -#endif /* WL_TEST */ - -/* - * Initialize nonvolatile variable table from sprom. - * Return 0 on success, nonzero on error. - */ - -typedef struct -{ - const char *name; - uint32 revmask; - uint32 flags; - uint16 off; - uint16 mask; -} sromvar_t; - -#define SRFL_MORE 1 /* value continues as described by the next entry */ -#define SRFL_NOFFS 2 /* value bits can't be all one's */ -#define SRFL_PRHEX 4 /* value is in hexdecimal format */ -#define SRFL_PRSIGN 8 /* value is in signed decimal format */ -#define SRFL_CCODE 0x10 /* value is in country code format */ -#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ -#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ - -/* Assumptions: - * - Ethernet address spins across 3 consective words - * - * Table rules: - * - Add multiple entries next to each other if a value spins across multiple words - * (even multiple fields in the same word) with each entry except the last having - * it's SRFL_MORE bit set. - * - Ethernet address entry does not follow above rule and must not have SRFL_MORE - * bit set. Its SRFL_ETHADDR bit implies it takes multiple words. - * - The last entry's name field must be NULL to indicate the end of the table. Other - * entries must have non-NULL name. - */ - -static const sromvar_t pci_sromvars[] = { - {"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK}, - {"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff}, - {"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, - {"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff}, - {"boardflags", 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff}, - {"", 0, 0, SROM_BFL2, 0xffff}, - {"boardflags", 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff}, - {"", 0, 0, SROM3_BFL2, 0xffff}, - {"boardflags", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, 0xffff}, - {"", 0, 0, SROM4_BFL1, 0xffff}, - {"boardflags", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, 0xffff}, - {"", 0, 0, SROM5_BFL1, 0xffff}, - {"boardflags", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, 0xffff}, - {"", 0, 0, SROM8_BFL1, 0xffff}, - {"boardflags2", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, 0xffff}, - {"", 0, 0, SROM4_BFL3, 0xffff}, - {"boardflags2", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, 0xffff}, - {"", 0, 0, SROM5_BFL3, 0xffff}, - {"boardflags2", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, 0xffff}, - {"", 0, 0, SROM8_BFL3, 0xffff}, - {"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, - {"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff}, - {"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff}, - {"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff}, - {"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff}, - {"boardnum", 0xffffff00, 0, SROM8_MACLO, 0xffff}, - {"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK}, - {"regrev", 0x00000008, 0, SROM_OPO, 0xff00}, - {"regrev", 0x00000010, 0, SROM4_REGREV, 0xff}, - {"regrev", 0x000000e0, 0, SROM5_REGREV, 0xff}, - {"regrev", 0xffffff00, 0, SROM8_REGREV, 0xff}, - {"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff}, - {"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00}, - {"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff}, - {"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00}, - {"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff}, - {"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00}, - {"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff}, - {"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00}, - {"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff}, - {"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00}, - {"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff}, - {"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00}, - {"ledbh0", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff}, - {"ledbh1", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, - {"ledbh2", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff}, - {"ledbh3", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, - {"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff}, - {"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff}, - {"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff}, - {"pa0itssit", 0x0000000e, 0, SROM_ITT, 0xff}, - {"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff}, - {"pa0b0", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, - {"pa0b1", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, - {"pa0b2", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, - {"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00}, - {"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff}, - {"opo", 0x0000000c, 0, SROM_OPO, 0xff}, - {"opo", 0xffffff00, 0, SROM8_2G_OFDMPO, 0xff}, - {"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK}, - {"aa2g", 0x000000f0, 0, SROM4_AA, 0xff}, - {"aa2g", 0xffffff00, 0, SROM8_AA, 0xff}, - {"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK}, - {"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00}, - {"aa5g", 0xffffff00, 0, SROM8_AA, 0xff00}, - {"ag0", 0x0000000e, 0, SROM_AG10, 0xff}, - {"ag1", 0x0000000e, 0, SROM_AG10, 0xff00}, - {"ag0", 0x000000f0, 0, SROM4_AG10, 0xff}, - {"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00}, - {"ag2", 0x000000f0, 0, SROM4_AG32, 0xff}, - {"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00}, - {"ag0", 0xffffff00, 0, SROM8_AG10, 0xff}, - {"ag1", 0xffffff00, 0, SROM8_AG10, 0xff00}, - {"ag2", 0xffffff00, 0, SROM8_AG32, 0xff}, - {"ag3", 0xffffff00, 0, SROM8_AG32, 0xff00}, - {"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff}, - {"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff}, - {"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff}, - {"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff}, - {"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff}, - {"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff}, - {"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff}, - {"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff}, - {"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff}, - {"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00}, - {"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00}, - {"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00}, - {"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff}, - {"pa1b0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, - {"pa1b1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, - {"pa1b2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, - {"pa1lob0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff}, - {"pa1lob1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff}, - {"pa1lob2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff}, - {"pa1hib0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff}, - {"pa1hib1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff}, - {"pa1hib2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff}, - {"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00}, - {"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff}, - {"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00}, - {"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff}, - {"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800}, - {"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700}, - {"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0}, - {"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f}, - {"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800}, - {"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700}, - {"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0}, - {"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f}, - {"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800}, - {"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700}, - {"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0}, - {"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f}, - {"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800}, - {"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700}, - {"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0}, - {"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f}, - {"tri2g", 0x00000008, 0, SROM_TRI52G, 0xff}, - {"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00}, - {"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0xff}, - {"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00}, - {"tri2g", 0xffffff00, 0, SROM8_TRI52G, 0xff}, - {"tri5g", 0xffffff00, 0, SROM8_TRI52G, 0xff00}, - {"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL, 0xff}, - {"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL, 0xff00}, - {"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff}, - {"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00}, - {"rxpo2g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff}, - {"rxpo5g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, - {"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK}, - {"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK}, - {"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK}, - {"txchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK}, - {"rxchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK}, - {"antswitch", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK}, - {"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0xff}, - {"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00}, - {"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff}, - {"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00}, - {"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0xff}, - {"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00}, - {"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff}, - {"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00}, - {"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0xff}, - {"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00}, - {"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff}, - {"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00}, - {"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0xff}, - {"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00}, - {"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff}, - {"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00}, - {"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff}, - {"cck2gpo", 0xffffff00, 0, SROM8_2G_CCKPO, 0xffff}, - {"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff}, - {"", 0, 0, SROM4_2G_OFDMPO + 1, 0xffff}, - {"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff}, - {"", 0, 0, SROM4_5G_OFDMPO + 1, 0xffff}, - {"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff}, - {"", 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff}, - {"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff}, - {"", 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff}, - {"ofdm2gpo", 0xffffff00, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, - {"", 0, 0, SROM8_2G_OFDMPO + 1, 0xffff}, - {"ofdm5gpo", 0xffffff00, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, - {"", 0, 0, SROM8_5G_OFDMPO + 1, 0xffff}, - {"ofdm5glpo", 0xffffff00, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff}, - {"", 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff}, - {"ofdm5ghpo", 0xffffff00, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, - {"", 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff}, - {"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff}, - {"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff}, - {"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff}, - {"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff}, - {"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff}, - {"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff}, - {"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff}, - {"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff}, - {"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff}, - {"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff}, - {"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff}, - {"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff}, - {"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff}, - {"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff}, - {"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff}, - {"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff}, - {"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff}, - {"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff}, - {"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff}, - {"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff}, - {"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff}, - {"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff}, - {"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff}, - {"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff}, - {"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff}, - {"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff}, - {"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff}, - {"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff}, - {"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff}, - {"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff}, - {"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff}, - {"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff}, - {"mcs2gpo0", 0xffffff00, 0, SROM8_2G_MCSPO, 0xffff}, - {"mcs2gpo1", 0xffffff00, 0, SROM8_2G_MCSPO + 1, 0xffff}, - {"mcs2gpo2", 0xffffff00, 0, SROM8_2G_MCSPO + 2, 0xffff}, - {"mcs2gpo3", 0xffffff00, 0, SROM8_2G_MCSPO + 3, 0xffff}, - {"mcs2gpo4", 0xffffff00, 0, SROM8_2G_MCSPO + 4, 0xffff}, - {"mcs2gpo5", 0xffffff00, 0, SROM8_2G_MCSPO + 5, 0xffff}, - {"mcs2gpo6", 0xffffff00, 0, SROM8_2G_MCSPO + 6, 0xffff}, - {"mcs2gpo7", 0xffffff00, 0, SROM8_2G_MCSPO + 7, 0xffff}, - {"mcs5gpo0", 0xffffff00, 0, SROM8_5G_MCSPO, 0xffff}, - {"mcs5gpo1", 0xffffff00, 0, SROM8_5G_MCSPO + 1, 0xffff}, - {"mcs5gpo2", 0xffffff00, 0, SROM8_5G_MCSPO + 2, 0xffff}, - {"mcs5gpo3", 0xffffff00, 0, SROM8_5G_MCSPO + 3, 0xffff}, - {"mcs5gpo4", 0xffffff00, 0, SROM8_5G_MCSPO + 4, 0xffff}, - {"mcs5gpo5", 0xffffff00, 0, SROM8_5G_MCSPO + 5, 0xffff}, - {"mcs5gpo6", 0xffffff00, 0, SROM8_5G_MCSPO + 6, 0xffff}, - {"mcs5gpo7", 0xffffff00, 0, SROM8_5G_MCSPO + 7, 0xffff}, - {"mcs5glpo0", 0xffffff00, 0, SROM8_5GL_MCSPO, 0xffff}, - {"mcs5glpo1", 0xffffff00, 0, SROM8_5GL_MCSPO + 1, 0xffff}, - {"mcs5glpo2", 0xffffff00, 0, SROM8_5GL_MCSPO + 2, 0xffff}, - {"mcs5glpo3", 0xffffff00, 0, SROM8_5GL_MCSPO + 3, 0xffff}, - {"mcs5glpo4", 0xffffff00, 0, SROM8_5GL_MCSPO + 4, 0xffff}, - {"mcs5glpo5", 0xffffff00, 0, SROM8_5GL_MCSPO + 5, 0xffff}, - {"mcs5glpo6", 0xffffff00, 0, SROM8_5GL_MCSPO + 6, 0xffff}, - {"mcs5glpo7", 0xffffff00, 0, SROM8_5GL_MCSPO + 7, 0xffff}, - {"mcs5ghpo0", 0xffffff00, 0, SROM8_5GH_MCSPO, 0xffff}, - {"mcs5ghpo1", 0xffffff00, 0, SROM8_5GH_MCSPO + 1, 0xffff}, - {"mcs5ghpo2", 0xffffff00, 0, SROM8_5GH_MCSPO + 2, 0xffff}, - {"mcs5ghpo3", 0xffffff00, 0, SROM8_5GH_MCSPO + 3, 0xffff}, - {"mcs5ghpo4", 0xffffff00, 0, SROM8_5GH_MCSPO + 4, 0xffff}, - {"mcs5ghpo5", 0xffffff00, 0, SROM8_5GH_MCSPO + 5, 0xffff}, - {"mcs5ghpo6", 0xffffff00, 0, SROM8_5GH_MCSPO + 6, 0xffff}, - {"mcs5ghpo7", 0xffffff00, 0, SROM8_5GH_MCSPO + 7, 0xffff}, - {"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff}, - {"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff}, - {"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff}, - {"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff}, - {"cddpo", 0xffffff00, 0, SROM8_CDDPO, 0xffff}, - {"stbcpo", 0xffffff00, 0, SROM8_STBCPO, 0xffff}, - {"bw40po", 0xffffff00, 0, SROM8_BW40PO, 0xffff}, - {"bwduppo", 0xffffff00, 0, SROM8_BWDUPPO, 0xffff}, - {"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff}, - {"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff}, - {"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff}, - {"ccode", 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff}, - {"macaddr", 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, - {"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff}, - {"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff}, - {"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff}, - {"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff}, - {"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff}, - {"leddc", 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, 0xffff}, - {"leddc", 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, 0xffff}, - {"leddc", 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, 0xffff}, - {"leddc", 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, 0xffff}, - {NULL, 0, 0, 0, 0} -}; - -static const sromvar_t perpath_pci_sromvars[] = { - {"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff}, - {"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00}, - {"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00}, - {"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff}, - {"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff}, - {"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff}, - {"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff}, - {"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff}, - {"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff}, - {"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00}, - {"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff}, - {"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff}, - {"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff}, - {"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff}, - {"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff}, - {"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, 0xffff}, - {"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, 0xffff}, - {"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, 0xffff}, - {"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff}, - {"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, 0xffff}, - {"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, 0xffff}, - {"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, 0xffff}, - {"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff}, - {"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00}, - {"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00}, - {"pa2gw0a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff}, - {"pa2gw1a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff}, - {"pa2gw2a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff}, - {"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff}, - {"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff}, - {"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00}, - {"pa5gw0a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff}, - {"pa5gw1a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff}, - {"pa5gw2a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff}, - {"pa5glw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff}, - {"pa5glw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, 0xffff}, - {"pa5glw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, 0xffff}, - {"pa5ghw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff}, - {"pa5ghw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, 0xffff}, - {"pa5ghw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, 0xffff}, - {NULL, 0, 0, 0, 0} -}; - -/* Parse SROM and create name=value pairs. 'srom' points to - * the SROM word array. 'off' specifies the offset of the - * first word 'srom' points to, which should be either 0 or - * SROM3_SWRG_OFF (full SROM or software region). - */ - -static uint -mask_shift (uint16 mask) -{ - uint i; - for (i = 0; i < (sizeof (mask) << 3); i++) - { - if (mask & (1 << i)) - return i; - } - ASSERT (mask); - return 0; -} - -static uint -mask_width (uint16 mask) -{ - int i; - for (i = (sizeof (mask) << 3) - 1; i >= 0; i--) - { - if (mask & (1 << i)) - return (uint) (i - mask_shift (mask) + 1); - } - ASSERT (mask); - return 0; -} - -#ifdef BCMDBG_ASSERT -static bool -mask_valid (uint16 mask) -{ - uint shift = mask_shift (mask); - uint width = mask_width (mask); - return mask == ((~0 << shift) & ~(~0 << (shift + width))); -} -#endif - -static void -_initvars_srom_pci (uint8 sromrev, uint16 * srom, uint off, varbuf_t * b) -{ - uint16 w; - uint32 val; - const sromvar_t *srv; - uint width; - uint flags; - uint32 sr = (1 << sromrev); - - varbuf_append (b, "sromrev=%d", sromrev); - - for (srv = pci_sromvars; srv->name != NULL; srv++) - { - const char *name; - - if ((srv->revmask & sr) == 0) - continue; - - if (srv->off < off) - continue; - - flags = srv->flags; - name = srv->name; - - if (flags & SRFL_ETHADDR) - { - char eabuf[ETHER_ADDR_STR_LEN]; - struct ether_addr ea; - - ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff; - ea.octet[1] = srom[srv->off - off] & 0xff; - ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff; - ea.octet[3] = srom[srv->off + 1 - off] & 0xff; - ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff; - ea.octet[5] = srom[srv->off + 2 - off] & 0xff; - bcm_ether_ntoa (&ea, eabuf); - - varbuf_append (b, "%s=%s", name, eabuf); - } - else - { - ASSERT (mask_valid (srv->mask)); - ASSERT (mask_width (srv->mask)); - - w = srom[srv->off - off]; - val = (w & srv->mask) >> mask_shift (srv->mask); - width = mask_width (srv->mask); - - while (srv->flags & SRFL_MORE) - { - srv++; - ASSERT (srv->name); - - if (srv->off == 0 || srv->off < off) - continue; - - ASSERT (mask_valid (srv->mask)); - ASSERT (mask_width (srv->mask)); - - w = srom[srv->off - off]; - val += ((w & srv->mask) >> mask_shift (srv->mask)) << width; - width += mask_width (srv->mask); - } - - if ((flags & SRFL_NOFFS) && ((int) val == (1 << width) - 1)) - continue; - - if (flags & SRFL_CCODE) - { - if (val == 0) - varbuf_append (b, "ccode="); - else - varbuf_append (b, "ccode=%c%c", (val >> 8), (val & 0xff)); - } - /* LED Powersave duty cycle has to be scaled: - *(oncount >> 24) (offcount >> 8) - */ - else if (flags & SRFL_LEDDC) - { - uint32 w32 = (((val >> 8) & 0xff) << 24) | /* oncount */ - (((val & 0xff)) << 8); /* offcount */ - varbuf_append (b, "leddc=%d", w32); - } - else if (flags & SRFL_PRHEX) - varbuf_append (b, "%s=0x%x", name, val); - else if ((flags & SRFL_PRSIGN) && (val & (1 << (width - 1)))) - varbuf_append (b, "%s=%d", name, (int) (val | (~0 << width))); - else - varbuf_append (b, "%s=%u", name, val); - } - } - - if (sromrev >= 4) - { - /* Do per-path variables */ - uint p, pb, psz; - - if (sromrev >= 8) - { - pb = SROM8_PATH0; - psz = SROM8_PATH1 - SROM8_PATH0; - } - else - { - pb = SROM4_PATH0; - psz = SROM4_PATH1 - SROM4_PATH0; - } - - for (p = 0; p < MAX_PATH; p++) - { - for (srv = perpath_pci_sromvars; srv->name != NULL; srv++) - { - if ((srv->revmask & sr) == 0) - continue; - - if (pb + srv->off < off) - continue; - - w = srom[pb + srv->off - off]; - ASSERT (mask_valid (srv->mask)); - val = (w & srv->mask) >> mask_shift (srv->mask); - width = mask_width (srv->mask); - - /* Cheating: no per-path var is more than 1 word */ - - if ((srv->flags & SRFL_NOFFS) - && ((int) val == (1 << width) - 1)) - continue; - - if (srv->flags & SRFL_PRHEX) - varbuf_append (b, "%s%d=0x%x", srv->name, p, val); - else - varbuf_append (b, "%s%d=%d", srv->name, p, val); - } - pb += psz; - } - } -} - -static int -initvars_srom_pci (sb_t * sbh, void *curmap, char **vars, uint * count) -{ - uint16 *srom; - uint8 sromrev = 0; - uint32 sr; - varbuf_t b; - char *vp, *base = NULL; - osl_t *osh = sb_osh (sbh); - bool flash = FALSE; - char *value; - int err; - - /* - * Apply CRC over SROM content regardless SROM is present or not, - * and use variable <devpath>sromrev's existance in flash to decide - * if we should return an error when CRC fails or read SROM variables - * from flash. - */ - srom = MALLOC (osh, SROM_MAX); - ASSERT (srom); - if (!srom) - return -2; - - err = - sprom_read_pci (osh, (void *) ((int8 *) curmap + PCI_BAR0_SPROM_OFFSET), - 0, srom, SROM_WORDS, TRUE); - - if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || - ((sbh->buscoretype == SB_PCIE) && (sbh->buscorerev >= 6))) - { - /* sromrev >= 4, read more */ - err = - sprom_read_pci (osh, - (void *) ((int8 *) curmap + PCI_BAR0_SPROM_OFFSET), 0, - srom, SROM4_WORDS, TRUE); - sromrev = srom[SROM4_CRCREV] & 0xff; - } - else if (err == 0) - { - /* srom is good and is rev < 4 */ - /* top word of sprom contains version and crc8 */ - sromrev = srom[SROM_CRCREV] & 0xff; - /* bcm4401 sroms misprogrammed */ - if (sromrev == 0x10) - sromrev = 1; - } - - if (err) - { -#ifdef WLTEST - uint32 val; - - BS_ERROR (("SROM Crc Error, so see if we could use a default\n")); - val = OSL_PCI_READ_CONFIG (osh, PCI_SPROM_CONTROL, sizeof (uint32)); - if (val & SPROM_OTPIN_USE) - { - BS_ERROR (("srom crc failed with OTP, use default vars....\n")); - vp = base = mfgsromvars; - if (sb_chip (sbh) == BCM4311_CHIP_ID) - { - const char *devid = "devid=0x4311"; - const size_t devid_strlen = strlen (devid); - BS_ERROR (("setting the devid to be 4311\n")); - bcopy (devid, vp, devid_strlen + 1); - vp += devid_strlen + 1; - } - bcopy (defaultsromvars, vp, MFGSROM_DEFVARSLEN); - vp += MFGSROM_DEFVARSLEN; - goto varsdone; - } - else - { -#endif /* WLTEST */ - BS_ERROR (("srom crc failed with SPROM....\n")); - if (!(value = sb_getdevpathvar (sbh, "sromrev"))) - { - err = -1; - goto errout; - } - sromrev = (uint8) simple_strtoul (value, NULL, 0); - flash = TRUE; -#ifdef WLTEST - } -#endif /* WLTEST */ - } - - /* Bitmask for the sromrev */ - sr = 1 << sromrev; - - /* srom version check - * Current valid versions: 1, 2, 3, 4, 5, 8 - */ - if ((sr & 0x13e) == 0) - { - err = -2; - goto errout; - } - - ASSERT (vars); - ASSERT (count); - - base = vp = MALLOC (osh, MAXSZ_NVRAM_VARS); - ASSERT (vp); - if (!vp) - { - err = -2; - goto errout; - } - - /* read variables from flash */ - if (flash) - { - if ((err = initvars_flash (sbh, osh, &vp, MAXSZ_NVRAM_VARS))) - goto errout; - goto varsdone; - } - - varbuf_init (&b, base, MAXSZ_NVRAM_VARS); - - /* parse SROM into name=value pairs. */ - _initvars_srom_pci (sromrev, srom, 0, &b); - - /* final nullbyte terminator */ - ASSERT (b.size >= 1); - vp = b.buf; - *vp++ = '\0'; - - ASSERT ((vp - base) <= MAXSZ_NVRAM_VARS); - -varsdone: - err = initvars_table (osh, base, vp, vars, count); - -errout: -#ifdef WLTEST - if (base && (base != mfgsromvars)) -#else - if (base) -#endif - MFREE (osh, base, MAXSZ_NVRAM_VARS); - - MFREE (osh, srom, SROM_MAX); - return err; -} - -/* - * Read the cis and call parsecis to initialize the vars. - * Return 0 on success, nonzero on error. - */ -static int -initvars_cis_pcmcia (sb_t * sbh, osl_t * osh, char **vars, uint * count) -{ - uint8 *cis = NULL; - int rc; - uint data_sz; - - data_sz = (sb_pcmciarev (sbh) == 1) ? (SPROM_SIZE * 2) : CIS_SIZE; - - if ((cis = MALLOC (osh, data_sz)) == NULL) - return (-2); - - if (sb_pcmciarev (sbh) == 1) - { - if (srom_read - (sbh, PCMCIA_BUS, (void *) NULL, osh, 0, data_sz, (uint16 *) cis)) - { - MFREE (osh, cis, data_sz); - return (-1); - } - /* fix up endianess for 16-bit data vs 8-bit parsing */ - htol16_buf ((uint16 *) cis, data_sz); - } - else - OSL_PCMCIA_READ_ATTR (osh, 0, cis, data_sz); - - rc = srom_parsecis (osh, &cis, 1, vars, count); - - MFREE (osh, cis, data_sz); - - return (rc); -} - - -static int -BCMINITFN (initvars_srom_sb) (sb_t * sbh, osl_t * osh, void *curmap, - char **vars, uint * varsz) -{ -#if defined(BCMSDIODEV) - /* CIS is read and supplied by the host */ - return BCME_OK; -#elif defined(BCMUSBDEV) - static bool srvars = FALSE; /* Use OTP/SPROM as global variables */ - - int sel = 0; /* where to read the srom. 0 - nowhere, 1 - otp, 2 - sprom */ - uint sz = 0; /* srom size in bytes */ - void *oh = NULL; - int rc = BCME_OK; - - /* Bail out if we've dealt with OTP/SPROM before! */ - if (srvars) - return 0; - -#if defined(BCM4328) - if (sbh->chip == BCM4328_CHIP_ID) - { - /* Access the SPROM if it is present */ - if ((sz = srom_size (sbh, osh)) != 0) - { - sz <<= 1; - sel = 2; - } - } -#endif -#if defined(BCM4325) - if (sbh->chip == BCM4325_CHIP_ID) - { - uint32 cst = sbh->chipst & CST4325_SPROM_OTP_SEL_MASK; - - /* Access OTP if it is present, powered on, and programmed */ - if ((oh = otp_init (sbh)) != NULL && (otp_status (oh) & OTPS_GUP_SW)) - { - sz = otp_size (oh); - sel = 1; - } - /* Access the SPROM if it is present and allow to be accessed */ - else if ((cst == CST4325_OTP_PWRDN || cst == CST4325_SPROM_SEL) && - (sz = srom_size (sbh, osh)) != 0) - { - sz <<= 1; - sel = 2; - } - } -#endif /* BCM4325 */ - - /* Read CIS in OTP/SPROM */ - if (sel != 0) - { - uint16 *srom; - uint8 *body = NULL; - - ASSERT (sz); - - /* Allocate memory */ - if ((srom = (uint16 *) MALLOC (osh, sz)) == NULL) - return BCME_NOMEM; - - /* Read CIS */ - switch (sel) - { - case 1: - rc = otp_read_region (oh, OTP_SW_RGN, srom, sz); - body = (uint8 *) srom; - break; - case 2: - rc = srom_read (sbh, SB_BUS, curmap, osh, 0, sz, srom); - /* sprom has 8 byte h/w header */ - body = (uint8 *) srom + SBSDIO_SPROM_CIS_OFFSET; - break; - default: - /* impossible to come here */ - ASSERT (0); - break; - } - - /* Parse CIS */ - if (rc == BCME_OK) - { - uint i, tpls = 0xffffffff; - /* # sdiod fns + common + extra */ - uint8 *cis[SBSDIO_NUM_FUNCTION + 2]; - uint ciss = 0; - - /* each word is in host endian */ - htol16_buf ((uint8 *) srom, sz); - - ASSERT (body); - - /* count cis tuple chains */ - for (i = 0; i < sz && ciss < ARRAYSIZE (cis) && tpls != 0; i++) - { - cis[ciss++] = &body[i]; - for (tpls = 0; i < sz - 1; tpls++) - { - if (body[i++] == CISTPL_END) - break; - i += body[i] + 1; - } - } - - /* call parser routine only when there are tuple chains */ - if (ciss > 1) - rc = srom_parsecis (osh, cis, ciss, vars, varsz); - } - - /* Clean up */ - MFREE (osh, srom, sz); - - /* Make SROM variables global */ - if (rc == BCME_OK) - { - rc = nvram_append ((void *) sbh, *vars, *varsz); - srvars = TRUE; - - /* Tell the caller there is no individual SROM variables */ - *vars = NULL; - *varsz = 0; - } - } - - return rc; -#else /* !BCMUSBDEV && !BCMSDIODEV */ - /* Search flash nvram section for srom variables */ - return initvars_flash_sb (sbh, vars, varsz); -#endif /* !BCMUSBDEV && !BCMSDIODEV */ -} - -#ifdef BCMUSBDEV -/* Return sprom size in 16-bit words */ -static uint -srom_size (sb_t * sbh, osl_t * osh) -{ - uint size = 0; - if (SPROMBUS == PCMCIA_BUS) - { - uint32 origidx; - sdpcmd_regs_t *pcmregs; - bool wasup; - - origidx = sb_coreidx (sbh); - pcmregs = sb_setcore (sbh, SB_PCMCIA, 0); - ASSERT (pcmregs); - - if (!(wasup = sb_iscoreup (sbh))) - sb_core_reset (sbh, 0, 0); - - /* not worry about earlier core revs */ - if (sb_corerev (sbh) < 8) - goto done; - - /* SPROM is accessible only in PCMCIA mode unless there is SDIO clock */ - if (!(R_REG (osh, &pcmregs->corestatus) & CS_PCMCIAMODE)) - goto done; - - switch (SB_PCMCIA_READ (osh, pcmregs, SROM_INFO) & SRI_SZ_MASK) - { - case 1: - size = 256; /* SROM_INFO == 1 means 4kbit */ - break; - case 2: - size = 1024; /* SROM_INFO == 2 means 16kbit */ - break; - default: - break; - } - - done: - if (!wasup) - sb_core_disable (sbh, 0); - - sb_setcoreidx (sbh, origidx); - } - return size; -} -#endif /* def BCMUSBDEV */ |