| /* |
| * Routines to access SPROM and to parse SROM/CIS variables. |
| * |
| * Despite its file name, OTP contents is also parsed in this file. |
| * |
| * Copyright (C) 2021, Broadcom. |
| * |
| * Unless you and Broadcom execute a separate written software license |
| * agreement governing use of this software, this software is licensed to you |
| * under the terms of the GNU General Public License version 2 (the "GPL"), |
| * available at http://www.broadcom.com/licenses/GPLv2.php, with the |
| * following added to such license: |
| * |
| * As a special exception, the copyright holders of this software give you |
| * permission to link this software with independent modules, and to copy and |
| * distribute the resulting executable under terms of your choice, provided that |
| * you also meet, for each linked independent module, the terms and conditions of |
| * the license of that module. An independent module is a module which is not |
| * derived from this software. The special exception does not apply to any |
| * modifications of the software. |
| * |
| * |
| * <<Broadcom-WL-IPTag/Dual:>> |
| */ |
| |
| /* |
| * List of non obvious preprocessor defines used in this file and their meaning: |
| * DONGLEBUILD : building firmware that runs on the dongle's CPU |
| * BCM_DONGLEVARS : NVRAM variables can be read from OTP/S(P)ROM. |
| * When host may supply nvram vars in addition to the ones in OTP/SROM: |
| * BCMHOSTVARS : full nic / full dongle |
| * BCMDONGLEHOST : defined when building DHD, code executes on the host in a dongle environment. |
| * DHD_SPROM : defined when building a DHD that supports reading/writing to SPROM |
| */ |
| |
| #include <typedefs.h> |
| #include <bcmdefs.h> |
| #include <osl.h> |
| #include <stdarg.h> |
| #include <bcmutils.h> |
| #include <hndsoc.h> |
| #include <sbchipc.h> |
| #include <bcmdevs.h> |
| #include <bcmendian.h> |
| #include <sbpcmcia.h> |
| #include <pcicfg.h> |
| #include <siutils.h> |
| #include <bcmsrom.h> |
| #include <bcmsrom_tbl.h> |
| #ifdef BCMSDIO |
| #include <bcmsdh.h> |
| #include <sdio.h> |
| #endif |
| #ifdef BCMSPI |
| #include <spid.h> |
| #endif |
| |
| #include <bcmnvram.h> |
| #include <bcmotp.h> |
| #ifndef BCMUSBDEV_COMPOSITE |
| #define BCMUSBDEV_COMPOSITE |
| #endif |
| #if defined(BCMUSBDEV) || defined(BCMSDIO) || defined(BCMSDIODEV) |
| #include <sbsdio.h> |
| #include <sbhnddma.h> |
| #include <sbsdpcmdev.h> |
| #endif |
| |
| #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) |
| #include <sbsprom.h> |
| #endif |
| #include <ethernet.h> /* for sprom content groking */ |
| |
| #include <sbgci.h> |
| #ifdef EVENT_LOG_COMPILE |
| #include <event_log.h> |
| #endif |
| |
| #if defined(EVENT_LOG_COMPILE) && defined(BCMDBG_ERR) && defined(ERR_USE_EVENT_LOG) |
| #if defined(ERR_USE_EVENT_LOG_RA) |
| #define BS_ERROR(args) EVENT_LOG_RA(EVENT_LOG_TAG_BSROM_ERROR, args) |
| #else |
| #define BS_ERROR(args) EVENT_LOG_COMPACT_CAST_PAREN_ARGS(EVENT_LOG_TAG_BSROM_ERROR, args) |
| #endif /* ERR_USE_EVENT_LOG_RA */ |
| #elif defined(BCMDBG_ERR) || defined(WLTEST) |
| #define BS_ERROR(args) printf args |
| #else |
| #define BS_ERROR(args) |
| #endif /* defined(BCMDBG_ERR) && defined(ERR_USE_EVENT_LOG) */ |
| |
| #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) |
| static bool BCMATTACHDATA(is_caldata_prsnt) = FALSE; |
| static uint16 BCMATTACHDATA(caldata_array)[SROM_MAX / 2]; |
| static uint8 BCMATTACHDATA(srom_sromrev); |
| #endif |
| |
| static const char BCMATTACHDATA(rstr_uuidstr)[] = |
| "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X"; |
| static const char BCMATTACHDATA(rstr_paddr)[] = "pa%d=0x%%x"; |
| static const char BCMATTACHDATA(rstr_pdata)[] = "pd%d=0x%%x"; |
| static const char BCMATTACHDATA(rstr_pdatah)[] = "pdh%d=0x%%x"; |
| static const char BCMATTACHDATA(rstr_pdatal)[] = "pdl%d=0x%%x"; |
| static const char BCMATTACHDATA(rstr_gci_ccreg_entry)[] = "gcr%d=0x%%x"; |
| static const char BCMATTACHDATA(rstr_hex)[] = "0x%x"; |
| |
| /** curmap: contains host start address of PCI BAR0 window */ |
| static volatile uint8* srom_offset(si_t *sih, volatile void *curmap) |
| { |
| if (sih->ccrev <= 31) |
| return (volatile uint8*)curmap + PCI_BAR0_SPROM_OFFSET; |
| if ((sih->cccaps & CC_CAP_SROM) == 0) |
| return NULL; |
| |
| if (BUSTYPE(sih->bustype) == SI_BUS) |
| return (uint8 *)((uintptr)SI_ENUM_BASE(sih) + CC_SROM_OTP); |
| |
| return (volatile uint8*)curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP; |
| } |
| |
| #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) |
| #define WRITE_ENABLE_DELAY 500 /* 500 ms after write enable/disable toggle */ |
| #define WRITE_WORD_DELAY 20 /* 20 ms between each word write */ |
| #endif |
| |
| srom_info_t *sromh = NULL; |
| |
| extern char *_vars; |
| extern uint _varsz; |
| #ifdef DONGLEBUILD |
| char * BCMATTACHDATA(_vars_otp) = NULL; |
| #define DONGLE_STORE_VARS_OTP_PTR(v) (_vars_otp = (v)) |
| #else |
| #define DONGLE_STORE_VARS_OTP_PTR(v) |
| #endif |
| |
| #define SROM_CIS_SINGLE 1 |
| |
| #if !defined(BCMDONGLEHOST) |
| static int initvars_srom_si(si_t *sih, osl_t *osh, volatile 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(si_t *sih, volatile void *curmap, char **vars, uint *count); |
| static int initvars_cis_pci(si_t *sih, osl_t *osh, volatile void *curmap, char **vars, uint *count); |
| #endif /* !defined(BCMDONGLEHOST) */ |
| #if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED) &&\ |
| !defined(BCMDONGLEHOST) && !defined(BCMPCIEDEV_ENABLED) |
| static int initvars_flash_si(si_t *sih, char **vars, uint *count); |
| #endif /* !defined(BCMUSBDEV) && !defined(BCMSDIODEV) && !defined(BCMDONGLEHOST) */ |
| #ifdef BCMSDIO |
| #if !defined(BCMDONGLEHOST) |
| static int initvars_cis_sdio(si_t *sih, osl_t *osh, char **vars, uint *count); |
| #endif /* !defined(BCMDONGLEHOST) */ |
| static int sprom_cmd_sdio(osl_t *osh, uint8 cmd); |
| static int sprom_read_sdio(osl_t *osh, uint16 addr, uint16 *data); |
| #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) |
| static int sprom_write_sdio(osl_t *osh, uint16 addr, uint16 data); |
| #endif /* defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) */ |
| #endif /* BCMSDIO */ |
| #if !defined(BCMDONGLEHOST) |
| #ifdef BCMSPI |
| static int initvars_cis_spi(si_t *sih, osl_t *osh, char **vars, uint *count); |
| #endif /* BCMSPI */ |
| #endif /* !defined(BCMDONGLEHOST) */ |
| static int sprom_read_pci(osl_t *osh, si_t *sih, volatile uint16 *sprom, uint wordoff, uint16 *buf, |
| uint nwords, bool check_crc); |
| #if !defined(BCMDONGLEHOST) |
| #if defined(BCMNVRAMW) || defined(BCMNVRAMR) |
| static int otp_read_pci(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz); |
| #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */ |
| #endif /* !defined(BCMDONGLEHOST) */ |
| static uint16 srom_cc_cmd(si_t *sih, osl_t *osh, volatile void *ccregs, uint32 cmd, uint wordoff, |
| uint16 data); |
| |
| #if !defined(BCMDONGLEHOST) |
| static int initvars_flash(si_t *sih, osl_t *osh, char **vp, uint len); |
| int dbushost_initvars_flash(si_t *sih, osl_t *osh, char **base, uint len); |
| static uint get_max_cis_size(si_t *sih); |
| #endif /* !defined(BCMDONGLEHOST) */ |
| |
| #if defined (BCMHOSTVARS) |
| /* Also used by wl_readconfigdata for vars download */ |
| char BCMATTACHDATA(mfgsromvars)[VARS_MAX]; |
| int BCMATTACHDATA(defvarslen) = 0; |
| #endif /* defined(BCMHOSTVARS) */ |
| |
| #if !defined(BCMDONGLEHOST) |
| #if defined (BCMHOSTVARS) |
| /* FIXME: Fake 4331 SROM to boot 4331 driver on QT w/o SPROM/OTP */ |
| static char BCMATTACHDATA(defaultsromvars_4331)[] = |
| "sromrev=9\0" |
| "boardrev=0x1104\0" |
| "boardflags=0x200\0" |
| "boardflags2=0x0\0" |
| "boardtype=0x524\0" |
| "boardvendor=0x14e4\0" |
| "boardnum=0x2064\0" |
| "macaddr=00:90:4c:1a:20:64\0" |
| "ccode=0x0\0" |
| "regrev=0x0\0" |
| "opo=0x0\0" |
| "aa2g=0x7\0" |
| "aa5g=0x7\0" |
| "ag0=0x2\0" |
| "ag1=0x2\0" |
| "ag2=0x2\0" |
| "ag3=0xff\0" |
| "pa0b0=0xfe7f\0" |
| "pa0b1=0x15d9\0" |
| "pa0b2=0xfac6\0" |
| "pa0itssit=0x20\0" |
| "pa0maxpwr=0x48\0" |
| "pa1b0=0xfe89\0" |
| "pa1b1=0x14b1\0" |
| "pa1b2=0xfada\0" |
| "pa1lob0=0xffff\0" |
| "pa1lob1=0xffff\0" |
| "pa1lob2=0xffff\0" |
| "pa1hib0=0xfe8f\0" |
| "pa1hib1=0x13df\0" |
| "pa1hib2=0xfafa\0" |
| "pa1itssit=0x3e\0" |
| "pa1maxpwr=0x3c\0" |
| "pa1lomaxpwr=0x3c\0" |
| "pa1himaxpwr=0x3c\0" |
| "bxa2g=0x3\0" |
| "rssisav2g=0x7\0" |
| "rssismc2g=0xf\0" |
| "rssismf2g=0xf\0" |
| "bxa5g=0x3\0" |
| "rssisav5g=0x7\0" |
| "rssismc5g=0xf\0" |
| "rssismf5g=0xf\0" |
| "tri2g=0xff\0" |
| "tri5g=0xff\0" |
| "tri5gl=0xff\0" |
| "tri5gh=0xff\0" |
| "rxpo2g=0xff\0" |
| "rxpo5g=0xff\0" |
| "txchain=0x7\0" |
| "rxchain=0x7\0" |
| "antswitch=0x0\0" |
| "tssipos2g=0x1\0" |
| "extpagain2g=0x2\0" |
| "pdetrange2g=0x4\0" |
| "triso2g=0x3\0" |
| "antswctl2g=0x0\0" |
| "tssipos5g=0x1\0" |
| "elna2g=0xff\0" |
| "extpagain5g=0x2\0" |
| "pdetrange5g=0x4\0" |
| "triso5g=0x3\0" |
| "antswctl5g=0x0\0" |
| "elna5g=0xff\0" |
| "cckbw202gpo=0x0\0" |
| "cckbw20ul2gpo=0x0\0" |
| "legofdmbw202gpo=0x0\0" |
| "legofdmbw20ul2gpo=0x0\0" |
| "legofdmbw205glpo=0x0\0" |
| "legofdmbw20ul5glpo=0x0\0" |
| "legofdmbw205gmpo=0x0\0" |
| "legofdmbw20ul5gmpo=0x0\0" |
| "legofdmbw205ghpo=0x0\0" |
| "legofdmbw20ul5ghpo=0x0\0" |
| "mcsbw202gpo=0x0\0" |
| "mcsbw20ul2gpo=0x0\0" |
| "mcsbw402gpo=0x0\0" |
| "mcsbw205glpo=0x0\0" |
| "mcsbw20ul5glpo=0x0\0" |
| "mcsbw405glpo=0x0\0" |
| "mcsbw205gmpo=0x0\0" |
| "mcsbw20ul5gmpo=0x0\0" |
| "mcsbw405gmpo=0x0\0" |
| "mcsbw205ghpo=0x0\0" |
| "mcsbw20ul5ghpo=0x0\0" |
| "mcsbw405ghpo=0x0\0" |
| "mcs32po=0x0\0" |
| "legofdm40duppo=0x0\0" |
| "maxp2ga0=0x48\0" |
| "itt2ga0=0x20\0" |
| "itt5ga0=0x3e\0" |
| "pa2gw0a0=0xfe7f\0" |
| "pa2gw1a0=0x15d9\0" |
| "pa2gw2a0=0xfac6\0" |
| "maxp5ga0=0x3c\0" |
| "maxp5gha0=0x3c\0" |
| "maxp5gla0=0x3c\0" |
| "pa5gw0a0=0xfe89\0" |
| "pa5gw1a0=0x14b1\0" |
| "pa5gw2a0=0xfada\0" |
| "pa5glw0a0=0xffff\0" |
| "pa5glw1a0=0xffff\0" |
| "pa5glw2a0=0xffff\0" |
| "pa5ghw0a0=0xfe8f\0" |
| "pa5ghw1a0=0x13df\0" |
| "pa5ghw2a0=0xfafa\0" |
| "maxp2ga1=0x48\0" |
| "itt2ga1=0x20\0" |
| "itt5ga1=0x3e\0" |
| "pa2gw0a1=0xfe54\0" |
| "pa2gw1a1=0x1563\0" |
| "pa2gw2a1=0xfa7f\0" |
| "maxp5ga1=0x3c\0" |
| "maxp5gha1=0x3c\0" |
| "maxp5gla1=0x3c\0" |
| "pa5gw0a1=0xfe53\0" |
| "pa5gw1a1=0x14fe\0" |
| "pa5gw2a1=0xfa94\0" |
| "pa5glw0a1=0xffff\0" |
| "pa5glw1a1=0xffff\0" |
| "pa5glw2a1=0xffff\0" |
| "pa5ghw0a1=0xfe6e\0" |
| "pa5ghw1a1=0x1457\0" |
| "pa5ghw2a1=0xfab9\0" |
| "END\0"; |
| |
| static char BCMATTACHDATA(defaultsromvars_4360)[] = |
| "sromrev=11\0" |
| "boardrev=0x1421\0" |
| "boardflags=0x10401001\0" |
| "boardflags2=0x0\0" |
| "boardtype=0x61b\0" |
| "subvid=0x14e4\0" |
| "boardflags3=0x1\0" |
| "boardnum=62526\0" |
| "macaddr=00:90:4c:0d:f4:3e\0" |
| "ccode=X0\0" |
| "regrev=15\0" |
| "aa2g=7\0" |
| "aa5g=7\0" |
| "agbg0=71\0" |
| "agbg1=71\0" |
| "agbg2=133\0" |
| "aga0=71\0" |
| "aga1=133\0" |
| "aga2=133\0" |
| "antswitch=0\0" |
| "tssiposslope2g=1\0" |
| "epagain2g=0\0" |
| "pdgain2g=9\0" |
| "tworangetssi2g=0\0" |
| "papdcap2g=0\0" |
| "femctrl=2\0" |
| "tssiposslope5g=1\0" |
| "epagain5g=0\0" |
| "pdgain5g=9\0" |
| "tworangetssi5g=0\0" |
| "papdcap5g=0\0" |
| "gainctrlsph=0\0" |
| "tempthresh=255\0" |
| "tempoffset=255\0" |
| "rawtempsense=0x1ff\0" |
| "measpower=0x7f\0" |
| "tempsense_slope=0xff\0" |
| "tempcorrx=0x3f\0" |
| "tempsense_option=0x3\0" |
| "xtalfreq=65535\0" |
| "phycal_tempdelta=255\0" |
| "temps_period=15\0" |
| "temps_hysteresis=15\0" |
| "measpower1=0x7f\0" |
| "measpower2=0x7f\0" |
| "pdoffset2g40ma0=15\0" |
| "pdoffset2g40ma1=15\0" |
| "pdoffset2g40ma2=15\0" |
| "pdoffset2g40mvalid=1\0" |
| "pdoffset40ma0=9010\0" |
| "pdoffset40ma1=12834\0" |
| "pdoffset40ma2=8994\0" |
| "pdoffset80ma0=16\0" |
| "pdoffset80ma1=4096\0" |
| "pdoffset80ma2=0\0" |
| "subband5gver=0x4\0" |
| "cckbw202gpo=0\0" |
| "cckbw20ul2gpo=0\0" |
| "mcsbw202gpo=2571386880\0" |
| "mcsbw402gpo=2571386880\0" |
| "dot11agofdmhrbw202gpo=17408\0" |
| "ofdmlrbw202gpo=0\0" |
| "mcsbw205glpo=4001923072\0" |
| "mcsbw405glpo=4001923072\0" |
| "mcsbw805glpo=4001923072\0" |
| "mcsbw1605glpo=0\0" |
| "mcsbw205gmpo=3431497728\0" |
| "mcsbw405gmpo=3431497728\0" |
| "mcsbw805gmpo=3431497728\0" |
| "mcsbw1605gmpo=0\0" |
| "mcsbw205ghpo=3431497728\0" |
| "mcsbw405ghpo=3431497728\0" |
| "mcsbw805ghpo=3431497728\0" |
| "mcsbw1605ghpo=0\0" |
| "mcslr5glpo=0\0" |
| "mcslr5gmpo=0\0" |
| "mcslr5ghpo=0\0" |
| "sb20in40hrpo=0\0" |
| "sb20in80and160hr5glpo=0\0" |
| "sb40and80hr5glpo=0\0" |
| "sb20in80and160hr5gmpo=0\0" |
| "sb40and80hr5gmpo=0\0" |
| "sb20in80and160hr5ghpo=0\0" |
| "sb40and80hr5ghpo=0\0" |
| "sb20in40lrpo=0\0" |
| "sb20in80and160lr5glpo=0\0" |
| "sb40and80lr5glpo=0\0" |
| "sb20in80and160lr5gmpo=0\0" |
| "sb40and80lr5gmpo=0\0" |
| "sb20in80and160lr5ghpo=0\0" |
| "sb40and80lr5ghpo=0\0" |
| "dot11agduphrpo=0\0" |
| "dot11agduplrpo=0\0" |
| "pcieingress_war=15\0" |
| "sar2g=18\0" |
| "sar5g=15\0" |
| "noiselvl2ga0=31\0" |
| "noiselvl2ga1=31\0" |
| "noiselvl2ga2=31\0" |
| "noiselvl5ga0=31,31,31,31\0" |
| "noiselvl5ga1=31,31,31,31\0" |
| "noiselvl5ga2=31,31,31,31\0" |
| "rxgainerr2ga0=63\0" |
| "rxgainerr2ga1=31\0" |
| "rxgainerr2ga2=31\0" |
| "rxgainerr5ga0=63,63,63,63\0" |
| "rxgainerr5ga1=31,31,31,31\0" |
| "rxgainerr5ga2=31,31,31,31\0" |
| "maxp2ga0=76\0" |
| "pa2ga0=0xff3c,0x172c,0xfd20\0" |
| "rxgains5gmelnagaina0=7\0" |
| "rxgains5gmtrisoa0=15\0" |
| "rxgains5gmtrelnabypa0=1\0" |
| "rxgains5ghelnagaina0=7\0" |
| "rxgains5ghtrisoa0=15\0" |
| "rxgains5ghtrelnabypa0=1\0" |
| "rxgains2gelnagaina0=4\0" |
| "rxgains2gtrisoa0=7\0" |
| "rxgains2gtrelnabypa0=1\0" |
| "rxgains5gelnagaina0=3\0" |
| "rxgains5gtrisoa0=7\0" |
| "rxgains5gtrelnabypa0=1\0" |
| "maxp5ga0=76,76,76,76\0" |
| "pa5ga0=0xff3a,0x14d4,0xfd5f,0xff36,0x1626,0xfd2e,0xff42,0x15bd,0xfd47,0xff39,0x15a3,0xfd3d\0" |
| "maxp2ga1=76\0" |
| "pa2ga1=0xff2a,0x16b2,0xfd28\0" |
| "rxgains5gmelnagaina1=7\0" |
| "rxgains5gmtrisoa1=15\0" |
| "rxgains5gmtrelnabypa1=1\0" |
| "rxgains5ghelnagaina1=7\0" |
| "rxgains5ghtrisoa1=15\0" |
| "rxgains5ghtrelnabypa1=1\0" |
| "rxgains2gelnagaina1=3\0" |
| "rxgains2gtrisoa1=6\0" |
| "rxgains2gtrelnabypa1=1\0" |
| "rxgains5gelnagaina1=3\0" |
| "rxgains5gtrisoa1=6\0" |
| "rxgains5gtrelnabypa1=1\0" |
| "maxp5ga1=76,76,76,76\0" |
| "pa5ga1=0xff4e,0x1530,0xfd53,0xff58,0x15b4,0xfd4d,0xff58,0x1671,0xfd2f,0xff55,0x15e2,0xfd46\0" |
| "maxp2ga2=76\0" |
| "pa2ga2=0xff3c,0x1736,0xfd1f\0" |
| "rxgains5gmelnagaina2=7\0" |
| "rxgains5gmtrisoa2=15\0" |
| "rxgains5gmtrelnabypa2=1\0" |
| "rxgains5ghelnagaina2=7\0" |
| "rxgains5ghtrisoa2=15\0" |
| "rxgains5ghtrelnabypa2=1\0" |
| "rxgains2gelnagaina2=4\0" |
| "rxgains2gtrisoa2=7\0" |
| "rxgains2gtrelnabypa2=1\0" |
| "rxgains5gelnagaina2=3\0" |
| "rxgains5gtrisoa2=7\0" |
| "rxgains5gtrelnabypa2=1\0" |
| "maxp5ga2=76,76,76,76\0" |
| "pa5ga2=0xff2d,0x144a,0xfd63,0xff35,0x15d7,0xfd3b,0xff35,0x1668,0xfd2f,0xff31,0x1664,0xfd27\0" |
| "END\0"; |
| |
| #endif /* defined(BCMHOSTVARS) */ |
| #endif /* !defined(BCMDONGLEHOST) */ |
| |
| #if !defined(BCMDONGLEHOST) |
| #if defined(BCMHOSTVARS) |
| static char BCMATTACHDATA(defaultsromvars_wltest)[] = |
| "macaddr=00:90:4c:f8:00:01\0" |
| "et0macaddr=00:11:22:33:44:52\0" |
| "et0phyaddr=30\0" |
| "et0mdcport=0\0" |
| "gpio2=robo_reset\0" |
| "boardvendor=0x14e4\0" |
| "boardflags=0x210\0" |
| "boardflags2=0\0" |
| "boardtype=0x04c3\0" |
| "boardrev=0x1100\0" |
| "sromrev=8\0" |
| "devid=0x432c\0" |
| "ccode=0\0" |
| "regrev=0\0" |
| "aa2g=3\0" |
| "ag0=2\0" |
| "ag1=2\0" |
| "aa5g=3\0" |
| "aa0=2\0" |
| "aa1=2\0" |
| "txchain=3\0" |
| "rxchain=3\0" |
| "antswitch=0\0" |
| "itt2ga0=0x20\0" |
| "maxp2ga0=0x48\0" |
| "pa2gw0a0=0xfe9e\0" |
| "pa2gw1a0=0x15d5\0" |
| "pa2gw2a0=0xfae9\0" |
| "itt2ga1=0x20\0" |
| "maxp2ga1=0x48\0" |
| "pa2gw0a1=0xfeb3\0" |
| "pa2gw1a1=0x15c9\0" |
| "pa2gw2a1=0xfaf7\0" |
| "tssipos2g=1\0" |
| "extpagain2g=0\0" |
| "pdetrange2g=0\0" |
| "triso2g=3\0" |
| "antswctl2g=0\0" |
| "tssipos5g=1\0" |
| "extpagain5g=0\0" |
| "pdetrange5g=0\0" |
| "triso5g=3\0" |
| "antswctl5g=0\0" |
| "cck2gpo=0\0" |
| "ofdm2gpo=0\0" |
| "mcs2gpo0=0\0" |
| "mcs2gpo1=0\0" |
| "mcs2gpo2=0\0" |
| "mcs2gpo3=0\0" |
| "mcs2gpo4=0\0" |
| "mcs2gpo5=0\0" |
| "mcs2gpo6=0\0" |
| "mcs2gpo7=0\0" |
| "cddpo=0\0" |
| "stbcpo=0\0" |
| "bw40po=4\0" |
| "bwduppo=0\0" |
| "END\0"; |
| |
| /** |
| * The contents of this array is a first attempt, is likely incorrect for 43602, needs to be |
| * edited in a later stage. |
| */ |
| static char BCMATTACHDATA(defaultsromvars_43602)[] = |
| "sromrev=11\0" |
| "boardrev=0x1421\0" |
| "boardflags=0x10401001\0" |
| "boardflags2=0x00000002\0" |
| "boardflags3=0x00000003\0" |
| "boardtype=0x61b\0" |
| "subvid=0x14e4\0" |
| "boardnum=62526\0" |
| "macaddr=00:90:4c:0d:f4:3e\0" |
| "ccode=X0\0" |
| "regrev=15\0" |
| "aa2g=7\0" |
| "aa5g=7\0" |
| "agbg0=71\0" |
| "agbg1=71\0" |
| "agbg2=133\0" |
| "aga0=71\0" |
| "aga1=133\0" |
| "aga2=133\0" |
| "antswitch=0\0" |
| "tssiposslope2g=1\0" |
| "epagain2g=0\0" |
| "pdgain2g=9\0" |
| "tworangetssi2g=0\0" |
| "papdcap2g=0\0" |
| "femctrl=2\0" |
| "tssiposslope5g=1\0" |
| "epagain5g=0\0" |
| "pdgain5g=9\0" |
| "tworangetssi5g=0\0" |
| "papdcap5g=0\0" |
| "gainctrlsph=0\0" |
| "tempthresh=255\0" |
| "tempoffset=255\0" |
| "rawtempsense=0x1ff\0" |
| "measpower=0x7f\0" |
| "tempsense_slope=0xff\0" |
| "tempcorrx=0x3f\0" |
| "tempsense_option=0x3\0" |
| "xtalfreq=40000\0" |
| "phycal_tempdelta=255\0" |
| "temps_period=15\0" |
| "temps_hysteresis=15\0" |
| "measpower1=0x7f\0" |
| "measpower2=0x7f\0" |
| "pdoffset2g40ma0=15\0" |
| "pdoffset2g40ma1=15\0" |
| "pdoffset2g40ma2=15\0" |
| "pdoffset2g40mvalid=1\0" |
| "pdoffset40ma0=9010\0" |
| "pdoffset40ma1=12834\0" |
| "pdoffset40ma2=8994\0" |
| "pdoffset80ma0=16\0" |
| "pdoffset80ma1=4096\0" |
| "pdoffset80ma2=0\0" |
| "subband5gver=0x4\0" |
| "cckbw202gpo=0\0" |
| "cckbw20ul2gpo=0\0" |
| "mcsbw202gpo=2571386880\0" |
| "mcsbw402gpo=2571386880\0" |
| "dot11agofdmhrbw202gpo=17408\0" |
| "ofdmlrbw202gpo=0\0" |
| "mcsbw205glpo=4001923072\0" |
| "mcsbw405glpo=4001923072\0" |
| "mcsbw805glpo=4001923072\0" |
| "mcsbw1605glpo=0\0" |
| "mcsbw205gmpo=3431497728\0" |
| "mcsbw405gmpo=3431497728\0" |
| "mcsbw805gmpo=3431497728\0" |
| "mcsbw1605gmpo=0\0" |
| "mcsbw205ghpo=3431497728\0" |
| "mcsbw405ghpo=3431497728\0" |
| "mcsbw805ghpo=3431497728\0" |
| "mcsbw1605ghpo=0\0" |
| "mcslr5glpo=0\0" |
| "mcslr5gmpo=0\0" |
| "mcslr5ghpo=0\0" |
| "sb20in40hrpo=0\0" |
| "sb20in80and160hr5glpo=0\0" |
| "sb40and80hr5glpo=0\0" |
| "sb20in80and160hr5gmpo=0\0" |
| "sb40and80hr5gmpo=0\0" |
| "sb20in80and160hr5ghpo=0\0" |
| "sb40and80hr5ghpo=0\0" |
| "sb20in40lrpo=0\0" |
| "sb20in80and160lr5glpo=0\0" |
| "sb40and80lr5glpo=0\0" |
| "sb20in80and160lr5gmpo=0\0" |
| "sb40and80lr5gmpo=0\0" |
| "sb20in80and160lr5ghpo=0\0" |
| "sb40and80lr5ghpo=0\0" |
| "dot11agduphrpo=0\0" |
| "dot11agduplrpo=0\0" |
| "pcieingress_war=15\0" |
| "sar2g=18\0" |
| "sar5g=15\0" |
| "noiselvl2ga0=31\0" |
| "noiselvl2ga1=31\0" |
| "noiselvl2ga2=31\0" |
| "noiselvl5ga0=31,31,31,31\0" |
| "noiselvl5ga1=31,31,31,31\0" |
| "noiselvl5ga2=31,31,31,31\0" |
| "rxgainerr2ga0=63\0" |
| "rxgainerr2ga1=31\0" |
| "rxgainerr2ga2=31\0" |
| "rxgainerr5ga0=63,63,63,63\0" |
| "rxgainerr5ga1=31,31,31,31\0" |
| "rxgainerr5ga2=31,31,31,31\0" |
| "maxp2ga0=76\0" |
| "pa2ga0=0xff3c,0x172c,0xfd20\0" |
| "rxgains5gmelnagaina0=7\0" |
| "rxgains5gmtrisoa0=15\0" |
| "rxgains5gmtrelnabypa0=1\0" |
| "rxgains5ghelnagaina0=7\0" |
| "rxgains5ghtrisoa0=15\0" |
| "rxgains5ghtrelnabypa0=1\0" |
| "rxgains2gelnagaina0=4\0" |
| "rxgains2gtrisoa0=7\0" |
| "rxgains2gtrelnabypa0=1\0" |
| "rxgains5gelnagaina0=3\0" |
| "rxgains5gtrisoa0=7\0" |
| "rxgains5gtrelnabypa0=1\0" |
| "maxp5ga0=76,76,76,76\0" |
| "pa5ga0=0xff3a,0x14d4,0xfd5f,0xff36,0x1626,0xfd2e,0xff42,0x15bd,0xfd47,0xff39,0x15a3,0xfd3d\0" |
| "maxp2ga1=76\0" |
| "pa2ga1=0xff2a,0x16b2,0xfd28\0" |
| "rxgains5gmelnagaina1=7\0" |
| "rxgains5gmtrisoa1=15\0" |
| "rxgains5gmtrelnabypa1=1\0" |
| "rxgains5ghelnagaina1=7\0" |
| "rxgains5ghtrisoa1=15\0" |
| "rxgains5ghtrelnabypa1=1\0" |
| "rxgains2gelnagaina1=3\0" |
| "rxgains2gtrisoa1=6\0" |
| "rxgains2gtrelnabypa1=1\0" |
| "rxgains5gelnagaina1=3\0" |
| "rxgains5gtrisoa1=6\0" |
| "rxgains5gtrelnabypa1=1\0" |
| "maxp5ga1=76,76,76,76\0" |
| "pa5ga1=0xff4e,0x1530,0xfd53,0xff58,0x15b4,0xfd4d,0xff58,0x1671,0xfd2f,0xff55,0x15e2,0xfd46\0" |
| "maxp2ga2=76\0" |
| "pa2ga2=0xff3c,0x1736,0xfd1f\0" |
| "rxgains5gmelnagaina2=7\0" |
| "rxgains5gmtrisoa2=15\0" |
| "rxgains5gmtrelnabypa2=1\0" |
| "rxgains5ghelnagaina2=7\0" |
| "rxgains5ghtrisoa2=15\0" |
| "rxgains5ghtrelnabypa2=1\0" |
| "rxgains2gelnagaina2=4\0" |
| "rxgains2gtrisoa2=7\0" |
| "rxgains2gtrelnabypa2=1\0" |
| "rxgains5gelnagaina2=3\0" |
| "rxgains5gtrisoa2=7\0" |
| "rxgains5gtrelnabypa2=1\0" |
| "maxp5ga2=76,76,76,76\0" |
| "pa5ga2=0xff2d,0x144a,0xfd63,0xff35,0x15d7,0xfd3b,0xff35,0x1668,0xfd2f,0xff31,0x1664,0xfd27\0" |
| "END\0"; |
| |
| /** |
| * The contents of this array is a first attempt, was copied from 4378, needs to be edited in |
| * a later stage. |
| */ |
| static char BCMATTACHDATA(defaultsromvars_4378)[] = |
| "cckdigfilttype=4\0" |
| "sromrev=11\0" |
| "boardrev=0x1102\0" |
| "boardtype=0x0771\0" |
| "boardflags=0x10481201\0" |
| "boardflags2=0x00000000\0" |
| "boardflags3=0x04000080\0" |
| "macaddr=00:90:4c:12:43:47\0" |
| "ccode=0\0" |
| "regrev=0\0" |
| "antswitch=0\0" |
| "pdgain5g=0\0" |
| "pdgain2g=0\0" |
| "tworangetssi2g=0\0" |
| "tworangetssi5g=0\0" |
| "femctrl=16\0" |
| "vendid=0x14e4\0" |
| "devid=0x4425\0" |
| "manfid=0x2d0\0" |
| "nocrc=1\0" |
| "btc_params82=0x1a0\0" |
| "otpimagesize=502\0" |
| "xtalfreq=37400\0" |
| "rxgains2gelnagaina0=3\0" |
| "rxgains2gtrisoa0=7\0" |
| "rxgains2gtrelnabypa0=1\0" |
| "rxgains5gelnagaina0=3\0" |
| "rxgains5gtrisoa0=6\0" |
| "rxgains5gtrelnabypa0=1\0" |
| "rxgains5gmelnagaina0=3\0" |
| "rxgains5gmtrisoa0=6\0" |
| "rxgains5gmtrelnabypa0=1\0" |
| "rxgains5ghelnagaina0=3\0" |
| "rxgains5ghtrisoa0=6\0" |
| "rxgains5ghtrelnabypa0=1\0" |
| "rxgains2gelnagaina1=3\0" |
| "rxgains2gtrisoa1=7\0" |
| "rxgains2gtrelnabypa1=1\0" |
| "rxgains5gelnagaina1=3\0" |
| "rxgains5gtrisoa1=6\0" |
| "rxgains5gtrelnabypa1=1\0" |
| "rxgains5gmelnagaina1=3\0" |
| "rxgains5gmtrisoa1=6\0" |
| "rxgains5gmtrelnabypa1=1\0" |
| "rxgains5ghelnagaina1=3\0" |
| "rxgains5ghtrisoa1=6\0" |
| "rxgains5ghtrelnabypa1=1\0" |
| "rxchain=3\0" |
| "txchain=3\0" |
| "aa2g=3\0" |
| "aa5g=3\0" |
| "agbg0=2\0" |
| "agbg1=2\0" |
| "aga0=2\0" |
| "aga1=2\0" |
| "tssipos2g=1\0" |
| "tssipos5g=1\0" |
| "tempthresh=255\0" |
| "tempoffset=255\0" |
| "rawtempsense=0x1ff\0" |
| "pa2gccka0=-200,7392,-897\0" |
| "pa2gccka1=-198,7522,-907\0" |
| "pa2ga0=-174,7035,-838\0" |
| "pa2ga1=-185,6772,-811\0" |
| "pa5ga0=-175,7296,-887,-164,7553,-910,-155,7801,-936,-149,7908,-951\0" |
| "pa5ga1=-155,7675,-925,-148,7851,-940,-152,7930,-954,-143,8121,-969\0" |
| "pa5gbw4080a0=-178,7872,-959,-173,8107,-986,-165,8398,-1019,-150,8809,-1063\0" |
| "pa5gbw4080a1=-166,8179,-993,-161,8378,-1015,-165,8402,-1019,-155,8757,-1057\0" |
| "maxp2ga0=66\0" |
| "maxp2ga1=66\0" |
| "maxp5ga0=66,66,66,66\0" |
| "maxp5ga1=66,66,66,66\0" |
| "subband5gver=0x4\0" |
| "paparambwver=3\0" |
| "cckpwroffset0=0\0" |
| "cckpwroffset1=0\0" |
| "pdoffset40ma0=0x0000\0" |
| "pdoffset80ma0=0xeeee\0" |
| "pdoffset40ma1=0x0000\0" |
| "pdoffset80ma1=0xeeee\0" |
| "cckbw202gpo=0\0" |
| "cckbw20ul2gpo=0\0" |
| "mcsbw202gpo=0xEC888222\0" |
| "mcsbw402gpo=0xEC888222\0" |
| "dot11agofdmhrbw202gpo=0x6622\0" |
| "ofdmlrbw202gpo=0x0000\0" |
| "mcsbw205glpo=0xCA666000\0" |
| "mcsbw405glpo=0xCA666000\0" |
| "mcsbw805glpo=0xEA666000\0" |
| "mcsbw1605glpo=0\0" |
| "mcsbw205gmpo=0xCA666000\0" |
| "mcsbw405gmpo=0xCA666000\0" |
| "mcsbw805gmpo=0xEA666000\0" |
| "mcsbw1605gmpo=0\0" |
| "mcsbw205ghpo=0xCA666000\0" |
| "mcsbw405ghpo=0xCA666000\0" |
| "mcsbw805ghpo=0xEA666000\0" |
| "mcsbw1605ghpo=0\0" |
| "mcslr5glpo=0x0000\0" |
| "mcslr5gmpo=0x0000\0" |
| "mcslr5ghpo=0x0000\0" |
| "sb20in40hrpo=0x0\0" |
| "sb20in80and160hr5glpo=0x0\0" |
| "sb40and80hr5glpo=0x0\0" |
| "sb20in80and160hr5gmpo=0x0\0" |
| "sb40and80hr5gmpo=0x0\0" |
| "sb20in80and160hr5ghpo=0x0\0" |
| "sb40and80hr5ghpo=0x0\0" |
| "sb20in40lrpo=0x0\0" |
| "sb20in80and160lr5glpo=0x0\0" |
| "sb40and80lr5glpo=0x0\0" |
| "sb20in80and160lr5gmpo=0x0\0" |
| "sb40and80lr5gmpo=0x0\0" |
| "sb20in80and160lr5ghpo=0x0\0" |
| "sb40and80lr5ghpo=0x0\0" |
| "dot11agduphrpo=0x0\0" |
| "dot11agduplrpo=0x0\0" |
| "phycal_tempdelta=15\0" |
| "temps_period=15\0" |
| "temps_hysteresis=15\0" |
| "swctrlmap_2g=0x00000404,0x0a0a0000,0x02020000,0x010a02,0x1fe\0" |
| "swctrlmapext_2g=0x00000000,0x00000000,0x00000000,0x000000,0x000\0" |
| "swctrlmap_5g=0x00001010,0x60600000,0x40400000,0x000000,0x0f0\0" |
| "swctrlmapext_5g=0x00000000,0x00000000,0x00000000,0x000000,0x000\0" |
| "powoffs2gtna0=1,3,3,1,0,0,1,2,2,2,1,1,0,0\0" |
| "powoffs2gtna1=-1,1,1,1,0,0,1,2,3,2,2,0,0,0\0" |
| "END\0"; |
| |
| /** |
| * The contents of this array is a first attempt, was copied from 4387, needs to be edited in |
| * a later stage. |
| */ |
| static char BCMATTACHDATA(defaultsromvars_4387)[] = |
| "cckdigfilttype=4\0" |
| "sromrev=11\0" |
| "boardrev=0x1102\0" |
| "boardtype=0x0771\0" |
| "boardflags=0x10481201\0" |
| "boardflags2=0x00000000\0" |
| "boardflags3=0x04000080\0" |
| "macaddr=00:90:4c:12:43:47\0" |
| "ccode=0\0" |
| "regrev=0\0" |
| "antswitch=0\0" |
| "pdgain5g=0\0" |
| "pdgain2g=0\0" |
| "tworangetssi2g=0\0" |
| "tworangetssi5g=0\0" |
| "femctrl=16\0" |
| "vendid=0x14e4\0" |
| "devid=0x4425\0" |
| "manfid=0x2d0\0" |
| "nocrc=1\0" |
| "btc_params82=0x1a0\0" |
| "otpimagesize=502\0" |
| "xtalfreq=37400\0" |
| "rxgains2gelnagaina0=3\0" |
| "rxgains2gtrisoa0=7\0" |
| "rxgains2gtrelnabypa0=1\0" |
| "rxgains5gelnagaina0=3\0" |
| "rxgains5gtrisoa0=6\0" |
| "rxgains5gtrelnabypa0=1\0" |
| "rxgains5gmelnagaina0=3\0" |
| "rxgains5gmtrisoa0=6\0" |
| "rxgains5gmtrelnabypa0=1\0" |
| "rxgains5ghelnagaina0=3\0" |
| "rxgains5ghtrisoa0=6\0" |
| "rxgains5ghtrelnabypa0=1\0" |
| "rxgains2gelnagaina1=3\0" |
| "rxgains2gtrisoa1=7\0" |
| "rxgains2gtrelnabypa1=1\0" |
| "rxgains5gelnagaina1=3\0" |
| "rxgains5gtrisoa1=6\0" |
| "rxgains5gtrelnabypa1=1\0" |
| "rxgains5gmelnagaina1=3\0" |
| "rxgains5gmtrisoa1=6\0" |
| "rxgains5gmtrelnabypa1=1\0" |
| "rxgains5ghelnagaina1=3\0" |
| "rxgains5ghtrisoa1=6\0" |
| "rxgains5ghtrelnabypa1=1\0" |
| "rxchain=3\0" |
| "txchain=3\0" |
| "aa2g=3\0" |
| "aa5g=3\0" |
| "agbg0=2\0" |
| "agbg1=2\0" |
| "aga0=2\0" |
| "aga1=2\0" |
| "tssipos2g=1\0" |
| "tssipos5g=1\0" |
| "tempthresh=255\0" |
| "tempoffset=255\0" |
| "rawtempsense=0x1ff\0" |
| "pa2gccka0=-200,7392,-897\0" |
| "pa2gccka1=-198,7522,-907\0" |
| "pa2ga0=-174,7035,-838\0" |
| "pa2ga1=-185,6772,-811\0" |
| "pa5ga0=-175,7296,-887,-164,7553,-910,-155,7801,-936,-149,7908,-951\0" |
| "pa5ga1=-155,7675,-925,-148,7851,-940,-152,7930,-954,-143,8121,-969\0" |
| "pa5gbw4080a0=-178,7872,-959,-173,8107,-986,-165,8398,-1019,-150,8809,-1063\0" |
| "pa5gbw4080a1=-166,8179,-993,-161,8378,-1015,-165,8402,-1019,-155,8757,-1057\0" |
| "maxp2ga0=66\0" |
| "maxp2ga1=66\0" |
| "maxp5ga0=66,66,66,66\0" |
| "maxp5ga1=66,66,66,66\0" |
| "subband5gver=0x4\0" |
| "paparambwver=3\0" |
| "cckpwroffset0=0\0" |
| "cckpwroffset1=0\0" |
| "pdoffset40ma0=0x0000\0" |
| "pdoffset80ma0=0xeeee\0" |
| "pdoffset40ma1=0x0000\0" |
| "pdoffset80ma1=0xeeee\0" |
| "cckbw202gpo=0\0" |
| "cckbw20ul2gpo=0\0" |
| "mcsbw202gpo=0xEC888222\0" |
| "mcsbw402gpo=0xEC888222\0" |
| "dot11agofdmhrbw202gpo=0x6622\0" |
| "ofdmlrbw202gpo=0x0000\0" |
| "mcsbw205glpo=0xCA666000\0" |
| "mcsbw405glpo=0xCA666000\0" |
| "mcsbw805glpo=0xEA666000\0" |
| "mcsbw1605glpo=0\0" |
| "mcsbw205gmpo=0xCA666000\0" |
| "mcsbw405gmpo=0xCA666000\0" |
| "mcsbw805gmpo=0xEA666000\0" |
| "mcsbw1605gmpo=0\0" |
| "mcsbw205ghpo=0xCA666000\0" |
| "mcsbw405ghpo=0xCA666000\0" |
| "mcsbw805ghpo=0xEA666000\0" |
| "mcsbw1605ghpo=0\0" |
| "mcslr5glpo=0x0000\0" |
| "mcslr5gmpo=0x0000\0" |
| "mcslr5ghpo=0x0000\0" |
| "sb20in40hrpo=0x0\0" |
| "sb20in80and160hr5glpo=0x0\0" |
| "sb40and80hr5glpo=0x0\0" |
| "sb20in80and160hr5gmpo=0x0\0" |
| "sb40and80hr5gmpo=0x0\0" |
| "sb20in80and160hr5ghpo=0x0\0" |
| "sb40and80hr5ghpo=0x0\0" |
| "sb20in40lrpo=0x0\0" |
| "sb20in80and160lr5glpo=0x0\0" |
| "sb40and80lr5glpo=0x0\0" |
| "sb20in80and160lr5gmpo=0x0\0" |
| "sb40and80lr5gmpo=0x0\0" |
| "sb20in80and160lr5ghpo=0x0\0" |
| "sb40and80lr5ghpo=0x0\0" |
| "dot11agduphrpo=0x0\0" |
| "dot11agduplrpo=0x0\0" |
| "phycal_tempdelta=15\0" |
| "temps_period=15\0" |
| "temps_hysteresis=15\0" |
| "swctrlmap_2g=0x00000404,0x0a0a0000,0x02020000,0x010a02,0x1fe\0" |
| "swctrlmapext_2g=0x00000000,0x00000000,0x00000000,0x000000,0x000\0" |
| "swctrlmap_5g=0x00001010,0x60600000,0x40400000,0x000000,0x0f0\0" |
| "swctrlmapext_5g=0x00000000,0x00000000,0x00000000,0x000000,0x000\0" |
| "powoffs2gtna0=1,3,3,1,0,0,1,2,2,2,1,1,0,0\0" |
| "powoffs2gtna1=-1,1,1,1,0,0,1,2,3,2,2,0,0,0\0" |
| "END\0"; |
| |
| #endif /* defined(BCMHOSTVARS) */ |
| #endif /* !defined(BCMDONGLEHOST) */ |
| |
| static bool srvars_inited = FALSE; /* Use OTP/SROM as global variables */ |
| |
| #if (!defined(BCMDONGLEHOST) && defined(BCMHOSTVARS)) |
| /* It must end with pattern of "END" */ |
| static uint |
| BCMATTACHFN(srom_vars_len)(char *vars) |
| { |
| uint pos = 0; |
| uint len; |
| char *s; |
| char *emark = "END"; |
| uint emark_len = strlen(emark) + 1; |
| |
| for (s = vars; s && *s;) { |
| |
| if (strcmp(s, emark) == 0) |
| break; |
| |
| len = strlen(s); |
| s += strlen(s) + 1; |
| pos += len + 1; |
| /* BS_ERROR(("len %d vars[pos] %s\n", pos, s)); */ |
| if (pos >= (VARS_MAX - emark_len)) { |
| return 0; |
| } |
| } |
| |
| return pos + emark_len; /* include the "END\0" */ |
| } |
| #endif /* BCMHOSTVARS */ |
| |
| #if !defined(BCMDONGLEHOST) |
| #ifdef BCMNVRAMVARS |
| static int |
| BCMATTACHFN(initvars_nvram_vars)(si_t *sih, osl_t *osh, char **vars, uint *vars_sz) |
| { |
| int ret; |
| |
| ASSERT(vars != NULL && vars_sz != NULL); |
| |
| /* allocate maximum buffer as we don't know big it should be */ |
| *vars = MALLOC(osh, MAXSZ_NVRAM_VARS); |
| if (*vars == NULL) { |
| ret = BCME_NOMEM; |
| goto fail; |
| } |
| *vars_sz = MAXSZ_NVRAM_VARS; |
| |
| /* query the name=value pairs */ |
| if ((ret = nvram_getall(*vars, *vars_sz)) != BCME_OK) { |
| goto fail; |
| } |
| |
| /* treat empty name=value list as an error so that we can indicate |
| * the condition up throught error code return... |
| */ |
| if (*vars_sz == 0) { |
| ret = BCME_ERROR; |
| goto fail; |
| } |
| |
| return BCME_OK; |
| |
| fail: |
| if (*vars != NULL) { |
| MFREE(osh, *vars, MAXSZ_NVRAM_VARS); |
| } |
| *vars = NULL; |
| *vars_sz = 0; |
| return ret; |
| } |
| #endif /* BCMNVRAMVARS */ |
| |
| /** |
| * Initialize local vars from the right source for this platform. Called from siutils.c. |
| * |
| * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this |
| * function set 'vars' to NULL, in that case this function will prematurely return. |
| * |
| * Return 0 on success, nonzero on error. |
| */ |
| int |
| BCMATTACHFN(srom_var_init)(si_t *sih, uint bustype, volatile 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 SI_BUS: |
| #ifdef BCMPCIEDEV |
| if (BCMPCIEDEV_ENAB()) { |
| int ret; |
| |
| ret = initvars_cis_pci(sih, osh, curmap, vars, count); |
| |
| #ifdef BCMPCIEDEV_SROM_FORMAT |
| if (ret) |
| ret = initvars_srom_pci(sih, curmap, vars, count); |
| #endif |
| if (ret) |
| ret = initvars_srom_si(sih, osh, curmap, vars, count); |
| return ret; |
| } else |
| #endif /* BCMPCIEDEV */ |
| { |
| return initvars_srom_si(sih, osh, curmap, vars, count); |
| } |
| case PCI_BUS: { |
| int ret; |
| |
| #ifdef BCMNVRAMVARS |
| if ((ret = initvars_nvram_vars(sih, osh, vars, count)) == BCME_OK) { |
| return ret; |
| } else |
| #endif |
| { |
| ASSERT(curmap != NULL); |
| if (curmap == NULL) |
| return (-1); |
| |
| /* First check for CIS format. if not CIS, try SROM format */ |
| if ((ret = initvars_cis_pci(sih, osh, curmap, vars, count))) |
| return initvars_srom_pci(sih, curmap, vars, count); |
| return ret; |
| } |
| } |
| |
| #ifdef BCMSDIO |
| case SDIO_BUS: |
| return initvars_cis_sdio(sih, osh, vars, count); |
| #endif /* BCMSDIO */ |
| |
| #ifdef BCMSPI |
| case SPI_BUS: |
| return initvars_cis_spi(sih, osh, vars, count); |
| #endif /* BCMSPI */ |
| |
| default: |
| ASSERT(0); |
| } |
| return (-1); |
| } |
| #endif /* !defined(BCMDONGLEHOST) */ |
| |
| /** support only 16-bit word read from srom */ |
| int |
| srom_read(si_t *sih, uint bustype, volatile void *curmap, osl_t *osh, |
| uint byteoff, uint nbytes, uint16 *buf, bool check_crc) |
| { |
| uint i, off, nw; |
| |
| BCM_REFERENCE(i); |
| |
| ASSERT(bustype == BUSTYPE(bustype)); |
| |
| /* check input - 16-bit access only */ |
| if (byteoff & 1 || nbytes & 1 || (byteoff + nbytes) > SROM_MAX) |
| return 1; |
| |
| off = byteoff / 2; |
| nw = nbytes / 2; |
| |
| #ifdef BCMPCIEDEV |
| if ((BUSTYPE(bustype) == SI_BUS) && |
| (BCM43602_CHIP(sih->chip) || |
| (BCM4369_CHIP(sih->chip)) || |
| (BCM4378_CHIP(sih->chip)) || |
| (BCM4387_CHIP(sih->chip)) || |
| (BCM4388_CHIP(sih->chip)) || |
| (BCM4362_CHIP(sih->chip)) || |
| (BCM4385_CHIP(sih->chip)) || |
| (BCM4389_CHIP(sih->chip)) || |
| (BCM4397_CHIP(sih->chip)) || |
| |
| #ifdef UNRELEASEDCHIP |
| #endif |
| |
| FALSE)) { /* building firmware for chips with a PCIe interface and internal SI bus */ |
| #else |
| if (BUSTYPE(bustype) == PCI_BUS) { |
| #endif /* BCMPCIEDEV */ |
| if (!curmap) |
| return 1; |
| |
| if (si_is_sprom_available(sih)) { |
| volatile uint16 *srom; |
| |
| srom = (volatile uint16 *)srom_offset(sih, curmap); |
| if (srom == NULL) |
| return 1; |
| |
| if (sprom_read_pci(osh, sih, srom, off, buf, nw, check_crc)) |
| return 1; |
| } |
| #if !defined(BCMDONGLEHOST) && (defined(BCMNVRAMW) || defined(BCMNVRAMR)) |
| else if (!((BUSTYPE(bustype) == SI_BUS) && |
| (BCM43602_CHIP(sih->chip) || |
| (BCM4369_CHIP(sih->chip)) || |
| (BCM4362_CHIP(sih->chip)) || |
| (BCM4378_CHIP(sih->chip)) || |
| (BCM4385_CHIP(sih->chip)) || |
| (BCM4389_CHIP(sih->chip)) || |
| (BCM4387_CHIP(sih->chip)) || |
| (BCM4388_CHIP(sih->chip)) || |
| (BCM4397_CHIP(sih->chip)) || |
| 0))) { |
| if (otp_read_pci(osh, sih, buf, nbytes)) |
| return 1; |
| } |
| #endif /* !BCMDONGLEHOST && (BCMNVRAMW||BCMNVRAMR) */ |
| #ifdef BCMSDIO |
| } else if (BUSTYPE(bustype) == SDIO_BUS) { |
| off = byteoff / 2; |
| nw = nbytes / 2; |
| for (i = 0; i < nw; i++) { |
| if (sprom_read_sdio(osh, (uint16)(off + i), (uint16 *)(buf + i))) |
| return 1; |
| } |
| #endif /* BCMSDIO */ |
| #ifdef BCMSPI |
| } else if (BUSTYPE(bustype) == SPI_BUS) { |
| if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, (uint8 *)buf, byteoff + nbytes) != 0) |
| return 1; |
| #endif /* BCMSPI */ |
| } else if (BUSTYPE(bustype) == SI_BUS) { |
| return 1; |
| } else { |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) |
| /** support only 16-bit word write into srom */ |
| int |
| srom_write(si_t *sih, uint bustype, volatile void *curmap, osl_t *osh, |
| uint byteoff, uint nbytes, uint16 *buf) |
| { |
| uint i, nw, crc_range; |
| uint16 *old, *new; |
| uint8 crc; |
| volatile uint32 val32; |
| int rc = 1; |
| |
| ASSERT(bustype == BUSTYPE(bustype)); |
| |
| /* freed in same function */ |
| old = MALLOC_NOPERSIST(osh, SROM_MAXW * sizeof(uint16)); |
| new = MALLOC_NOPERSIST(osh, SROM_MAXW * sizeof(uint16)); |
| |
| if (old == NULL || new == NULL) |
| goto done; |
| |
| /* check input - 16-bit access only. use byteoff 0x55aa to indicate |
| * srclear |
| */ |
| if ((byteoff != 0x55aa) && ((byteoff & 1) || (nbytes & 1))) |
| goto done; |
| |
| if ((byteoff != 0x55aa) && ((byteoff + nbytes) > SROM_MAX)) |
| goto done; |
| |
| if (FALSE) { |
| } |
| #ifdef BCMSDIO |
| else if (BUSTYPE(bustype) == SDIO_BUS) { |
| crc_range = SROM_MAX; |
| } |
| #endif |
| else { |
| crc_range = srom_size(sih, osh); |
| } |
| |
| nw = crc_range / 2; |
| /* read first small number words from srom, then adjust the length, read all */ |
| if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) |
| goto done; |
| |
| BS_ERROR(("srom_write: old[SROM4_SIGN] 0x%x, old[SROM8_SIGN] 0x%x\n", |
| old[SROM4_SIGN], old[SROM8_SIGN])); |
| /* Deal with blank srom */ |
| if (old[0] == 0xffff) { |
| /* Do nothing to blank srom when it's srclear */ |
| if (byteoff == 0x55aa) { |
| rc = 0; |
| goto done; |
| } |
| |
| /* see if the input buffer is valid SROM image or not */ |
| if (buf[SROM11_SIGN] == SROM11_SIGNATURE) { |
| BS_ERROR(("srom_write: buf[SROM11_SIGN] 0x%x\n", |
| buf[SROM11_SIGN])); |
| |
| /* block invalid buffer size */ |
| if (nbytes < SROM11_WORDS * 2) { |
| rc = BCME_BUFTOOSHORT; |
| goto done; |
| } else if (nbytes > SROM11_WORDS * 2) { |
| rc = BCME_BUFTOOLONG; |
| goto done; |
| } |
| |
| nw = SROM11_WORDS; |
| |
| } else if (buf[SROM12_SIGN] == SROM12_SIGNATURE) { |
| BS_ERROR(("srom_write: buf[SROM12_SIGN] 0x%x\n", |
| buf[SROM12_SIGN])); |
| |
| /* block invalid buffer size */ |
| if (nbytes < SROM12_WORDS * 2) { |
| rc = BCME_BUFTOOSHORT; |
| goto done; |
| } else if (nbytes > SROM12_WORDS * 2) { |
| rc = BCME_BUFTOOLONG; |
| goto done; |
| } |
| |
| nw = SROM12_WORDS; |
| |
| } else if (buf[SROM13_SIGN] == SROM13_SIGNATURE) { |
| BS_ERROR(("srom_write: buf[SROM13_SIGN] 0x%x\n", |
| buf[SROM13_SIGN])); |
| |
| /* block invalid buffer size */ |
| if (nbytes < SROM13_WORDS * 2) { |
| rc = BCME_BUFTOOSHORT; |
| goto done; |
| } else if (nbytes > SROM13_WORDS * 2) { |
| rc = BCME_BUFTOOLONG; |
| goto done; |
| } |
| |
| nw = SROM13_WORDS; |
| |
| } else if (buf[SROM16_SIGN] == SROM16_SIGNATURE) { |
| BS_ERROR(("srom_write: buf[SROM16_SIGN] 0x%x\n", |
| buf[SROM16_SIGN])); |
| |
| /* block invalid buffer size */ |
| if (nbytes < SROM16_WORDS * 2) { |
| rc = BCME_BUFTOOSHORT; |
| goto done; |
| } else if (nbytes > SROM16_WORDS * 2) { |
| rc = BCME_BUFTOOLONG; |
| goto done; |
| } |
| |
| nw = SROM16_WORDS; |
| |
| } else if (buf[SROM17_SIGN] == SROM17_SIGNATURE) { |
| BS_ERROR(("srom_write: buf[SROM17_SIGN] 0x%x\n", |
| buf[SROM17_SIGN])); |
| |
| /* block invalid buffer size */ |
| if (nbytes < SROM17_WORDS * 2) { |
| rc = BCME_BUFTOOSHORT; |
| goto done; |
| } else if (nbytes > SROM17_WORDS * 2) { |
| rc = BCME_BUFTOOLONG; |
| goto done; |
| } |
| |
| nw = SROM17_WORDS; |
| } else if (buf[SROM18_SIGN] == SROM18_SIGNATURE) { |
| BS_ERROR(("srom_write: buf[SROM18_SIGN] 0x%x\n", |
| buf[SROM18_SIGN])); |
| |
| /* block invalid buffer size */ |
| /* nbytes can be < SROM18 bytes since host limits transfer chunk size |
| * to 1500 Bytes |
| */ |
| if (nbytes > SROM18_WORDS * 2) { |
| rc = BCME_BUFTOOLONG; |
| goto done; |
| } |
| |
| nw = SROM18_WORDS; |
| |
| } else if (buf[SROM11_SIGN] == SROM15_SIGNATURE) { |
| BS_ERROR(("srom_write: buf[SROM15_SIGN] 0x%x\n", |
| buf[SROM11_SIGN])); |
| /* nbytes can be < SROM15 bytes since host limits trasnfer chunk size |
| * to 1518 Bytes |
| */ |
| if (nbytes > SROM15_WORDS * 2) { |
| rc = BCME_BUFTOOLONG; |
| goto done; |
| } |
| nw = SROM15_WORDS; |
| } else if ((buf[SROM4_SIGN] == SROM4_SIGNATURE) || |
| (buf[SROM8_SIGN] == SROM4_SIGNATURE)) { |
| BS_ERROR(("srom_write: buf[SROM4_SIGN] 0x%x, buf[SROM8_SIGN] 0x%x\n", |
| buf[SROM4_SIGN], buf[SROM8_SIGN])); |
| |
| /* block invalid buffer size */ |
| if (nbytes < SROM4_WORDS * 2) { |
| rc = BCME_BUFTOOSHORT; |
| goto done; |
| } else if (nbytes > SROM4_WORDS * 2) { |
| rc = BCME_BUFTOOLONG; |
| goto done; |
| } |
| |
| nw = SROM4_WORDS; |
| } else if (nbytes == SROM_WORDS * 2){ /* the other possible SROM format */ |
| BS_ERROR(("srom_write: Not SROM4 or SROM8.\n")); |
| |
| nw = SROM_WORDS; |
| } else { |
| BS_ERROR(("srom_write: Invalid input file signature\n")); |
| rc = BCME_BADARG; |
| goto done; |
| } |
| crc_range = nw * 2; |
| if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) { |
| goto done; |
| } |
| } else if (old[SROM18_SIGN] == SROM18_SIGNATURE) { |
| nw = SROM18_WORDS; |
| crc_range = nw * 2; |
| if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) { |
| goto done; |
| } |
| } else if (old[SROM17_SIGN] == SROM17_SIGNATURE) { |
| nw = SROM17_WORDS; |
| crc_range = nw * 2; |
| if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) { |
| goto done; |
| } |
| } else if (old[SROM16_SIGN] == SROM16_SIGNATURE) { |
| nw = SROM16_WORDS; |
| crc_range = nw * 2; |
| if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) { |
| goto done; |
| } |
| } else if (old[SROM15_SIGN] == SROM15_SIGNATURE) { |
| nw = SROM15_WORDS; |
| crc_range = nw * 2; |
| if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) { |
| goto done; |
| } |
| } else if (old[SROM13_SIGN] == SROM13_SIGNATURE) { |
| nw = SROM13_WORDS; |
| crc_range = nw * 2; |
| if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) { |
| goto done; |
| } |
| } else if (old[SROM12_SIGN] == SROM12_SIGNATURE) { |
| nw = SROM12_WORDS; |
| crc_range = nw * 2; |
| if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) { |
| goto done; |
| } |
| } else if (old[SROM11_SIGN] == SROM11_SIGNATURE) { |
| nw = SROM11_WORDS; |
| crc_range = nw * 2; |
| if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) { |
| goto done; |
| } |
| } else if ((old[SROM4_SIGN] == SROM4_SIGNATURE) || |
| (old[SROM8_SIGN] == SROM4_SIGNATURE)) { |
| nw = SROM4_WORDS; |
| crc_range = nw * 2; |
| if (srom_read(sih, bustype, curmap, osh, 0, crc_range, old, FALSE)) { |
| goto done; |
| } |
| } else { |
| /* Assert that we have already read enough for sromrev 2 */ |
| ASSERT(crc_range >= SROM_WORDS * 2); |
| nw = SROM_WORDS; |
| crc_range = nw * 2; |
| } |
| |
| if (byteoff == 0x55aa) { |
| /* Erase request */ |
| crc_range = 0; |
| memset((void *)new, 0xff, nw * 2); |
| } else { |
| /* Copy old contents */ |
| bcopy((void *)old, (void *)new, nw * 2); |
| /* make changes */ |
| bcopy((void *)buf, (void *)&new[byteoff / 2], nbytes); |
| } |
| |
| if (crc_range) { |
| /* calculate crc */ |
| htol16_buf(new, crc_range); |
| crc = ~hndcrc8((uint8 *)new, crc_range - 1, CRC8_INIT_VALUE); |
| ltoh16_buf(new, crc_range); |
| new[nw - 1] = (crc << 8) | (new[nw - 1] & 0xff); |
| } |
| |
| #ifdef BCMPCIEDEV |
| if ((BUSTYPE(bustype) == SI_BUS) && |
| (BCM43602_CHIP(sih->chip) || |
| (BCM4369_CHIP(sih->chip)) || |
| (BCM4362_CHIP(sih->chip)) || |
| (BCM4378_CHIP(sih->chip)) || |
| (BCM4387_CHIP(sih->chip)) || |
| (BCM4388_CHIP(sih->chip)) || |
| (BCM4385_CHIP(sih->chip)) || |
| (BCM4389_CHIP(sih->chip)) || |
| (BCM4397_CHIP(sih->chip)) || |
| |
| #ifdef UNRELEASEDCHIP |
| #endif /* UNRELEASEDCHIP */ |
| |
| FALSE)) { |
| #else |
| if (BUSTYPE(bustype) == PCI_BUS) { |
| #endif /* BCMPCIEDEV */ |
| volatile uint16 *srom = NULL; |
| volatile void *ccregs = NULL; |
| uint32 ccval = 0; |
| |
| if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43460_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43526_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM4352_CHIP_ID) || |
| BCM43602_CHIP(sih->chip)) { |
| /* save current control setting */ |
| ccval = si_chipcontrl_read(sih); |
| } |
| |
| if (BCM43602_CHIP(sih->chip) || |
| (((CHIPID(sih->chip) == BCM4360_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43460_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM4352_CHIP_ID)) && |
| (CHIPREV(sih->chiprev) <= 2))) { |
| si_chipcontrl_srom4360(sih, TRUE); |
| } |
| |
| if (FALSE) { |
| si_srom_clk_set(sih); /* corrects srom clock frequency */ |
| } |
| |
| /* enable writes to the SPROM */ |
| if (sih->ccrev > 31) { |
| if (BUSTYPE(sih->bustype) == SI_BUS) |
| ccregs = (void *)(uintptr)SI_ENUM_BASE(sih); |
| else |
| ccregs = ((volatile uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET); |
| srom = (volatile uint16 *)((volatile uint8 *)ccregs + CC_SROM_OTP); |
| (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WREN, 0, 0); |
| } else { |
| srom = (volatile uint16 *) |
| ((volatile uint8 *)curmap + PCI_BAR0_SPROM_OFFSET); |
| 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++) { |
| if (old[i] != new[i]) { |
| if (sih->ccrev > 31) { |
| if ((sih->cccaps & CC_CAP_SROM) == 0) { |
| /* No srom support in this chip */ |
| BS_ERROR(("srom_write, invalid srom, skip\n")); |
| } else |
| (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRITE, |
| i, new[i]); |
| } else { |
| W_REG(osh, &srom[i], new[i]); |
| } |
| bcm_mdelay(WRITE_WORD_DELAY); |
| } |
| } |
| /* disable writes to the SPROM */ |
| if (sih->ccrev > 31) { |
| (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRDIS, 0, 0); |
| } else { |
| OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 & |
| ~SPROM_WRITEEN); |
| } |
| |
| if (BCM43602_CHIP(sih->chip) || |
| (CHIPID(sih->chip) == BCM4360_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43460_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { |
| /* Restore config after reading SROM */ |
| si_chipcontrl_restore(sih, ccval); |
| } |
| #ifdef BCMSDIO |
| } else if (BUSTYPE(bustype) == SDIO_BUS) { |
| /* enable writes to the SPROM */ |
| if (sprom_cmd_sdio(osh, SBSDIO_SPROM_WEN)) |
| goto done; |
| bcm_mdelay(WRITE_ENABLE_DELAY); |
| /* write srom */ |
| for (i = 0; i < nw; i++) { |
| if (old[i] != new[i]) { |
| sprom_write_sdio(osh, (uint16)(i), new[i]); |
| bcm_mdelay(WRITE_WORD_DELAY); |
| } |
| } |
| /* disable writes to the SPROM */ |
| if (sprom_cmd_sdio(osh, SBSDIO_SPROM_WDS)) |
| goto done; |
| #endif /* BCMSDIO */ |
| } else if (BUSTYPE(bustype) == SI_BUS) { |
| goto done; |
| } else { |
| goto done; |
| } |
| |
| bcm_mdelay(WRITE_ENABLE_DELAY); |
| rc = 0; |
| |
| done: |
| if (old != NULL) |
| MFREE(osh, old, SROM_MAXW * sizeof(uint16)); |
| if (new != NULL) |
| MFREE(osh, new, SROM_MAXW * sizeof(uint16)); |
| |
| return rc; |
| } |
| |
| /** support only 16-bit word write into srom */ |
| int |
| srom_write_short(si_t *sih, uint bustype, volatile void *curmap, osl_t *osh, |
| uint byteoff, uint16 value) |
| { |
| volatile uint32 val32; |
| int rc = 1; |
| |
| ASSERT(bustype == BUSTYPE(bustype)); |
| |
| if (byteoff & 1) |
| goto done; |
| |
| #ifdef BCMPCIEDEV |
| if ((BUSTYPE(bustype) == SI_BUS) && |
| (BCM43602_CHIP(sih->chip) || |
| FALSE)) { |
| #else |
| if (BUSTYPE(bustype) == PCI_BUS) { |
| #endif /* BCMPCIEDEV */ |
| volatile uint16 *srom = NULL; |
| volatile void *ccregs = NULL; |
| uint32 ccval = 0; |
| |
| if (BCM43602_CHIP(sih->chip) || |
| (CHIPID(sih->chip) == BCM4360_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43460_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43526_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { |
| /* save current control setting */ |
| ccval = si_chipcontrl_read(sih); |
| } |
| |
| if (BCM43602_CHIP(sih->chip) || |
| (((CHIPID(sih->chip) == BCM4360_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43460_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM4352_CHIP_ID)) && |
| (CHIPREV(sih->chiprev) <= 2))) { |
| si_chipcontrl_srom4360(sih, TRUE); |
| } |
| |
| if (FALSE) { |
| si_srom_clk_set(sih); /* corrects srom clock frequency */ |
| } |
| |
| /* enable writes to the SPROM */ |
| if (sih->ccrev > 31) { |
| if (BUSTYPE(sih->bustype) == SI_BUS) |
| ccregs = (void *)(uintptr)SI_ENUM_BASE(sih); |
| else |
| ccregs = ((volatile uint8 *)curmap + PCI_16KB0_CCREGS_OFFSET); |
| srom = (volatile uint16 *)((volatile uint8 *)ccregs + CC_SROM_OTP); |
| (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WREN, 0, 0); |
| } else { |
| srom = (volatile uint16 *) |
| ((volatile uint8 *)curmap + PCI_BAR0_SPROM_OFFSET); |
| 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 */ |
| if (sih->ccrev > 31) { |
| if ((sih->cccaps & CC_CAP_SROM) == 0) { |
| /* No srom support in this chip */ |
| BS_ERROR(("srom_write, invalid srom, skip\n")); |
| } else |
| (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRITE, |
| byteoff/2, value); |
| } else { |
| W_REG(osh, &srom[byteoff/2], value); |
| } |
| bcm_mdelay(WRITE_WORD_DELAY); |
| |
| /* disable writes to the SPROM */ |
| if (sih->ccrev > 31) { |
| (void)srom_cc_cmd(sih, osh, ccregs, SRC_OP_WRDIS, 0, 0); |
| } else { |
| OSL_PCI_WRITE_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32), val32 & |
| ~SPROM_WRITEEN); |
| } |
| |
| if (BCM43602_CHIP(sih->chip) || |
| (CHIPID(sih->chip) == BCM4360_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43460_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43526_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { |
| /* Restore config after reading SROM */ |
| si_chipcontrl_restore(sih, ccval); |
| } |
| #ifdef BCMSDIO |
| } else if (BUSTYPE(bustype) == SDIO_BUS) { |
| /* enable writes to the SPROM */ |
| if (sprom_cmd_sdio(osh, SBSDIO_SPROM_WEN)) |
| goto done; |
| bcm_mdelay(WRITE_ENABLE_DELAY); |
| /* write srom */ |
| sprom_write_sdio(osh, (uint16)(byteoff/2), value); |
| bcm_mdelay(WRITE_WORD_DELAY); |
| |
| /* disable writes to the SPROM */ |
| if (sprom_cmd_sdio(osh, SBSDIO_SPROM_WDS)) |
| goto done; |
| #endif /* BCMSDIO */ |
| } else if (BUSTYPE(bustype) == SI_BUS) { |
| goto done; |
| } else { |
| goto done; |
| } |
| |
| bcm_mdelay(WRITE_ENABLE_DELAY); |
| rc = 0; |
| |
| done: |
| return rc; |
| } |
| #endif /* defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) */ |
| |
| /** |
| * These 'vstr_*' definitions are used to convert from CIS format to a 'NVRAM var=val' format, the |
| * NVRAM format is used throughout the rest of the firmware. |
| */ |
| #if !defined(BCMDONGLEHOST) |
| static const char BCMATTACHDATA(vstr_manf)[] = "manf=%s"; |
| static const char BCMATTACHDATA(vstr_productname)[] = "productname=%s"; |
| static const char BCMATTACHDATA(vstr_manfid)[] = "manfid=0x%x"; |
| static const char BCMATTACHDATA(vstr_prodid)[] = "prodid=0x%x"; |
| #ifdef BCMSDIO |
| static const char BCMATTACHDATA(vstr_sdmaxspeed)[] = "sdmaxspeed=%d"; |
| static const char BCMATTACHDATA(vstr_sdmaxblk)[][13] = |
| { "sdmaxblk0=%d", "sdmaxblk1=%d", "sdmaxblk2=%d" }; |
| #endif |
| static const char BCMATTACHDATA(vstr_regwindowsz)[] = "regwindowsz=%d"; |
| static const char BCMATTACHDATA(vstr_sromrev)[] = "sromrev=%d"; |
| static const char BCMATTACHDATA(vstr_chiprev)[] = "chiprev=%d"; |
| static const char BCMATTACHDATA(vstr_subvendid)[] = "subvendid=0x%x"; |
| static const char BCMATTACHDATA(vstr_subdevid)[] = "subdevid=0x%x"; |
| static const char BCMATTACHDATA(vstr_boardrev)[] = "boardrev=0x%x"; |
| static const char BCMATTACHDATA(vstr_aa2g)[] = "aa2g=0x%x"; |
| static const char BCMATTACHDATA(vstr_aa5g)[] = "aa5g=0x%x"; |
| static const char BCMATTACHDATA(vstr_ag)[] = "ag%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_cc)[] = "cc=%d"; |
| static const char BCMATTACHDATA(vstr_opo)[] = "opo=%d"; |
| static const char BCMATTACHDATA(vstr_pa0b)[][9] = { "pa0b0=%d", "pa0b1=%d", "pa0b2=%d" }; |
| static const char BCMATTACHDATA(vstr_pa0b_lo)[][12] = |
| { "pa0b0_lo=%d", "pa0b1_lo=%d", "pa0b2_lo=%d" }; |
| static const char BCMATTACHDATA(vstr_pa0itssit)[] = "pa0itssit=%d"; |
| static const char BCMATTACHDATA(vstr_pa0maxpwr)[] = "pa0maxpwr=%d"; |
| static const char BCMATTACHDATA(vstr_pa1b)[][9] = { "pa1b0=%d", "pa1b1=%d", "pa1b2=%d" }; |
| static const char BCMATTACHDATA(vstr_pa1lob)[][11] = |
| { "pa1lob0=%d", "pa1lob1=%d", "pa1lob2=%d" }; |
| static const char BCMATTACHDATA(vstr_pa1hib)[][11] = |
| { "pa1hib0=%d", "pa1hib1=%d", "pa1hib2=%d" }; |
| static const char BCMATTACHDATA(vstr_pa1itssit)[] = "pa1itssit=%d"; |
| static const char BCMATTACHDATA(vstr_pa1maxpwr)[] = "pa1maxpwr=%d"; |
| static const char BCMATTACHDATA(vstr_pa1lomaxpwr)[] = "pa1lomaxpwr=%d"; |
| static const char BCMATTACHDATA(vstr_pa1himaxpwr)[] = "pa1himaxpwr=%d"; |
| static const char BCMATTACHDATA(vstr_oem)[] = "oem=%02x%02x%02x%02x%02x%02x%02x%02x"; |
| static const char BCMATTACHDATA(vstr_boardflags)[] = "boardflags=0x%x"; |
| static const char BCMATTACHDATA(vstr_boardflags2)[] = "boardflags2=0x%x"; |
| static const char BCMATTACHDATA(vstr_boardflags3)[] = "boardflags3=0x%x"; |
| static const char BCMATTACHDATA(vstr_boardflags4)[] = "boardflags4=0x%x"; |
| static const char BCMATTACHDATA(vstr_boardflags5)[] = "boardflags5=0x%x"; |
| static const char BCMATTACHDATA(vstr_noccode)[] = "ccode=0x0"; |
| static const char BCMATTACHDATA(vstr_ccode)[] = "ccode=%c%c"; |
| static const char BCMATTACHDATA(vstr_cctl)[] = "cctl=0x%x"; |
| static const char BCMATTACHDATA(vstr_cckpo)[] = "cckpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_ofdmpo)[] = "ofdmpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_rdlid)[] = "rdlid=0x%x"; |
| #ifdef BCM_BOOTLOADER |
| static const char BCMATTACHDATA(vstr_rdlrndis)[] = "rdlrndis=%d"; |
| static const char BCMATTACHDATA(vstr_rdlrwu)[] = "rdlrwu=%d"; |
| static const char BCMATTACHDATA(vstr_rdlsn)[] = "rdlsn=%d"; |
| #endif /* BCM_BOOTLOADER */ |
| static const char BCMATTACHDATA(vstr_usbfs)[] = "usbfs=%d"; |
| static const char BCMATTACHDATA(vstr_wpsgpio)[] = "wpsgpio=%d"; |
| static const char BCMATTACHDATA(vstr_wpsled)[] = "wpsled=%d"; |
| static const char BCMATTACHDATA(vstr_rssismf2g)[] = "rssismf2g=%d"; |
| static const char BCMATTACHDATA(vstr_rssismc2g)[] = "rssismc2g=%d"; |
| static const char BCMATTACHDATA(vstr_rssisav2g)[] = "rssisav2g=%d"; |
| static const char BCMATTACHDATA(vstr_bxa2g)[] = "bxa2g=%d"; |
| static const char BCMATTACHDATA(vstr_rssismf5g)[] = "rssismf5g=%d"; |
| static const char BCMATTACHDATA(vstr_rssismc5g)[] = "rssismc5g=%d"; |
| static const char BCMATTACHDATA(vstr_rssisav5g)[] = "rssisav5g=%d"; |
| static const char BCMATTACHDATA(vstr_bxa5g)[] = "bxa5g=%d"; |
| static const char BCMATTACHDATA(vstr_tri2g)[] = "tri2g=%d"; |
| static const char BCMATTACHDATA(vstr_tri5gl)[] = "tri5gl=%d"; |
| static const char BCMATTACHDATA(vstr_tri5g)[] = "tri5g=%d"; |
| static const char BCMATTACHDATA(vstr_tri5gh)[] = "tri5gh=%d"; |
| static const char BCMATTACHDATA(vstr_rxpo2g)[] = "rxpo2g=%d"; |
| static const char BCMATTACHDATA(vstr_rxpo5g)[] = "rxpo5g=%d"; |
| static const char BCMATTACHDATA(vstr_boardtype)[] = "boardtype=0x%x"; |
| static const char BCMATTACHDATA(vstr_vendid)[] = "vendid=0x%x"; |
| static const char BCMATTACHDATA(vstr_devid)[] = "devid=0x%x"; |
| static const char BCMATTACHDATA(vstr_xtalfreq)[] = "xtalfreq=%d"; |
| static const char BCMATTACHDATA(vstr_txchain)[] = "txchain=0x%x"; |
| static const char BCMATTACHDATA(vstr_rxchain)[] = "rxchain=0x%x"; |
| static const char BCMATTACHDATA(vstr_elna2g)[] = "elna2g=0x%x"; |
| static const char BCMATTACHDATA(vstr_elna5g)[] = "elna5g=0x%x"; |
| static const char BCMATTACHDATA(vstr_antswitch)[] = "antswitch=0x%x"; |
| static const char BCMATTACHDATA(vstr_regrev)[] = "regrev=0x%x"; |
| static const char BCMATTACHDATA(vstr_antswctl2g)[] = "antswctl2g=0x%x"; |
| static const char BCMATTACHDATA(vstr_triso2g)[] = "triso2g=0x%x"; |
| static const char BCMATTACHDATA(vstr_pdetrange2g)[] = "pdetrange2g=0x%x"; |
| static const char BCMATTACHDATA(vstr_extpagain2g)[] = "extpagain2g=0x%x"; |
| static const char BCMATTACHDATA(vstr_tssipos2g)[] = "tssipos2g=0x%x"; |
| static const char BCMATTACHDATA(vstr_antswctl5g)[] = "antswctl5g=0x%x"; |
| static const char BCMATTACHDATA(vstr_triso5g)[] = "triso5g=0x%x"; |
| static const char BCMATTACHDATA(vstr_pdetrange5g)[] = "pdetrange5g=0x%x"; |
| static const char BCMATTACHDATA(vstr_extpagain5g)[] = "extpagain5g=0x%x"; |
| static const char BCMATTACHDATA(vstr_tssipos5g)[] = "tssipos5g=0x%x"; |
| static const char BCMATTACHDATA(vstr_maxp2ga)[] = "maxp2ga%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_itt2ga0)[] = "itt2ga0=0x%x"; |
| static const char BCMATTACHDATA(vstr_pa)[] = "pa%dgw%da%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_pahl)[] = "pa%dg%cw%da%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_maxp5ga0)[] = "maxp5ga0=0x%x"; |
| static const char BCMATTACHDATA(vstr_itt5ga0)[] = "itt5ga0=0x%x"; |
| static const char BCMATTACHDATA(vstr_maxp5gha0)[] = "maxp5gha0=0x%x"; |
| static const char BCMATTACHDATA(vstr_maxp5gla0)[] = "maxp5gla0=0x%x"; |
| static const char BCMATTACHDATA(vstr_itt2ga1)[] = "itt2ga1=0x%x"; |
| static const char BCMATTACHDATA(vstr_maxp5ga1)[] = "maxp5ga1=0x%x"; |
| static const char BCMATTACHDATA(vstr_itt5ga1)[] = "itt5ga1=0x%x"; |
| static const char BCMATTACHDATA(vstr_maxp5gha1)[] = "maxp5gha1=0x%x"; |
| static const char BCMATTACHDATA(vstr_maxp5gla1)[] = "maxp5gla1=0x%x"; |
| static const char BCMATTACHDATA(vstr_cck2gpo)[] = "cck2gpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_ofdm2gpo)[] = "ofdm2gpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_ofdm5gpo)[] = "ofdm5gpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_ofdm5glpo)[] = "ofdm5glpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_ofdm5ghpo)[] = "ofdm5ghpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_cddpo)[] = "cddpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_stbcpo)[] = "stbcpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_bw40po)[] = "bw40po=0x%x"; |
| static const char BCMATTACHDATA(vstr_bwduppo)[] = "bwduppo=0x%x"; |
| static const char BCMATTACHDATA(vstr_mcspo)[] = "mcs%dgpo%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_mcspohl)[] = "mcs%dg%cpo%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_custom)[] = "customvar%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_cckdigfilttype)[] = "cckdigfilttype=%d"; |
| static const char BCMATTACHDATA(vstr_usbflags)[] = "usbflags=0x%x"; |
| #ifdef BCM_BOOTLOADER |
| static const char BCMATTACHDATA(vstr_mdio)[] = "mdio%d=0x%%x"; |
| static const char BCMATTACHDATA(vstr_mdioex)[] = "mdioex%d=0x%%x"; |
| static const char BCMATTACHDATA(vstr_brmin)[] = "brmin=0x%x"; |
| static const char BCMATTACHDATA(vstr_brmax)[] = "brmax=0x%x"; |
| static const char BCMATTACHDATA(vstr_pllreg)[] = "pll%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_ccreg)[] = "chipc%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_regctrl)[] = "reg%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_time)[] = "r%dt=0x%x"; |
| static const char BCMATTACHDATA(vstr_depreg)[] = "r%dd=0x%x"; |
| static const char BCMATTACHDATA(vstr_usbpredly)[] = "usbpredly=0x%x"; |
| static const char BCMATTACHDATA(vstr_usbpostdly)[] = "usbpostdly=0x%x"; |
| static const char BCMATTACHDATA(vstr_usbrdy)[] = "usbrdy=0x%x"; |
| static const char BCMATTACHDATA(vstr_hsicphyctrl1)[] = "hsicphyctrl1=0x%x"; |
| static const char BCMATTACHDATA(vstr_hsicphyctrl2)[] = "hsicphyctrl2=0x%x"; |
| static const char BCMATTACHDATA(vstr_usbdevctrl)[] = "usbdevctrl=0x%x"; |
| static const char BCMATTACHDATA(vstr_bldr_reset_timeout)[] = "bldr_to=0x%x"; |
| static const char BCMATTACHDATA(vstr_muxenab)[] = "muxenab=0x%x"; |
| static const char BCMATTACHDATA(vstr_pubkey)[] = "pubkey=%s"; |
| #endif /* BCM_BOOTLOADER */ |
| static const char BCMATTACHDATA(vstr_boardnum)[] = "boardnum=%d"; |
| static const char BCMATTACHDATA(vstr_macaddr)[] = "macaddr=%s"; |
| static const char BCMATTACHDATA(vstr_macaddr2)[] = "macaddr2=%s"; |
| static const char BCMATTACHDATA(vstr_usbepnum)[] = "usbepnum=0x%x"; |
| #ifdef BCMUSBDEV_COMPOSITE |
| static const char BCMATTACHDATA(vstr_usbdesc_composite)[] = "usbdesc_composite=0x%x"; |
| #endif /* BCMUSBDEV_COMPOSITE */ |
| static const char BCMATTACHDATA(vstr_usbutmi_ctl)[] = "usbutmi_ctl=0x%x"; |
| static const char BCMATTACHDATA(vstr_usbssphy_utmi_ctl0)[] = "usbssphy_utmi_ctl0=0x%x"; |
| static const char BCMATTACHDATA(vstr_usbssphy_utmi_ctl1)[] = "usbssphy_utmi_ctl1=0x%x"; |
| static const char BCMATTACHDATA(vstr_usbssphy_utmi_ctl2)[] = "usbssphy_utmi_ctl2=0x%x"; |
| static const char BCMATTACHDATA(vstr_usbssphy_sleep0)[] = "usbssphy_sleep0=0x%x"; |
| static const char BCMATTACHDATA(vstr_usbssphy_sleep1)[] = "usbssphy_sleep1=0x%x"; |
| static const char BCMATTACHDATA(vstr_usbssphy_sleep2)[] = "usbssphy_sleep2=0x%x"; |
| static const char BCMATTACHDATA(vstr_usbssphy_sleep3)[] = "usbssphy_sleep3=0x%x"; |
| static const char BCMATTACHDATA(vstr_usbssphy_mdio)[] = "usbssmdio%d=0x%x,0x%x,0x%x,0x%x"; |
| static const char BCMATTACHDATA(vstr_usb30phy_noss)[] = "usbnoss=0x%x"; |
| static const char BCMATTACHDATA(vstr_usb30phy_u1u2)[] = "usb30u1u2=0x%x"; |
| static const char BCMATTACHDATA(vstr_usb30phy_regs)[] = "usb30regs%d=0x%x,0x%x,0x%x,0x%x"; |
| |
| /* Power per rate for SROM V9 */ |
| static const char BCMATTACHDATA(vstr_cckbw202gpo)[][21] = |
| { "cckbw202gpo=0x%x", "cckbw20ul2gpo=0x%x", "cckbw20in802gpo=0x%x" }; |
| static const char BCMATTACHDATA(vstr_legofdmbw202gpo)[][23] = |
| { "legofdmbw202gpo=0x%x", "legofdmbw20ul2gpo=0x%x" }; |
| static const char BCMATTACHDATA(vstr_legofdmbw205gpo)[][24] = |
| { "legofdmbw205glpo=0x%x", "legofdmbw20ul5glpo=0x%x", |
| "legofdmbw205gmpo=0x%x", "legofdmbw20ul5gmpo=0x%x", |
| "legofdmbw205ghpo=0x%x", "legofdmbw20ul5ghpo=0x%x" }; |
| |
| static const char BCMATTACHDATA(vstr_mcs2gpo)[][19] = |
| { "mcsbw202gpo=0x%x", "mcsbw20ul2gpo=0x%x", "mcsbw402gpo=0x%x", "mcsbw802gpo=0x%x" }; |
| |
| static const char BCMATTACHDATA(vstr_mcs5glpo)[][20] = |
| { "mcsbw205glpo=0x%x", "mcsbw20ul5glpo=0x%x", "mcsbw405glpo=0x%x" }; |
| |
| static const char BCMATTACHDATA(vstr_mcs5gmpo)[][20] = |
| { "mcsbw205gmpo=0x%x", "mcsbw20ul5gmpo=0x%x", "mcsbw405gmpo=0x%x" }; |
| |
| static const char BCMATTACHDATA(vstr_mcs5ghpo)[][20] = |
| { "mcsbw205ghpo=0x%x", "mcsbw20ul5ghpo=0x%x", "mcsbw405ghpo=0x%x" }; |
| |
| static const char BCMATTACHDATA(vstr_mcs32po)[] = "mcs32po=0x%x"; |
| static const char BCMATTACHDATA(vstr_legofdm40duppo)[] = "legofdm40duppo=0x%x"; |
| |
| /* SROM V11 */ |
| static const char BCMATTACHDATA(vstr_tempthresh)[] = "tempthresh=%d"; /* HNBU_TEMPTHRESH */ |
| static const char BCMATTACHDATA(vstr_temps_period)[] = "temps_period=%d"; |
| static const char BCMATTACHDATA(vstr_temps_hysteresis)[] = "temps_hysteresis=%d"; |
| static const char BCMATTACHDATA(vstr_tempoffset)[] = "tempoffset=%d"; |
| static const char BCMATTACHDATA(vstr_tempsense_slope)[] = "tempsense_slope=%d"; |
| static const char BCMATTACHDATA(vstr_temp_corrx)[] = "tempcorrx=%d"; |
| static const char BCMATTACHDATA(vstr_tempsense_option)[] = "tempsense_option=%d"; |
| static const char BCMATTACHDATA(vstr_phycal_tempdelta)[] = "phycal_tempdelta=%d"; |
| static const char BCMATTACHDATA(vstr_tssiposslopeg)[] = "tssiposslope%dg=%d"; /* HNBU_FEM_CFG */ |
| static const char BCMATTACHDATA(vstr_epagaing)[] = "epagain%dg=%d"; |
| static const char BCMATTACHDATA(vstr_pdgaing)[] = "pdgain%dg=%d"; |
| static const char BCMATTACHDATA(vstr_tworangetssi)[] = "tworangetssi%dg=%d"; |
| static const char BCMATTACHDATA(vstr_papdcap)[] = "papdcap%dg=%d"; |
| static const char BCMATTACHDATA(vstr_femctrl)[] = "femctrl=%d"; |
| static const char BCMATTACHDATA(vstr_gainctrlsph)[] = "gainctrlsph=%d"; |
| static const char BCMATTACHDATA(vstr_subband5gver)[] = "subband5gver=%d"; /* HNBU_ACPA_CX */ |
| static const char BCMATTACHDATA(vstr_pa2ga)[] = "pa2ga%d=0x%x,0x%x,0x%x"; |
| static const char BCMATTACHDATA(vstr_maxp5ga)[] = "maxp5ga%d=0x%x,0x%x,0x%x,0x%x"; |
| static const char BCMATTACHDATA(vstr_pa5ga)[] = "pa5ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x," |
| "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x"; |
| static const char BCMATTACHDATA(vstr_subband6gver)[] = "subband6gver=%d"; /* HNBU_ACPA_CX */ |
| static const char BCMATTACHDATA(vstr_maxp6ga)[] = "maxp6ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x"; |
| static const char BCMATTACHDATA(vstr_pa6ga)[] = "pa6ga%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x," |
| "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x"; |
| static const char BCMATTACHDATA(vstr_pa2gccka)[] = "pa2gccka%d=0x%x,0x%x,0x%x"; |
| static const char BCMATTACHDATA(vstr_pa5gbw40a)[] = "pa5gbw40a%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x," |
| "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x"; |
| static const char BCMATTACHDATA(vstr_pa5gbw80a)[] = "pa5gbw80a%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x," |
| "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x"; |
| static const char BCMATTACHDATA(vstr_pa5gbw4080a)[] = "pa5gbw4080a%d=0x%x,0x%x,0x%x,0x%x,0x%x,0x%x," |
| "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x"; |
| static const char BCMATTACHDATA(vstr_rxgainsgelnagaina)[] = "rxgains%dgelnagaina%d=%d"; |
| static const char BCMATTACHDATA(vstr_rxgainsgtrisoa)[] = "rxgains%dgtrisoa%d=%d"; |
| static const char BCMATTACHDATA(vstr_rxgainsgtrelnabypa)[] = "rxgains%dgtrelnabypa%d=%d"; |
| static const char BCMATTACHDATA(vstr_rxgainsgxelnagaina)[] = "rxgains%dg%celnagaina%d=%d"; |
| static const char BCMATTACHDATA(vstr_rxgainsgxtrisoa)[] = "rxgains%dg%ctrisoa%d=%d"; |
| static const char BCMATTACHDATA(vstr_rxgainsgxtrelnabypa)[] = "rxgains%dg%ctrelnabypa%d=%d"; |
| static const char BCMATTACHDATA(vstr_measpower)[] = "measpower=0x%x"; /* HNBU_MEAS_PWR */ |
| static const char BCMATTACHDATA(vstr_measpowerX)[] = "measpower%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_pdoffsetma)[] = "pdoffset%dma%d=0x%x"; /* HNBU_PDOFF */ |
| static const char BCMATTACHDATA(vstr_pdoffset2gma)[] = "pdoffset2g%dma%d=0x%x"; /* HNBU_PDOFF_2G */ |
| static const char BCMATTACHDATA(vstr_pdoffset2gmvalid)[] = "pdoffset2g%dmvalid=0x%x"; |
| static const char BCMATTACHDATA(vstr_rawtempsense)[] = "rawtempsense=0x%x"; |
| /* HNBU_ACPPR_2GPO */ |
| static const char BCMATTACHDATA(vstr_dot11agofdmhrbw202gpo)[] = "dot11agofdmhrbw202gpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_ofdmlrbw202gpo)[] = "ofdmlrbw202gpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_mcsbw805gpo)[] = "mcsbw805g%cpo=0x%x"; /* HNBU_ACPPR_5GPO */ |
| static const char BCMATTACHDATA(vstr_mcsbw1605gpo)[] = "mcsbw1605g%cpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_mcsbw80p805gpo)[] = "mcsbw80p805g%cpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_mcsbw80p805g1po)[] = "mcsbw80p805g%c1po=0x%x"; |
| static const char BCMATTACHDATA(vstr_mcsbw1605g1po)[] = "mcsbw1605g%c1po=0x%x"; |
| static const char BCMATTACHDATA(vstr_mcsbw805g1po)[] = "mcsbw805g%c1po=0x%x"; |
| static const char BCMATTACHDATA(vstr_mcsbw405g1po)[] = "mcsbw405g%c1po=0x%x"; |
| static const char BCMATTACHDATA(vstr_mcsbw205g1po)[] = "mcsbw205g%c1po=0x%x"; |
| static const char BCMATTACHDATA(vstr_mcslr5gpo)[] = "mcslr5g%cpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_mcslr5g1po)[] = "mcslr5g%c1po=0x%x"; |
| static const char BCMATTACHDATA(vstr_mcslr5g80p80po)[] = "mcslr5g80p80po=0x%x"; |
| /* HNBU_ACPPR_SBPO */ |
| static const char BCMATTACHDATA(vstr_sb20in40rpo)[] = "sb20in40%crpo=0x%x"; |
| /* HNBU_ACPPR_SBPO */ |
| static const char BCMATTACHDATA(vstr_sb20in40and80rpo)[] = "sb20in40and80%crpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_sb20in80and160r5gpo)[] = "sb20in80and160%cr5g%cpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_sb20in80and160r5g1po)[] = "sb20in80and160%cr5g%c1po=0x%x"; |
| static const char BCMATTACHDATA(vstr_sb2040and80in80p80r5gpo)[] = |
| "sb2040and80in80p80%cr5g%cpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_sb2040and80in80p80r5g1po)[] = |
| "sb2040and80in80p80%cr5g%c1po=0x%x"; |
| static const char BCMATTACHDATA(vstr_sb20in40dot11agofdm2gpo)[] = "sb20in40dot11agofdm2gpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_sb20in80dot11agofdm2gpo)[] = "sb20in80dot11agofdm2gpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_sb20in40ofdmlrbw202gpo)[] = "sb20in40ofdmlrbw202gpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_sb20in80ofdmlrbw202gpo)[] = "sb20in80ofdmlrbw202gpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_sb20in80p80r5gpo)[] = "sb20in80p80%cr5gpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_sb40and80r5gpo)[] = "sb40and80%cr5g%cpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_sb40and80r5g1po)[] = "sb40and80%cr5g%c1po=0x%x"; |
| static const char BCMATTACHDATA(vstr_dot11agduprpo)[] = "dot11agdup%crpo=0x%x"; |
| static const char BCMATTACHDATA(vstr_dot11agduppo)[] = "dot11agduppo=0x%x"; |
| static const char BCMATTACHDATA(vstr_noiselvl2ga)[] = "noiselvl2ga%d=%d"; /* HNBU_NOISELVL */ |
| static const char BCMATTACHDATA(vstr_noiselvl5ga)[] = "noiselvl5ga%d=%d,%d,%d,%d"; |
| /* HNBU_RXGAIN_ERR */ |
| static const char BCMATTACHDATA(vstr_rxgainerr2ga)[] = "rxgainerr2ga%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_rxgainerr5ga)[] = "rxgainerr5ga%d=0x%x,0x%x,0x%x,0x%x"; |
| static const char BCMATTACHDATA(vstr_agbg)[] = "agbg%d=0x%x"; /* HNBU_AGBGA */ |
| static const char BCMATTACHDATA(vstr_aga)[] = "aga%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_txduty_ofdm)[] = "tx_duty_cycle_ofdm_%d_5g=%d"; |
| static const char BCMATTACHDATA(vstr_txduty_thresh)[] = "tx_duty_cycle_thresh_%d_5g=%d"; |
| static const char BCMATTACHDATA(vstr_paparambwver)[] = "paparambwver=%d"; |
| |
| static const char BCMATTACHDATA(vstr_uuid)[] = "uuid=%s"; |
| |
| static const char BCMATTACHDATA(vstr_wowlgpio)[] = "wowl_gpio=%d"; |
| static const char BCMATTACHDATA(vstr_wowlgpiopol)[] = "wowl_gpiopol=%d"; |
| |
| static const char BCMATTACHDATA(rstr_ag0)[] = "ag0"; |
| static const char BCMATTACHDATA(rstr_sromrev)[] = "sromrev"; |
| |
| static const char BCMATTACHDATA(vstr_paparamrpcalvars)[][20] = |
| {"rpcal2g=0x%x", "rpcal5gb0=0x%x", "rpcal5gb1=0x%x", |
| "rpcal5gb2=0x%x", "rpcal5gb3=0x%x"}; |
| |
| static const char BCMATTACHDATA(vstr_gpdn)[] = "gpdn=0x%x"; |
| |
| /* SROM V13 PA */ |
| static const char BCMATTACHDATA(vstr_sr13pa2ga)[] = "pa2ga%d=0x%x,0x%x,0x%x,0x%x"; |
| static const char BCMATTACHDATA(vstr_maxp5gba)[] = "maxp5gb%da%d=0x%x"; |
| static const char BCMATTACHDATA(vstr_sr13pa5ga)[] = "pa5ga%d=%s"; |
| static const char BCMATTACHDATA(vstr_sr13pa5gbwa)[] = "pa5g%da%d=%s"; |
| static const char BCMATTACHDATA(vstr_pa2g40a)[] = "pa2g40a%d=0x%x,0x%x,0x%x,0x%x"; |
| |
| /* RSSI Cal parameters */ |
| static const char BCMATTACHDATA(vstr_rssicalfrqg)[] = |
| "rssi_cal_freq_grp_2g=0x%x0x%x0x%x0x%x0x%x0x%x0x%x"; |
| static const char BCMATTACHDATA(vstr_rssidelta2g)[] = |
| "rssi_delta_2gb%d=%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"; |
| static const char BCMATTACHDATA(vstr_rssidelta5g)[] = |
| "rssi_delta_5g%s=%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"; |
| |
| uint8 patch_pair = 0; |
| |
| /* For dongle HW, accept partial calibration parameters */ |
| #if defined(BCMSDIODEV) || defined(BCMUSBDEV) || defined(BCMDONGLEHOST) |
| #define BCMDONGLECASE(n) case n: |
| #else |
| #define BCMDONGLECASE(n) |
| #endif |
| |
| #ifdef BCM_BOOTLOADER |
| /* The format of the PMUREGS OTP Tuple -> |
| * 1 byte -> Lower 5 bits has the address of the register |
| * Higher 3 bits has the mode of the register like |
| * PLL, ChipCtrl, RegCtrl, UpDwn or Dependency mask |
| * 4 bytes -> Value of the register to be updated. |
| */ |
| #define PMUREGS_MODE_MASK 0xE0 |
| #define PMUREGS_MODE_SHIFT 5 |
| #define PMUREGS_ADDR_MASK 0x1F |
| #define PMUREGS_TPL_SIZE 5 |
| |
| enum { |
| PMU_PLLREG_MODE, |
| PMU_CCREG_MODE, |
| PMU_VOLTREG_MODE, |
| PMU_RES_TIME_MODE, |
| PMU_RESDEPEND_MODE |
| }; |
| |
| #define USBREGS_TPL_SIZE 5 |
| enum { |
| USB_DEV_CTRL_REG, |
| HSIC_PHY_CTRL1_REG, |
| HSIC_PHY_CTRL2_REG |
| }; |
| |
| #define USBRDY_DLY_TYPE 0x8000 /* Bit indicating if the byte is pre or post delay value */ |
| #define USBRDY_DLY_MASK 0x7FFF /* Bits indicating the amount of delay */ |
| #define USBRDY_MAXOTP_SIZE 5 /* Max size of the OTP parameter */ |
| |
| #endif /* BCM_BOOTLOADER */ |
| |
| static uint |
| BCMATTACHFN(get_max_cis_size)(si_t *sih) |
| { |
| uint max_cis_size; |
| void *oh; |
| |
| max_cis_size = (sih && sih->ccrev >= 49) ? CIS_SIZE_12K : CIS_SIZE; |
| if (sih && (oh = otp_init(sih)) != NULL) { |
| max_cis_size -= otp_avsbitslen(oh); |
| } |
| return max_cis_size; |
| } |
| |
| #ifndef BCM_BOOTLOADER |
| static uint32 |
| BCMATTACHFN(srom_data2value)(uint8 *p, uint8 len) |
| { |
| uint8 pos = 0; |
| uint32 value = 0; |
| |
| ASSERT(len <= 4); |
| |
| while (pos < len) { |
| value += (p[pos] << (pos * 8)); |
| pos++; |
| } |
| |
| return value; |
| } |
| #endif /* BCM_BOOTLOADER */ |
| |
| /** |
| * Both SROM and OTP contain variables in 'CIS' format, whereas the rest of the firmware works with |
| * 'variable/value' string pairs. |
| */ |
| int |
| BCMATTACHFN(srom_parsecis)(si_t *sih, osl_t *osh, uint8 *pcis[], uint ciscnt, char **vars, |
| uint *count) |
| { |
| char eabuf[32]; |
| char eabuf2[32]; |
| char *base; |
| varbuf_t b; |
| uint8 *cis, tup, tlen, sromrev = 1; |
| uint i; |
| uint16 j; |
| #ifndef BCM_BOOTLOADER |
| bool ag_init = FALSE; |
| #endif |
| uint32 w32; |
| uint funcid; |
| uint cisnum; |
| int32 boardnum; |
| int err; |
| bool standard_cis; |
| uint max_cis_size; |
| uint var_cis_size = 0; |
| |
| ASSERT(count != NULL); |
| |
| if (vars == NULL) { |
| ASSERT(0); /* crash debug images for investigation */ |
| return BCME_BADARG; |
| } |
| |
| boardnum = -1; |
| |
| /* freed in same function */ |
| max_cis_size = get_max_cis_size(sih); |
| var_cis_size = *count + ((max_cis_size + 2u) * ciscnt); |
| |
| ASSERT(var_cis_size <= MAXSZ_NVRAM_VARS); |
| |
| base = MALLOC_NOPERSIST(osh, var_cis_size); |
| ASSERT(base != NULL); |
| if (!base) |
| return -2; |
| |
| varbuf_init(&b, base, var_cis_size); |
| bzero(base, var_cis_size); |
| /* Append from vars if there's already something inside */ |
| if (*vars && **vars && (*count >= 3)) { |
| /* back off \0 at the end, leaving only one \0 for the last param */ |
| while (((*vars)[(*count)-1] == '\0') && ((*vars)[(*count)-2] == '\0')) |
| (*count)--; |
| |
| bcopy(*vars, base, *count); |
| b.buf += *count; |
| } |
| eabuf[0] = '\0'; |
| eabuf2[0] = '\0'; |
| for (cisnum = 0; cisnum < ciscnt; cisnum++) { |
| cis = *pcis++; |
| i = 0; |
| funcid = 0; |
| standard_cis = TRUE; |
| do { |
| if (standard_cis) { |
| tup = cis[i++]; |
| if (tup == CISTPL_NULL || tup == CISTPL_END) |
| tlen = 0; |
| else |
| tlen = cis[i++]; |
| } else { |
| if (cis[i] == CISTPL_NULL || cis[i] == CISTPL_END) { |
| tlen = 0; |
| tup = cis[i]; |
| } else { |
| tlen = cis[i]; |
| tup = CISTPL_BRCM_HNBU; |
| } |
| ++i; |
| } |
| if ((i + tlen) >= max_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, vstr_manf, &cis[i + 2]); |
| varbuf_append(&b, vstr_productname, |
| &cis[i + 3 + strlen((char *)&cis[i + 2])]); |
| break; |
| } |
| |
| case CISTPL_MANFID: |
| varbuf_append(&b, vstr_manfid, (cis[i + 1] << 8) + cis[i]); |
| varbuf_append(&b, vstr_prodid, (cis[i + 3] << 8) + cis[i + 2]); |
| break; |
| |
| case CISTPL_FUNCID: |
| funcid = cis[i]; |
| break; |
| |
| case CISTPL_FUNCE: |
| switch (funcid) { |
| case CISTPL_FID_SDIO: |
| #ifdef BCMSDIO |
| if (cis[i] == 0) { |
| uint8 spd = cis[i + 3]; |
| static int lbase[] = { |
| -1, 10, 12, 13, 15, 20, 25, 30, |
| 35, 40, 45, 50, 55, 60, 70, 80 |
| }; |
| static int mult[] = { |
| 10, 100, 1000, 10000, |
| -1, -1, -1, -1 |
| }; |
| ASSERT((mult[spd & 0x7] != -1) && |
| (lbase[(spd >> 3) & 0x0f])); |
| varbuf_append(&b, vstr_sdmaxblk[0], |
| (cis[i + 2] << 8) + cis[i + 1]); |
| varbuf_append(&b, vstr_sdmaxspeed, |
| (mult[spd & 0x7] * |
| lbase[(spd >> 3) & 0x0f])); |
| } else if (cis[i] == 1) { |
| varbuf_append(&b, vstr_sdmaxblk[cisnum], |
| (cis[i + 13] << 8) | cis[i + 12]); |
| } |
| #endif /* BCMSDIO */ |
| funcid = 0; |
| break; |
| default: |
| /* set macaddr if HNBU_MACADDR not seen yet */ |
| if (eabuf[0] == '\0' && cis[i] == LAN_NID && |
| !(ETHER_ISNULLADDR(&cis[i + 2])) && |
| !(ETHER_ISMULTI(&cis[i + 2]))) { |
| 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, vstr_regwindowsz, (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, vstr_sromrev, sromrev); |
| break; |
| |
| case HNBU_XTALFREQ: |
| varbuf_append(&b, vstr_xtalfreq, |
| (cis[i + 4] << 24) | |
| (cis[i + 3] << 16) | |
| (cis[i + 2] << 8) | |
| cis[i + 1]); |
| break; |
| |
| case HNBU_CHIPID: |
| varbuf_append(&b, vstr_vendid, (cis[i + 2] << 8) + |
| cis[i + 1]); |
| varbuf_append(&b, vstr_devid, (cis[i + 4] << 8) + |
| cis[i + 3]); |
| if (tlen >= 7) { |
| varbuf_append(&b, vstr_chiprev, |
| (cis[i + 6] << 8) + cis[i + 5]); |
| } |
| if (tlen >= 9) { |
| varbuf_append(&b, vstr_subvendid, |
| (cis[i + 8] << 8) + cis[i + 7]); |
| } |
| if (tlen >= 11) { |
| varbuf_append(&b, vstr_subdevid, |
| (cis[i + 10] << 8) + cis[i + 9]); |
| /* subdevid doubles for boardtype */ |
| varbuf_append(&b, vstr_boardtype, |
| (cis[i + 10] << 8) + cis[i + 9]); |
| } |
| break; |
| |
| case HNBU_BOARDNUM: |
| boardnum = (cis[i + 2] << 8) + cis[i + 1]; |
| break; |
| |
| case HNBU_PATCH: { |
| char vstr_paddr[16]; |
| char vstr_pdata[16]; |
| |
| /* retrieve the patch pairs |
| * from tlen/6; where 6 is |
| * sizeof(patch addr(2)) + |
| * sizeof(patch data(4)). |
| */ |
| patch_pair = tlen/6; |
| |
| for (j = 0; j < patch_pair; j++) { |
| snprintf(vstr_paddr, sizeof(vstr_paddr), |
| rstr_paddr, j); |
| snprintf(vstr_pdata, sizeof(vstr_pdata), |
| rstr_pdata, j); |
| |
| varbuf_append(&b, vstr_paddr, |
| (cis[i + (j*6) + 2] << 8) | |
| cis[i + (j*6) + 1]); |
| |
| varbuf_append(&b, vstr_pdata, |
| (cis[i + (j*6) + 6] << 24) | |
| (cis[i + (j*6) + 5] << 16) | |
| (cis[i + (j*6) + 4] << 8) | |
| cis[i + (j*6) + 3]); |
| } |
| break; |
| } |
| |
| case HNBU_BOARDREV: |
| if (tlen == 2) |
| varbuf_append(&b, vstr_boardrev, cis[i + 1]); |
| else |
| varbuf_append(&b, vstr_boardrev, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| 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, vstr_boardflags, w32); |
| |
| if (tlen >= 7) { |
| w32 = (cis[i + 6] << 8) + cis[i + 5]; |
| if (tlen >= 9) |
| w32 |= ((cis[i + 8] << 24) + |
| (cis[i + 7] << 16)); |
| varbuf_append(&b, vstr_boardflags2, w32); |
| } |
| if (tlen >= 11) { |
| w32 = (cis[i + 10] << 8) + cis[i + 9]; |
| if (tlen >= 13) |
| w32 |= ((cis[i + 12] << 24) + |
| (cis[i + 11] << 16)); |
| varbuf_append(&b, vstr_boardflags3, w32); |
| } |
| if (tlen >= 15) { |
| w32 = (cis[i + 14] << 8) + cis[i + 13]; |
| if (tlen >= 17) |
| w32 |= ((cis[i + 16] << 24) + |
| (cis[i + 15] << 16)); |
| varbuf_append(&b, vstr_boardflags4, w32); |
| } |
| if (tlen >= 19) { |
| w32 = (cis[i + 18] << 8) + cis[i + 17]; |
| if (tlen >= 21) |
| w32 |= ((cis[i + 20] << 24) + |
| (cis[i + 19] << 16)); |
| varbuf_append(&b, vstr_boardflags5, w32); |
| } |
| break; |
| |
| case HNBU_USBFS: |
| varbuf_append(&b, vstr_usbfs, cis[i + 1]); |
| break; |
| |
| case HNBU_BOARDTYPE: |
| varbuf_append(&b, vstr_boardtype, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| break; |
| |
| case HNBU_HNBUCIS: |
| /* |
| * what follows is a nonstandard HNBU CIS |
| * that lacks CISTPL_BRCM_HNBU tags |
| * |
| * skip 0xff (end of standard CIS) |
| * after this tuple |
| */ |
| tlen++; |
| standard_cis = FALSE; |
| break; |
| |
| case HNBU_USBEPNUM: |
| varbuf_append(&b, vstr_usbepnum, |
| (cis[i + 2] << 8) | cis[i + 1]); |
| break; |
| |
| case HNBU_PATCH_AUTOINC: { |
| char vstr_paddr[16]; |
| char vstr_pdata[16]; |
| uint32 addr_inc; |
| uint8 pcnt; |
| |
| addr_inc = (cis[i + 4] << 24) | |
| (cis[i + 3] << 16) | |
| (cis[i + 2] << 8) | |
| (cis[i + 1]); |
| |
| pcnt = (tlen - 5)/4; |
| for (j = 0; j < pcnt; j++) { |
| snprintf(vstr_paddr, sizeof(vstr_paddr), |
| rstr_paddr, j + patch_pair); |
| snprintf(vstr_pdata, sizeof(vstr_pdata), |
| rstr_pdata, j + patch_pair); |
| |
| varbuf_append(&b, vstr_paddr, addr_inc); |
| varbuf_append(&b, vstr_pdata, |
| (cis[i + (j*4) + 8] << 24) | |
| (cis[i + (j*4) + 7] << 16) | |
| (cis[i + (j*4) + 6] << 8) | |
| cis[i + (j*4) + 5]); |
| addr_inc += 4; |
| } |
| patch_pair += pcnt; |
| break; |
| } |
| case HNBU_PATCH2: { |
| char vstr_paddr[16]; |
| char vstr_pdata[16]; |
| |
| /* retrieve the patch pairs |
| * from tlen/8; where 8 is |
| * sizeof(patch addr(4)) + |
| * sizeof(patch data(4)). |
| */ |
| patch_pair = tlen/8; |
| |
| for (j = 0; j < patch_pair; j++) { |
| snprintf(vstr_paddr, sizeof(vstr_paddr), |
| rstr_paddr, j); |
| snprintf(vstr_pdata, sizeof(vstr_pdata), |
| rstr_pdata, j); |
| |
| varbuf_append(&b, vstr_paddr, |
| (cis[i + (j*8) + 4] << 24) | |
| (cis[i + (j*8) + 3] << 16) | |
| (cis[i + (j*8) + 2] << 8) | |
| cis[i + (j*8) + 1]); |
| |
| varbuf_append(&b, vstr_pdata, |
| (cis[i + (j*8) + 8] << 24) | |
| (cis[i + (j*8) + 7] << 16) | |
| (cis[i + (j*8) + 6] << 8) | |
| cis[i + (j*8) + 5]); |
| } |
| break; |
| } |
| case HNBU_PATCH_AUTOINC8: { |
| char vstr_paddr[16]; |
| char vstr_pdatah[16]; |
| char vstr_pdatal[16]; |
| uint32 addr_inc; |
| uint8 pcnt; |
| |
| addr_inc = (cis[i + 4] << 24) | |
| (cis[i + 3] << 16) | |
| (cis[i + 2] << 8) | |
| (cis[i + 1]); |
| |
| pcnt = (tlen - 5)/8; |
| for (j = 0; j < pcnt; j++) { |
| snprintf(vstr_paddr, sizeof(vstr_paddr), |
| rstr_paddr, j + patch_pair); |
| snprintf(vstr_pdatah, sizeof(vstr_pdatah), |
| rstr_pdatah, j + patch_pair); |
| snprintf(vstr_pdatal, sizeof(vstr_pdatal), |
| rstr_pdatal, j + patch_pair); |
| |
| varbuf_append(&b, vstr_paddr, addr_inc); |
| varbuf_append(&b, vstr_pdatal, |
| (cis[i + (j*8) + 8] << 24) | |
| (cis[i + (j*8) + 7] << 16) | |
| (cis[i + (j*8) + 6] << 8) | |
| cis[i + (j*8) + 5]); |
| varbuf_append(&b, vstr_pdatah, |
| (cis[i + (j*8) + 12] << 24) | |
| (cis[i + (j*8) + 11] << 16) | |
| (cis[i + (j*8) + 10] << 8) | |
| cis[i + (j*8) + 9]); |
| addr_inc += 8; |
| } |
| patch_pair += pcnt; |
| break; |
| } |
| case HNBU_PATCH8: { |
| char vstr_paddr[16]; |
| char vstr_pdatah[16]; |
| char vstr_pdatal[16]; |
| |
| /* retrieve the patch pairs |
| * from tlen/8; where 8 is |
| * sizeof(patch addr(4)) + |
| * sizeof(patch data(4)). |
| */ |
| patch_pair = tlen/12; |
| |
| for (j = 0; j < patch_pair; j++) { |
| snprintf(vstr_paddr, sizeof(vstr_paddr), |
| rstr_paddr, j); |
| snprintf(vstr_pdatah, sizeof(vstr_pdatah), |
| rstr_pdatah, j); |
| snprintf(vstr_pdatal, sizeof(vstr_pdatal), |
| rstr_pdatal, j); |
| |
| varbuf_append(&b, vstr_paddr, |
| (cis[i + (j*12) + 4] << 24) | |
| (cis[i + (j*12) + 3] << 16) | |
| (cis[i + (j*12) + 2] << 8) | |
| cis[i + (j*12) + 1]); |
| |
| varbuf_append(&b, vstr_pdatal, |
| (cis[i + (j*12) + 8] << 24) | |
| (cis[i + (j*12) + 7] << 16) | |
| (cis[i + (j*12) + 6] << 8) | |
| cis[i + (j*12) + 5]); |
| |
| varbuf_append(&b, vstr_pdatah, |
| (cis[i + (j*12) + 12] << 24) | |
| (cis[i + (j*12) + 11] << 16) | |
| (cis[i + (j*12) + 10] << 8) | |
| cis[i + (j*12) + 9]); |
| } |
| break; |
| } |
| case HNBU_USBFLAGS: |
| varbuf_append(&b, vstr_usbflags, |
| (cis[i + 4] << 24) | |
| (cis[i + 3] << 16) | |
| (cis[i + 2] << 8) | |
| cis[i + 1]); |
| break; |
| #ifdef BCM_BOOTLOADER |
| case HNBU_MDIOEX_REGLIST: |
| case HNBU_MDIO_REGLIST: { |
| /* Format: addr (8 bits) | val (16 bits) */ |
| const uint8 msize = 3; |
| char mdiostr[24]; |
| const char *mdiodesc; |
| uint8 *st; |
| |
| mdiodesc = (cis[i] == HNBU_MDIO_REGLIST) ? |
| vstr_mdio : vstr_mdioex; |
| |
| ASSERT(((tlen - 1) % msize) == 0); |
| |
| st = &cis[i + 1]; /* start of reg list */ |
| for (j = 0; j < (tlen - 1); j += msize, st += msize) { |
| snprintf(mdiostr, sizeof(mdiostr), |
| mdiodesc, st[0]); |
| varbuf_append(&b, mdiostr, (st[2] << 8) | st[1]); |
| } |
| break; |
| } |
| case HNBU_BRMIN: |
| varbuf_append(&b, vstr_brmin, |
| (cis[i + 4] << 24) | |
| (cis[i + 3] << 16) | |
| (cis[i + 2] << 8) | |
| cis[i + 1]); |
| break; |
| |
| case HNBU_BRMAX: |
| varbuf_append(&b, vstr_brmax, |
| (cis[i + 4] << 24) | |
| (cis[i + 3] << 16) | |
| (cis[i + 2] << 8) | |
| cis[i + 1]); |
| break; |
| #endif /* BCM_BOOTLOADER */ |
| |
| case HNBU_RDLID: |
| varbuf_append(&b, vstr_rdlid, |
| (cis[i + 2] << 8) | cis[i + 1]); |
| break; |
| |
| case HNBU_GCI_CCR: { |
| /* format: |
| * |0x80| <== brcm |
| * |len| <== variable, multiple of 5 |
| * |tup| <== tupletype |
| * |ccreg_ix0| <== ix of ccreg [1byte] |
| * |ccreg_val0| <== corr value [4bytes] |
| * --- |
| * Multiple registers are possible. for eg: we |
| * can specify reg_ix3val3 and reg_ix5val5, etc |
| */ |
| char vstr_gci_ccreg_entry[16]; |
| uint8 num_entries = 0; |
| |
| /* retrieve the index-value pairs |
| * from tlen/5; where 5 is |
| * sizeof(ccreg_ix(1)) + |
| * sizeof(ccreg_val(4)). |
| */ |
| num_entries = tlen/5; |
| |
| for (j = 0; j < num_entries; j++) { |
| snprintf(vstr_gci_ccreg_entry, |
| sizeof(vstr_gci_ccreg_entry), |
| rstr_gci_ccreg_entry, |
| cis[i + (j*5) + 1]); |
| |
| varbuf_append(&b, vstr_gci_ccreg_entry, |
| (cis[i + (j*5) + 5] << 24) | |
| (cis[i + (j*5) + 4] << 16) | |
| (cis[i + (j*5) + 3] << 8) | |
| cis[i + (j*5) + 2]); |
| } |
| break; |
| } |
| |
| #ifdef BCM_BOOTLOADER |
| case HNBU_RDLRNDIS: |
| varbuf_append(&b, vstr_rdlrndis, cis[i + 1]); |
| break; |
| |
| case HNBU_RDLRWU: |
| varbuf_append(&b, vstr_rdlrwu, cis[i + 1]); |
| break; |
| |
| case HNBU_RDLSN: |
| if (tlen >= 5) |
| varbuf_append(&b, vstr_rdlsn, |
| (cis[i + 4] << 24) | |
| (cis[i + 3] << 16) | |
| (cis[i + 2] << 8) | |
| cis[i + 1]); |
| else |
| varbuf_append(&b, vstr_rdlsn, |
| (cis[i + 2] << 8) | |
| cis[i + 1]); |
| break; |
| |
| case HNBU_PMUREGS: { |
| uint8 offset = 1, mode_addr, mode, addr; |
| const char *fmt; |
| |
| do { |
| mode_addr = cis[i+offset]; |
| |
| mode = (mode_addr & PMUREGS_MODE_MASK) |
| >> PMUREGS_MODE_SHIFT; |
| addr = mode_addr & PMUREGS_ADDR_MASK; |
| |
| switch (mode) { |
| case PMU_PLLREG_MODE: |
| fmt = vstr_pllreg; |
| break; |
| case PMU_CCREG_MODE: |
| fmt = vstr_ccreg; |
| break; |
| case PMU_VOLTREG_MODE: |
| fmt = vstr_regctrl; |
| break; |
| case PMU_RES_TIME_MODE: |
| fmt = vstr_time; |
| break; |
| case PMU_RESDEPEND_MODE: |
| fmt = vstr_depreg; |
| break; |
| default: |
| fmt = NULL; |
| break; |
| } |
| |
| if (fmt != NULL) { |
| varbuf_append(&b, fmt, addr, |
| (cis[i + offset + 4] << 24) | |
| (cis[i + offset + 3] << 16) | |
| (cis[i + offset + 2] << 8) | |
| cis[i + offset + 1]); |
| } |
| |
| offset += PMUREGS_TPL_SIZE; |
| } while (offset < tlen); |
| break; |
| } |
| |
| case HNBU_USBREGS: { |
| uint8 offset = 1, usb_reg; |
| const char *fmt; |
| |
| do { |
| usb_reg = cis[i+offset]; |
| |
| switch (usb_reg) { |
| case USB_DEV_CTRL_REG: |
| fmt = vstr_usbdevctrl; |
| break; |
| case HSIC_PHY_CTRL1_REG: |
| fmt = vstr_hsicphyctrl1; |
| break; |
| case HSIC_PHY_CTRL2_REG: |
| fmt = vstr_hsicphyctrl2; |
| break; |
| default: |
| fmt = NULL; |
| break; |
| } |
| |
| if (fmt != NULL) { |
| varbuf_append(&b, fmt, |
| (cis[i + offset + 4] << 24) | |
| (cis[i + offset + 3] << 16) | |
| (cis[i + offset + 2] << 8) | |
| cis[i + offset + 1]); |
| } |
| |
| offset += USBREGS_TPL_SIZE; |
| } while (offset < tlen); |
| break; |
| } |
| |
| case HNBU_USBRDY: |
| /* The first byte of this tuple indicate if the host |
| * needs to be informed about the readiness of |
| * the HSIC/USB for enumeration on which GPIO should |
| * the device assert this event. |
| */ |
| varbuf_append(&b, vstr_usbrdy, cis[i + 1]); |
| |
| /* The following fields in this OTP are optional. |
| * The remaining bytes will indicate the delay required |
| * before and/or after the ch_init(). The delay is defined |
| * using 16-bits of this the MSB(bit15 of 15:0) will be |
| * used indicate if the parameter is for Pre or Post delay. |
| */ |
| for (j = 2; j < USBRDY_MAXOTP_SIZE && j < tlen; |
| j += 2) { |
| uint16 usb_delay; |
| |
| usb_delay = cis[i + j] | (cis[i + j + 1] << 8); |
| |
| /* The bit-15 of the delay field will indicate the |
| * type of delay (pre or post). |
| */ |
| if (usb_delay & USBRDY_DLY_TYPE) { |
| varbuf_append(&b, vstr_usbpostdly, |
| (usb_delay & USBRDY_DLY_MASK)); |
| } else { |
| varbuf_append(&b, vstr_usbpredly, |
| (usb_delay & USBRDY_DLY_MASK)); |
| } |
| } |
| break; |
| |
| case HNBU_BLDR_TIMEOUT: |
| /* The Delay after USBConnect for timeout till dongle |
| * receives get_descriptor request. |
| */ |
| varbuf_append(&b, vstr_bldr_reset_timeout, |
| (cis[i + 1] | (cis[i + 2] << 8))); |
| break; |
| |
| case HNBU_MUXENAB: |
| varbuf_append(&b, vstr_muxenab, cis[i + 1]); |
| break; |
| case HNBU_PUBKEY: { |
| /* The public key is in binary format in OTP, |
| * convert to string format before appending |
| * buffer string. |
| * public key(12 bytes) + crc (1byte) = 129 |
| */ |
| unsigned char a[300]; |
| int k; |
| |
| for (k = 1, j = 0; k < 129; k++) |
| j += snprintf((char *)(a + j), |
| sizeof(a) - j, |
| "%02x", cis[i + k]); |
| |
| a[256] = 0; |
| |
| varbuf_append(&b, vstr_pubkey, a); |
| break; |
| } |
| #else |
| case HNBU_AA: |
| varbuf_append(&b, vstr_aa2g, cis[i + 1]); |
| if (tlen >= 3) |
| varbuf_append(&b, vstr_aa5g, cis[i + 2]); |
| break; |
| |
| case HNBU_AG: |
| varbuf_append(&b, vstr_ag, 0, cis[i + 1]); |
| if (tlen >= 3) |
| varbuf_append(&b, vstr_ag, 1, cis[i + 2]); |
| if (tlen >= 4) |
| varbuf_append(&b, vstr_ag, 2, cis[i + 3]); |
| if (tlen >= 5) |
| varbuf_append(&b, vstr_ag, 3, cis[i + 4]); |
| ag_init = TRUE; |
| break; |
| |
| case HNBU_ANT5G: |
| varbuf_append(&b, vstr_aa5g, cis[i + 1]); |
| varbuf_append(&b, vstr_ag, 1, cis[i + 2]); |
| break; |
| |
| case HNBU_CC: |
| ASSERT(sromrev == 1); |
| varbuf_append(&b, vstr_cc, cis[i + 1]); |
| break; |
| |
| case HNBU_PAPARMS: { |
| uint8 pa0_lo_offset = 0; |
| switch (tlen) { |
| case 2: |
| ASSERT(sromrev == 1); |
| varbuf_append(&b, vstr_pa0maxpwr, cis[i + 1]); |
| break; |
| /* case 16: |
| ASSERT(sromrev >= 11); |
| for (j = 0; j < 3; j++) { |
| varbuf_append(&b, vstr_pa0b_lo[j], |
| (cis[i + (j * 2) + 11] << 8) + |
| cis[i + (j * 2) + 10]); |
| } |
| FALLTHROUGH |
| */ |
| case 10: |
| case 16: |
| ASSERT(sromrev >= 2); |
| varbuf_append(&b, vstr_opo, cis[i + 9]); |
| if (tlen >= 13 && pa0_lo_offset == 0) |
| pa0_lo_offset = 9; |
| /* FALLTHROUGH */ |
| case 9: |
| case 15: |
| varbuf_append(&b, vstr_pa0maxpwr, cis[i + 8]); |
| if (tlen >= 13 && pa0_lo_offset == 0) |
| pa0_lo_offset = 8; |
| /* FALLTHROUGH */ |
| BCMDONGLECASE(8) |
| BCMDONGLECASE(14) |
| varbuf_append(&b, vstr_pa0itssit, cis[i + 7]); |
| varbuf_append(&b, vstr_maxp2ga, 0, cis[i + 7]); |
| if (tlen >= 13 && pa0_lo_offset == 0) |
| pa0_lo_offset = 7; |
| /* FALLTHROUGH */ |
| BCMDONGLECASE(7) |
| BCMDONGLECASE(13) |
| for (j = 0; j < 3; j++) { |
| varbuf_append(&b, vstr_pa0b[j], |
| (cis[i + (j * 2) + 2] << 8) + |
| cis[i + (j * 2) + 1]); |
| } |
| if (tlen >= 13 && pa0_lo_offset == 0) |
| pa0_lo_offset = 6; |
| |
| if (tlen >= 13 && pa0_lo_offset != 0) { |
| for (j = 0; j < 3; j++) { |
| varbuf_append(&b, vstr_pa0b_lo[j], |
| (cis[pa0_lo_offset+i+(j*2)+2]<<8)+ |
| cis[pa0_lo_offset+i+(j*2)+1]); |
| } |
| } |
| break; |
| default: |
| ASSERT((tlen == 2) || (tlen == 9) || (tlen == 10) || |
| (tlen == 15) || (tlen == 16)); |
| break; |
| } |
| break; |
| } |
| case HNBU_PAPARMS5G: |
| ASSERT((sromrev == 2) || (sromrev == 3)); |
| switch (tlen) { |
| case 23: |
| varbuf_append(&b, vstr_pa1himaxpwr, cis[i + 22]); |
| varbuf_append(&b, vstr_pa1lomaxpwr, cis[i + 21]); |
| varbuf_append(&b, vstr_pa1maxpwr, cis[i + 20]); |
| /* FALLTHROUGH */ |
| case 20: |
| varbuf_append(&b, vstr_pa1itssit, cis[i + 19]); |
| /* FALLTHROUGH */ |
| case 19: |
| for (j = 0; j < 3; j++) { |
| varbuf_append(&b, vstr_pa1b[j], |
| (cis[i + (j * 2) + 2] << 8) + |
| cis[i + (j * 2) + 1]); |
| } |
| for (j = 3; j < 6; j++) { |
| varbuf_append(&b, vstr_pa1lob[j - 3], |
| (cis[i + (j * 2) + 2] << 8) + |
| cis[i + (j * 2) + 1]); |
| } |
| for (j = 6; j < 9; j++) { |
| varbuf_append(&b, vstr_pa1hib[j - 6], |
| (cis[i + (j * 2) + 2] << 8) + |
| cis[i + (j * 2) + 1]); |
| } |
| break; |
| default: |
| ASSERT((tlen == 19) || |
| (tlen == 20) || (tlen == 23)); |
| break; |
| } |
| break; |
| |
| case HNBU_OEM: |
| ASSERT(sromrev == 1); |
| varbuf_append(&b, vstr_oem, |
| 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_CCODE: |
| ASSERT(sromrev > 1); |
| if ((cis[i + 1] == 0) || (cis[i + 2] == 0)) |
| varbuf_append(&b, vstr_noccode); |
| else |
| varbuf_append(&b, vstr_ccode, |
| cis[i + 1], cis[i + 2]); |
| varbuf_append(&b, vstr_cctl, cis[i + 3]); |
| break; |
| |
| case HNBU_CCKPO: |
| ASSERT(sromrev > 2); |
| varbuf_append(&b, vstr_cckpo, |
| (cis[i + 2] << 8) | cis[i + 1]); |
| break; |
| |
| case HNBU_OFDMPO: |
| ASSERT(sromrev > 2); |
| varbuf_append(&b, vstr_ofdmpo, |
| (cis[i + 4] << 24) | |
| (cis[i + 3] << 16) | |
| (cis[i + 2] << 8) | |
| cis[i + 1]); |
| break; |
| |
| case HNBU_WPS: |
| varbuf_append(&b, vstr_wpsgpio, cis[i + 1]); |
| if (tlen >= 3) |
| varbuf_append(&b, vstr_wpsled, cis[i + 2]); |
| break; |
| |
| case HNBU_RSSISMBXA2G: |
| ASSERT(sromrev == 3); |
| varbuf_append(&b, vstr_rssismf2g, cis[i + 1] & 0xf); |
| varbuf_append(&b, vstr_rssismc2g, (cis[i + 1] >> 4) & 0xf); |
| varbuf_append(&b, vstr_rssisav2g, cis[i + 2] & 0x7); |
| varbuf_append(&b, vstr_bxa2g, (cis[i + 2] >> 3) & 0x3); |
| break; |
| |
| case HNBU_RSSISMBXA5G: |
| ASSERT(sromrev == 3); |
| varbuf_append(&b, vstr_rssismf5g, cis[i + 1] & 0xf); |
| varbuf_append(&b, vstr_rssismc5g, (cis[i + 1] >> 4) & 0xf); |
| varbuf_append(&b, vstr_rssisav5g, cis[i + 2] & 0x7); |
| varbuf_append(&b, vstr_bxa5g, (cis[i + 2] >> 3) & 0x3); |
| break; |
| |
| case HNBU_TRI2G: |
| ASSERT(sromrev == 3); |
| varbuf_append(&b, vstr_tri2g, cis[i + 1]); |
| break; |
| |
| case HNBU_TRI5G: |
| ASSERT(sromrev == 3); |
| varbuf_append(&b, vstr_tri5gl, cis[i + 1]); |
| varbuf_append(&b, vstr_tri5g, cis[i + 2]); |
| varbuf_append(&b, vstr_tri5gh, cis[i + 3]); |
| break; |
| |
| case HNBU_RXPO2G: |
| ASSERT(sromrev == 3); |
| varbuf_append(&b, vstr_rxpo2g, cis[i + 1]); |
| break; |
| |
| case HNBU_RXPO5G: |
| ASSERT(sromrev == 3); |
| varbuf_append(&b, vstr_rxpo5g, cis[i + 1]); |
| break; |
| |
| case HNBU_MACADDR: |
| if (!(ETHER_ISNULLADDR(&cis[i+1])) && |
| !(ETHER_ISMULTI(&cis[i+1]))) { |
| bcm_ether_ntoa((struct ether_addr *)&cis[i + 1], |
| eabuf); |
| |
| /* set boardnum if HNBU_BOARDNUM not seen yet */ |
| if (boardnum == -1) |
| boardnum = (cis[i + 5] << 8) + cis[i + 6]; |
| } |
| break; |
| |
| case HNBU_CHAINSWITCH: |
| varbuf_append(&b, vstr_txchain, cis[i + 1]); |
| varbuf_append(&b, vstr_rxchain, cis[i + 2]); |
| varbuf_append(&b, vstr_antswitch, |
| (cis[i + 4] << 8) + cis[i + 3]); |
| break; |
| |
| case HNBU_ELNA2G: |
| varbuf_append(&b, vstr_elna2g, cis[i + 1]); |
| break; |
| |
| case HNBU_ELNA5G: |
| varbuf_append(&b, vstr_elna5g, cis[i + 1]); |
| break; |
| |
| case HNBU_REGREV: |
| varbuf_append(&b, vstr_regrev, |
| srom_data2value(&cis[i + 1], tlen - 1)); |
| break; |
| |
| case HNBU_FEM: { |
| uint16 fem = (cis[i + 2] << 8) + cis[i + 1]; |
| varbuf_append(&b, vstr_antswctl2g, (fem & |
| SROM8_FEM_ANTSWLUT_MASK) >> |
| SROM8_FEM_ANTSWLUT_SHIFT); |
| varbuf_append(&b, vstr_triso2g, (fem & |
| SROM8_FEM_TR_ISO_MASK) >> |
| SROM8_FEM_TR_ISO_SHIFT); |
| varbuf_append(&b, vstr_pdetrange2g, (fem & |
| SROM8_FEM_PDET_RANGE_MASK) >> |
| SROM8_FEM_PDET_RANGE_SHIFT); |
| varbuf_append(&b, vstr_extpagain2g, (fem & |
| SROM8_FEM_EXTPA_GAIN_MASK) >> |
| SROM8_FEM_EXTPA_GAIN_SHIFT); |
| varbuf_append(&b, vstr_tssipos2g, (fem & |
| SROM8_FEM_TSSIPOS_MASK) >> |
| SROM8_FEM_TSSIPOS_SHIFT); |
| if (tlen < 5) break; |
| |
| fem = (cis[i + 4] << 8) + cis[i + 3]; |
| varbuf_append(&b, vstr_antswctl5g, (fem & |
| SROM8_FEM_ANTSWLUT_MASK) >> |
| SROM8_FEM_ANTSWLUT_SHIFT); |
| varbuf_append(&b, vstr_triso5g, (fem & |
| SROM8_FEM_TR_ISO_MASK) >> |
| SROM8_FEM_TR_ISO_SHIFT); |
| varbuf_append(&b, vstr_pdetrange5g, (fem & |
| SROM8_FEM_PDET_RANGE_MASK) >> |
| SROM8_FEM_PDET_RANGE_SHIFT); |
| varbuf_append(&b, vstr_extpagain5g, (fem & |
| SROM8_FEM_EXTPA_GAIN_MASK) >> |
| SROM8_FEM_EXTPA_GAIN_SHIFT); |
| varbuf_append(&b, vstr_tssipos5g, (fem & |
| SROM8_FEM_TSSIPOS_MASK) >> |
| SROM8_FEM_TSSIPOS_SHIFT); |
| break; |
| } |
| |
| case HNBU_PAPARMS_C0: |
| varbuf_append(&b, vstr_maxp2ga, 0, cis[i + 1]); |
| varbuf_append(&b, vstr_itt2ga0, cis[i + 2]); |
| varbuf_append(&b, vstr_pa, 2, 0, 0, |
| (cis[i + 4] << 8) + cis[i + 3]); |
| varbuf_append(&b, vstr_pa, 2, 1, 0, |
| (cis[i + 6] << 8) + cis[i + 5]); |
| varbuf_append(&b, vstr_pa, 2, 2, 0, |
| (cis[i + 8] << 8) + cis[i + 7]); |
| if (tlen < 31) break; |
| |
| varbuf_append(&b, vstr_maxp5ga0, cis[i + 9]); |
| varbuf_append(&b, vstr_itt5ga0, cis[i + 10]); |
| varbuf_append(&b, vstr_maxp5gha0, cis[i + 11]); |
| varbuf_append(&b, vstr_maxp5gla0, cis[i + 12]); |
| varbuf_append(&b, vstr_pa, 5, 0, 0, |
| (cis[i + 14] << 8) + cis[i + 13]); |
| varbuf_append(&b, vstr_pa, 5, 1, 0, |
| (cis[i + 16] << 8) + cis[i + 15]); |
| varbuf_append(&b, vstr_pa, 5, 2, 0, |
| (cis[i + 18] << 8) + cis[i + 17]); |
| varbuf_append(&b, vstr_pahl, 5, 'l', 0, 0, |
| (cis[i + 20] << 8) + cis[i + 19]); |
| varbuf_append(&b, vstr_pahl, 5, 'l', 1, 0, |
| (cis[i + 22] << 8) + cis[i + 21]); |
| varbuf_append(&b, vstr_pahl, 5, 'l', 2, 0, |
| (cis[i + 24] << 8) + cis[i + 23]); |
| varbuf_append(&b, vstr_pahl, 5, 'h', 0, 0, |
| (cis[i + 26] << 8) + cis[i + 25]); |
| varbuf_append(&b, vstr_pahl, 5, 'h', 1, 0, |
| (cis[i + 28] << 8) + cis[i + 27]); |
| varbuf_append(&b, vstr_pahl, 5, 'h', 2, 0, |
| (cis[i + 30] << 8) + cis[i + 29]); |
| break; |
| |
| case HNBU_PAPARMS_C1: |
| varbuf_append(&b, vstr_maxp2ga, 1, cis[i + 1]); |
| varbuf_append(&b, vstr_itt2ga1, cis[i + 2]); |
| varbuf_append(&b, vstr_pa, 2, 0, 1, |
| (cis[i + 4] << 8) + cis[i + 3]); |
| varbuf_append(&b, vstr_pa, 2, 1, 1, |
| (cis[i + 6] << 8) + cis[i + 5]); |
| varbuf_append(&b, vstr_pa, 2, 2, 1, |
| (cis[i + 8] << 8) + cis[i + 7]); |
| if (tlen < 31) break; |
| |
| varbuf_append(&b, vstr_maxp5ga1, cis[i + 9]); |
| varbuf_append(&b, vstr_itt5ga1, cis[i + 10]); |
| varbuf_append(&b, vstr_maxp5gha1, cis[i + 11]); |
| varbuf_append(&b, vstr_maxp5gla1, cis[i + 12]); |
| varbuf_append(&b, vstr_pa, 5, 0, 1, |
| (cis[i + 14] << 8) + cis[i + 13]); |
| varbuf_append(&b, vstr_pa, 5, 1, 1, |
| (cis[i + 16] << 8) + cis[i + 15]); |
| varbuf_append(&b, vstr_pa, 5, 2, 1, |
| (cis[i + 18] << 8) + cis[i + 17]); |
| varbuf_append(&b, vstr_pahl, 5, 'l', 0, 1, |
| (cis[i + 20] << 8) + cis[i + 19]); |
| varbuf_append(&b, vstr_pahl, 5, 'l', 1, 1, |
| (cis[i + 22] << 8) + cis[i + 21]); |
| varbuf_append(&b, vstr_pahl, 5, 'l', 2, 1, |
| (cis[i + 24] << 8) + cis[i + 23]); |
| varbuf_append(&b, vstr_pahl, 5, 'h', 0, 1, |
| (cis[i + 26] << 8) + cis[i + 25]); |
| varbuf_append(&b, vstr_pahl, 5, 'h', 1, 1, |
| (cis[i + 28] << 8) + cis[i + 27]); |
| varbuf_append(&b, vstr_pahl, 5, 'h', 2, 1, |
| (cis[i + 30] << 8) + cis[i + 29]); |
| break; |
| |
| case HNBU_PO_CCKOFDM: |
| varbuf_append(&b, vstr_cck2gpo, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| varbuf_append(&b, vstr_ofdm2gpo, |
| (cis[i + 6] << 24) + (cis[i + 5] << 16) + |
| (cis[i + 4] << 8) + cis[i + 3]); |
| if (tlen < 19) break; |
| |
| varbuf_append(&b, vstr_ofdm5gpo, |
| (cis[i + 10] << 24) + (cis[i + 9] << 16) + |
| (cis[i + 8] << 8) + cis[i + 7]); |
| varbuf_append(&b, vstr_ofdm5glpo, |
| (cis[i + 14] << 24) + (cis[i + 13] << 16) + |
| (cis[i + 12] << 8) + cis[i + 11]); |
| varbuf_append(&b, vstr_ofdm5ghpo, |
| (cis[i + 18] << 24) + (cis[i + 17] << 16) + |
| (cis[i + 16] << 8) + cis[i + 15]); |
| break; |
| |
| case HNBU_PO_MCS2G: |
| for (j = 0; j <= (tlen/2); j++) { |
| varbuf_append(&b, vstr_mcspo, 2, j, |
| (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]); |
| } |
| break; |
| |
| case HNBU_PO_MCS5GM: |
| for (j = 0; j <= (tlen/2); j++) { |
| varbuf_append(&b, vstr_mcspo, 5, j, |
| (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]); |
| } |
| break; |
| |
| case HNBU_PO_MCS5GLH: |
| for (j = 0; j <= (tlen/4); j++) { |
| varbuf_append(&b, vstr_mcspohl, 5, 'l', j, |
| (cis[i + 2 + 2*j] << 8) + cis[i + 1 + 2*j]); |
| } |
| |
| for (j = 0; j <= (tlen/4); j++) { |
| varbuf_append(&b, vstr_mcspohl, 5, 'h', j, |
| (cis[i + ((tlen/2)+2) + 2*j] << 8) + |
| cis[i + ((tlen/2)+1) + 2*j]); |
| } |
| |
| break; |
| |
| case HNBU_PO_CDD: |
| varbuf_append(&b, vstr_cddpo, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| break; |
| |
| case HNBU_PO_STBC: |
| varbuf_append(&b, vstr_stbcpo, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| break; |
| |
| case HNBU_PO_40M: |
| varbuf_append(&b, vstr_bw40po, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| break; |
| |
| case HNBU_PO_40MDUP: |
| varbuf_append(&b, vstr_bwduppo, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| break; |
| |
| case HNBU_OFDMPO5G: |
| varbuf_append(&b, vstr_ofdm5gpo, |
| (cis[i + 4] << 24) + (cis[i + 3] << 16) + |
| (cis[i + 2] << 8) + cis[i + 1]); |
| varbuf_append(&b, vstr_ofdm5glpo, |
| (cis[i + 8] << 24) + (cis[i + 7] << 16) + |
| (cis[i + 6] << 8) + cis[i + 5]); |
| varbuf_append(&b, vstr_ofdm5ghpo, |
| (cis[i + 12] << 24) + (cis[i + 11] << 16) + |
| (cis[i + 10] << 8) + cis[i + 9]); |
| break; |
| /* Power per rate for SROM V9 */ |
| case HNBU_CCKBW202GPO: |
| varbuf_append(&b, vstr_cckbw202gpo[0], |
| ((cis[i + 2] << 8) + cis[i + 1])); |
| if (tlen > 4) |
| varbuf_append(&b, vstr_cckbw202gpo[1], |
| ((cis[i + 4] << 8) + cis[i + 3])); |
| if (tlen > 6) |
| varbuf_append(&b, vstr_cckbw202gpo[2], |
| ((cis[i + 6] << 8) + cis[i + 5])); |
| break; |
| |
| case HNBU_LEGOFDMBW202GPO: |
| varbuf_append(&b, vstr_legofdmbw202gpo[0], |
| ((cis[i + 4] << 24) + (cis[i + 3] << 16) + |
| (cis[i + 2] << 8) + cis[i + 1])); |
| if (tlen > 6) { |
| varbuf_append(&b, vstr_legofdmbw202gpo[1], |
| ((cis[i + 8] << 24) + (cis[i + 7] << 16) + |
| (cis[i + 6] << 8) + cis[i + 5])); |
| } |
| break; |
| |
| case HNBU_LEGOFDMBW205GPO: |
| for (j = 0; j < 6; j++) { |
| if (tlen < (2 + 4 * j)) |
| break; |
| varbuf_append(&b, vstr_legofdmbw205gpo[j], |
| ((cis[4 * j + i + 4] << 24) |
| + (cis[4 * j + i + 3] << 16) |
| + (cis[4 * j + i + 2] << 8) |
| + cis[4 * j + i + 1])); |
| } |
| break; |
| |
| case HNBU_MCS2GPO: |
| for (j = 0; j < 4; j++) { |
| if (tlen < (2 + 4 * j)) |
| break; |
| varbuf_append(&b, vstr_mcs2gpo[j], |
| ((cis[4 * j + i + 4] << 24) |
| + (cis[4 * j + i + 3] << 16) |
| + (cis[4 * j + i + 2] << 8) |
| + cis[4 * j + i + 1])); |
| } |
| break; |
| |
| case HNBU_MCS5GLPO: |
| for (j = 0; j < 3; j++) { |
| if (tlen < (2 + 4 * j)) |
| break; |
| varbuf_append(&b, vstr_mcs5glpo[j], |
| ((cis[4 * j + i + 4] << 24) |
| + (cis[4 * j + i + 3] << 16) |
| + (cis[4 * j + i + 2] << 8) |
| + cis[4 * j + i + 1])); |
| } |
| break; |
| |
| case HNBU_MCS5GMPO: |
| for (j = 0; j < 3; j++) { |
| if (tlen < (2 + 4 * j)) |
| break; |
| varbuf_append(&b, vstr_mcs5gmpo[j], |
| ((cis[4 * j + i + 4] << 24) |
| + (cis[4 * j + i + 3] << 16) |
| + (cis[4 * j + i + 2] << 8) |
| + cis[4 * j + i + 1])); |
| } |
| break; |
| |
| case HNBU_MCS5GHPO: |
| for (j = 0; j < 3; j++) { |
| if (tlen < (2 + 4 * j)) |
| break; |
| varbuf_append(&b, vstr_mcs5ghpo[j], |
| ((cis[4 * j + i + 4] << 24) |
| + (cis[4 * j + i + 3] << 16) |
| + (cis[4 * j + i + 2] << 8) |
| + cis[4 * j + i + 1])); |
| } |
| break; |
| |
| case HNBU_MCS32PO: |
| varbuf_append(&b, vstr_mcs32po, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| break; |
| |
| case HNBU_LEG40DUPPO: |
| varbuf_append(&b, vstr_legofdm40duppo, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| break; |
| |
| case HNBU_CUSTOM1: |
| varbuf_append(&b, vstr_custom, 1, ((cis[i + 4] << 24) + |
| (cis[i + 3] << 16) + (cis[i + 2] << 8) + |
| cis[i + 1])); |
| break; |
| |
| #if defined(BCMSDIO) || defined(BCMCCISSR3) |
| case HNBU_SROM3SWRGN: |
| if (tlen >= 73) { |
| 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); |
| /* 2.4G antenna gain is included in SROM */ |
| ag_init = TRUE; |
| /* Ethernet MAC address is included in SROM */ |
| eabuf[0] = 0; |
| /* why boardnum is not -1? */ |
| boardnum = -1; |
| } |
| /* create extra variables */ |
| if (tlen >= 75) |
| varbuf_append(&b, vstr_vendid, |
| (cis[i + 1 + 73] << 8) + |
| cis[i + 1 + 72]); |
| if (tlen >= 77) |
| varbuf_append(&b, vstr_devid, |
| (cis[i + 1 + 75] << 8) + |
| cis[i + 1 + 74]); |
| if (tlen >= 79) |
| varbuf_append(&b, vstr_xtalfreq, |
| (cis[i + 1 + 77] << 8) + |
| cis[i + 1 + 76]); |
| break; |
| #endif /* BCMSDIO || BCMCCISSR3 */ |
| |
| case HNBU_CCKFILTTYPE: |
| varbuf_append(&b, vstr_cckdigfilttype, |
| (cis[i + 1])); |
| break; |
| |
| case HNBU_TEMPTHRESH: |
| varbuf_append(&b, vstr_tempthresh, |
| (cis[i + 1])); |
| /* period in msb nibble */ |
| varbuf_append(&b, vstr_temps_period, |
| (cis[i + 2] & SROM11_TEMPS_PERIOD_MASK) >> |
| SROM11_TEMPS_PERIOD_SHIFT); |
| /* hysterisis in lsb nibble */ |
| varbuf_append(&b, vstr_temps_hysteresis, |
| (cis[i + 2] & SROM11_TEMPS_HYSTERESIS_MASK) >> |
| SROM11_TEMPS_HYSTERESIS_SHIFT); |
| if (tlen >= 4) { |
| varbuf_append(&b, vstr_tempoffset, |
| (cis[i + 3])); |
| varbuf_append(&b, vstr_tempsense_slope, |
| (cis[i + 4])); |
| varbuf_append(&b, vstr_temp_corrx, |
| (cis[i + 5] & SROM11_TEMPCORRX_MASK) >> |
| SROM11_TEMPCORRX_SHIFT); |
| varbuf_append(&b, vstr_tempsense_option, |
| (cis[i + 5] & SROM11_TEMPSENSE_OPTION_MASK) >> |
| SROM11_TEMPSENSE_OPTION_SHIFT); |
| varbuf_append(&b, vstr_phycal_tempdelta, |
| (cis[i + 6])); |
| } |
| break; |
| |
| case HNBU_FEM_CFG: { |
| /* fem_cfg1 */ |
| uint16 fem_cfg = (cis[i + 2] << 8) + cis[i + 1]; |
| varbuf_append(&b, vstr_femctrl, |
| (fem_cfg & SROM11_FEMCTRL_MASK) >> |
| SROM11_FEMCTRL_SHIFT); |
| varbuf_append(&b, vstr_papdcap, 2, |
| (fem_cfg & SROM11_PAPDCAP_MASK) >> |
| SROM11_PAPDCAP_SHIFT); |
| varbuf_append(&b, vstr_tworangetssi, 2, |
| (fem_cfg & SROM11_TWORANGETSSI_MASK) >> |
| SROM11_TWORANGETSSI_SHIFT); |
| varbuf_append(&b, vstr_pdgaing, 2, |
| (fem_cfg & SROM11_PDGAIN_MASK) >> |
| SROM11_PDGAIN_SHIFT); |
| varbuf_append(&b, vstr_epagaing, 2, |
| (fem_cfg & SROM11_EPAGAIN_MASK) >> |
| SROM11_EPAGAIN_SHIFT); |
| varbuf_append(&b, vstr_tssiposslopeg, 2, |
| (fem_cfg & SROM11_TSSIPOSSLOPE_MASK) >> |
| SROM11_TSSIPOSSLOPE_SHIFT); |
| /* fem_cfg2 */ |
| fem_cfg = (cis[i + 4] << 8) + cis[i + 3]; |
| varbuf_append(&b, vstr_gainctrlsph, |
| (fem_cfg & SROM11_GAINCTRLSPH_MASK) >> |
| SROM11_GAINCTRLSPH_SHIFT); |
| varbuf_append(&b, vstr_papdcap, 5, |
| (fem_cfg & SROM11_PAPDCAP_MASK) >> |
| SROM11_PAPDCAP_SHIFT); |
| varbuf_append(&b, vstr_tworangetssi, 5, |
| (fem_cfg & SROM11_TWORANGETSSI_MASK) >> |
| SROM11_TWORANGETSSI_SHIFT); |
| varbuf_append(&b, vstr_pdgaing, 5, |
| (fem_cfg & SROM11_PDGAIN_MASK) >> |
| SROM11_PDGAIN_SHIFT); |
| varbuf_append(&b, vstr_epagaing, 5, |
| (fem_cfg & SROM11_EPAGAIN_MASK) >> |
| SROM11_EPAGAIN_SHIFT); |
| varbuf_append(&b, vstr_tssiposslopeg, 5, |
| (fem_cfg & SROM11_TSSIPOSSLOPE_MASK) >> |
| SROM11_TSSIPOSSLOPE_SHIFT); |
| break; |
| } |
| |
| case HNBU_ACPA_C0: { |
| const int a = 0; |
| |
| #ifndef OTP_SKIP_MAXP_PAPARAMS |
| varbuf_append(&b, vstr_subband5gver, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| /* maxp2g */ |
| /* Decoupling this touple to program from NVRAM */ |
| varbuf_append(&b, vstr_maxp2ga, a, |
| (cis[i + 4] << 8) + cis[i + 3]); |
| #endif /* OTP_SKIP_MAXP_PAPARAMS */ |
| /* pa2g */ |
| varbuf_append(&b, vstr_pa2ga, a, |
| (cis[i + 6] << 8) + cis[i + 5], |
| (cis[i + 8] << 8) + cis[i + 7], |
| (cis[i + 10] << 8) + cis[i + 9]); |
| #ifndef OTP_SKIP_MAXP_PAPARAMS |
| /* maxp5g */ |
| varbuf_append(&b, vstr_maxp5ga, a, |
| cis[i + 11], |
| cis[i + 12], |
| cis[i + 13], |
| cis[i + 14]); |
| #endif /* OTP_SKIP_MAXP_PAPARAMS */ |
| /* pa5g */ |
| varbuf_append(&b, vstr_pa5ga, a, |
| (cis[i + 16] << 8) + cis[i + 15], |
| (cis[i + 18] << 8) + cis[i + 17], |
| (cis[i + 20] << 8) + cis[i + 19], |
| (cis[i + 22] << 8) + cis[i + 21], |
| (cis[i + 24] << 8) + cis[i + 23], |
| (cis[i + 26] << 8) + cis[i + 25], |
| (cis[i + 28] << 8) + cis[i + 27], |
| (cis[i + 30] << 8) + cis[i + 29], |
| (cis[i + 32] << 8) + cis[i + 31], |
| (cis[i + 34] << 8) + cis[i + 33], |
| (cis[i + 36] << 8) + cis[i + 35], |
| (cis[i + 38] << 8) + cis[i + 37]); |
| break; |
| } |
| |
| case HNBU_ACPA_C1: { |
| const int a = 1; |
| |
| #ifndef OTP_SKIP_MAXP_PAPARAMS |
| /* maxp2g */ |
| /* Decoupling this touple to program from NVRAM */ |
| varbuf_append(&b, vstr_maxp2ga, a, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| #endif /* OTP_SKIP_MAXP_PAPARAMS */ |
| /* pa2g */ |
| varbuf_append(&b, vstr_pa2ga, a, |
| (cis[i + 4] << 8) + cis[i + 3], |
| (cis[i + 6] << 8) + cis[i + 5], |
| (cis[i + 8] << 8) + cis[i + 7]); |
| #ifndef OTP_SKIP_MAXP_PAPARAMS |
| /* maxp5g */ |
| varbuf_append(&b, vstr_maxp5ga, a, |
| cis[i + 9], |
| cis[i + 10], |
| cis[i + 11], |
| cis[i + 12]); |
| #endif /* OTP_SKIP_MAXP_PAPARAMS */ |
| /* pa5g */ |
| varbuf_append(&b, vstr_pa5ga, a, |
| (cis[i + 14] << 8) + cis[i + 13], |
| (cis[i + 16] << 8) + cis[i + 15], |
| (cis[i + 18] << 8) + cis[i + 17], |
| (cis[i + 20] << 8) + cis[i + 19], |
| (cis[i + 22] << 8) + cis[i + 21], |
| (cis[i + 24] << 8) + cis[i + 23], |
| (cis[i + 26] << 8) + cis[i + 25], |
| (cis[i + 28] << 8) + cis[i + 27], |
| (cis[i + 30] << 8) + cis[i + 29], |
| (cis[i + 32] << 8) + cis[i + 31], |
| (cis[i + 34] << 8) + cis[i + 33], |
| (cis[i + 36] << 8) + cis[i + 35]); |
| break; |
| } |
| |
| case HNBU_ACPA_C2: { |
| const int a = 2; |
| |
| #ifndef OTP_SKIP_MAXP_PAPARAMS |
| /* maxp2g */ |
| /* Decoupling this touple to program from NVRAM */ |
| varbuf_append(&b, vstr_maxp2ga, a, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| #endif /* OTP_SKIP_MAXP_PAPARAMS */ |
| /* pa2g */ |
| varbuf_append(&b, vstr_pa2ga, a, |
| (cis[i + 4] << 8) + cis[i + 3], |
| (cis[i + 6] << 8) + cis[i + 5], |
| (cis[i + 8] << 8) + cis[i + 7]); |
| #ifndef OTP_SKIP_MAXP_PAPARAMS |
| /* maxp5g */ |
| varbuf_append(&b, vstr_maxp5ga, a, |
| cis[i + 9], |
| cis[i + 10], |
| cis[i + 11], |
| cis[i + 12]); |
| #endif /* OTP_SKIP_MAXP_PAPARAMS */ |
| /* pa5g */ |
| varbuf_append(&b, vstr_pa5ga, a, |
| (cis[i + 14] << 8) + cis[i + 13], |
| (cis[i + 16] << 8) + cis[i + 15], |
| (cis[i + 18] << 8) + cis[i + 17], |
| (cis[i + 20] << 8) + cis[i + 19], |
| (cis[i + 22] << 8) + cis[i + 21], |
| (cis[i + 24] << 8) + cis[i + 23], |
| (cis[i + 26] << 8) + cis[i + 25], |
| (cis[i + 28] << 8) + cis[i + 27], |
| (cis[i + 30] << 8) + cis[i + 29], |
| (cis[i + 32] << 8) + cis[i + 31], |
| (cis[i + 34] << 8) + cis[i + 33], |
| (cis[i + 36] << 8) + cis[i + 35]); |
| break; |
| } |
| |
| case HNBU_MEAS_PWR: |
| varbuf_append(&b, vstr_measpower, cis[i + 1]); |
| varbuf_append(&b, vstr_measpowerX, 1, (cis[i + 2])); |
| varbuf_append(&b, vstr_measpowerX, 2, (cis[i + 3])); |
| varbuf_append(&b, vstr_rawtempsense, |
| ((cis[i + 5] & 0x1) << 8) + cis[i + 4]); |
| break; |
| |
| case HNBU_PDOFF: |
| varbuf_append(&b, vstr_pdoffsetma, 40, 0, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| varbuf_append(&b, vstr_pdoffsetma, 40, 1, |
| (cis[i + 4] << 8) + cis[i + 3]); |
| varbuf_append(&b, vstr_pdoffsetma, 40, 2, |
| (cis[i + 6] << 8) + cis[i + 5]); |
| varbuf_append(&b, vstr_pdoffsetma, 80, 0, |
| (cis[i + 8] << 8) + cis[i + 7]); |
| varbuf_append(&b, vstr_pdoffsetma, 80, 1, |
| (cis[i + 10] << 8) + cis[i + 9]); |
| varbuf_append(&b, vstr_pdoffsetma, 80, 2, |
| (cis[i + 12] << 8) + cis[i + 11]); |
| break; |
| |
| case HNBU_ACPPR_2GPO: |
| varbuf_append(&b, vstr_dot11agofdmhrbw202gpo, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| varbuf_append(&b, vstr_ofdmlrbw202gpo, |
| (cis[i + 4] << 8) + cis[i + 3]); |
| |
| if (tlen < 13) break; |
| varbuf_append(&b, vstr_sb20in40dot11agofdm2gpo, |
| (cis[i + 6] << 8) + cis[i + 5]); |
| varbuf_append(&b, vstr_sb20in80dot11agofdm2gpo, |
| (cis[i + 8] << 8) + cis[i + 7]); |
| varbuf_append(&b, vstr_sb20in40ofdmlrbw202gpo, |
| (cis[i + 10] << 8) + cis[i + 9]); |
| varbuf_append(&b, vstr_sb20in80ofdmlrbw202gpo, |
| (cis[i + 12] << 8) + cis[i + 11]); |
| break; |
| |
| case HNBU_ACPPR_5GPO: |
| varbuf_append(&b, vstr_mcsbw805gpo, 'l', |
| (cis[i + 4] << 24) + (cis[i + 3] << 16) + |
| (cis[i + 2] << 8) + cis[i + 1]); |
| varbuf_append(&b, vstr_mcsbw1605gpo, 'l', |
| (cis[i + 8] << 24) + (cis[i + 7] << 16) + |
| (cis[i + 6] << 8) + cis[i + 5]); |
| varbuf_append(&b, vstr_mcsbw805gpo, 'm', |
| (cis[i + 12] << 24) + (cis[i + 11] << 16) + |
| (cis[i + 10] << 8) + cis[i + 9]); |
| varbuf_append(&b, vstr_mcsbw1605gpo, 'm', |
| (cis[i + 16] << 24) + (cis[i + 15] << 16) + |
| (cis[i + 14] << 8) + cis[i + 13]); |
| varbuf_append(&b, vstr_mcsbw805gpo, 'h', |
| (cis[i + 20] << 24) + (cis[i + 19] << 16) + |
| (cis[i + 18] << 8) + cis[i + 17]); |
| varbuf_append(&b, vstr_mcsbw1605gpo, 'h', |
| (cis[i + 24] << 24) + (cis[i + 23] << 16) + |
| (cis[i + 22] << 8) + cis[i + 21]); |
| varbuf_append(&b, vstr_mcslr5gpo, 'l', |
| (cis[i + 26] << 8) + cis[i + 25]); |
| varbuf_append(&b, vstr_mcslr5gpo, 'm', |
| (cis[i + 28] << 8) + cis[i + 27]); |
| varbuf_append(&b, vstr_mcslr5gpo, 'h', |
| (cis[i + 30] << 8) + cis[i + 29]); |
| |
| if (tlen < 51) break; |
| varbuf_append(&b, vstr_mcsbw80p805gpo, 'l', |
| (cis[i + 34] << 24) + (cis[i + 33] << 16) + |
| (cis[i + 32] << 8) + cis[i + 31]); |
| varbuf_append(&b, vstr_mcsbw80p805gpo, 'm', |
| (cis[i + 38] << 24) + (cis[i + 37] << 16) + |
| (cis[i + 36] << 8) + cis[i + 35]); |
| varbuf_append(&b, vstr_mcsbw80p805gpo, 'h', |
| (cis[i + 42] << 24) + (cis[i + 41] << 16) + |
| (cis[i + 40] << 8) + cis[i + 39]); |
| varbuf_append(&b, vstr_mcsbw80p805g1po, 'x', |
| (cis[i + 46] << 24) + (cis[i + 45] << 16) + |
| (cis[i + 44] << 8) + cis[i + 43]); |
| varbuf_append(&b, vstr_mcslr5g1po, 'x', |
| (cis[i + 48] << 8) + cis[i + 47]); |
| varbuf_append(&b, vstr_mcslr5g80p80po, |
| (cis[i + 50] << 8) + cis[i + 49]); |
| varbuf_append(&b, vstr_mcsbw805g1po, 'x', |
| (cis[i + 54] << 24) + (cis[i + 53] << 16) + |
| (cis[i + 52] << 8) + cis[i + 51]); |
| varbuf_append(&b, vstr_mcsbw1605g1po, 'x', |
| (cis[i + 58] << 24) + (cis[i + 57] << 16) + |
| (cis[i + 56] << 8) + cis[i + 55]); |
| |
| break; |
| |
| case HNBU_MCS5Gx1PO: |
| varbuf_append(&b, vstr_mcsbw205g1po, 'x', |
| (cis[i + 4] << 24) + (cis[i + 3] << 16) + |
| (cis[i + 2] << 8) + cis[i + 1]); |
| varbuf_append(&b, vstr_mcsbw405g1po, 'x', |
| (cis[i + 8] << 24) + (cis[i + 7] << 16) + |
| (cis[i + 6] << 8) + cis[i + 5]); |
| break; |
| |
| case HNBU_ACPPR_SBPO: |
| varbuf_append(&b, vstr_sb20in40rpo, 'h', |
| (cis[i + 2] << 8) + cis[i + 1]); |
| varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'l', |
| (cis[i + 4] << 8) + cis[i + 3]); |
| varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'l', |
| (cis[i + 6] << 8) + cis[i + 5]); |
| varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'm', |
| (cis[i + 8] << 8) + cis[i + 7]); |
| varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'm', |
| (cis[i + 10] << 8) + cis[i + 9]); |
| varbuf_append(&b, vstr_sb20in80and160r5gpo, 'h', 'h', |
| (cis[i + 12] << 8) + cis[i + 11]); |
| varbuf_append(&b, vstr_sb40and80r5gpo, 'h', 'h', |
| (cis[i + 14] << 8) + cis[i + 13]); |
| varbuf_append(&b, vstr_sb20in40rpo, 'l', |
| (cis[i + 16] << 8) + cis[i + 15]); |
| varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'l', |
| (cis[i + 18] << 8) + cis[i + 17]); |
| varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'l', |
| (cis[i + 20] << 8) + cis[i + 19]); |
| varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'm', |
| (cis[i + 22] << 8) + cis[i + 21]); |
| varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'm', |
| (cis[i + 24] << 8) + cis[i + 23]); |
| varbuf_append(&b, vstr_sb20in80and160r5gpo, 'l', 'h', |
| (cis[i + 26] << 8) + cis[i + 25]); |
| varbuf_append(&b, vstr_sb40and80r5gpo, 'l', 'h', |
| (cis[i + 28] << 8) + cis[i + 27]); |
| varbuf_append(&b, vstr_dot11agduprpo, 'h', |
| (cis[i + 32] << 24) + (cis[i + 31] << 16) + |
| (cis[i + 30] << 8) + cis[i + 29]); |
| varbuf_append(&b, vstr_dot11agduprpo, 'l', |
| (cis[i + 36] << 24) + (cis[i + 35] << 16) + |
| (cis[i + 34] << 8) + cis[i + 33]); |
| |
| if (tlen < 49) break; |
| varbuf_append(&b, vstr_sb20in40and80rpo, 'h', |
| (cis[i + 38] << 8) + cis[i + 37]); |
| varbuf_append(&b, vstr_sb20in40and80rpo, 'l', |
| (cis[i + 40] << 8) + cis[i + 39]); |
| varbuf_append(&b, vstr_sb20in80and160r5g1po, 'h', 'x', |
| (cis[i + 42] << 8) + cis[i + 41]); |
| varbuf_append(&b, vstr_sb20in80and160r5g1po, 'l', 'x', |
| (cis[i + 44] << 8) + cis[i + 43]); |
| varbuf_append(&b, vstr_sb40and80r5g1po, 'h', 'x', |
| (cis[i + 46] << 8) + cis[i + 45]); |
| varbuf_append(&b, vstr_sb40and80r5g1po, 'l', 'x', |
| (cis[i + 48] << 8) + cis[i + 47]); |
| break; |
| |
| case HNBU_ACPPR_SB8080_PO: |
| varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'h', 'l', |
| (cis[i + 2] << 8) + cis[i + 1]); |
| varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'l', 'l', |
| (cis[i + 4] << 8) + cis[i + 3]); |
| varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'h', 'm', |
| (cis[i + 6] << 8) + cis[i + 5]); |
| varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'l', 'm', |
| (cis[i + 8] << 8) + cis[i + 7]); |
| varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'h', 'h', |
| (cis[i + 10] << 8) + cis[i + 9]); |
| varbuf_append(&b, vstr_sb2040and80in80p80r5gpo, 'l', 'h', |
| (cis[i + 12] << 8) + cis[i + 11]); |
| varbuf_append(&b, vstr_sb2040and80in80p80r5g1po, 'h', 'x', |
| (cis[i + 14] << 8) + cis[i + 13]); |
| varbuf_append(&b, vstr_sb2040and80in80p80r5g1po, 'l', 'x', |
| (cis[i + 16] << 8) + cis[i + 15]); |
| varbuf_append(&b, vstr_sb20in80p80r5gpo, 'h', |
| (cis[i + 18] << 8) + cis[i + 17]); |
| varbuf_append(&b, vstr_sb20in80p80r5gpo, 'l', |
| (cis[i + 20] << 8) + cis[i + 19]); |
| varbuf_append(&b, vstr_dot11agduppo, |
| (cis[i + 22] << 8) + cis[i + 21]); |
| break; |
| |
| case HNBU_NOISELVL: |
| /* noiselvl2g */ |
| varbuf_append(&b, vstr_noiselvl2ga, 0, |
| (cis[i + 1] & 0x1f)); |
| varbuf_append(&b, vstr_noiselvl2ga, 1, |
| (cis[i + 2] & 0x1f)); |
| varbuf_append(&b, vstr_noiselvl2ga, 2, |
| (cis[i + 3] & 0x1f)); |
| /* noiselvl5g */ |
| varbuf_append(&b, vstr_noiselvl5ga, 0, |
| (cis[i + 4] & 0x1f), |
| (cis[i + 5] & 0x1f), |
| (cis[i + 6] & 0x1f), |
| (cis[i + 7] & 0x1f)); |
| varbuf_append(&b, vstr_noiselvl5ga, 1, |
| (cis[i + 8] & 0x1f), |
| (cis[i + 9] & 0x1f), |
| (cis[i + 10] & 0x1f), |
| (cis[i + 11] & 0x1f)); |
| varbuf_append(&b, vstr_noiselvl5ga, 2, |
| (cis[i + 12] & 0x1f), |
| (cis[i + 13] & 0x1f), |
| (cis[i + 14] & 0x1f), |
| (cis[i + 15] & 0x1f)); |
| break; |
| |
| case HNBU_RXGAIN_ERR: |
| varbuf_append(&b, vstr_rxgainerr2ga, 0, |
| (cis[i + 1] & 0x3f)); |
| varbuf_append(&b, vstr_rxgainerr2ga, 1, |
| (cis[i + 2] & 0x1f)); |
| varbuf_append(&b, vstr_rxgainerr2ga, 2, |
| (cis[i + 3] & 0x1f)); |
| varbuf_append(&b, vstr_rxgainerr5ga, 0, |
| (cis[i + 4] & 0x3f), |
| (cis[i + 5] & 0x3f), |
| (cis[i + 6] & 0x3f), |
| (cis[i + 7] & 0x3f)); |
| varbuf_append(&b, vstr_rxgainerr5ga, 1, |
| (cis[i + 8] & 0x1f), |
| (cis[i + 9] & 0x1f), |
| (cis[i + 10] & 0x1f), |
| (cis[i + 11] & 0x1f)); |
| varbuf_append(&b, vstr_rxgainerr5ga, 2, |
| (cis[i + 12] & 0x1f), |
| (cis[i + 13] & 0x1f), |
| (cis[i + 14] & 0x1f), |
| (cis[i + 15] & 0x1f)); |
| break; |
| |
| case HNBU_AGBGA: |
| varbuf_append(&b, vstr_agbg, 0, cis[i + 1]); |
| varbuf_append(&b, vstr_agbg, 1, cis[i + 2]); |
| varbuf_append(&b, vstr_agbg, 2, cis[i + 3]); |
| varbuf_append(&b, vstr_aga, 0, cis[i + 4]); |
| varbuf_append(&b, vstr_aga, 1, cis[i + 5]); |
| varbuf_append(&b, vstr_aga, 2, cis[i + 6]); |
| break; |
| |
| case HNBU_ACRXGAINS_C0: { |
| int a = 0; |
| |
| /* rxgains */ |
| uint16 rxgains = (cis[i + 2] << 8) + cis[i + 1]; |
| varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a, |
| (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >> |
| SROM11_RXGAINS5GTRELNABYPA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a, |
| (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >> |
| SROM11_RXGAINS5GTRISOA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a, |
| (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >> |
| SROM11_RXGAINS5GELNAGAINA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a, |
| (rxgains & SROM11_RXGAINS2GTRELNABYPA_MASK) >> |
| SROM11_RXGAINS2GTRELNABYPA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a, |
| (rxgains & SROM11_RXGAINS2GTRISOA_MASK) >> |
| SROM11_RXGAINS2GTRISOA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a, |
| (rxgains & SROM11_RXGAINS2GELNAGAINA_MASK) >> |
| SROM11_RXGAINS2GELNAGAINA_SHIFT); |
| /* rxgains1 */ |
| rxgains = (cis[i + 4] << 8) + cis[i + 3]; |
| varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'h', a, |
| (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >> |
| SROM11_RXGAINS5GTRELNABYPA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'h', a, |
| (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >> |
| SROM11_RXGAINS5GTRISOA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'h', a, |
| (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >> |
| SROM11_RXGAINS5GELNAGAINA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'm', a, |
| (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >> |
| SROM11_RXGAINS5GTRELNABYPA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'm', a, |
| (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >> |
| SROM11_RXGAINS5GTRISOA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'm', a, |
| (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >> |
| SROM11_RXGAINS5GELNAGAINA_SHIFT); |
| break; |
| } |
| |
| case HNBU_ACRXGAINS_C1: { |
| int a = 1; |
| |
| /* rxgains */ |
| uint16 rxgains = (cis[i + 2] << 8) + cis[i + 1]; |
| varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a, |
| (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >> |
| SROM11_RXGAINS5GTRELNABYPA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a, |
| (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >> |
| SROM11_RXGAINS5GTRISOA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a, |
| (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >> |
| SROM11_RXGAINS5GELNAGAINA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a, |
| (rxgains & SROM11_RXGAINS2GTRELNABYPA_MASK) >> |
| SROM11_RXGAINS2GTRELNABYPA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a, |
| (rxgains & SROM11_RXGAINS2GTRISOA_MASK) >> |
| SROM11_RXGAINS2GTRISOA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a, |
| (rxgains & SROM11_RXGAINS2GELNAGAINA_MASK) >> |
| SROM11_RXGAINS2GELNAGAINA_SHIFT); |
| /* rxgains1 */ |
| rxgains = (cis[i + 4] << 8) + cis[i + 3]; |
| varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'h', a, |
| (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >> |
| SROM11_RXGAINS5GTRELNABYPA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'h', a, |
| (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >> |
| SROM11_RXGAINS5GTRISOA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'h', a, |
| (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >> |
| SROM11_RXGAINS5GELNAGAINA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'm', a, |
| (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >> |
| SROM11_RXGAINS5GTRELNABYPA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'm', a, |
| (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >> |
| SROM11_RXGAINS5GTRISOA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'm', a, |
| (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >> |
| SROM11_RXGAINS5GELNAGAINA_SHIFT); |
| break; |
| } |
| |
| case HNBU_ACRXGAINS_C2: { |
| int a = 2; |
| |
| /* rxgains */ |
| uint16 rxgains = (cis[i + 2] << 8) + cis[i + 1]; |
| varbuf_append(&b, vstr_rxgainsgtrelnabypa, 5, a, |
| (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >> |
| SROM11_RXGAINS5GTRELNABYPA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgtrisoa, 5, a, |
| (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >> |
| SROM11_RXGAINS5GTRISOA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgelnagaina, 5, a, |
| (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >> |
| SROM11_RXGAINS5GELNAGAINA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgtrelnabypa, 2, a, |
| (rxgains & SROM11_RXGAINS2GTRELNABYPA_MASK) >> |
| SROM11_RXGAINS2GTRELNABYPA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgtrisoa, 2, a, |
| (rxgains & SROM11_RXGAINS2GTRISOA_MASK) >> |
| SROM11_RXGAINS2GTRISOA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgelnagaina, 2, a, |
| (rxgains & SROM11_RXGAINS2GELNAGAINA_MASK) >> |
| SROM11_RXGAINS2GELNAGAINA_SHIFT); |
| /* rxgains1 */ |
| rxgains = (cis[i + 4] << 8) + cis[i + 3]; |
| varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'h', a, |
| (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >> |
| SROM11_RXGAINS5GTRELNABYPA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'h', a, |
| (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >> |
| SROM11_RXGAINS5GTRISOA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'h', a, |
| (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >> |
| SROM11_RXGAINS5GELNAGAINA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxtrelnabypa, 5, 'm', a, |
| (rxgains & SROM11_RXGAINS5GTRELNABYPA_MASK) >> |
| SROM11_RXGAINS5GTRELNABYPA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxtrisoa, 5, 'm', a, |
| (rxgains & SROM11_RXGAINS5GTRISOA_MASK) >> |
| SROM11_RXGAINS5GTRISOA_SHIFT); |
| varbuf_append(&b, vstr_rxgainsgxelnagaina, 5, 'm', a, |
| (rxgains & SROM11_RXGAINS5GELNAGAINA_MASK) >> |
| SROM11_RXGAINS5GELNAGAINA_SHIFT); |
| break; |
| } |
| |
| case HNBU_TXDUTY: { |
| varbuf_append(&b, vstr_txduty_ofdm, 40, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| varbuf_append(&b, vstr_txduty_thresh, 40, |
| (cis[i + 4] << 8) + cis[i + 3]); |
| varbuf_append(&b, vstr_txduty_ofdm, 80, |
| (cis[i + 6] << 8) + cis[i + 5]); |
| varbuf_append(&b, vstr_txduty_thresh, 80, |
| (cis[i + 8] << 8) + cis[i + 7]); |
| break; |
| } |
| |
| case HNBU_UUID: { |
| /* uuid format 12345678-1234-5678-1234-567812345678 */ |
| |
| char uuidstr[37]; /* 32 ids, 4 '-', 1 Null */ |
| |
| snprintf(uuidstr, sizeof(uuidstr), |
| rstr_uuidstr, |
| cis[i + 1], cis[i + 2], cis[i + 3], cis[i + 4], |
| cis[i + 5], cis[i + 6], cis[i + 7], cis[i + 8], |
| cis[i + 9], cis[i + 10], cis[i + 11], cis[i + 12], |
| cis[i + 13], cis[i + 14], cis[i + 15], cis[i + 16]); |
| |
| varbuf_append(&b, vstr_uuid, uuidstr); |
| break; |
| } |
| |
| case HNBU_WOWLGPIO: |
| varbuf_append(&b, vstr_wowlgpio, ((cis[i + 1]) & 0x7F)); |
| varbuf_append(&b, vstr_wowlgpiopol, |
| (((cis[i + 1]) >> 7) & 0x1)); |
| break; |
| |
| #endif /* !BCM_BOOTLOADER */ |
| #ifdef BCMUSBDEV_COMPOSITE |
| case HNBU_USBDESC_COMPOSITE: |
| varbuf_append(&b, vstr_usbdesc_composite, |
| (cis[i + 2] << 8) | cis[i + 1]); |
| break; |
| #endif /* BCMUSBDEV_COMPOSITE */ |
| case HNBU_USBUTMI_CTL: |
| varbuf_append(&b, vstr_usbutmi_ctl, |
| (cis[i + 2] << 8) | cis[i + 1]); |
| break; |
| |
| case HNBU_USBSSPHY_UTMI_CTL0: |
| varbuf_append(&b, vstr_usbssphy_utmi_ctl0, |
| (cis[i + 4] << 24) | (cis[i + 3] << 16) | |
| (cis[i + 2] << 8) | cis[i + 1]); |
| break; |
| |
| case HNBU_USBSSPHY_UTMI_CTL1: |
| varbuf_append(&b, vstr_usbssphy_utmi_ctl1, |
| (cis[i + 4] << 24) | (cis[i + 3] << 16) | |
| (cis[i + 2] << 8) | cis[i + 1]); |
| break; |
| |
| case HNBU_USBSSPHY_UTMI_CTL2: |
| varbuf_append(&b, vstr_usbssphy_utmi_ctl2, |
| (cis[i + 4] << 24) | (cis[i + 3] << 16) | |
| (cis[i + 2] << 8) | cis[i + 1]); |
| break; |
| |
| case HNBU_USBSSPHY_SLEEP0: |
| varbuf_append(&b, vstr_usbssphy_sleep0, |
| (cis[i + 2] << 8) | cis[i + 1]); |
| break; |
| |
| case HNBU_USBSSPHY_SLEEP1: |
| varbuf_append(&b, vstr_usbssphy_sleep1, |
| (cis[i + 2] << 8) | cis[i + 1]); |
| break; |
| |
| case HNBU_USBSSPHY_SLEEP2: |
| varbuf_append(&b, vstr_usbssphy_sleep2, |
| (cis[i + 2] << 8) | cis[i + 1]); |
| break; |
| |
| case HNBU_USBSSPHY_SLEEP3: |
| varbuf_append(&b, vstr_usbssphy_sleep3, |
| (cis[i + 2] << 8) | cis[i + 1]); |
| break; |
| case HNBU_USBSSPHY_MDIO: { |
| uint8 setnum; |
| uint16 k; |
| |
| setnum = (cis[i + 1])/4; |
| if (setnum == 0) |
| break; |
| for (j = 0; j < setnum; j++) { |
| k = j*12; |
| varbuf_append(&b, vstr_usbssphy_mdio, j, |
| (cis[i+4+k]<<16) | (cis[i+3+k]<<8) | cis[i+2+k], |
| (cis[i+7+k]<<16) | (cis[i+6+k]<<8) | cis[i+5+k], |
| (cis[i+10+k]<<16) | (cis[i+9+k]<<8) | cis[i+8+k], |
| (cis[i+13+k]<<16) | (cis[i+12+k]<<8) | cis[i+11+k]); |
| } |
| break; |
| } |
| case HNBU_USB30PHY_NOSS: |
| varbuf_append(&b, vstr_usb30phy_noss, cis[i + 1]); |
| break; |
| case HNBU_USB30PHY_U1U2: |
| varbuf_append(&b, vstr_usb30phy_u1u2, cis[i + 1]); |
| break; |
| case HNBU_USB30PHY_REGS: |
| varbuf_append(&b, vstr_usb30phy_regs, 0, |
| cis[i+4]|cis[i+3]|cis[i+2]|cis[i+1], |
| cis[i+8]|cis[i+7]|cis[i+6]|cis[i+5], |
| cis[i+12]|cis[i+11]|cis[i+10]|cis[i+9], |
| cis[i+16]|cis[i+15]|cis[i+14]|cis[i+13]); |
| varbuf_append(&b, vstr_usb30phy_regs, 1, |
| cis[i+20]|cis[i+19]|cis[i+18]|cis[i+17], |
| cis[i+24]|cis[i+23]|cis[i+22]|cis[i+21], |
| cis[i+28]|cis[i+27]|cis[i+26]|cis[i+25], |
| cis[i+32]|cis[i+31]|cis[i+30]|cis[i+29]); |
| |
| break; |
| |
| case HNBU_PDOFF_2G: { |
| uint16 pdoff_2g = (cis[i + 2] << 8) + cis[i + 1]; |
| varbuf_append(&b, vstr_pdoffset2gma, 40, 0, |
| (pdoff_2g & SROM11_PDOFF_2G_40M_A0_MASK) >> |
| SROM11_PDOFF_2G_40M_A0_SHIFT); |
| varbuf_append(&b, vstr_pdoffset2gma, 40, 1, |
| (pdoff_2g & SROM11_PDOFF_2G_40M_A1_MASK) >> |
| SROM11_PDOFF_2G_40M_A1_SHIFT); |
| varbuf_append(&b, vstr_pdoffset2gma, 40, 2, |
| (pdoff_2g & SROM11_PDOFF_2G_40M_A2_MASK) >> |
| SROM11_PDOFF_2G_40M_A2_SHIFT); |
| varbuf_append(&b, vstr_pdoffset2gmvalid, 40, |
| (pdoff_2g & SROM11_PDOFF_2G_40M_VALID_MASK) >> |
| SROM11_PDOFF_2G_40M_VALID_SHIFT); |
| break; |
| } |
| |
| case HNBU_ACPA_CCK_C0: |
| varbuf_append(&b, vstr_pa2gccka, 0, |
| (cis[i + 2] << 8) + cis[i + 1], |
| (cis[i + 4] << 8) + cis[i + 3], |
| (cis[i + 6] << 8) + cis[i + 5]); |
| break; |
| |
| case HNBU_ACPA_CCK_C1: |
| varbuf_append(&b, vstr_pa2gccka, 1, |
| (cis[i + 2] << 8) + cis[i + 1], |
| (cis[i + 4] << 8) + cis[i + 3], |
| (cis[i + 6] << 8) + cis[i + 5]); |
| break; |
| |
| case HNBU_ACPA_40: |
| varbuf_append(&b, vstr_pa5gbw40a, 0, |
| (cis[i + 2] << 8) + cis[i + 1], |
| (cis[i + 4] << 8) + cis[i + 3], |
| (cis[i + 6] << 8) + cis[i + 5], |
| (cis[i + 8] << 8) + cis[i + 7], |
| (cis[i + 10] << 8) + cis[i + 9], |
| (cis[i + 12] << 8) + cis[i + 11], |
| (cis[i + 14] << 8) + cis[i + 13], |
| (cis[i + 16] << 8) + cis[i + 15], |
| (cis[i + 18] << 8) + cis[i + 17], |
| (cis[i + 20] << 8) + cis[i + 19], |
| (cis[i + 22] << 8) + cis[i + 21], |
| (cis[i + 24] << 8) + cis[i + 23]); |
| break; |
| |
| case HNBU_ACPA_80: |
| varbuf_append(&b, vstr_pa5gbw80a, 0, |
| (cis[i + 2] << 8) + cis[i + 1], |
| (cis[i + 4] << 8) + cis[i + 3], |
| (cis[i + 6] << 8) + cis[i + 5], |
| (cis[i + 8] << 8) + cis[i + 7], |
| (cis[i + 10] << 8) + cis[i + 9], |
| (cis[i + 12] << 8) + cis[i + 11], |
| (cis[i + 14] << 8) + cis[i + 13], |
| (cis[i + 16] << 8) + cis[i + 15], |
| (cis[i + 18] << 8) + cis[i + 17], |
| (cis[i + 20] << 8) + cis[i + 19], |
| (cis[i + 22] << 8) + cis[i + 21], |
| (cis[i + 24] << 8) + cis[i + 23]); |
| break; |
| |
| case HNBU_ACPA_4080: |
| varbuf_append(&b, vstr_pa5gbw4080a, 0, |
| (cis[i + 2] << 8) + cis[i + 1], |
| (cis[i + 4] << 8) + cis[i + 3], |
| (cis[i + 6] << 8) + cis[i + 5], |
| (cis[i + 8] << 8) + cis[i + 7], |
| (cis[i + 10] << 8) + cis[i + 9], |
| (cis[i + 12] << 8) + cis[i + 11], |
| (cis[i + 14] << 8) + cis[i + 13], |
| (cis[i + 16] << 8) + cis[i + 15], |
| (cis[i + 18] << 8) + cis[i + 17], |
| (cis[i + 20] << 8) + cis[i + 19], |
| (cis[i + 22] << 8) + cis[i + 21], |
| (cis[i + 24] << 8) + cis[i + 23]); |
| varbuf_append(&b, vstr_pa5gbw4080a, 1, |
| (cis[i + 26] << 8) + cis[i + 25], |
| (cis[i + 28] << 8) + cis[i + 27], |
| (cis[i + 30] << 8) + cis[i + 29], |
| (cis[i + 32] << 8) + cis[i + 31], |
| (cis[i + 34] << 8) + cis[i + 33], |
| (cis[i + 36] << 8) + cis[i + 35], |
| (cis[i + 38] << 8) + cis[i + 37], |
| (cis[i + 40] << 8) + cis[i + 39], |
| (cis[i + 42] << 8) + cis[i + 41], |
| (cis[i + 44] << 8) + cis[i + 43], |
| (cis[i + 46] << 8) + cis[i + 45], |
| (cis[i + 48] << 8) + cis[i + 47]); |
| break; |
| |
| case HNBU_ACPA_4X4C0: |
| case HNBU_ACPA_4X4C1: |
| case HNBU_ACPA_4X4C2: |
| case HNBU_ACPA_4X4C3: { |
| int core_num = 0; |
| uint8 tuple = cis[i]; |
| |
| if (tuple == HNBU_ACPA_4X4C1) { |
| core_num = 1; |
| } else if (tuple == HNBU_ACPA_4X4C2) { |
| core_num = 2; |
| } else if (tuple == HNBU_ACPA_4X4C3) { |
| core_num = 3; |
| } |
| |
| varbuf_append(&b, vstr_maxp2ga, core_num, cis[i + 1]); |
| /* pa2g */ |
| varbuf_append(&b, vstr_sr13pa2ga, core_num, |
| (cis[i + 3] << 8) + cis[i + 2], |
| (cis[i + 5] << 8) + cis[i + 4], |
| (cis[i + 7] << 8) + cis[i + 6], |
| (cis[i + 9] << 8) + cis[i + 8]); |
| /* pa2g40 */ |
| varbuf_append(&b, vstr_pa2g40a, core_num, |
| (cis[i + 11] << 8) + cis[i + 10], |
| (cis[i + 13] << 8) + cis[i + 12], |
| (cis[i + 15] << 8) + cis[i + 14], |
| (cis[i + 17] << 8) + cis[i + 16]); |
| for (j = 0; j < 5; j++) { |
| varbuf_append(&b, vstr_maxp5gba, j, core_num, |
| cis[i + j + 18]); |
| } |
| break; |
| } |
| |
| case HNBU_ACPA_BW20_4X4C0: |
| case HNBU_ACPA_BW40_4X4C0: |
| case HNBU_ACPA_BW80_4X4C0: |
| case HNBU_ACPA_BW20_4X4C1: |
| case HNBU_ACPA_BW40_4X4C1: |
| case HNBU_ACPA_BW80_4X4C1: |
| case HNBU_ACPA_BW20_4X4C2: |
| case HNBU_ACPA_BW40_4X4C2: |
| case HNBU_ACPA_BW80_4X4C2: |
| case HNBU_ACPA_BW20_4X4C3: |
| case HNBU_ACPA_BW40_4X4C3: |
| case HNBU_ACPA_BW80_4X4C3: { |
| int k = 0; |
| char pabuf[140]; /* max: 20 '0x????'s + 19 ','s + 1 Null */ |
| int core_num = 0, buflen = 0; |
| uint8 tuple = cis[i]; |
| |
| if (tuple == HNBU_ACPA_BW20_4X4C1 || |
| tuple == HNBU_ACPA_BW40_4X4C1 || |
| tuple == HNBU_ACPA_BW80_4X4C1) { |
| core_num = 1; |
| } else if (tuple == HNBU_ACPA_BW20_4X4C2 || |
| tuple == HNBU_ACPA_BW40_4X4C2 || |
| tuple == HNBU_ACPA_BW80_4X4C2) { |
| core_num = 2; |
| } else if (tuple == HNBU_ACPA_BW20_4X4C3 || |
| tuple == HNBU_ACPA_BW40_4X4C3 || |
| tuple == HNBU_ACPA_BW80_4X4C3) { |
| core_num = 3; |
| } |
| |
| buflen = sizeof(pabuf); |
| for (j = 0; j < 20; j++) { /* cis[i+1] - cis[i+40] */ |
| k += snprintf(pabuf+k, buflen-k, rstr_hex, |
| ((cis[i + (2*j) + 2] << 8) + |
| cis[i + (2*j) + 1])); |
| if (j < 19) { |
| k += snprintf(pabuf+k, buflen-k, |
| ","); |
| } |
| } |
| |
| if (tuple == HNBU_ACPA_BW20_4X4C0 || |
| tuple == HNBU_ACPA_BW20_4X4C1 || |
| tuple == HNBU_ACPA_BW20_4X4C2 || |
| tuple == HNBU_ACPA_BW20_4X4C3) { |
| varbuf_append(&b, vstr_sr13pa5ga, core_num, pabuf); |
| } else { |
| int bw = 40; |
| |
| if (tuple == HNBU_ACPA_BW80_4X4C0 || |
| tuple == HNBU_ACPA_BW80_4X4C1 || |
| tuple == HNBU_ACPA_BW80_4X4C2 || |
| tuple == HNBU_ACPA_BW80_4X4C3) { |
| bw = 80; |
| } |
| varbuf_append(&b, vstr_sr13pa5gbwa, bw, |
| core_num, pabuf); |
| } |
| break; |
| } |
| |
| case HNBU_RSSI_DELTA_2G_B0: |
| case HNBU_RSSI_DELTA_2G_B1: |
| case HNBU_RSSI_DELTA_2G_B2: |
| case HNBU_RSSI_DELTA_2G_B3: |
| case HNBU_RSSI_DELTA_2G_B4: { |
| uint8 tuple = cis[i]; |
| uint8 grp; |
| if (tuple == HNBU_RSSI_DELTA_2G_B0) { |
| grp = 0; |
| } else if (tuple == HNBU_RSSI_DELTA_2G_B1) { |
| grp = 1; |
| } else if (tuple == HNBU_RSSI_DELTA_2G_B2) { |
| grp = 2; |
| } else if (tuple == HNBU_RSSI_DELTA_2G_B3) { |
| grp = 3; |
| } else { |
| grp = 4; |
| } |
| /* 2G Band Gourp = grp */ |
| varbuf_append(&b, vstr_rssidelta2g, grp, |
| cis[i + 1], cis[i + 2], |
| cis[i + 3], cis[i + 4], |
| cis[i + 5], cis[i + 6], |
| cis[i + 7], cis[i + 8], |
| cis[i + 9], cis[i + 10], |
| cis[i + 11], cis[i + 12], |
| cis[i + 13], cis[i + 14], |
| cis[i + 15], cis[i + 16]); |
| break; |
| } |
| |
| case HNBU_RSSI_CAL_FREQ_GRP_2G: |
| /* 2G Band Gourp Defintion */ |
| varbuf_append(&b, vstr_rssicalfrqg, |
| cis[i + 1], cis[i + 2], |
| cis[i + 3], cis[i + 4], |
| cis[i + 5], cis[i + 6], |
| cis[i + 7]); |
| break; |
| |
| case HNBU_RSSI_DELTA_5GL: |
| case HNBU_RSSI_DELTA_5GML: |
| case HNBU_RSSI_DELTA_5GMU: |
| case HNBU_RSSI_DELTA_5GH: { |
| uint8 tuple = cis[i]; |
| char *band[] = {"l", "ml", "mu", "h"}; |
| char *pband; |
| if (tuple == HNBU_RSSI_DELTA_5GL) { |
| pband = band[0]; |
| } else if (tuple == HNBU_RSSI_DELTA_5GML) { |
| pband = band[1]; |
| } else if (tuple == HNBU_RSSI_DELTA_5GMU) { |
| pband = band[2]; |
| } else { |
| pband = band[3]; |
| } |
| /* 5G Band = band */ |
| varbuf_append(&b, vstr_rssidelta5g, pband, |
| cis[i + 1], cis[i + 2], |
| cis[i + 3], cis[i + 4], |
| cis[i + 5], cis[i + 6], |
| cis[i + 7], cis[i + 8], |
| cis[i + 9], cis[i + 10], |
| cis[i + 11], cis[i + 12], |
| cis[i + 13], cis[i + 14], |
| cis[i + 15], cis[i + 16], |
| cis[i + 17], cis[i + 17], |
| cis[i + 19], cis[i + 20], |
| cis[i + 21], cis[i + 22], |
| cis[i + 9], cis[i + 24]); |
| break; |
| } |
| |
| case HNBU_ACPA_6G_C0: { |
| const int a = 0; |
| #ifndef OTP_SKIP_MAXP_PAPARAMS |
| varbuf_append(&b, vstr_subband6gver, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| /* maxp5g */ |
| varbuf_append(&b, vstr_maxp6ga, a, |
| cis[i + 3], |
| cis[i + 4], |
| cis[i + 5], |
| cis[i + 6], |
| cis[i + 7], |
| cis[i + 8]); |
| #endif /* OTP_SKIP_MAXP_PAPARAMS */ |
| /* pa5g */ |
| varbuf_append(&b, vstr_pa6ga, a, |
| (cis[i + 10] << 8) + cis[i + 9], |
| (cis[i + 12] << 8) + cis[i + 11], |
| (cis[i + 14] << 8) + cis[i + 13], |
| (cis[i + 16] << 8) + cis[i + 15], |
| (cis[i + 18] << 8) + cis[i + 17], |
| (cis[i + 20] << 8) + cis[i + 19], |
| (cis[i + 22] << 8) + cis[i + 21], |
| (cis[i + 24] << 8) + cis[i + 23], |
| (cis[i + 26] << 8) + cis[i + 25], |
| (cis[i + 28] << 8) + cis[i + 27], |
| (cis[i + 30] << 8) + cis[i + 29], |
| (cis[i + 32] << 8) + cis[i + 31], |
| (cis[i + 34] << 8) + cis[i + 33], |
| (cis[i + 36] << 8) + cis[i + 35], |
| (cis[i + 38] << 8) + cis[i + 37], |
| (cis[i + 40] << 8) + cis[i + 39], |
| (cis[i + 42] << 8) + cis[i + 41], |
| (cis[i + 44] << 8) + cis[i + 43]); |
| break; |
| } |
| |
| case HNBU_ACPA_6G_C1: { |
| const int a = 1; |
| #ifndef OTP_SKIP_MAXP_PAPARAMS |
| /* maxp6g */ |
| varbuf_append(&b, vstr_maxp6ga, a, |
| cis[i + 1], |
| cis[i + 2], |
| cis[i + 3], |
| cis[i + 4], |
| cis[i + 5], |
| cis[i + 6]); |
| #endif /* OTP_SKIP_MAXP_PAPARAMS */ |
| /* pa6g */ |
| varbuf_append(&b, vstr_pa6ga, a, |
| (cis[i + 8] << 8) + cis[i + 7], |
| (cis[i + 10] << 8) + cis[i + 9], |
| (cis[i + 12] << 8) + cis[i + 11], |
| (cis[i + 14] << 8) + cis[i + 13], |
| (cis[i + 16] << 8) + cis[i + 15], |
| (cis[i + 18] << 8) + cis[i + 17], |
| (cis[i + 20] << 8) + cis[i + 19], |
| (cis[i + 22] << 8) + cis[i + 21], |
| (cis[i + 24] << 8) + cis[i + 23], |
| (cis[i + 26] << 8) + cis[i + 25], |
| (cis[i + 28] << 8) + cis[i + 27], |
| (cis[i + 30] << 8) + cis[i + 29], |
| (cis[i + 32] << 8) + cis[i + 31], |
| (cis[i + 34] << 8) + cis[i + 33], |
| (cis[i + 36] << 8) + cis[i + 35], |
| (cis[i + 38] << 8) + cis[i + 37], |
| (cis[i + 40] << 8) + cis[i + 39], |
| (cis[i + 42] << 8) + cis[i + 41]); |
| break; |
| } |
| |
| case HNBU_ACPA_6G_C2: { |
| const int a = 2; |
| #ifndef OTP_SKIP_MAXP_PAPARAMS |
| /* maxp6g */ |
| varbuf_append(&b, vstr_maxp6ga, a, |
| cis[i + 1], |
| cis[i + 2], |
| cis[i + 3], |
| cis[i + 4], |
| cis[i + 5], |
| cis[i + 6]); |
| #endif /* OTP_SKIP_MAXP_PAPARAMS */ |
| /* pa6g */ |
| varbuf_append(&b, vstr_pa6ga, a, |
| (cis[i + 8] << 8) + cis[i + 7], |
| (cis[i + 10] << 8) + cis[i + 9], |
| (cis[i + 12] << 8) + cis[i + 11], |
| (cis[i + 14] << 8) + cis[i + 13], |
| (cis[i + 16] << 8) + cis[i + 15], |
| (cis[i + 18] << 8) + cis[i + 17], |
| (cis[i + 20] << 8) + cis[i + 19], |
| (cis[i + 22] << 8) + cis[i + 21], |
| (cis[i + 24] << 8) + cis[i + 23], |
| (cis[i + 26] << 8) + cis[i + 25], |
| (cis[i + 28] << 8) + cis[i + 27], |
| (cis[i + 30] << 8) + cis[i + 29], |
| (cis[i + 32] << 8) + cis[i + 31], |
| (cis[i + 34] << 8) + cis[i + 33], |
| (cis[i + 36] << 8) + cis[i + 35], |
| (cis[i + 38] << 8) + cis[i + 37], |
| (cis[i + 40] << 8) + cis[i + 39], |
| (cis[i + 42] << 8) + cis[i + 41]); |
| break; |
| } |
| |
| case HNBU_SUBBAND5GVER: |
| varbuf_append(&b, vstr_subband5gver, |
| (cis[i + 2] << 8) + cis[i + 1]); |
| break; |
| |
| case HNBU_PAPARAMBWVER: |
| varbuf_append(&b, vstr_paparambwver, cis[i + 1]); |
| break; |
| |
| case HNBU_TXBFRPCALS: |
| /* note: all 5 rpcal parameters are expected to be */ |
| /* inside one tuple record, i.e written with one */ |
| /* wl wrvar cmd as follows: */ |
| /* wl wrvar rpcal2g=0x1211 ... rpcal5gb3=0x0 */ |
| if (tlen != 11 ) { /* sanity check */ |
| BS_ERROR(("srom_parsecis:incorrect length:%d for" |
| " HNBU_TXBFRPCALS tuple\n", |
| tlen)); |
| break; |
| } |
| |
| varbuf_append(&b, vstr_paparamrpcalvars[0], |
| (cis[i + 1] + (cis[i + 2] << 8))); |
| varbuf_append(&b, vstr_paparamrpcalvars[1], |
| (cis[i + 3] + (cis[i + 4] << 8))); |
| varbuf_append(&b, vstr_paparamrpcalvars[2], |
| (cis[i + 5] + (cis[i + 6] << 8))); |
| varbuf_append(&b, vstr_paparamrpcalvars[3], |
| (cis[i + 7] + (cis[i + 8] << 8))); |
| varbuf_append(&b, vstr_paparamrpcalvars[4], |
| (cis[i + 9] + (cis[i + 10] << 8))); |
| break; |
| |
| case HNBU_GPIO_PULL_DOWN: |
| varbuf_append(&b, vstr_gpdn, |
| (cis[i + 4] << 24) | |
| (cis[i + 3] << 16) | |
| (cis[i + 2] << 8) | |
| cis[i + 1]); |
| break; |
| |
| case HNBU_MACADDR2: |
| if (!(ETHER_ISNULLADDR(&cis[i+1])) && |
| !(ETHER_ISMULTI(&cis[i+1]))) { |
| bcm_ether_ntoa((struct ether_addr *)&cis[i + 1], |
| eabuf2); |
| } |
| break; |
| } /* CISTPL_BRCM_HNBU */ |
| break; |
| } /* switch (tup) */ |
| |
| i += tlen; |
| } while (tup != CISTPL_END); |
| } |
| |
| if (boardnum != -1) { |
| varbuf_append(&b, vstr_boardnum, boardnum); |
| } |
| |
| if (eabuf[0]) { |
| varbuf_append(&b, vstr_macaddr, eabuf); |
| } |
| |
| if (eabuf2[0]) { |
| varbuf_append(&b, vstr_macaddr2, eabuf2); |
| } |
| |
| #ifndef BCM_BOOTLOADER |
| /* if there is no antenna gain field, set default */ |
| sromrev = (sromrev == 1u) ? (uint8)getintvar(NULL, rstr_sromrev) : sromrev; |
| if (sromrev <= 10u && getvar(NULL, rstr_ag0) == NULL && ag_init == FALSE) { |
| varbuf_append(&b, vstr_ag, 0, 0xff); |
| } |
| #endif |
| |
| /* final nullbyte terminator */ |
| ASSERT(b.size >= 1u); |
| *b.buf++ = '\0'; |
| |
| ASSERT((uint)(b.buf - base) <= var_cis_size); |
| |
| /* initvars_table() MALLOCs, copies and assigns the MALLOCed buffer to '*vars' */ |
| err = initvars_table(osh, base /* start */, b.buf /* end */, vars, count); |
| |
| MFREE(osh, base, var_cis_size); |
| return err; |
| } |
| #endif /* !defined(BCMDONGLEHOST) */ |
| |
| /** |
| * In chips with chipcommon rev 32 and later, the srom is in chipcommon, |
| * not in the bus cores. |
| */ |
| static uint16 |
| srom_cc_cmd(si_t *sih, osl_t *osh, volatile void *ccregs, uint32 cmd, uint wordoff, uint16 data) |
| { |
| chipcregs_t *cc = ccregs; |
| uint wait_cnt = 1000; |
| uint32 byteoff = 0, sprom_size = 0; |
| |
| BCM_REFERENCE(sih); |
| byteoff = wordoff * 2; |
| |
| sprom_size = R_REG(osh, &cc->sromcontrol); |
| sprom_size = (sprom_size & SROM_SIZE_MASK) >> SROM_SIZE_SHFT_MASK; |
| if (sprom_size == SROM_SIZE_2K) |
| sprom_size = 2048; |
| else if (sprom_size == SROM_SIZE_512) |
| sprom_size = 512; |
| else if (sprom_size == SROM_SIZE_128) |
| sprom_size = 128; |
| if (byteoff >= sprom_size) |
| return 0xffff; |
| |
| if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) { |
| if (sih->ccrev >= 59) |
| W_REG(osh, &cc->chipcontrol, (byteoff & SROM16K_BANK_SEL_MASK) >> |
| SROM16K_BANK_SHFT_MASK); |
| W_REG(osh, &cc->sromaddress, (byteoff & SROM16K_ADDR_SEL_MASK)); |
| if (cmd == SRC_OP_WRITE) |
| W_REG(osh, &cc->sromdata, data); |
| } |
| |
| W_REG(osh, &cc->sromcontrol, SRC_START | cmd); |
| |
| while (wait_cnt--) { |
| if ((R_REG(osh, &cc->sromcontrol) & SRC_BUSY) == 0) |
| break; |
| } |
| |
| if (!wait_cnt) { |
| BS_ERROR(("srom_cc_cmd: Command 0x%x timed out\n", cmd)); |
| return 0xffff; |
| } |
| if (cmd == SRC_OP_READ) |
| return (uint16)R_REG(osh, &cc->sromdata); |
| else |
| return 0xffff; |
| } |
| |
| #define CC_SROM_SHADOW_WSIZE 512 /* 0x800 - 0xC00 */ |
| |
| /** |
| * Read in and validate sprom. |
| * Return 0 on success, nonzero on error. |
| * Returns success on an SPROM containing only ones, unclear if this is intended. |
| */ |
| static int |
| sprom_read_pci(osl_t *osh, si_t *sih, volatile uint16 *sprom, uint wordoff, |
| uint16 *buf, uint nwords, bool check_crc) |
| { |
| int err = 0; |
| uint i; |
| volatile void *ccregs = NULL; |
| chipcregs_t *cc = NULL; |
| uint32 ccval = 0, sprom_size = 0; |
| uint32 sprom_num_words; |
| |
| if (BCM43602_CHIP(sih->chip) || |
| (CHIPID(sih->chip) == BCM4360_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43460_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { |
| /* save current control setting */ |
| ccval = si_chipcontrl_read(sih); |
| } |
| |
| if (BCM43602_CHIP(sih->chip) || |
| (((CHIPID(sih->chip) == BCM4360_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43460_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM4352_CHIP_ID)) && |
| (CHIPREV(sih->chiprev) <= 2))) { |
| si_chipcontrl_srom4360(sih, TRUE); |
| } |
| |
| if (FALSE) { |
| si_srom_clk_set(sih); /* corrects srom clock frequency */ |
| } |
| |
| ccregs = ((volatile uint8 *)sprom - CC_SROM_OTP); |
| cc = ccregs; |
| sprom_size = R_REG(osh, &cc->sromcontrol); |
| sprom_size = (sprom_size & SROM_SIZE_MASK) >> SROM_SIZE_SHFT_MASK; |
| if (sprom_size == SROM_SIZE_2K) |
| sprom_size = 2048; |
| else if (sprom_size == SROM_SIZE_512) |
| sprom_size = 512; |
| else if (sprom_size == SROM_SIZE_128) |
| sprom_size = 128; |
| sprom_num_words = sprom_size/2; |
| |
| /* read the sprom */ |
| for (i = 0; i < nwords; i++) { |
| if (sih->ccrev > 31 && ISSIM_ENAB(sih)) { |
| /* use indirect since direct is too slow on QT */ |
| if ((sih->cccaps & CC_CAP_SROM) == 0) { |
| err = 1; |
| goto error; |
| } |
| |
| /* hack to get ccregs */ |
| ccregs = (volatile void *)((volatile uint8 *)sprom - CC_SROM_OTP); |
| buf[i] = srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ, wordoff + i, 0); |
| |
| } else { |
| /* Because of the slow emulation we need to read twice in QT */ |
| if (ISSIM_ENAB(sih)) { |
| buf[i] = R_REG(osh, &sprom[wordoff + i]); |
| } |
| |
| if ((wordoff + i) >= sprom_num_words) { |
| buf[i] = 0xffff; |
| } else if ((wordoff + i) >= CC_SROM_SHADOW_WSIZE) { |
| /* Srom shadow region in chipcommon is only 512 words |
| * use indirect access for Srom beyond 512 words |
| */ |
| buf[i] = srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ, wordoff + i, 0); |
| } else { |
| buf[i] = R_REG(osh, &sprom[wordoff + i]); |
| } |
| } |
| if (i == SROM13_SIGN) { |
| if ((buf[SROM13_SIGN] != SROM13_SIGNATURE) && (nwords == SROM13_WORDS)) { |
| err = 1; |
| goto error; |
| } |
| } |
| } |
| |
| /* bypass crc checking for simulation to allow srom hack */ |
| if (ISSIM_ENAB(sih)) { |
| goto error; |
| } |
| |
| 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(("sprom_read_pci: buf[0] = 0x%x, returning bad-crc\n", buf[0])); |
| err = 1; |
| goto error; |
| } |
| |
| /* fixup the endianness so crc8 will pass */ |
| htol16_buf(buf, nwords * 2); |
| if (hndcrc8((uint8 *)buf, nwords * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) { |
| /* DBG only pci always read srom4 first, then srom8/9 */ |
| /* BS_ERROR(("sprom_read_pci: bad crc\n")); */ |
| err = 1; |
| } |
| /* now correct the endianness of the byte array */ |
| ltoh16_buf(buf, nwords * 2); |
| } |
| |
| error: |
| if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43460_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM4352_CHIP_ID) || |
| BCM43602_CHIP(sih->chip)) { |
| /* Restore config after reading SROM */ |
| si_chipcontrl_restore(sih, ccval); |
| } |
| |
| return err; |
| } |
| |
| #if !defined(BCMDONGLEHOST) |
| #if defined(BCMNVRAMW) || defined(BCMNVRAMR) |
| static int |
| BCMSROMATTACHFN(otp_read_pci)(osl_t *osh, si_t *sih, uint16 *buf, uint bufsz) |
| { |
| uint8 *otp; |
| uint sz = OTP_SZ_MAX/2; /* size in words */ |
| int err = 0; |
| |
| if (bufsz > OTP_SZ_MAX) { |
| return BCME_ERROR; |
| } |
| |
| /* freed in same function */ |
| if ((otp = MALLOC_NOPERSIST(osh, OTP_SZ_MAX)) == NULL) { |
| return BCME_ERROR; |
| } |
| |
| bzero(otp, OTP_SZ_MAX); |
| |
| err = otp_read_region(sih, OTP_HW_RGN, (uint16 *)otp, &sz); |
| |
| if (err) { |
| MFREE(osh, otp, OTP_SZ_MAX); |
| return err; |
| } |
| |
| bcopy(otp, buf, bufsz); |
| |
| /* Check CRC */ |
| if (((uint16 *)otp)[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(("otp_read_pci: otp[0] = 0x%x, returning bad-crc\n", |
| ((uint16 *)otp)[0])); |
| MFREE(osh, otp, OTP_SZ_MAX); |
| return 1; |
| } |
| |
| /* fixup the endianness so crc8 will pass */ |
| htol16_buf(otp, OTP_SZ_MAX); |
| if (hndcrc8(otp, SROM4_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE && |
| hndcrc8(otp, SROM10_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE && |
| hndcrc8(otp, SROM11_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE && |
| hndcrc8(otp, SROM12_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE && |
| hndcrc8(otp, SROM13_WORDS * 2, CRC8_INIT_VALUE) != CRC8_GOOD_VALUE) { |
| BS_ERROR(("otp_read_pci: bad crc\n")); |
| err = 1; |
| } |
| |
| MFREE(osh, otp, OTP_SZ_MAX); |
| |
| return err; |
| } |
| #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */ |
| #endif /* !defined(BCMDONGLEHOST) */ |
| |
| int |
| srom_otp_write_region_crc(si_t *sih, uint nbytes, uint16* buf16, bool write) |
| { |
| #if defined(WLTEST) || defined(BCMDBG) |
| int err = 0, crc = 0; |
| #if !defined(BCMDONGLEHOST) |
| uint8 *buf8; |
| |
| /* Check nbytes is not odd or too big */ |
| if ((nbytes & 1) || (nbytes > SROM_MAX)) |
| return 1; |
| |
| /* block invalid buffer size */ |
| if (nbytes < SROM4_WORDS * 2) |
| return BCME_BUFTOOSHORT; |
| else if (nbytes > SROM13_WORDS * 2) |
| return BCME_BUFTOOLONG; |
| |
| /* Verify signatures */ |
| if (!((buf16[SROM4_SIGN] == SROM4_SIGNATURE) || |
| (buf16[SROM8_SIGN] == SROM4_SIGNATURE) || |
| (buf16[SROM10_SIGN] == SROM4_SIGNATURE) || |
| (buf16[SROM11_SIGN] == SROM11_SIGNATURE)|| |
| (buf16[SROM12_SIGN] == SROM12_SIGNATURE)|| |
| (buf16[SROM13_SIGN] == SROM13_SIGNATURE))) { |
| BS_ERROR(("srom_otp_write_region_crc: wrong signature SROM4_SIGN %x SROM8_SIGN %x" |
| " SROM10_SIGN %x\n", |
| buf16[SROM4_SIGN], buf16[SROM8_SIGN], buf16[SROM10_SIGN])); |
| return BCME_ERROR; |
| } |
| |
| /* Check CRC */ |
| if (buf16[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(("srom_otp_write_region_crc: invalid buf16[0] = 0x%x\n", buf16[0])); |
| goto out; |
| } |
| |
| buf8 = (uint8*)buf16; |
| /* fixup the endianness and then calculate crc */ |
| htol16_buf(buf8, nbytes); |
| crc = ~hndcrc8(buf8, nbytes - 1, CRC8_INIT_VALUE); |
| /* now correct the endianness of the byte array */ |
| ltoh16_buf(buf8, nbytes); |
| |
| if (nbytes == SROM11_WORDS * 2) |
| buf16[SROM11_CRCREV] = (crc << 8) | (buf16[SROM11_CRCREV] & 0xff); |
| else if (nbytes == SROM12_WORDS * 2) |
| buf16[SROM12_CRCREV] = (crc << 8) | (buf16[SROM12_CRCREV] & 0xff); |
| else if (nbytes == SROM13_WORDS * 2) |
| buf16[SROM13_CRCREV] = (crc << 8) | (buf16[SROM13_CRCREV] & 0xff); |
| else if (nbytes == SROM10_WORDS * 2) |
| buf16[SROM10_CRCREV] = (crc << 8) | (buf16[SROM10_CRCREV] & 0xff); |
| else |
| buf16[SROM4_CRCREV] = (crc << 8) | (buf16[SROM4_CRCREV] & 0xff); |
| |
| #ifdef BCMNVRAMW |
| /* Write the CRC back */ |
| if (write) |
| err = otp_write_region(sih, OTP_HW_RGN, buf16, nbytes/2, 0); |
| #endif /* BCMNVRAMW */ |
| |
| out: |
| #endif /* !defined(BCMDONGLEHOST) */ |
| return write ? err : crc; |
| #else |
| BCM_REFERENCE(sih); |
| BCM_REFERENCE(nbytes); |
| BCM_REFERENCE(buf16); |
| BCM_REFERENCE(write); |
| return 0; |
| #endif /* WLTEST || BCMDBG */ |
| |
| } |
| |
| #if !defined(BCMDONGLEHOST) |
| int |
| BCMATTACHFN(dbushost_initvars_flash)(si_t *sih, osl_t *osh, char **base, uint len) |
| { |
| return initvars_flash(sih, osh, base, len); |
| } |
| |
| /** |
| * 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 |
| BCMATTACHFN(initvars_flash)(si_t *sih, osl_t *osh, char **base, uint len) |
| { |
| char *vp = *base; |
| char *flash; |
| int err; |
| char *s; |
| uint l, dl, copy_len; |
| char devpath[SI_DEVPATH_BUFSZ], devpath_pcie[SI_DEVPATH_BUFSZ]; |
| char coded_name[SI_DEVPATH_BUFSZ] = {0}; |
| int path_len, coded_len, devid_len, pcie_path_len; |
| |
| /* allocate memory and read in flash */ |
| /* freed in same function */ |
| if (!(flash = MALLOC_NOPERSIST(osh, MAX_NVRAM_SPACE))) |
| return BCME_NOMEM; |
| if ((err = nvram_getall(flash, MAX_NVRAM_SPACE))) |
| goto exit; |
| |
| /* create legacy devpath prefix */ |
| si_devpath(sih, devpath, sizeof(devpath)); |
| path_len = strlen(devpath); |
| |
| if (BUSTYPE(sih->bustype) == PCI_BUS) { |
| si_devpath_pcie(sih, devpath_pcie, sizeof(devpath_pcie)); |
| pcie_path_len = strlen(devpath_pcie); |
| } else |
| pcie_path_len = 0; |
| |
| /* create coded devpath prefix */ |
| si_coded_devpathvar(sih, coded_name, sizeof(coded_name), "devid"); |
| |
| /* coded_name now is 'xx:devid, eat ending 'devid' */ |
| /* to be 'xx:' */ |
| devid_len = strlen("devid"); |
| coded_len = strlen(coded_name); |
| if (coded_len > devid_len) { |
| coded_name[coded_len - devid_len] = '\0'; |
| coded_len -= devid_len; |
| } |
| else |
| coded_len = 0; |
| |
| /* grab vars with the <devpath> prefix or <coded_name> previx in name */ |
| for (s = flash; s && *s; s += l + 1) { |
| l = strlen(s); |
| |
| /* skip non-matching variable */ |
| if (strncmp(s, devpath, path_len) == 0) |
| dl = path_len; |
| else if (pcie_path_len && strncmp(s, devpath_pcie, pcie_path_len) == 0) |
| dl = pcie_path_len; |
| else if (coded_len && strncmp(s, coded_name, coded_len) == 0) |
| dl = coded_len; |
| else |
| 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 */ |
| strlcpy(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, MAX_NVRAM_SPACE); |
| return err; |
| } |
| #endif /* !defined(BCMDONGLEHOST) */ |
| |
| #if !defined(BCMUSBDEV_ENABLED) && !defined(BCMSDIODEV_ENABLED) && \ |
| !defined(BCMPCIEDEV_ENABLED) |
| #if !defined(BCMDONGLEHOST) |
| /** |
| * Initialize nonvolatile variable table from flash. |
| * Return 0 on success, nonzero on error. |
| */ |
| /* no needs to load the nvram variables from the flash for dongles. |
| * These variables are mainly for supporting SROM-less devices although |
| * we can use the same machenism to support configuration of multiple |
| * cores of the same type. |
| */ |
| static int |
| BCMATTACHFN(initvars_flash_si)(si_t *sih, char **vars, uint *count) |
| { |
| osl_t *osh = si_osh(sih); |
| char *vp, *base; |
| int err; |
| |
| ASSERT(vars != NULL); |
| ASSERT(count != NULL); |
| |
| /* freed in same function */ |
| base = vp = MALLOC_NOPERSIST(osh, MAXSZ_NVRAM_VARS); |
| ASSERT(vp != NULL); |
| if (!vp) |
| return BCME_NOMEM; |
| |
| if ((err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS)) == 0) |
| err = initvars_table(osh, base, vp, vars, count); |
| |
| MFREE(osh, base, MAXSZ_NVRAM_VARS); |
| |
| return err; |
| } |
| #endif /* !defined(BCMDONGLEHOST) */ |
| #endif /* !BCMUSBDEV && !BCMSDIODEV */ |
| |
| #if !defined(BCMDONGLEHOST) |
| |
| /** returns position of rightmost bit that was set in caller supplied mask */ |
| 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 BCMASSERT_SUPPORT |
| static bool |
| mask_valid(uint16 mask) |
| { |
| uint shift = mask_shift(mask); |
| uint width = mask_width(mask); |
| return mask == ((~0 << shift) & ~(~0 << (shift + width))); |
| } |
| #endif |
| #ifdef NVSRCX |
| void |
| srom_set_sromvars(char *vars) |
| { |
| if (sromh) |
| sromh->_srom_vars = vars; |
| } |
| char * |
| srom_get_sromvars() |
| { |
| if (sromh) |
| return sromh->_srom_vars; |
| else |
| return NULL; |
| } |
| |
| srom_info_t * |
| srom_info_init(osl_t *osh) |
| { |
| sromh = (srom_info_t *) MALLOC_NOPERSIST(osh, sizeof(srom_info_t)); |
| if (!sromh) |
| return NULL; |
| sromh->_srom_vars = NULL; |
| sromh->is_caldata_prsnt = FALSE; |
| return sromh; |
| } |
| #endif /* NVSRCX */ |
| /** |
| * Parses caller supplied SROM contents into name=value pairs. Global array pci_sromvars[] contains |
| * the link between a word offset in SROM and the corresponding NVRAM variable name.'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 void |
| BCMATTACHFN(_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); |
| bool in_array = FALSE; |
| static char array_temp[256]; |
| uint array_curr = 0; |
| const char* array_name = NULL; |
| |
| varbuf_append(b, "sromrev=%d", sromrev); |
| #if !defined(SROM15_MEMOPT) && !defined(SROM17_MEMOPT) |
| if (sromrev == 15) { |
| srv = pci_srom15vars; |
| } else if (sromrev == 16) { |
| srv = pci_srom16vars; |
| } else if (sromrev == 17) { |
| srv = pci_srom17vars; |
| } else if (sromrev == 18) { |
| srv = pci_srom18vars; |
| } else { |
| srv = pci_sromvars; |
| } |
| #else |
| #if defined(SROM15_MEMOPT) |
| srv = pci_srom15vars; |
| #endif /* defined(SROM15_MEMOPT) */ |
| #if defined(SROM17_MEMOPT) |
| srv = pci_srom17vars; |
| #endif /* defined(SROM17_MEMOPT) */ |
| #endif /* !defined(SROM15_MEMOPT) && !defined(SROM17_MEMOPT) */ |
| |
| for (; srv->name != NULL; srv ++) { |
| const char *name; |
| static bool in_array2 = FALSE; |
| static char array_temp2[256]; |
| static uint array_curr2 = 0; |
| static const char* array_name2 = NULL; |
| |
| if ((srv->revmask & sr) == 0) |
| continue; |
| |
| if (srv->off < off) |
| continue; |
| |
| flags = srv->flags; |
| name = srv->name; |
| |
| /* This entry is for mfgc only. Don't generate param for it, */ |
| if (flags & SRFL_NOVAR) |
| continue; |
| |
| 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)); |
| |
| /* Start of an array */ |
| if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array2) { |
| array_curr2 = 0; |
| array_name2 = (const char*)srv->name; |
| bzero((void*)array_temp2, sizeof(array_temp2)); |
| in_array2 = TRUE; |
| } |
| |
| 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 != NULL); |
| |
| 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; |
| |
| /* Array support starts in sromrev 10. Skip arrays for sromrev <= 9 */ |
| if (sromrev <= 9 && srv->flags & SRFL_ARRAY) { |
| while (srv->flags & SRFL_ARRAY) |
| srv ++; |
| srv ++; |
| } |
| |
| if (in_array2) { |
| int ret; |
| |
| if (flags & SRFL_PRHEX) { |
| ret = snprintf(array_temp2 + array_curr2, |
| sizeof(array_temp2) - array_curr2, "0x%x,", val); |
| } else if ((flags & SRFL_PRSIGN) && |
| (val & (1 << (width - 1)))) { |
| ret = snprintf(array_temp2 + array_curr2, |
| sizeof(array_temp2) - array_curr2, "%d,", |
| (int)(val | (~0 << width))); |
| } else { |
| ret = snprintf(array_temp2 + array_curr2, |
| sizeof(array_temp2) - array_curr2, "%u,", val); |
| } |
| |
| if (ret > 0) { |
| array_curr2 += ret; |
| } else { |
| BS_ERROR(("_initvars_srom_pci: array %s parsing error." |
| " buffer too short.\n", |
| array_name2)); |
| ASSERT(0); |
| |
| /* buffer too small, skip this param */ |
| while (srv->flags & SRFL_ARRAY) |
| srv ++; |
| srv ++; |
| in_array2 = FALSE; |
| continue; |
| } |
| |
| if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */ |
| /* Remove the last ',' */ |
| array_temp2[array_curr2-1] = '\0'; |
| in_array2 = FALSE; |
| varbuf_append(b, "%s=%s", array_name2, array_temp2); |
| } |
| } else if (flags & SRFL_CCODE) { |
| if (val == 0) |
| varbuf_append(b, "ccode="); |
| else |
| varbuf_append(b, "ccode=%c%c", (val >> 8), (val & 0xff)); |
| } 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) && (sromrev != 16) && (sromrev != 18)) { |
| /* Do per-path variables */ |
| uint p, pb, psz, path_num; |
| |
| if ((sromrev == 17) || (sromrev == 15)) { |
| pb = psz = 0; |
| path_num = 0; |
| if (sromh) |
| sromh->is_caldata_prsnt = TRUE; |
| } else if (sromrev >= 13) { |
| pb = SROM13_PATH0; |
| psz = SROM13_PATH1 - SROM13_PATH0; |
| path_num = MAX_PATH_SROM_13; |
| } else if (sromrev >= 12) { |
| pb = SROM12_PATH0; |
| psz = SROM12_PATH1 - SROM12_PATH0; |
| path_num = MAX_PATH_SROM_12; |
| } else if (sromrev >= 11) { |
| pb = SROM11_PATH0; |
| psz = SROM11_PATH1 - SROM11_PATH0; |
| path_num = MAX_PATH_SROM_11; |
| } else if (sromrev >= 8) { |
| pb = SROM8_PATH0; |
| psz = SROM8_PATH1 - SROM8_PATH0; |
| path_num = MAX_PATH_SROM; |
| } else { |
| pb = SROM4_PATH0; |
| psz = SROM4_PATH1 - SROM4_PATH0; |
| path_num = MAX_PATH_SROM; |
| } |
| |
| for (p = 0; p < path_num; p++) { |
| for (srv = perpath_pci_sromvars; srv->name != NULL; srv ++) { |
| |
| if ((srv->revmask & sr) == 0) |
| continue; |
| |
| if (pb + srv->off < off) |
| continue; |
| |
| /* This entry is for mfgc only. Don't generate param for it, */ |
| if (srv->flags & SRFL_NOVAR) |
| continue; |
| |
| /* Start of an array */ |
| if (sromrev >= 10 && (srv->flags & SRFL_ARRAY) && !in_array) { |
| array_curr = 0; |
| array_name = (const char*)srv->name; |
| bzero((void*)array_temp, sizeof(array_temp)); |
| in_array = TRUE; |
| } |
| |
| w = srom[pb + srv->off - off]; |
| |
| ASSERT(mask_valid(srv->mask)); |
| val = (w & srv->mask) >> mask_shift(srv->mask); |
| width = mask_width(srv->mask); |
| |
| flags = srv->flags; |
| |
| /* Cheating: no per-path var is more than 1 word */ |
| |
| if ((srv->flags & SRFL_NOFFS) && ((int)val == (1 << width) - 1)) |
| continue; |
| |
| if (in_array) { |
| int ret; |
| |
| if (flags & SRFL_PRHEX) { |
| ret = snprintf(array_temp + array_curr, |
| sizeof(array_temp) - array_curr, "0x%x,", val); |
| } else if ((flags & SRFL_PRSIGN) && |
| (val & (1 << (width - 1)))) { |
| ret = snprintf(array_temp + array_curr, |
| sizeof(array_temp) - array_curr, "%d,", |
| (int)(val | (~0 << width))); |
| } else { |
| ret = snprintf(array_temp + array_curr, |
| sizeof(array_temp) - array_curr, "%u,", val); |
| } |
| |
| if (ret > 0) { |
| array_curr += ret; |
| } else { |
| BS_ERROR( |
| ("_initvars_srom_pci: array %s parsing error." |
| " buffer too short.\n", |
| array_name)); |
| ASSERT(0); |
| |
| /* buffer too small, skip this param */ |
| while (srv->flags & SRFL_ARRAY) |
| srv ++; |
| srv ++; |
| in_array = FALSE; |
| continue; |
| } |
| |
| if (!(srv->flags & SRFL_ARRAY)) { /* Array ends */ |
| /* Remove the last ',' */ |
| array_temp[array_curr-1] = '\0'; |
| in_array = FALSE; |
| varbuf_append(b, "%s%d=%s", |
| array_name, p, array_temp); |
| } |
| } else 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); |
| } |
| if (sromrev >= 13 && (p == (MAX_PATH_SROM_13 - 2))) { |
| psz = SROM13_PATH3 - SROM13_PATH2; |
| } |
| pb += psz; |
| } |
| } /* per path variables */ |
| } /* _initvars_srom_pci */ |
| |
| int |
| BCMATTACHFN(get_srom_pci_caldata_size)(uint32 sromrev) |
| { |
| uint32 caldata_size; |
| |
| switch (sromrev) { |
| case 15: |
| caldata_size = (SROM15_CALDATA_WORDS * 2); |
| break; |
| case 17: |
| caldata_size = (SROM17_CALDATA_WORDS * 2); |
| break; |
| default: |
| caldata_size = 0; |
| break; |
| } |
| return caldata_size; |
| } |
| |
| uint32 |
| BCMATTACHFN(get_srom_size)(uint32 sromrev) |
| { |
| uint32 size; |
| |
| switch (sromrev) { |
| case 15: |
| size = (SROM15_WORDS * 2); |
| break; |
| case 17: |
| size = (SROM17_WORDS * 2); |
| break; |
| default: |
| size = 0; |
| break; |
| } |
| return size; |
| } |
| #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) |
| |
| int |
| BCMATTACHFN(_initvars_srom_pci_caldata)(si_t *sih, uint16 *srom, uint32 sromrev) |
| { |
| int err = BCME_ERROR; |
| |
| if (sromh && (!sromh->is_caldata_prsnt)) { |
| return err; |
| } |
| |
| if (si_is_sprom_available(sih)) { |
| uint32 caldata_size; |
| |
| caldata_size = get_srom_pci_caldata_size(sromrev); |
| memcpy(srom, caldata_array, caldata_size); |
| err = BCME_OK; |
| } |
| return err; |
| } |
| #endif /* defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) */ |
| /** |
| * Initialize nonvolatile variable table from sprom, or OTP when SPROM is not available, or |
| * optionally a set of 'defaultsromvars' (compiled-in) variables when both OTP and SPROM bear no |
| * contents. |
| * |
| * On success, a buffer containing var/val pairs is allocated and returned in params vars and count. |
| * |
| * Return 0 on success, nonzero on error. |
| */ |
| static int |
| BCMATTACHFN(initvars_srom_pci)(si_t *sih, volatile void *curmap, char **vars, uint *count) |
| { |
| uint16 *srom; |
| volatile uint16 *sromwindow; |
| uint8 sromrev = 0; |
| uint32 sr; |
| varbuf_t b; |
| char *vp, *base = NULL; |
| osl_t *osh = si_osh(sih); |
| bool flash = FALSE; |
| int err = 0; |
| #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) |
| uint16 cal_wordoffset; |
| #endif |
| |
| /* |
| * 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. |
| */ |
| |
| /* freed in same function */ |
| srom = MALLOC_NOPERSIST(osh, SROM_MAX); |
| ASSERT(srom != NULL); |
| if (!srom) |
| return -2; |
| |
| sromwindow = (volatile uint16 *)srom_offset(sih, curmap); |
| if (si_is_sprom_available(sih)) { |
| err = sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM_SIGN_MINWORDS + 1, FALSE); |
| if (err == 0) { |
| if (srom[SROM18_SIGN] == SROM18_SIGNATURE) { |
| err = sprom_read_pci(osh, sih, sromwindow, |
| 0, srom, SROM18_WORDS, TRUE); |
| sromrev = srom[SROM18_CRCREV] & 0xff; |
| } else if (srom[SROM17_SIGN] == SROM17_SIGNATURE) { |
| err = sprom_read_pci(osh, sih, sromwindow, |
| 0, srom, SROM17_WORDS, TRUE); |
| sromrev = srom[SROM17_CRCREV] & 0xff; |
| } else if (srom[SROM16_SIGN] == SROM16_SIGNATURE) { |
| err = sprom_read_pci(osh, sih, sromwindow, |
| 0, srom, SROM16_WORDS, TRUE); |
| sromrev = srom[SROM16_CRCREV] & 0xff; |
| } else if (srom[SROM15_SIGN] == SROM15_SIGNATURE) { /* srom 15 */ |
| err = sprom_read_pci(osh, sih, sromwindow, |
| 0, srom, SROM15_WORDS, TRUE); |
| sromrev = srom[SROM15_CRCREV] & 0xff; |
| } else if (srom[SROM11_SIGN] == SROM13_SIGNATURE) { |
| err = sprom_read_pci(osh, sih, sromwindow, |
| 0, srom, SROM13_WORDS, TRUE); |
| sromrev = srom[SROM13_CRCREV] & 0xff; |
| } else if (srom[SROM11_SIGN] == SROM12_SIGNATURE) { |
| err = sprom_read_pci(osh, sih, sromwindow, |
| 0, srom, SROM12_WORDS, TRUE); |
| sromrev = srom[SROM12_CRCREV] & 0xff; |
| } else if (srom[SROM11_SIGN] == SROM11_SIGNATURE) { |
| err = sprom_read_pci(osh, sih, sromwindow, |
| 0, srom, SROM11_WORDS, TRUE); |
| sromrev = srom[SROM11_CRCREV] & 0xff; |
| } else if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) || /* srom 4 */ |
| (srom[SROM8_SIGN] == SROM4_SIGNATURE)) { /* srom 8,9 */ |
| err = sprom_read_pci(osh, sih, sromwindow, |
| 0, srom, SROM4_WORDS, TRUE); |
| sromrev = srom[SROM4_CRCREV] & 0xff; |
| } else { |
| err = sprom_read_pci(osh, sih, sromwindow, 0, |
| srom, SROM_WORDS, TRUE); |
| 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) |
| BS_ERROR(("srom read failed\n")); |
| } |
| else |
| BS_ERROR(("srom read failed\n")); |
| } |
| |
| #if defined(BCMNVRAMW) || defined(BCMNVRAMR) |
| /* Use OTP if SPROM not available */ |
| else if ((err = otp_read_pci(osh, sih, srom, SROM_MAX)) == 0) { |
| /* OTP only contain SROM rev8/rev9/rev10/Rev11 for now */ |
| |
| if (srom[SROM13_SIGN] == SROM13_SIGNATURE) |
| sromrev = srom[SROM13_CRCREV] & 0xff; |
| else if (srom[SROM12_SIGN] == SROM12_SIGNATURE) |
| sromrev = srom[SROM12_CRCREV] & 0xff; |
| else if (srom[SROM11_SIGN] == SROM11_SIGNATURE) |
| sromrev = srom[SROM11_CRCREV] & 0xff; |
| else if (srom[SROM10_SIGN] == SROM10_SIGNATURE) |
| sromrev = srom[SROM10_CRCREV] & 0xff; |
| else |
| sromrev = srom[SROM4_CRCREV] & 0xff; |
| } |
| #endif /* defined(BCMNVRAMW) || defined(BCMNVRAMR) */ |
| else { |
| err = 1; |
| BS_ERROR(("Neither SPROM nor OTP has valid image\n")); |
| } |
| |
| BS_ERROR(("srom rev:%d\n", sromrev)); |
| |
| /* We want internal/wltest driver to come up with default sromvars so we can |
| * program a blank SPROM/OTP. |
| */ |
| if (err || sromrev == 0) { |
| char *value; |
| #if defined(BCMHOSTVARS) |
| uint32 val; |
| #endif |
| |
| if ((value = si_getdevpathvar(sih, "sromrev"))) { |
| sromrev = (uint8)bcm_strtoul(value, NULL, 0); |
| flash = TRUE; |
| goto varscont; |
| } |
| |
| BS_ERROR(("initvars_srom_pci, SROM CRC Error\n")); |
| |
| #if !defined(DONGLEBUILD) || defined(BCMPCIEDEV_SROM_FORMAT) |
| /* NIC build or PCIe FD using SROM format shouldn't load driver |
| * default when external nvram exists. |
| */ |
| if ((value = getvar(NULL, "sromrev"))) { |
| BS_ERROR(("initvars_srom_pci, Using external nvram\n")); |
| err = 0; |
| goto errout; |
| } |
| #endif /* !DONGLEBUILD || BCMPCIEDEV_SROM_FORMAT */ |
| |
| #if defined(BCMHOSTVARS) |
| /* |
| * CRC failed on srom, so if the device is using OTP |
| * and if OTP is not programmed use the default variables. |
| * for 4311 A1 there is no signature to indicate that OTP is |
| * programmed, so can't really verify the OTP is unprogrammed |
| * or a bad OTP. |
| */ |
| val = OSL_PCI_READ_CONFIG(osh, PCI_SPROM_CONTROL, sizeof(uint32)); |
| if ((si_is_sprom_available(sih) && srom[0] == 0xffff) || |
| #ifdef BCMQT |
| (si_is_sprom_available(sih) && sromrev == 0) || |
| #endif |
| (val & SPROM_OTPIN_USE)) { |
| vp = base = mfgsromvars; |
| |
| /* For windows internal/wltest driver, a .nvm file with default |
| * nvram parameters is downloaded from the file system (in src/wl/sys: |
| * wl_readconfigdata()). |
| * Only when we cannot download default vars from the file system, use |
| * defaultsromvars_wltest as default |
| */ |
| if (defvarslen == 0) { |
| BS_ERROR(("No nvm file, use generic default (for programming" |
| " SPROM/OTP only)\n")); |
| |
| if (BCM43602_CHIP(sih->chip)) { |
| defvarslen = srom_vars_len(defaultsromvars_43602); |
| bcopy(defaultsromvars_43602, vp, defvarslen); |
| } else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM4352_CHIP_ID)) { |
| defvarslen = srom_vars_len(defaultsromvars_4360); |
| bcopy(defaultsromvars_4360, vp, defvarslen); |
| } else if (BCM4378_CHIP(sih->chip)) { |
| defvarslen = srom_vars_len(defaultsromvars_4378); |
| bcopy(defaultsromvars_4378, vp, defvarslen); |
| } else if (BCM4387_CHIP(sih->chip)) { |
| defvarslen = srom_vars_len(defaultsromvars_4387); |
| bcopy(defaultsromvars_4387, vp, defvarslen); |
| } else { |
| defvarslen = srom_vars_len(defaultsromvars_wltest); |
| bcopy(defaultsromvars_wltest, vp, defvarslen); |
| } |
| } else { |
| BS_ERROR(("Use nvm file as default\n")); |
| } |
| |
| vp += defvarslen; |
| /* add final null terminator */ |
| *vp++ = '\0'; |
| |
| BS_ERROR(("Used %d bytes of defaultsromvars\n", defvarslen)); |
| goto varsdone; |
| |
| } else if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43460_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM4352_CHIP_ID) || |
| BCM43602_CHIP(sih->chip)) { |
| |
| base = vp = mfgsromvars; |
| |
| if ((CHIPID(sih->chip) == BCM4360_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM43460_CHIP_ID) || |
| (CHIPID(sih->chip) == BCM4352_CHIP_ID) || |
| BCM43602_CHIP(sih->chip)) |
| BS_ERROR(("4360 BOOT w/o SPROM or OTP\n")); |
| else |
| BS_ERROR(("BOOT w/o SPROM or OTP\n")); |
| |
| if (defvarslen == 0) { |
| if (BCM43602_CHIP(sih->chip)) { |
| defvarslen = srom_vars_len(defaultsromvars_43602); |
| bcopy(defaultsromvars_43602, vp, defvarslen); |
| } else if ((sih->chip == BCM4360_CHIP_ID) || |
| (sih->chip == BCM4352_CHIP_ID)) { |
| defvarslen = srom_vars_len(defaultsromvars_4360); |
| bcopy(defaultsromvars_4360, vp, defvarslen); |
| } else { |
| defvarslen = srom_vars_len(defaultsromvars_4331); |
| bcopy(defaultsromvars_4331, vp, defvarslen); |
| } |
| } |
| vp += defvarslen; |
| *vp++ = '\0'; |
| goto varsdone; |
| } else |
| #endif /* defined(BCMHOSTVARS) */ |
| { |
| err = -1; |
| goto errout; |
| } |
| } |
| #if defined(BCM_ONE_NVRAM_SRC) |
| /* Discard hostvars if SROM parsing is successful, so only one nvram source |
| * will be used. |
| * Routers use combined srom/host nvram so shouldn't define BCM_ONE_NVRAM_SRC. |
| */ |
| else { |
| nvram_exit((void *)sih); /* free up global vars */ |
| } |
| #endif /* BCM_ONE_NVRAM_SRC */ |
| |
| varscont: |
| /* Bitmask for the sromrev */ |
| sr = 1 << sromrev; |
| |
| /* srom version check: Current valid versions are: |
| * 1-5, 8-11, 12, 13, 15, 16, 17, 18 SROM_MAXREV |
| * This is a bit mask of all valid SROM versions. |
| */ |
| if ((sr & 0x7bf3e) == 0) { |
| BS_ERROR(("Invalid SROM rev %d\n", sromrev)); |
| err = -2; |
| goto errout; |
| } |
| |
| ASSERT(vars != NULL); |
| ASSERT(count != NULL); |
| |
| #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) |
| srom_sromrev = sromrev; |
| #endif /* defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) */ |
| |
| /* freed in same function */ |
| base = vp = MALLOC_NOPERSIST(osh, MAXSZ_NVRAM_VARS); |
| ASSERT(vp != NULL); |
| if (!vp) { |
| err = -2; |
| goto errout; |
| } |
| |
| /* read variables from flash */ |
| if (flash) { |
| if ((err = initvars_flash(sih, 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); /* allocates buffer in 'vars' */ |
| |
| #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) |
| if (sromrev == 18) { |
| int caldata_wordoffset = srom[SROM18_CALDATA_OFFSET_LOC] / 2; |
| |
| if ((caldata_wordoffset != 0) && |
| (caldata_wordoffset + SROM_CALDATA_WORDS < SROM18_WORDS)) { |
| memcpy(caldata_array, srom + caldata_wordoffset, SROM18_CALDATA_WORDS * 2); |
| is_caldata_prsnt = TRUE; |
| } |
| } else if (sromrev == 16) { |
| int caldata_wordoffset = srom[SROM16_CALDATA_OFFSET_LOC] / 2; |
| |
| if ((caldata_wordoffset != 0) && |
| (caldata_wordoffset + SROM_CALDATA_WORDS < SROM16_WORDS)) { |
| memcpy(caldata_array, srom + caldata_wordoffset, SROM_CALDATA_WORDS * 2); |
| is_caldata_prsnt = TRUE; |
| } |
| } |
| #endif /* defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) */ |
| |
| #ifdef NVSRCX |
| if (sromrev != 0) |
| nvram_append((void *)sih, *vars, *count, VARBUF_PRIO_SROM); |
| #endif |
| #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) |
| if ((sromrev == 15) || (sromrev == 17)) { |
| uint32 caldata_size = get_srom_pci_caldata_size(sromrev); |
| |
| cal_wordoffset = getintvar(NULL, "caldata_offset")/2; |
| memcpy(caldata_array, srom + cal_wordoffset, caldata_size); |
| } |
| #endif |
| errout: |
| #if defined(BCMHOSTVARS) |
| if (base && (base != mfgsromvars)) |
| #else |
| if (base) |
| #endif /* defined(BCMHOSTVARS) */ |
| MFREE(osh, base, MAXSZ_NVRAM_VARS); |
| |
| MFREE(osh, srom, SROM_MAX); |
| return err; |
| } |
| |
| /** |
| * initvars_cis_pci() parses OTP CIS. This is specifically for PCIe full dongle that has SROM |
| * header plus CIS tuples programmed in OTP. |
| * Return error if the content is not in CIS format or OTP is not present. |
| */ |
| static int |
| BCMATTACHFN(initvars_cis_pci)(si_t *sih, osl_t *osh, volatile void *curmap, |
| char **vars, uint *count) |
| { |
| uint wsz = 0, sz = 0, base_len = 0; |
| void *oh = NULL; |
| int rc = BCME_OK; |
| uint16 *cisbuf = NULL; |
| uint8 *cis = NULL; |
| #if defined (BCMHOSTVARS) |
| char *vp = NULL; |
| #endif /* BCMHOSTVARS */ |
| char *base = NULL; |
| bool wasup; |
| uint32 min_res_mask = 0; |
| BCM_REFERENCE(curmap); |
| |
| /* Bail out if we've dealt with OTP/SPROM before! */ |
| if (srvars_inited) |
| goto exit; |
| |
| /* Turn on OTP if it's not already on */ |
| if (!(wasup = si_is_otp_powered(sih))) |
| si_otp_power(sih, TRUE, &min_res_mask); |
| |
| if (si_cis_source(sih) != CIS_OTP) |
| rc = BCME_NOTFOUND; |
| else if ((oh = otp_init(sih)) == NULL) |
| rc = BCME_ERROR; |
| else if (!(((BUSCORETYPE(sih->buscoretype) == PCIE2_CORE_ID) || otp_newcis(oh)) && |
| (otp_status(oh) & OTPS_GUP_HW))) { |
| /* OTP bit CIS format (507) not used by pcie core - only needed for sdio core */ |
| rc = BCME_NOTFOUND; |
| } else if ((sz = otp_size(oh)) != 0) { |
| if ((cisbuf = (uint16*)MALLOC_NOPERSIST(osh, sz))) { |
| /* otp_size() returns bytes, not words. */ |
| wsz = sz >> 1; |
| /* for 4389b0 (CCREV-70) sw region is before the hw region */ |
| if (CCREV(sih->ccrev) == 70) { |
| rc = otp_read_region(sih, OTP_SW_RGN, cisbuf, &wsz); |
| cis = (uint8*)cisbuf; |
| } else { |
| rc = otp_read_region(sih, OTP_HW_RGN, cisbuf, &wsz); |
| /* Bypass the HW header and signature */ |
| cis = (uint8*)(cisbuf + (otp_pcie_hwhdr_sz(sih) / 2)); |
| } |
| BS_ERROR(("initvars_cis_pci: Parsing CIS in OTP.\n")); |
| } else |
| rc = BCME_NOMEM; |
| } |
| |
| /* Restore original OTP state */ |
| if (!wasup) |
| si_otp_power(sih, FALSE, &min_res_mask); |
| |
| if (rc != BCME_OK) { |
| BS_ERROR(("initvars_cis_pci: Not CIS format\n")); |
| goto exit; |
| } |
| |
| #if defined (BCMHOSTVARS) |
| if (defvarslen) { |
| vp = mfgsromvars; |
| vp += defvarslen; |
| |
| /* allocates buffer in 'vars' */ |
| rc = initvars_table(osh, mfgsromvars, vp, &base, &base_len); |
| if (rc) |
| goto exit; |
| |
| *vars = base; |
| *count = base_len; |
| |
| BS_ERROR(("initvars_cis_pci external nvram %d bytes\n", defvarslen)); |
| } |
| |
| #endif /* BCMHOSTVARS */ |
| |
| /* Parse the CIS and allocate a(nother) buffer in 'vars' */ |
| rc = srom_parsecis(sih, osh, &cis, SROM_CIS_SINGLE, vars, count); |
| |
| srvars_inited = TRUE; |
| exit: |
| /* Clean up */ |
| if (base) |
| MFREE(osh, base, base_len); |
| if (cisbuf) |
| MFREE(osh, cisbuf, sz); |
| |
| /* return OK so the driver will load & use defaults if bad srom/otp */ |
| return rc; |
| } |
| #endif /* !defined(BCMDONGLEHOST) */ |
| |
| #ifdef BCMSDIO |
| #if !defined(BCMDONGLEHOST) |
| /** |
| * Read the SDIO cis and call parsecis to allocate and initialize the NVRAM vars buffer. |
| * Return 0 on success, nonzero on error. |
| */ |
| static int |
| BCMATTACHFN(initvars_cis_sdio)(si_t *sih, osl_t *osh, char **vars, uint *count) |
| { |
| uint8 *cis[SBSDIO_NUM_FUNCTION + 1]; |
| uint fn, numfn; |
| int rc = 0; |
| |
| /* Using MALLOC here causes the Windows driver to crash Needs Investigating */ |
| #ifdef NDIS |
| uint8 cisd[SBSDIO_NUM_FUNCTION + 1][SBSDIO_CIS_SIZE_LIMIT]; |
| #endif |
| |
| numfn = bcmsdh_query_iofnum(NULL); |
| ASSERT(numfn <= SDIOD_MAX_IOFUNCS); |
| |
| for (fn = 0; fn <= numfn; fn++) { |
| #ifdef NDIS |
| cis[fn] = (uint8*)cisd[fn]; |
| #else |
| /* freed in same function */ |
| if ((cis[fn] = MALLOC_NOPERSIST(osh, SBSDIO_CIS_SIZE_LIMIT)) == NULL) { |
| rc = -1; |
| break; |
| } |
| #endif /* NDIS */ |
| |
| bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT); |
| |
| if (bcmsdh_cis_read(NULL, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT) != 0) { |
| #ifdef NDIS |
| /* nothing to do */ |
| #else |
| MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); |
| #endif |
| rc = -2; |
| break; |
| } |
| } |
| |
| if (!rc) |
| rc = srom_parsecis(sih, osh, cis, fn, vars, count); |
| |
| #ifdef NDIS |
| /* nothing to do here */ |
| #else |
| while (fn-- > 0) |
| MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); |
| #endif |
| |
| return (rc); |
| } |
| #endif /* !defined(BCMDONGLEHOST) */ |
| |
| /** set SDIO sprom command register */ |
| static int |
| BCMATTACHFN(sprom_cmd_sdio)(osl_t *osh, uint8 cmd) |
| { |
| uint8 status = 0; |
| uint wait_cnt = 1000; |
| |
| /* write sprom command register */ |
| bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, cmd, NULL); |
| |
| /* wait status */ |
| while (wait_cnt--) { |
| status = bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_CS, NULL); |
| if (status & SBSDIO_SPROM_DONE) |
| return 0; |
| } |
| |
| return 1; |
| } |
| |
| /** read a word from the SDIO srom */ |
| static int |
| sprom_read_sdio(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 */ |
| bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_HIGH, addr_h, NULL); |
| bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_LOW, addr_l, NULL); |
| |
| /* do read */ |
| if (sprom_cmd_sdio(osh, SBSDIO_SPROM_READ)) |
| return 1; |
| |
| /* read data */ |
| data_h = bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_HIGH, NULL); |
| data_l = bcmsdh_cfg_read(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_LOW, NULL); |
| |
| *data = (data_h << 8) | data_l; |
| return 0; |
| } |
| |
| #if defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) |
| /** write a word to the SDIO srom */ |
| static int |
| sprom_write_sdio(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 */ |
| bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_HIGH, addr_h, NULL); |
| bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_ADDR_LOW, addr_l, NULL); |
| |
| /* write data */ |
| bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_HIGH, data_h, NULL); |
| bcmsdh_cfg_write(NULL, SDIO_FUNC_1, SBSDIO_SPROM_DATA_LOW, data_l, NULL); |
| |
| /* do write */ |
| return sprom_cmd_sdio(osh, SBSDIO_SPROM_WRITE); |
| } |
| #endif /* defined(WLTEST) || defined (DHD_SPROM) || defined (BCMDBG) */ |
| #endif /* BCMSDIO */ |
| |
| #if !defined(BCMDONGLEHOST) |
| #ifdef BCMSPI |
| /** |
| * Read the SPI cis and call parsecis to allocate and initialize the NVRAM vars buffer. |
| * Return 0 on success, nonzero on error. |
| */ |
| static int |
| BCMATTACHFN(initvars_cis_spi)(si_t *sih, osl_t *osh, char **vars, uint *count) |
| { |
| uint8 *cis; |
| int rc; |
| |
| /* Using MALLOC here causes the Windows driver to crash Needs Investigating */ |
| #ifdef NDIS |
| uint8 cisd[SBSDIO_CIS_SIZE_LIMIT]; |
| cis = (uint8*)cisd; |
| #else |
| /* freed in same function */ |
| if ((cis = MALLOC_NOPERSIST(osh, SBSDIO_CIS_SIZE_LIMIT)) == NULL) { |
| return -1; |
| } |
| #endif /* NDIS */ |
| |
| bzero(cis, SBSDIO_CIS_SIZE_LIMIT); |
| |
| if (bcmsdh_cis_read(NULL, SDIO_FUNC_1, cis, SBSDIO_CIS_SIZE_LIMIT) != 0) { |
| #ifdef NDIS |
| /* nothing to do */ |
| #else |
| MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT); |
| #endif /* NDIS */ |
| return -2; |
| } |
| |
| rc = srom_parsecis(sih, osh, &cis, SDIO_FUNC_1, vars, count); |
| |
| #ifdef NDIS |
| /* nothing to do here */ |
| #else |
| MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT); |
| #endif |
| |
| return (rc); |
| } |
| #endif /* BCMSPI */ |
| #endif /* !defined(BCMDONGLEHOST) */ |
| |
| /** Return sprom size in 16-bit words */ |
| uint |
| srom_size(si_t *sih, osl_t *osh) |
| { |
| uint size = (SROM16_SIGN + 1) * 2; /* must big enough for SROM16 */ |
| return size; |
| } |
| |
| /** |
| * initvars are different for BCMUSBDEV and BCMSDIODEV. This is OK when supporting both at |
| * the same time, but only because all of the code is in attach functions and not in ROM. |
| */ |
| |
| #if defined(BCMUSBDEV_ENABLED) |
| #ifdef BCM_DONGLEVARS |
| /*** reads a CIS structure (so not an SROM-MAP structure) from either OTP or SROM */ |
| static int |
| BCMATTACHFN(initvars_srom_si_bl)(si_t *sih, osl_t *osh, volatile void *curmap, |
| char **vars, uint *varsz) |
| { |
| int sel = 0; /* where to read srom/cis: 0 - none, 1 - otp, 2 - sprom */ |
| uint sz = 0; /* srom size in bytes */ |
| void *oh = NULL; |
| int rc = BCME_OK; |
| uint16 prio = VARBUF_PRIO_INVALID; |
| |
| if ((oh = otp_init(sih)) != NULL && (otp_status(oh) & OTPS_GUP_SW)) { |
| /* Access OTP if it is present, powered on, and programmed */ |
| sz = otp_size(oh); |
| sel = 1; |
| } else if ((sz = srom_size(sih, osh)) != 0) { |
| /* Access the SPROM if it is present */ |
| sz <<= 1; |
| sel = 2; |
| } |
| |
| /* Read CIS in OTP/SPROM */ |
| if (sel != 0) { |
| uint16 *srom; |
| uint8 *body = NULL; |
| uint otpsz = sz; |
| |
| ASSERT(sz); |
| |
| /* Allocate memory */ |
| if ((srom = (uint16 *)MALLOC(osh, sz)) == NULL) |
| return BCME_NOMEM; |
| |
| /* Read CIS */ |
| switch (sel) { |
| case 1: |
| rc = otp_read_region(sih, OTP_SW_RGN, srom, &otpsz); |
| sz = otpsz; |
| body = (uint8 *)srom; |
| prio = VARBUF_PRIO_OTP; |
| break; |
| case 2: |
| rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, srom, TRUE); |
| /* sprom has 8 byte h/w header */ |
| body = (uint8 *)srom + SBSDIO_SPROM_CIS_OFFSET; |
| prio = VARBUF_PRIO_SROM; |
| break; |
| default: |
| /* impossible to come here */ |
| ASSERT(0); |
| break; |
| } |
| |
| /* Parse CIS */ |
| if (rc == BCME_OK) { |
| /* each word is in host endian */ |
| htol16_buf((uint8 *)srom, sz); |
| ASSERT(body); |
| rc = srom_parsecis(sih, osh, &body, SROM_CIS_SINGLE, vars, varsz); |
| } |
| |
| MFREE(osh, srom, sz); /* Clean up */ |
| |
| /* Make SROM variables global */ |
| if (rc == BCME_OK) { |
| nvram_append((void *)sih, *vars, *varsz, prio); |
| DONGLE_STORE_VARS_OTP_PTR(*vars); |
| } |
| } |
| |
| return BCME_OK; |
| } |
| #endif /* #ifdef BCM_DONGLEVARS */ |
| |
| /** |
| * initvars_srom_si() is defined multiple times in this file. This is the 1st variant for chips with |
| * an active USB interface. It is called only for bus types SI_BUS, and only for CIS |
| * format in SPROM and/or OTP. Reads OTP or SPROM (bootloader only) and appends parsed contents to |
| * caller supplied var/value pairs. |
| */ |
| static int |
| BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap, |
| char **vars, uint *varsz) |
| { |
| |
| #if defined(BCM_DONGLEVARS) |
| BCM_REFERENCE(osh); |
| BCM_REFERENCE(sih); |
| BCM_REFERENCE(curmap); |
| #endif |
| |
| /* Bail out if we've dealt with OTP/SPROM before! */ |
| if (srvars_inited) |
| goto exit; |
| |
| #ifdef BCM_DONGLEVARS /* this flag should be defined for usb bootloader, to read OTP or SROM */ |
| if (BCME_OK != initvars_srom_si_bl(sih, osh, curmap, vars, varsz)) /* CIS format only */ |
| return BCME_ERROR; |
| #endif |
| |
| /* update static local var to skip for next call */ |
| srvars_inited = TRUE; |
| |
| exit: |
| /* Tell the caller there is no individual SROM variables */ |
| *vars = NULL; |
| *varsz = 0; |
| |
| /* return OK so the driver will load & use defaults if bad srom/otp */ |
| return BCME_OK; |
| } |
| |
| #elif defined(BCMSDIODEV_ENABLED) |
| |
| #ifdef BCM_DONGLEVARS |
| static uint8 BCMATTACHDATA(defcis4369)[] = { 0x20, 0x4, 0xd0, 0x2, 0x64, 0x43, 0xff, 0xff }; |
| static uint8 BCMATTACHDATA(defcis43012)[] = { 0x20, 0x4, 0xd0, 0x2, 0x04, 0xA8, 0xff, 0xff }; |
| static uint8 BCMATTACHDATA(defcis43013)[] = { 0x20, 0x4, 0xd0, 0x2, 0x05, 0xA8, 0xff, 0xff }; |
| static uint8 BCMATTACHDATA(defcis43014)[] = { 0x20, 0x4, 0xd0, 0x2, 0x06, 0xA8, 0xff, 0xff }; |
| static uint8 BCMATTACHDATA(defcis4362)[] = { 0x20, 0x4, 0xd0, 0x2, 0x62, 0x43, 0xff, 0xff }; |
| static uint8 BCMATTACHDATA(defcis4378)[] = { 0x20, 0x4, 0xd0, 0x2, 0x78, 0x43, 0xff, 0xff }; |
| static uint8 BCMATTACHDATA(defcis4385)[] = { 0x20, 0x4, 0xd0, 0x2, 0x85, 0x43, 0xff, 0xff }; |
| static uint8 BCMATTACHDATA(defcis4387)[] = { 0x20, 0x4, 0xd0, 0x2, 0x78, 0x43, 0xff, 0xff }; |
| static uint8 BCMATTACHDATA(defcis4388)[] = { 0x20, 0x4, 0xd0, 0x2, 0x88, 0x43, 0xff, 0xff }; |
| static uint8 BCMATTACHDATA(defcis4389)[] = { 0x20, 0x4, 0xd0, 0x2, 0x89, 0x43, 0xff, 0xff }; |
| static uint8 BCMATTACHDATA(defcis4397)[] = { 0x20, 0x4, 0xd0, 0x2, 0x97, 0x43, 0xff, 0xff }; |
| |
| /** |
| * initvars_srom_si() is defined multiple times in this file. This is the 2nd variant for chips with |
| * an active SDIOd interface using DONGLEVARS |
| */ |
| static int |
| BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap, |
| char **vars, uint *varsz) |
| { |
| int cis_src; |
| uint msz = 0; |
| uint sz = 0; |
| void *oh = NULL; |
| int rc = BCME_OK; |
| bool new_cisformat = FALSE; |
| |
| uint16 *cisbuf = NULL; |
| |
| /* # sdiod fns + common + extra */ |
| uint8 *cis[SBSDIO_NUM_FUNCTION + 2] = { 0 }; |
| |
| uint ciss = 0; |
| uint8 *defcis; |
| uint hdrsz; |
| uint16 prio = VARBUF_PRIO_INVALID; |
| |
| #if defined(BCMSDIODEV_ENABLED) && defined(ATE_BUILD) |
| if (si_chipcap_sdio_ate_only(sih)) { |
| BS_ERROR(("ATE BUILD: skip cis based var init\n")); |
| goto exit; |
| } |
| #endif /* BCMSDIODEV_ENABLED && ATE_BUILD */ |
| |
| /* Bail out if we've dealt with OTP/SPROM before! */ |
| if (srvars_inited) |
| goto exit; |
| |
| /* Initialize default and cis format count */ |
| switch (CHIPID(sih->chip)) { |
| case BCM4369_CHIP_GRPID: ciss = 1; defcis = defcis4369; hdrsz = 4; break; |
| case BCM4378_CHIP_GRPID: ciss = 1; defcis = defcis4378; hdrsz = 4; break; |
| case BCM4385_CHIP_GRPID: ciss = 1; defcis = defcis4385; hdrsz = 4; break; |
| case BCM4387_CHIP_GRPID: ciss = 1; defcis = defcis4387; hdrsz = 4; break; |
| case BCM4388_CHIP_GRPID: ciss = 1; defcis = defcis4388; hdrsz = 4; break; |
| case BCM4389_CHIP_GRPID: ciss = 1; defcis = defcis4389; hdrsz = 4; break; |
| case BCM4397_CHIP_GRPID: ciss = 1; defcis = defcis4397; hdrsz = 4; break; |
| case BCM43012_CHIP_ID: ciss = 1; defcis = defcis43012; hdrsz = 4; break; |
| case BCM43013_CHIP_ID: ciss = 1; defcis = defcis43013; hdrsz = 4; break; |
| case BCM43014_CHIP_ID: ciss = 1; defcis = defcis43014; hdrsz = 4; break; |
| case BCM4362_CHIP_GRPID: ciss = 1; defcis = defcis4362; hdrsz = 4; break; |
| default: |
| BS_ERROR(("initvars_srom_si: Unknown chip 0x%04x\n", CHIPID(sih->chip))); |
| return BCME_ERROR; |
| } |
| if (sih->ccrev >= 36) { |
| uint32 otplayout; |
| if (AOB_ENAB(sih)) { |
| otplayout = si_corereg(sih, si_findcoreidx(sih, GCI_CORE_ID, 0), |
| OFFSETOF(gciregs_t, otplayout), 0, 0); |
| } else { |
| otplayout = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, otplayout), |
| 0, 0); |
| } |
| if (otplayout & OTP_CISFORMAT_NEW) { |
| ciss = 1; |
| hdrsz = 2; |
| new_cisformat = TRUE; |
| } |
| else { |
| ciss = 3; |
| hdrsz = 12; |
| } |
| } |
| |
| cis_src = si_cis_source(sih); |
| switch (cis_src) { |
| case CIS_SROM: |
| sz = srom_size(sih, osh) << 1; |
| prio = VARBUF_PRIO_SROM; |
| break; |
| case CIS_OTP: |
| /* Note that for *this* type of OTP -- which otp_read_region() |
| * can operate on -- otp_size() returns bytes, not words. |
| */ |
| if (((oh = otp_init(sih)) != NULL) && (otp_status(oh) & OTPS_GUP_HW)) |
| sz = otp_size(oh); |
| prio = VARBUF_PRIO_OTP; |
| break; |
| } |
| |
| if (sz != 0) { |
| /* freed in same function */ |
| if ((cisbuf = (uint16*)MALLOC_NOPERSIST(osh, sz)) == NULL) |
| return BCME_NOMEM; |
| msz = sz; |
| |
| switch (cis_src) { |
| case CIS_SROM: |
| rc = srom_read(sih, SI_BUS, curmap, osh, 0, sz, cisbuf, FALSE); |
| break; |
| case CIS_OTP: |
| sz >>= 1; |
| rc = otp_read_region(sih, OTP_HW_RGN, cisbuf, &sz); |
| sz <<= 1; |
| break; |
| } |
| |
| ASSERT(sz > hdrsz); |
| if (rc == BCME_OK) { |
| if ((cisbuf[0] == 0xffff) || (cisbuf[0] == 0)) { |
| MFREE(osh, cisbuf, msz); |
| } else if (new_cisformat) { |
| cis[0] = (uint8*)(cisbuf + hdrsz); |
| } else { |
| cis[0] = (uint8*)cisbuf + hdrsz; |
| cis[1] = (uint8*)cisbuf + hdrsz + |
| (cisbuf[1] >> 8) + ((cisbuf[2] & 0x00ff) << 8) - |
| SBSDIO_CIS_BASE_COMMON; |
| cis[2] = (uint8*)cisbuf + hdrsz + |
| cisbuf[3] - SBSDIO_CIS_BASE_COMMON; |
| cis[3] = (uint8*)cisbuf + hdrsz + |
| cisbuf[4] - SBSDIO_CIS_BASE_COMMON; |
| ASSERT((cis[1] >= cis[0]) && (cis[1] < (uint8*)cisbuf + sz)); |
| ASSERT((cis[2] >= cis[0]) && (cis[2] < (uint8*)cisbuf + sz)); |
| ASSERT(((cis[3] >= cis[0]) && (cis[3] < (uint8*)cisbuf + sz)) || |
| (ciss <= 3)); |
| } |
| } |
| } |
| |
| /* Use default if strapped to, or strapped source empty */ |
| if (cisbuf == NULL) { |
| ciss = 1; |
| cis[0] = defcis; |
| } |
| |
| /* Parse the CIS */ |
| if (rc == BCME_OK) { |
| if ((rc = srom_parsecis(sih, osh, cis, ciss, vars, varsz)) == BCME_OK) { |
| nvram_append((void *)sih, *vars, *varsz, prio); |
| DONGLE_STORE_VARS_OTP_PTR(*vars); |
| } |
| } |
| |
| /* Clean up */ |
| if (cisbuf != NULL) |
| MFREE(osh, cisbuf, msz); |
| |
| srvars_inited = TRUE; |
| exit: |
| /* Tell the caller there is no individual SROM variables */ |
| *vars = NULL; |
| *varsz = 0; |
| |
| /* return OK so the driver will load & use defaults if bad srom/otp */ |
| return BCME_OK; |
| } /* initvars_srom_si */ |
| #else /* BCM_DONGLEVARS */ |
| |
| /** |
| * initvars_srom_si() is defined multiple times in this file. This is the variant for chips with an |
| * active SDIOd interface but without BCM_DONGLEVARS |
| */ |
| static int |
| BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap, |
| char **vars, uint *varsz) |
| { |
| *vars = NULL; |
| *varsz = 0; |
| return BCME_OK; |
| } |
| #endif /* BCM_DONGLEVARS */ |
| |
| #elif defined(BCMPCIEDEV_ENABLED) |
| |
| /** |
| * initvars_srom_si() is defined multiple times in this file. This is the variant for chips with an |
| * active PCIe interface *and* that use OTP for NVRAM storage. |
| * |
| * On success, a buffer containing var/val values has been allocated in parameter 'vars'. |
| * put an ifdef where if the host wants the dongle wants to parse sprom or not |
| */ |
| static int |
| BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap, |
| char **vars, uint *varsz) |
| { |
| #ifdef BCM_DONGLEVARS |
| void *oh = NULL; |
| uint8 *cis; |
| uint sz = 0; |
| int rc; |
| |
| if (si_cis_source(sih) != CIS_OTP) |
| return BCME_OK; |
| |
| if (((oh = otp_init(sih)) != NULL) && (otp_status(oh) & OTPS_GUP_HW)) |
| sz = otp_size(oh); |
| if (sz == 0) |
| return BCME_OK; |
| |
| if ((cis = MALLOC(osh, sz)) == NULL) |
| return BCME_NOMEM; |
| sz >>= 1; |
| rc = otp_read_region(sih, OTP_HW_RGN, (uint16 *)cis, &sz); |
| sz <<= 1; |
| |
| /* account for the Hardware header */ |
| if (sz == 128) |
| return BCME_OK; |
| |
| cis += 128; |
| |
| /* need to find a better way to identify sprom format content and ignore parse */ |
| if (*(uint16 *)cis == SROM11_SIGNATURE) { |
| return BCME_OK; |
| } |
| |
| if ((rc = srom_parsecis(sih, osh, &cis, SROM_CIS_SINGLE, vars, varsz)) == BCME_OK) |
| nvram_append((void *)sih, *vars, *varsz, VARBUF_PRIO_OTP); |
| |
| return rc; |
| #else /* BCM_DONGLEVARS */ |
| *vars = NULL; |
| *varsz = 0; |
| return BCME_OK; |
| #endif /* BCM_DONGLEVARS */ |
| } |
| #else /* !BCMUSBDEV && !BCMSDIODEV && !BCMPCIEDEV */ |
| |
| #ifndef BCMDONGLEHOST |
| |
| /** |
| * initvars_srom_si() is defined multiple times in this file. This is the variant for: |
| * !BCMDONGLEHOST && !BCMUSBDEV && !BCMSDIODEV && !BCMPCIEDEV |
| * So this function is defined for PCI (not PCIe) builds that are also non DHD builds. |
| * On success, a buffer containing var/val values has been allocated in parameter 'vars'. |
| */ |
| static int |
| BCMATTACHFN(initvars_srom_si)(si_t *sih, osl_t *osh, volatile void *curmap, |
| char **vars, uint *varsz) |
| { |
| /* Search flash nvram section for srom variables */ |
| BCM_REFERENCE(osh); |
| BCM_REFERENCE(curmap); |
| return initvars_flash_si(sih, vars, varsz); |
| } /* initvars_srom_si */ |
| #endif /* !BCMDONGLEHOST */ |
| #endif /* !BCMUSBDEV && !BCMSDIODEV && !BCMPCIEDEV */ |
| |
| void |
| BCMATTACHFN(srom_var_deinit)(si_t *sih) |
| { |
| BCM_REFERENCE(sih); |
| |
| srvars_inited = FALSE; |
| } |
| |
| #if defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) |
| bool |
| BCMATTACHFN(srom_caldata_prsnt)(si_t *sih) |
| { |
| return is_caldata_prsnt; |
| } |
| |
| int |
| BCMATTACHFN(srom_get_caldata)(si_t *sih, uint16 *srom) |
| { |
| if (!is_caldata_prsnt) { |
| return BCME_ERROR; |
| } |
| if (srom_sromrev == 18) { |
| memcpy(srom, caldata_array, SROM18_CALDATA_WORDS * 2); |
| } else { |
| memcpy(srom, caldata_array, SROM_CALDATA_WORDS * 2); |
| } |
| return BCME_OK; |
| } |
| #endif /* defined(BCMPCIEDEV_SROM_FORMAT) && defined(WLC_TXCAL) */ |