/*
|
* Routines to access SPROM and to parse SROM/CIS variables.
|
*
|
* Despite its file name, OTP contents is also parsed in this file.
|
*
|
* Copyright (C) 2020, 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) */
|