Index: head/sys/conf/files =================================================================== --- head/sys/conf/files +++ head/sys/conf/files @@ -9,6 +9,16 @@ compile-with "${AWK} -f $S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \ no-obj no-implicit-rule before-depend \ clean "acpi_quirks.h" +bhnd_nvram_map.h optional bhndbus | bhnd \ + dependency "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/tools/nvram_map_gen.awk $S/dev/bhnd/nvram/nvram_map" \ + compile-with "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/nvram/nvram_map -h" \ + no-obj no-implicit-rule before-depend \ + clean "bhnd_nvram_map.h" +bhnd_nvram_map_data.h optional bhndbus | bhnd \ + dependency "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/tools/nvram_map_gen.awk $S/dev/bhnd/nvram/nvram_map" \ + compile-with "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/nvram/nvram_map -d" \ + no-obj no-implicit-rule before-depend \ + clean "bhnd_nvram_map_data.h" # # The 'fdt_dtb_file' target covers an actual DTB file name, which is derived # from the specified source (DTS) file: .dts -> .dtb @@ -1121,6 +1131,7 @@ dev/bhnd/bhndb/bhndb_if.m optional bhndbus | bhndb dev/bhnd/bhndb/bhndb_pci.c optional bhndbus pci | bhndb pci dev/bhnd/bhndb/bhndb_pci_hwdata.c optional bhndbus pci | bhndb pci +dev/bhnd/bhndb/bhndb_pci_sprom.c optional bhndbus pci | bhndb pci dev/bhnd/bhndb/bhndb_subr.c optional bhndbus pci | bhndb dev/bhnd/bcma/bcma.c optional bhndbus | bcma dev/bhnd/bcma/bcma_bhndb.c optional bhndbus | bcma bhndb @@ -1132,6 +1143,8 @@ dev/bhnd/cores/pci/bhnd_pci_hostb.c optional bhndbus pci | bhndb pci dev/bhnd/cores/pci/bhnd_pcib.c optional bhnd_pcib bhnd pci dev/bhnd/nvram/bhnd_nvram_if.m optional bhndbus | bhnd +dev/bhnd/nvram/bhnd_sprom.c optional bhndbus | bhnd +dev/bhnd/nvram/nvram_subr.c optional bhndbus | bhnd dev/bhnd/siba/siba.c optional bhndbus | siba dev/bhnd/siba/siba_bhndb.c optional bhndbus | siba bhndb dev/bhnd/siba/siba_nexus.c optional siba_nexus siba Index: head/sys/conf/kmod.mk =================================================================== --- head/sys/conf/kmod.mk +++ head/sys/conf/kmod.mk @@ -411,6 +411,26 @@ .endif .endfor # _i +.if !empty(SRCS:Mbhnd_nvram_map.h) +CLEANFILES+= bhnd_nvram_map.h +bhnd_nvram_map.h: ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.awk \ + ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \ + ${SYSDIR}/dev/bhnd/nvram/nvram_map +bhnd_nvram_map.h: + ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \ + ${SYSDIR}/dev/bhnd/nvram/nvram_map -h +.endif + +.if !empty(SRCS:Mbhnd_nvram_map_data.h) +CLEANFILES+= bhnd_nvram_map_data.h +bhnd_nvram_map_data.h: ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.awk \ + ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \ + ${SYSDIR}/dev/bhnd/nvram/nvram_map +bhnd_nvram_map_data.h: + ${SYSDIR}/dev/bhnd/tools/nvram_map_gen.sh \ + ${SYSDIR}/dev/bhnd/nvram/nvram_map -d +.endif + .if !empty(SRCS:Musbdevs.h) CLEANFILES+= usbdevs.h usbdevs.h: ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs Index: head/sys/dev/bhnd/bcmsrom_fmt.h =================================================================== --- head/sys/dev/bhnd/bcmsrom_fmt.h +++ head/sys/dev/bhnd/bcmsrom_fmt.h @@ -1,373 +0,0 @@ -/*- - * Copyright (c) 2010 Broadcom Corporation - * - * This file is derived from the bcmsrom.h header distributed with Broadcom's - * brcm80211 Linux driver release, as contributed to the Linux staging - * repository. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#ifndef _BHND_BCMSROM_FMT_H_ -#define _BHND_BCMSROM_FMT_H_ - -/* Maximum srom: 6 Kilobits == 768 bytes */ -#define SROM_MAX 768 -#define SROM_MAXW 384 -#define VARS_MAX 4096 - -/* PCI fields */ -#define PCI_F0DEVID 48 - -#define SROM_WORDS 64 - -#define SROM3_SWRGN_OFF 28 /* s/w region offset in words */ - -#define SROM_SSID 2 - -#define SROM_WL1LHMAXP 29 - -#define SROM_WL1LPAB0 30 -#define SROM_WL1LPAB1 31 -#define SROM_WL1LPAB2 32 - -#define SROM_WL1HPAB0 33 -#define SROM_WL1HPAB1 34 -#define SROM_WL1HPAB2 35 - -#define SROM_MACHI_IL0 36 -#define SROM_MACMID_IL0 37 -#define SROM_MACLO_IL0 38 -#define SROM_MACHI_ET0 39 -#define SROM_MACMID_ET0 40 -#define SROM_MACLO_ET0 41 -#define SROM_MACHI_ET1 42 -#define SROM_MACMID_ET1 43 -#define SROM_MACLO_ET1 44 -#define SROM3_MACHI 37 -#define SROM3_MACMID 38 -#define SROM3_MACLO 39 - -#define SROM_BXARSSI2G 40 -#define SROM_BXARSSI5G 41 - -#define SROM_TRI52G 42 -#define SROM_TRI5GHL 43 - -#define SROM_RXPO52G 45 - -#define SROM2_ENETPHY 45 - -#define SROM_AABREV 46 -/* Fields in AABREV */ -#define SROM_BR_MASK 0x00ff -#define SROM_CC_MASK 0x0f00 -#define SROM_CC_SHIFT 8 -#define SROM_AA0_MASK 0x3000 -#define SROM_AA0_SHIFT 12 -#define SROM_AA1_MASK 0xc000 -#define SROM_AA1_SHIFT 14 - -#define SROM_WL0PAB0 47 -#define SROM_WL0PAB1 48 -#define SROM_WL0PAB2 49 - -#define SROM_LEDBH10 50 -#define SROM_LEDBH32 51 - -#define SROM_WL10MAXP 52 - -#define SROM_WL1PAB0 53 -#define SROM_WL1PAB1 54 -#define SROM_WL1PAB2 55 - -#define SROM_ITT 56 - -#define SROM_BFL 57 -#define SROM_BFL2 28 -#define SROM3_BFL2 61 - -#define SROM_AG10 58 - -#define SROM_CCODE 59 - -#define SROM_OPO 60 - -#define SROM3_LEDDC 62 - -#define SROM_CRCREV 63 - -/* SROM Rev 4: Reallocate the software part of the srom to accommodate - * MIMO features. It assumes up to two PCIE functions and 440 bytes - * of useable srom i.e. the useable storage in chips with OTP that - * implements hardware redundancy. - */ - -#define SROM4_WORDS 220 - -#define SROM4_SIGN 32 -#define SROM4_SIGNATURE 0x5372 - -#define SROM4_BREV 33 - -#define SROM4_BFL0 34 -#define SROM4_BFL1 35 -#define SROM4_BFL2 36 -#define SROM4_BFL3 37 -#define SROM5_BFL0 37 -#define SROM5_BFL1 38 -#define SROM5_BFL2 39 -#define SROM5_BFL3 40 - -#define SROM4_MACHI 38 -#define SROM4_MACMID 39 -#define SROM4_MACLO 40 -#define SROM5_MACHI 41 -#define SROM5_MACMID 42 -#define SROM5_MACLO 43 - -#define SROM4_CCODE 41 -#define SROM4_REGREV 42 -#define SROM5_CCODE 34 -#define SROM5_REGREV 35 - -#define SROM4_LEDBH10 43 -#define SROM4_LEDBH32 44 -#define SROM5_LEDBH10 59 -#define SROM5_LEDBH32 60 - -#define SROM4_LEDDC 45 -#define SROM5_LEDDC 45 - -#define SROM4_AA 46 -#define SROM4_AA2G_MASK 0x00ff -#define SROM4_AA2G_SHIFT 0 -#define SROM4_AA5G_MASK 0xff00 -#define SROM4_AA5G_SHIFT 8 - -#define SROM4_AG10 47 -#define SROM4_AG32 48 - -#define SROM4_TXPID2G 49 -#define SROM4_TXPID5G 51 -#define SROM4_TXPID5GL 53 -#define SROM4_TXPID5GH 55 - -#define SROM4_TXRXC 61 -#define SROM4_TXCHAIN_MASK 0x000f -#define SROM4_TXCHAIN_SHIFT 0 -#define SROM4_RXCHAIN_MASK 0x00f0 -#define SROM4_RXCHAIN_SHIFT 4 -#define SROM4_SWITCH_MASK 0xff00 -#define SROM4_SWITCH_SHIFT 8 - -/* Per-path fields */ -#define MAX_PATH_SROM 4 -#define SROM4_PATH0 64 -#define SROM4_PATH1 87 -#define SROM4_PATH2 110 -#define SROM4_PATH3 133 - -#define SROM4_2G_ITT_MAXP 0 -#define SROM4_2G_PA 1 -#define SROM4_5G_ITT_MAXP 5 -#define SROM4_5GLH_MAXP 6 -#define SROM4_5G_PA 7 -#define SROM4_5GL_PA 11 -#define SROM4_5GH_PA 15 - -/* Fields in the ITT_MAXP and 5GLH_MAXP words */ -#define B2G_MAXP_MASK 0xff -#define B2G_ITT_SHIFT 8 -#define B5G_MAXP_MASK 0xff -#define B5G_ITT_SHIFT 8 -#define B5GH_MAXP_MASK 0xff -#define B5GL_MAXP_SHIFT 8 - -/* All the miriad power offsets */ -#define SROM4_2G_CCKPO 156 -#define SROM4_2G_OFDMPO 157 -#define SROM4_5G_OFDMPO 159 -#define SROM4_5GL_OFDMPO 161 -#define SROM4_5GH_OFDMPO 163 -#define SROM4_2G_MCSPO 165 -#define SROM4_5G_MCSPO 173 -#define SROM4_5GL_MCSPO 181 -#define SROM4_5GH_MCSPO 189 -#define SROM4_CDDPO 197 -#define SROM4_STBCPO 198 -#define SROM4_BW40PO 199 -#define SROM4_BWDUPPO 200 - -#define SROM4_CRCREV 219 - -/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6. - * This is acombined srom for both MIMO and SISO boards, usable in - * the .130 4Kilobit OTP with hardware redundancy. - */ - -#define SROM8_SIGN 64 - -#define SROM8_BREV 65 - -#define SROM8_BFL0 66 -#define SROM8_BFL1 67 -#define SROM8_BFL2 68 -#define SROM8_BFL3 69 - -#define SROM8_MACHI 70 -#define SROM8_MACMID 71 -#define SROM8_MACLO 72 - -#define SROM8_CCODE 73 -#define SROM8_REGREV 74 - -#define SROM8_LEDBH10 75 -#define SROM8_LEDBH32 76 - -#define SROM8_LEDDC 77 - -#define SROM8_AA 78 - -#define SROM8_AG10 79 -#define SROM8_AG32 80 - -#define SROM8_TXRXC 81 - -#define SROM8_BXARSSI2G 82 -#define SROM8_BXARSSI5G 83 -#define SROM8_TRI52G 84 -#define SROM8_TRI5GHL 85 -#define SROM8_RXPO52G 86 - -#define SROM8_FEM2G 87 -#define SROM8_FEM5G 88 -#define SROM8_FEM_ANTSWLUT_MASK 0xf800 -#define SROM8_FEM_ANTSWLUT_SHIFT 11 -#define SROM8_FEM_TR_ISO_MASK 0x0700 -#define SROM8_FEM_TR_ISO_SHIFT 8 -#define SROM8_FEM_PDET_RANGE_MASK 0x00f8 -#define SROM8_FEM_PDET_RANGE_SHIFT 3 -#define SROM8_FEM_EXTPA_GAIN_MASK 0x0006 -#define SROM8_FEM_EXTPA_GAIN_SHIFT 1 -#define SROM8_FEM_TSSIPOS_MASK 0x0001 -#define SROM8_FEM_TSSIPOS_SHIFT 0 - -#define SROM8_THERMAL 89 - -/* Temp sense related entries */ -#define SROM8_MPWR_RAWTS 90 -#define SROM8_TS_SLP_OPT_CORRX 91 -/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */ -#define SROM8_FOC_HWIQ_IQSWP 92 - -/* Temperature delta for PHY calibration */ -#define SROM8_PHYCAL_TEMPDELTA 93 - -/* Per-path offsets & fields */ -#define SROM8_PATH0 96 -#define SROM8_PATH1 112 -#define SROM8_PATH2 128 -#define SROM8_PATH3 144 - -#define SROM8_2G_ITT_MAXP 0 -#define SROM8_2G_PA 1 -#define SROM8_5G_ITT_MAXP 4 -#define SROM8_5GLH_MAXP 5 -#define SROM8_5G_PA 6 -#define SROM8_5GL_PA 9 -#define SROM8_5GH_PA 12 - -/* All the miriad power offsets */ -#define SROM8_2G_CCKPO 160 - -#define SROM8_2G_OFDMPO 161 -#define SROM8_5G_OFDMPO 163 -#define SROM8_5GL_OFDMPO 165 -#define SROM8_5GH_OFDMPO 167 - -#define SROM8_2G_MCSPO 169 -#define SROM8_5G_MCSPO 177 -#define SROM8_5GL_MCSPO 185 -#define SROM8_5GH_MCSPO 193 - -#define SROM8_CDDPO 201 -#define SROM8_STBCPO 202 -#define SROM8_BW40PO 203 -#define SROM8_BWDUPPO 204 - -/* SISO PA parameters are in the path0 spaces */ -#define SROM8_SISO 96 - -/* Legacy names for SISO PA parameters */ -#define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP) -#define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA) -#define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1) -#define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2) -#define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP) -#define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP) -#define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA) -#define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1) -#define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2) -#define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA) -#define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1) -#define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2) -#define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA) -#define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1) -#define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2) - -#define SROM8_CRCREV 219 - -/* SROM REV 9 */ -#define SROM9_2GPO_CCKBW20 160 -#define SROM9_2GPO_CCKBW20UL 161 -#define SROM9_2GPO_LOFDMBW20 162 -#define SROM9_2GPO_LOFDMBW20UL 164 - -#define SROM9_5GLPO_LOFDMBW20 166 -#define SROM9_5GLPO_LOFDMBW20UL 168 -#define SROM9_5GMPO_LOFDMBW20 170 -#define SROM9_5GMPO_LOFDMBW20UL 172 -#define SROM9_5GHPO_LOFDMBW20 174 -#define SROM9_5GHPO_LOFDMBW20UL 176 - -#define SROM9_2GPO_MCSBW20 178 -#define SROM9_2GPO_MCSBW20UL 180 -#define SROM9_2GPO_MCSBW40 182 - -#define SROM9_5GLPO_MCSBW20 184 -#define SROM9_5GLPO_MCSBW20UL 186 -#define SROM9_5GLPO_MCSBW40 188 -#define SROM9_5GMPO_MCSBW20 190 -#define SROM9_5GMPO_MCSBW20UL 192 -#define SROM9_5GMPO_MCSBW40 194 -#define SROM9_5GHPO_MCSBW20 196 -#define SROM9_5GHPO_MCSBW20UL 198 -#define SROM9_5GHPO_MCSBW40 200 - -#define SROM9_PO_MCS32 202 -#define SROM9_PO_LOFDM40DUP 203 - -#define SROM9_REV_CRC 219 - -typedef struct { - u8 tssipos; /* TSSI positive slope, 1: positive, 0: negative */ - u8 extpagain; /* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */ - u8 pdetrange; /* support 32 combinations of different Pdet dynamic ranges */ - u8 triso; /* TR switch isolation */ - u8 antswctrllut; /* antswctrl lookup table configuration: 32 possible choices */ -} srom_fem_t; - -#endif /* _BHND_BCMSROM_TBL_H_ */ Index: head/sys/dev/bhnd/bcmsrom_tbl.h =================================================================== --- head/sys/dev/bhnd/bcmsrom_tbl.h +++ head/sys/dev/bhnd/bcmsrom_tbl.h @@ -1,577 +0,0 @@ -/*- - * Copyright (c) 2010 Broadcom Corporation - * - * This file is derived from the bcmsrom.h header distributed with Broadcom's - * brcm80211 Linux driver release, as contributed to the Linux staging - * repository. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#ifndef _BHND_BCMSROM_TBL_H_ -#define _BHND_BCMSROM_TBL_H_ - -#include "bcmsrom_fmt.h" - -typedef struct { - const char *name; - u32 revmask; - u32 flags; - u16 off; - u16 mask; -} sromvar_t; - -#define SRFL_MORE 1 /* value continues as described by the next entry */ -#define SRFL_NOFFS 2 /* value bits can't be all one's */ -#define SRFL_PRHEX 4 /* value is in hexdecimal format */ -#define SRFL_PRSIGN 8 /* value is in signed decimal format */ -#define SRFL_CCODE 0x10 /* value is in country code format */ -#define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ -#define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ -#define SRFL_NOVAR 0x80 /* do not generate a nvram param, entry is for mfgc */ - -/* Assumptions: - * - Ethernet address spans across 3 consective words - * - * Table rules: - * - Add multiple entries next to each other if a value spans across multiple words - * (even multiple fields in the same word) with each entry except the last having - * it's SRFL_MORE bit set. - * - Ethernet address entry does not follow above rule and must not have SRFL_MORE - * bit set. Its SRFL_ETHADDR bit implies it takes multiple words. - * - The last entry's name field must be NULL to indicate the end of the table. Other - * entries must have non-NULL name. - */ - -static const sromvar_t pci_sromvars[] = { - {"devid", 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, 0xffff}, - {"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK}, - {"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff}, - {"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, - {"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff}, - {"boardflags", 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff}, - {"", 0, 0, SROM_BFL2, 0xffff}, - {"boardflags", 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff}, - {"", 0, 0, SROM3_BFL2, 0xffff}, - {"boardflags", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, 0xffff}, - {"", 0, 0, SROM4_BFL1, 0xffff}, - {"boardflags", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, 0xffff}, - {"", 0, 0, SROM5_BFL1, 0xffff}, - {"boardflags", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, 0xffff}, - {"", 0, 0, SROM8_BFL1, 0xffff}, - {"boardflags2", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, 0xffff}, - {"", 0, 0, SROM4_BFL3, 0xffff}, - {"boardflags2", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, 0xffff}, - {"", 0, 0, SROM5_BFL3, 0xffff}, - {"boardflags2", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, 0xffff}, - {"", 0, 0, SROM8_BFL3, 0xffff}, - {"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, - {"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff}, - {"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff}, - {"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff}, - {"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff}, - {"boardnum", 0xffffff00, 0, SROM8_MACLO, 0xffff}, - {"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK}, - {"regrev", 0x00000008, 0, SROM_OPO, 0xff00}, - {"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff}, - {"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff}, - {"regrev", 0xffffff00, 0, SROM8_REGREV, 0x00ff}, - {"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff}, - {"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00}, - {"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff}, - {"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00}, - {"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff}, - {"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00}, - {"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff}, - {"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00}, - {"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff}, - {"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00}, - {"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff}, - {"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00}, - {"ledbh0", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff}, - {"ledbh1", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, - {"ledbh2", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff}, - {"ledbh3", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, - {"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff}, - {"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff}, - {"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff}, - {"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff}, - {"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff}, - {"pa0b0", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, - {"pa0b1", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, - {"pa0b2", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, - {"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00}, - {"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff}, - {"opo", 0x0000000c, 0, SROM_OPO, 0x00ff}, - {"opo", 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff}, - {"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK}, - {"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff}, - {"aa2g", 0xffffff00, 0, SROM8_AA, 0x00ff}, - {"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK}, - {"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00}, - {"aa5g", 0xffffff00, 0, SROM8_AA, 0xff00}, - {"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff}, - {"ag1", 0x0000000e, 0, SROM_AG10, 0xff00}, - {"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff}, - {"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00}, - {"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff}, - {"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00}, - {"ag0", 0xffffff00, 0, SROM8_AG10, 0x00ff}, - {"ag1", 0xffffff00, 0, SROM8_AG10, 0xff00}, - {"ag2", 0xffffff00, 0, SROM8_AG32, 0x00ff}, - {"ag3", 0xffffff00, 0, SROM8_AG32, 0xff00}, - {"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff}, - {"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff}, - {"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff}, - {"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff}, - {"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff}, - {"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff}, - {"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff}, - {"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff}, - {"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff}, - {"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00}, - {"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00}, - {"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00}, - {"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff}, - {"pa1b0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, - {"pa1b1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, - {"pa1b2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, - {"pa1lob0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff}, - {"pa1lob1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff}, - {"pa1lob2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff}, - {"pa1hib0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff}, - {"pa1hib1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff}, - {"pa1hib2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff}, - {"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00}, - {"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff}, - {"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00}, - {"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff}, - {"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800}, - {"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700}, - {"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0}, - {"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f}, - {"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800}, - {"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700}, - {"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0}, - {"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f}, - {"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800}, - {"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700}, - {"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0}, - {"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f}, - {"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800}, - {"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700}, - {"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0}, - {"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f}, - {"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff}, - {"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00}, - {"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff}, - {"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00}, - {"tri2g", 0xffffff00, 0, SROM8_TRI52G, 0x00ff}, - {"tri5g", 0xffffff00, 0, SROM8_TRI52G, 0xff00}, - {"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff}, - {"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL, 0xff00}, - {"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff}, - {"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00}, - {"rxpo2g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff}, - {"rxpo5g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, - {"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK}, - {"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK}, - {"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK}, - {"txchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK}, - {"rxchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK}, - {"antswitch", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK}, - {"tssipos2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK}, - {"extpagain2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK}, - {"pdetrange2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK}, - {"triso2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK}, - {"antswctl2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK}, - {"tssipos5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK}, - {"extpagain5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK}, - {"pdetrange5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK}, - {"triso5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK}, - {"antswctl5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK}, - {"tempthresh", 0xffffff00, 0, SROM8_THERMAL, 0xff00}, - {"tempoffset", 0xffffff00, 0, SROM8_THERMAL, 0x00ff}, - {"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff}, - {"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00}, - {"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G+1, 0x00ff}, - {"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G+1, 0xff00}, - {"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff}, - {"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00}, - {"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G+1, 0x00ff}, - {"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G+1, 0xff00}, - {"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff}, - {"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00}, - {"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL+1, 0x00ff}, - {"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL+1, 0xff00}, - {"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff}, - {"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00}, - {"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH+1, 0x00ff}, - {"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH+1, 0xff00}, - - {"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff}, - {"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff}, - {"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff}, - {"ccode", 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff}, - {"macaddr", 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, - {"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff}, - {"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff}, - {"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff}, - {"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff}, - {"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff}, - {"leddc", 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, 0xffff}, - {"leddc", 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, 0xffff}, - {"leddc", 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, 0xffff}, - {"leddc", 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, 0xffff}, - {"rawtempsense",0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff}, - {"measpower", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00}, - {"tempsense_slope",0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x00ff}, - {"tempcorrx", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00}, - {"tempsense_option",0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0x0300}, - {"freqoffset_corr",0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x000f}, - {"iqcal_swp_dis",0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010}, - {"hw_iqcal_en", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020}, - {"phycal_tempdelta",0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff}, - - {"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff}, - {"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff}, - {"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff}, - {"", 0, 0, SROM4_2G_OFDMPO+1, 0xffff}, - {"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff}, - {"", 0, 0, SROM4_5G_OFDMPO+1, 0xffff}, - {"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff}, - {"", 0, 0, SROM4_5GL_OFDMPO+1, 0xffff}, - {"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff}, - {"", 0, 0, SROM4_5GH_OFDMPO+1, 0xffff}, - {"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, - {"", 0, 0, SROM8_2G_OFDMPO+1, 0xffff}, - {"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, - {"", 0, 0, SROM8_5G_OFDMPO+1, 0xffff}, - {"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff}, - {"", 0, 0, SROM8_5GL_OFDMPO+1, 0xffff}, - {"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, - {"", 0, 0, SROM8_5GH_OFDMPO+1, 0xffff}, - - {"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff}, - {"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO+1, 0xffff}, - {"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO+2, 0xffff}, - {"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO+3, 0xffff}, - {"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO+4, 0xffff}, - {"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO+5, 0xffff}, - {"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO+6, 0xffff}, - {"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO+7, 0xffff}, - - {"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff}, - {"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO+1, 0xffff}, - {"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO+2, 0xffff}, - {"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO+3, 0xffff}, - {"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO+4, 0xffff}, - {"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO+5, 0xffff}, - {"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO+6, 0xffff}, - {"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO+7, 0xffff}, - - {"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff}, - {"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO+1, 0xffff}, - {"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO+2, 0xffff}, - {"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO+3, 0xffff}, - {"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO+4, 0xffff}, - {"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO+5, 0xffff}, - {"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO+6, 0xffff}, - {"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO+7, 0xffff}, - - {"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff}, - {"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO+1, 0xffff}, - {"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO+2, 0xffff}, - {"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO+3, 0xffff}, - {"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO+4, 0xffff}, - {"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO+5, 0xffff}, - {"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO+6, 0xffff}, - {"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO+7, 0xffff}, - - {"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff}, - {"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO+1, 0xffff}, - {"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO+2, 0xffff}, - {"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO+3, 0xffff}, - {"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO+4, 0xffff}, - {"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO+5, 0xffff}, - {"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO+6, 0xffff}, - {"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO+7, 0xffff}, - - {"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff}, - {"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO+1, 0xffff}, - {"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO+2, 0xffff}, - {"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO+3, 0xffff}, - {"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO+4, 0xffff}, - {"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO+5, 0xffff}, - {"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO+6, 0xffff}, - {"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO+7, 0xffff}, - - {"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff}, - {"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO+1, 0xffff}, - {"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO+2, 0xffff}, - {"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO+3, 0xffff}, - {"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO+4, 0xffff}, - {"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO+5, 0xffff}, - {"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO+6, 0xffff}, - {"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO+7, 0xffff}, - {"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff}, - {"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO+1, 0xffff}, - {"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO+2, 0xffff}, - {"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO+3, 0xffff}, - {"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO+4, 0xffff}, - {"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO+5, 0xffff}, - {"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO+6, 0xffff}, - {"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO+7, 0xffff}, - {"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff}, - {"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff}, - {"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff}, - {"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff}, - {"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff}, - {"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff}, - {"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff}, - {"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff}, - - /* power per rate from sromrev 9 */ - {"cckbw202gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff}, - {"cckbw20ul2gpo",0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff}, - {"legofdmbw202gpo",0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20, 0xffff}, - {"", 0, 0, SROM9_2GPO_LOFDMBW20+1, 0xffff}, - {"legofdmbw20ul2gpo",0xfffffe00,SRFL_MORE, SROM9_2GPO_LOFDMBW20UL, 0xffff}, - {"", 0, 0, SROM9_2GPO_LOFDMBW20UL+1,0xffff}, - {"legofdmbw205glpo",0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20, 0xffff}, - {"", 0, 0, SROM9_5GLPO_LOFDMBW20+1,0xffff}, - {"legofdmbw20ul5glpo",0xfffffe00,SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL,0xffff}, - {"", 0, 0, SROM9_5GLPO_LOFDMBW20UL+1,0xffff}, - {"legofdmbw205gmpo",0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20, 0xffff}, - {"", 0, 0, SROM9_5GMPO_LOFDMBW20+1,0xffff}, - {"legofdmbw20ul5gmpo",0xfffffe00,SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL,0xffff}, - {"", 0, 0, SROM9_5GMPO_LOFDMBW20UL+1,0xffff}, - {"legofdmbw205ghpo",0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20, 0xffff}, - {"", 0, 0, SROM9_5GHPO_LOFDMBW20+1,0xffff}, - {"legofdmbw20ul5ghpo",0xfffffe00,SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL,0xffff}, - {"", 0, 0, SROM9_5GHPO_LOFDMBW20UL+1,0xffff}, - {"mcsbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff}, - {"", 0, 0, SROM9_2GPO_MCSBW20+1, 0xffff}, - {"mcsbw20ul2gpo",0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff}, - {"", 0, 0, SROM9_2GPO_MCSBW20UL+1, 0xffff}, - {"mcsbw402gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff}, - {"", 0, 0, SROM9_2GPO_MCSBW40+1, 0xffff}, - {"mcsbw205glpo",0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff}, - {"", 0, 0, SROM9_5GLPO_MCSBW20+1, 0xffff}, - {"mcsbw20ul5glpo",0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20UL, 0xffff}, - {"", 0, 0, SROM9_5GLPO_MCSBW20UL+1,0xffff}, - {"mcsbw405glpo",0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff}, - {"", 0, 0, SROM9_5GLPO_MCSBW40+1, 0xffff}, - {"mcsbw205gmpo",0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff}, - {"", 0, 0, SROM9_5GMPO_MCSBW20+1, 0xffff}, - {"mcsbw20ul5gmpo",0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20UL, 0xffff}, - {"", 0, 0, SROM9_5GMPO_MCSBW20UL+1,0xffff}, - {"mcsbw405gmpo",0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff}, - {"", 0, 0, SROM9_5GMPO_MCSBW40+1, 0xffff}, - {"mcsbw205ghpo",0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff}, - {"", 0, 0, SROM9_5GHPO_MCSBW20+1, 0xffff}, - {"mcsbw20ul5ghpo",0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20UL, 0xffff}, - {"", 0, 0, SROM9_5GHPO_MCSBW20UL+1,0xffff}, - {"mcsbw405ghpo",0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff}, - {"", 0, 0, SROM9_5GHPO_MCSBW40+1, 0xffff}, - {"mcs32po", 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff}, - {"legofdm40duppo",0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff}, - - {NULL, 0, 0, 0, 0} -}; - -static const sromvar_t perpath_pci_sromvars[] = { - {"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff}, - {"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00}, - {"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00}, - {"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff}, - {"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA+1, 0xffff}, - {"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA+2, 0xffff}, - {"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA+3, 0xffff}, - {"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff}, - {"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff}, - {"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00}, - {"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff}, - {"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA+1, 0xffff}, - {"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA+2, 0xffff}, - {"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA+3, 0xffff}, - {"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff}, - {"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA+1, 0xffff}, - {"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA+2, 0xffff}, - {"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA+3, 0xffff}, - {"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff}, - {"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA+1, 0xffff}, - {"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA+2, 0xffff}, - {"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA+3, 0xffff}, - {"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff}, - {"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00}, - {"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00}, - {"pa2gw0a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff}, - {"pa2gw1a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA+1, 0xffff}, - {"pa2gw2a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA+2, 0xffff}, - {"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff}, - {"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff}, - {"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00}, - {"pa5gw0a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff}, - {"pa5gw1a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA+1, 0xffff}, - {"pa5gw2a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA+2, 0xffff}, - {"pa5glw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff}, - {"pa5glw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA+1, 0xffff}, - {"pa5glw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA+2, 0xffff}, - {"pa5ghw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff}, - {"pa5ghw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA+1, 0xffff}, - {"pa5ghw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA+2, 0xffff}, - {NULL, 0, 0, 0, 0} -}; - -#if !(defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) -#define PHY_TYPE_N 4 /* N-Phy value */ -#define PHY_TYPE_LP 5 /* LP-Phy value */ -#endif /* !(defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) */ -#if !defined(PHY_TYPE_NULL) -#define PHY_TYPE_NULL 0xf /* Invalid Phy value */ -#endif /* !defined(PHY_TYPE_NULL) */ - -typedef struct { - u16 phy_type; - u16 bandrange; - u16 chain; - const char *vars; -} pavars_t; - -static const pavars_t pavars[] = { - /* NPHY */ - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"}, - /* LPPHY */ - {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_2G, 0, "pa0b0 pa0b1 pa0b2"}, - {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GL, 0, "pa1lob0 pa1lob1 pa1lob2"}, - {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GM, 0, "pa1b0 pa1b1 pa1b2"}, - {PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GH, 0, "pa1hib0 pa1hib1 pa1hib2"}, - {PHY_TYPE_NULL, 0, 0, ""} -}; - -typedef struct { - u16 phy_type; - u16 bandrange; - const char *vars; -} povars_t; - -static const povars_t povars[] = { - /* NPHY */ - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, - "mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 " - "mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, - "mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 " - "mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, - "mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 " - "mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"}, - {PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, - "mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 " - "mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"}, - {PHY_TYPE_NULL, 0, ""} -}; - -typedef struct { - u8 tag; /* Broadcom subtag name */ - u8 len; /* Length field of the tuple, note that it includes the - * subtag name (1 byte): 1 + tuple content length - */ - const char *params; -} cis_tuple_t; - -#define OTP_RAW (0xff - 1) /* Reserved tuple number for wrvar Raw input */ -#define OTP_VERS_1 (0xff - 2) /* CISTPL_VERS_1 */ -#define OTP_MANFID (0xff - 3) /* CISTPL_MANFID */ -#define OTP_RAW1 (0xff - 4) /* Like RAW, but comes first */ - -static const cis_tuple_t cis_hnbuvars[] = { - {OTP_RAW1, 0, ""}, /* special case */ - {OTP_VERS_1, 0, "smanf sproductname"}, /* special case (non BRCM tuple) */ - {OTP_MANFID, 4, "2manfid 2prodid"}, /* special case (non BRCM tuple) */ - {HNBU_SROMREV, 2, "1sromrev"}, - /* NOTE: subdevid is also written to boardtype. - * Need to write HNBU_BOARDTYPE to change it if it is different. - */ - {HNBU_CHIPID, 11, "2vendid 2devid 2chiprev 2subvendid 2subdevid"}, - {HNBU_BOARDREV, 3, "2boardrev"}, - {HNBU_PAPARMS, 10, "2pa0b0 2pa0b1 2pa0b2 1pa0itssit 1pa0maxpwr 1opo"}, - {HNBU_AA, 3, "1aa2g 1aa5g"}, - {HNBU_AA, 3, "1aa0 1aa1"}, /* backward compatibility */ - {HNBU_AG, 5, "1ag0 1ag1 1ag2 1ag3"}, - {HNBU_BOARDFLAGS, 9, "4boardflags 4boardflags2"}, - {HNBU_LEDS, 5, "1ledbh0 1ledbh1 1ledbh2 1ledbh3"}, - {HNBU_CCODE, 4, "2ccode 1cctl"}, - {HNBU_CCKPO, 3, "2cckpo"}, - {HNBU_OFDMPO, 5, "4ofdmpo"}, - {HNBU_RDLID, 3, "2rdlid"}, - {HNBU_RSSISMBXA2G, 3, "0rssismf2g 0rssismc2g 0rssisav2g 0bxa2g"}, /* special case */ - {HNBU_RSSISMBXA5G, 3, "0rssismf5g 0rssismc5g 0rssisav5g 0bxa5g"}, /* special case */ - {HNBU_XTALFREQ, 5, "4xtalfreq"}, - {HNBU_TRI2G, 2, "1tri2g"}, - {HNBU_TRI5G, 4, "1tri5gl 1tri5g 1tri5gh"}, - {HNBU_RXPO2G, 2, "1rxpo2g"}, - {HNBU_RXPO5G, 2, "1rxpo5g"}, - {HNBU_BOARDNUM, 3, "2boardnum"}, - {HNBU_MACADDR, 7, "6macaddr"}, /* special case */ - {HNBU_RDLSN, 3, "2rdlsn"}, - {HNBU_BOARDTYPE, 3, "2boardtype"}, - {HNBU_LEDDC, 3, "2leddc"}, - {HNBU_RDLRNDIS, 2, "1rdlndis"}, - {HNBU_CHAINSWITCH, 5, "1txchain 1rxchain 2antswitch"}, - {HNBU_REGREV, 2, "1regrev"}, - {HNBU_FEM, 5, "0antswctl2g, 0triso2g, 0pdetrange2g, 0extpagain2g, 0tssipos2g" "0antswctl5g, 0triso5g, 0pdetrange5g, 0extpagain5g, 0tssipos5g"}, /* special case */ - {HNBU_PAPARMS_C0, 31, "1maxp2ga0 1itt2ga0 2pa2gw0a0 2pa2gw1a0 " - "2pa2gw2a0 1maxp5ga0 1itt5ga0 1maxp5gha0 1maxp5gla0 2pa5gw0a0 " - "2pa5gw1a0 2pa5gw2a0 2pa5glw0a0 2pa5glw1a0 2pa5glw2a0 2pa5ghw0a0 " - "2pa5ghw1a0 2pa5ghw2a0"}, - {HNBU_PAPARMS_C1, 31, "1maxp2ga1 1itt2ga1 2pa2gw0a1 2pa2gw1a1 " - "2pa2gw2a1 1maxp5ga1 1itt5ga1 1maxp5gha1 1maxp5gla1 2pa5gw0a1 " - "2pa5gw1a1 2pa5gw2a1 2pa5glw0a1 2pa5glw1a1 2pa5glw2a1 2pa5ghw0a1 " - "2pa5ghw1a1 2pa5ghw2a1"}, - {HNBU_PO_CCKOFDM, 19, "2cck2gpo 4ofdm2gpo 4ofdm5gpo 4ofdm5glpo " - "4ofdm5ghpo"}, - {HNBU_PO_MCS2G, 17, "2mcs2gpo0 2mcs2gpo1 2mcs2gpo2 2mcs2gpo3 " - "2mcs2gpo4 2mcs2gpo5 2mcs2gpo6 2mcs2gpo7"}, - {HNBU_PO_MCS5GM, 17, "2mcs5gpo0 2mcs5gpo1 2mcs5gpo2 2mcs5gpo3 " - "2mcs5gpo4 2mcs5gpo5 2mcs5gpo6 2mcs5gpo7"}, - {HNBU_PO_MCS5GLH, 33, "2mcs5glpo0 2mcs5glpo1 2mcs5glpo2 2mcs5glpo3 " - "2mcs5glpo4 2mcs5glpo5 2mcs5glpo6 2mcs5glpo7 " - "2mcs5ghpo0 2mcs5ghpo1 2mcs5ghpo2 2mcs5ghpo3 " - "2mcs5ghpo4 2mcs5ghpo5 2mcs5ghpo6 2mcs5ghpo7"}, - {HNBU_CCKFILTTYPE, 2, "1cckdigfilttype"}, - {HNBU_PO_CDD, 3, "2cddpo"}, - {HNBU_PO_STBC, 3, "2stbcpo"}, - {HNBU_PO_40M, 3, "2bw40po"}, - {HNBU_PO_40MDUP, 3, "2bwduppo"}, - {HNBU_RDLRWU, 2, "1rdlrwu"}, - {HNBU_WPS, 3, "1wpsgpio 1wpsled"}, - {HNBU_USBFS, 2, "1usbfs"}, - {HNBU_CUSTOM1, 5, "4customvar1"}, - {OTP_RAW, 0, ""}, /* special case */ - {HNBU_OFDMPO5G, 13, "4ofdm5gpo 4ofdm5glpo 4ofdm5ghpo"}, - {HNBU_USBEPNUM, 3, "2usbepnum"}, - {0xFF, 0, ""} -}; - -#endif /* _BHND_BCMSROM_TBL_H_ */ Index: head/sys/dev/bhnd/bhnd.h =================================================================== --- head/sys/dev/bhnd/bhnd.h +++ head/sys/dev/bhnd/bhnd.h @@ -464,6 +464,55 @@ return (BHND_BUS_GET_CHIPID(device_get_parent(dev), dev)); }; +/** + * Determine an NVRAM variable's expected size. + * + * @param dev A bhnd bus child device. + * @param name The variable name. + * @param[out] len On success, the variable's size, in bytes. + * + * @retval 0 success + * @retval ENOENT The requested variable was not found. + * @retval non-zero If reading @p name otherwise fails, a regular unix + * error code will be returned. + */ +static inline int +bhnd_nvram_getvarlen(device_t dev, const char *name, size_t *len) +{ + return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, NULL, + len)); +} + +/** + * Read an NVRAM variable. + * + * @param dev A bhnd bus child device. + * @param name The NVRAM variable name. + * @param buf A buffer large enough to hold @p len bytes. On success, + * the requested value will be written to this buffer. + * @param len The required variable length. + * + * @retval 0 success + * @retval ENOENT The requested variable was not found. + * @retval EINVAL If @p len does not match the actual variable size. + * @retval non-zero If reading @p name otherwise fails, a regular unix + * error code will be returned. + */ +static inline int +bhnd_nvram_getvar(device_t dev, const char *name, void *buf, size_t len) +{ + size_t var_len; + int error; + + if ((error = bhnd_nvram_getvarlen(dev, name, &var_len))) + return (error); + + if (len != var_len) + return (EINVAL); + + return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), dev, name, buf, + &len)); +} /** * Allocate a resource from a device's parent bhnd(4) bus. Index: head/sys/dev/bhnd/bhnd.c =================================================================== --- head/sys/dev/bhnd/bhnd.c +++ head/sys/dev/bhnd/bhnd.c @@ -58,11 +58,14 @@ #include #include -#include "bhnd.h" -#include "bhndvar.h" +#include "nvram/bhnd_nvram.h" +#include "bhnd_chipc_if.h" #include "bhnd_nvram_if.h" +#include "bhnd.h" +#include "bhndvar.h" + MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures"); /** @@ -386,23 +389,27 @@ static device_t find_nvram_child(device_t dev) { - device_t chipc, nvram; + device_t chipc, nvram; /* Look for a directly-attached NVRAM child */ - nvram = device_find_child(dev, devclass_get_name(bhnd_nvram_devclass), - -1); - if (nvram == NULL) - return (NULL); + nvram = device_find_child(dev, "bhnd_nvram", 0); + if (nvram != NULL) + return (nvram); - /* Further checks require a bhnd(4) bus */ + /* Remaining checks are only applicable when searching a bhnd(4) + * bus. */ if (device_get_devclass(dev) != bhnd_devclass) return (NULL); - /* Look for a ChipCommon-attached OTP device */ + /* Look for a ChipCommon device */ if ((chipc = bhnd_find_child(dev, BHND_DEVCLASS_CC, -1)) != NULL) { - /* Recursively search the ChipCommon device */ - if ((nvram = find_nvram_child(chipc)) != NULL) - return (nvram); + bhnd_nvram_src_t src; + + /* Query the NVRAM source and determine whether it's + * accessible via the ChipCommon device */ + src = BHND_CHIPC_NVRAM_SRC(chipc); + if (BHND_NVRAM_SRC_CC(src)) + return (chipc); } /* Not found */ @@ -410,22 +417,26 @@ } /** - * Default bhnd(4) bus driver implementation of BHND_BUS_READ_NVRAM_VAR(). + * Default bhnd(4) bus driver implementation of BHND_BUS_GET_NVRAM_VAR(). + * + * This implementation searches @p dev for a usable NVRAM child device: + * - The first child device implementing the bhnd_nvram devclass is + * returned, otherwise + * - If @p dev is a bhnd(4) bus, a ChipCommon core that advertises an + * attached NVRAM source. * - * This implementation searches @p dev for a valid NVRAM device. If no NVRAM - * child device is found on @p dev, the request is delegated to the - * BHND_BUS_READ_NVRAM_VAR() method on the parent - * of @p dev. + * If no usable child device is found on @p dev, the request is delegated to + * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev. */ static int -bhnd_generic_read_nvram_var(device_t dev, device_t child, const char *name, +bhnd_generic_get_nvram_var(device_t dev, device_t child, const char *name, void *buf, size_t *size) { device_t nvram; /* Try to find an NVRAM device applicable to @p child */ if ((nvram = find_nvram_child(dev)) == NULL) - return (BHND_BUS_READ_NVRAM_VAR(device_get_parent(dev), child, + return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, name, buf, size)); return BHND_NVRAM_GETVAR(nvram, name, buf, size); @@ -682,7 +693,7 @@ DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order), DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid), DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled), - DEVMETHOD(bhnd_bus_read_nvram_var, bhnd_generic_read_nvram_var), + DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var), DEVMETHOD(bhnd_bus_read_1, bhnd_read_1), DEVMETHOD(bhnd_bus_read_2, bhnd_read_2), DEVMETHOD(bhnd_bus_read_4, bhnd_read_4), Index: head/sys/dev/bhnd/bhnd_bus_if.m =================================================================== --- head/sys/dev/bhnd/bhnd_bus_if.m +++ head/sys/dev/bhnd/bhnd_bus_if.m @@ -96,7 +96,7 @@ } static int - bhnd_bus_null_read_nvram_var(device_t dev, device_t child, + bhnd_bus_null_get_nvram_var(device_t dev, device_t child, const char *name, void *buf, size_t *size) { return (ENOENT); @@ -403,13 +403,13 @@ * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ -METHOD int read_nvram_var { +METHOD int get_nvram_var { device_t dev; device_t child; const char *name; void *buf; size_t *size; -} DEFAULT bhnd_bus_null_read_nvram_var; +} DEFAULT bhnd_bus_null_get_nvram_var; /** An implementation of bus_read_1() compatible with bhnd_resource */ Index: head/sys/dev/bhnd/bhnd_ids.h =================================================================== --- head/sys/dev/bhnd/bhnd_ids.h +++ head/sys/dev/bhnd/bhnd_ids.h @@ -328,6 +328,7 @@ #define BHND_CHIPID_BCM43428 43428 /* 43228 chipcommon chipid (OTP, RBBU) */ #define BHND_CHIPID_BCM43431 43431 /* 4331 chipcommon chipid (OTP, RBBU) */ #define BHND_CHIPID_BCM43460 43460 /* 4360 chipcommon chipid (OTP, RBBU) */ +#define BHND_CHIPID_BCM43462 0xA9C6 /* 43462 chipcommon chipid */ #define BHND_CHIPID_BCM4325 0x4325 /* 4325 chip id */ #define BHND_CHIPID_BCM4328 0x4328 /* 4328 chip id */ #define BHND_CHIPID_BCM4329 0x4329 /* 4329 chipcommon chipid */ @@ -345,6 +346,7 @@ #define BHND_CHIPID_BCM4334 0x4334 /* 4334 chipcommon chipid */ #define BHND_CHIPID_BCM4335 0x4335 /* 4335 chipcommon chipid */ #define BHND_CHIPID_BCM4360 0x4360 /* 4360 chipcommon chipid */ +#define BHND_CHIPID_BCM43602 0xaa52 /* 43602 chipcommon chipid */ #define BHND_CHIPID_BCM4352 0x4352 /* 4352 chipcommon chipid */ #define BHND_CHIPID_BCM43526 0xAA06 #define BHND_CHIPID_BCM43341 43341 /* 43341 chipcommon chipid */ @@ -433,7 +435,6 @@ #define BHND_PKGID_BCM4335_FCBGAD (0x3) /* FCBGA Debug Debug/Dev All if's. */ #define BHND_PKGID_PKG_MASK_BCM4335 (0x3) - /* Broadcom Core IDs */ #define BHND_COREID_INVALID 0x700 /* Invalid coreid */ #define BHND_COREID_CC 0x800 /* chipcommon core */ Index: head/sys/dev/bhnd/bhndb/bhndb.c =================================================================== --- head/sys/dev/bhnd/bhndb/bhndb.c +++ head/sys/dev/bhnd/bhndb/bhndb.c @@ -51,6 +51,10 @@ #include #include +#include + +#include "bhnd_chipc_if.h" +#include "bhnd_nvram_if.h" #include "bhndbvar.h" #include "bhndb_bus_if.h" @@ -609,7 +613,7 @@ goto cleanup; } - if (bootverbose) + if (bootverbose || BHNDB_DEBUG(PRIO)) device_printf(sc->dev, "%s resource configuration\n", hw->name); /* Release existing resource state */ @@ -1298,9 +1302,10 @@ rman_get_size(r)); if (error) { device_printf(sc->dev, "dynamic window initialization " - "for 0x%llx-0x%llx failed\n", + "for 0x%llx-0x%llx failed: %d\n", (unsigned long long) r_start, - (unsigned long long) r_start + r_size - 1); + (unsigned long long) r_start + r_size - 1, + error); return (NULL); } @@ -1709,6 +1714,26 @@ return (dwa); } +/** + * Default bhndb(4) implementation of BHND_BUS_GET_NVRAM_VAR(). + */ +static int +bhndb_get_nvram_var(device_t dev, device_t child, const char *name, + void *buf, size_t *size) +{ + device_t nvram; + + /* Look for a directly-attached NVRAM child */ + nvram = device_find_child(dev, devclass_get_name(bhnd_nvram_devclass), + 0); + if (nvram != NULL) + return (BHND_NVRAM_GETVAR(nvram, name, buf, size)); + + /* Otherwise, delegate to our parent */ + return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, + name, buf, size)); +} + /* * BHND_BUS_(READ|WRITE_* implementations */ @@ -1936,6 +1961,7 @@ DEVMETHOD(bhnd_bus_get_chipid, bhndb_get_chipid), DEVMETHOD(bhnd_bus_activate_resource, bhndb_activate_bhnd_resource), DEVMETHOD(bhnd_bus_deactivate_resource, bhndb_deactivate_bhnd_resource), + DEVMETHOD(bhnd_bus_get_nvram_var, bhndb_get_nvram_var), DEVMETHOD(bhnd_bus_read_1, bhndb_bus_read_1), DEVMETHOD(bhnd_bus_read_2, bhndb_bus_read_2), DEVMETHOD(bhnd_bus_read_4, bhndb_bus_read_4), Index: head/sys/dev/bhnd/bhndb/bhndb_pci.c =================================================================== --- head/sys/dev/bhnd/bhndb/bhndb_pci.c +++ head/sys/dev/bhnd/bhndb/bhndb_pci.c @@ -61,15 +61,19 @@ #include "bhndb_pcivar.h" #include "bhndb_private.h" -static int bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc); -static int bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc); +static int bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc); +static int bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc); -static int bhndb_pci_compat_setregwin(struct bhndb_pci_softc *, - const struct bhndb_regwin *, bhnd_addr_t); -static int bhndb_pci_fast_setregwin(struct bhndb_pci_softc *, - const struct bhndb_regwin *, bhnd_addr_t); +static int bhndb_pci_compat_setregwin(struct bhndb_pci_softc *, + const struct bhndb_regwin *, bhnd_addr_t); +static int bhndb_pci_fast_setregwin(struct bhndb_pci_softc *, + const struct bhndb_regwin *, bhnd_addr_t); -static void bhndb_init_sromless_pci_config(struct bhndb_pci_softc *sc); +static void bhndb_init_sromless_pci_config( + struct bhndb_pci_softc *sc); + +static bus_addr_t bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc); +static size_t bhndb_pci_sprom_size(struct bhndb_pci_softc *sc); /** * Default bhndb_pci implementation of device_probe(). @@ -104,13 +108,14 @@ sc = device_get_softc(dev); sc->dev = dev; + sc->parent = device_get_parent(dev); /* Enable PCI bus mastering */ - pci_enable_busmaster(device_get_parent(dev)); + pci_enable_busmaster(sc->parent); /* Determine our bridge device class */ sc->pci_devclass = BHND_DEVCLASS_PCI; - if (pci_find_cap(device_get_parent(dev), PCIY_EXPRESS, ®) == 0) + if (pci_find_cap(sc->parent, PCIY_EXPRESS, ®) == 0) sc->pci_devclass = BHND_DEVCLASS_PCIE; /* Enable clocks (if supported by this hardware) */ @@ -142,6 +147,8 @@ const struct bhndb_hw_priority *hw_prio_table) { struct bhndb_pci_softc *sc; + device_t nv_dev; + bus_size_t nv_sz; int error; sc = device_get_softc(dev); @@ -153,9 +160,126 @@ /* Fix-up power on defaults for SROM-less devices. */ bhndb_init_sromless_pci_config(sc); + /* If SPROM is mapped directly into BAR0, add NVRAM device. */ + nv_sz = bhndb_pci_sprom_size(sc); + if (nv_sz > 0) { + struct bhndb_devinfo *dinfo; + const char *dname; + + if (bootverbose) { + device_printf(dev, "found SPROM (%zu bytes)\n", nv_sz); + } + + /* Add sprom device */ + dname = "bhnd_nvram"; + if ((nv_dev = BUS_ADD_CHILD(dev, 0, dname, -1)) == NULL) { + device_printf(dev, "failed to add sprom device\n"); + return (ENXIO); + } + + /* Initialize device address space and resource covering the + * BAR0 SPROM shadow. */ + dinfo = device_get_ivars(nv_dev); + dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE; + error = bus_set_resource(nv_dev, SYS_RES_MEMORY, 0, + bhndb_pci_sprom_addr(sc), nv_sz); + + if (error) { + device_printf(dev, + "failed to register sprom resources\n"); + return (error); + } + + /* Attach the device */ + if ((error = device_probe_and_attach(nv_dev))) { + device_printf(dev, "sprom attach failed\n"); + return (error); + } + } + return (0); } +static const struct bhndb_regwin * +bhndb_pci_sprom_regwin(struct bhndb_pci_softc *sc) +{ + struct bhndb_resources *bres; + const struct bhndb_hwcfg *cfg; + const struct bhndb_regwin *sprom_win; + + bres = sc->bhndb.bus_res; + cfg = bres->cfg; + + sprom_win = bhndb_regwin_find_type(cfg->register_windows, + BHNDB_REGWIN_T_SPROM, BHNDB_PCI_V0_BAR0_SPROM_SIZE); + + return (sprom_win); +} + +static bus_addr_t +bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc) +{ + const struct bhndb_regwin *sprom_win; + struct resource *r; + + /* Fetch the SPROM register window */ + sprom_win = bhndb_pci_sprom_regwin(sc); + KASSERT(sprom_win != NULL, ("requested sprom address on PCI_V2+")); + + /* Fetch the associated resource */ + r = bhndb_find_regwin_resource(sc->bhndb.bus_res, sprom_win); + KASSERT(r != NULL, ("missing resource for sprom window\n")); + + return (rman_get_start(r) + sprom_win->win_offset); +} + +static bus_size_t +bhndb_pci_sprom_size(struct bhndb_pci_softc *sc) +{ + const struct bhndb_regwin *sprom_win; + uint32_t sctl; + bus_size_t sprom_sz; + + sprom_win = bhndb_pci_sprom_regwin(sc); + + /* PCI_V2 and later devices map SPROM/OTP via ChipCommon */ + if (sprom_win == NULL) + return (0); + + /* Determine SPROM size */ + sctl = pci_read_config(sc->parent, BHNDB_PCI_SPROM_CONTROL, 4); + if (sctl & BHNDB_PCI_SPROM_BLANK) + return (0); + + switch (sctl & BHNDB_PCI_SPROM_SZ_MASK) { + case BHNDB_PCI_SPROM_SZ_1KB: + sprom_sz = (1 * 1024); + break; + + case BHNDB_PCI_SPROM_SZ_4KB: + sprom_sz = (4 * 1024); + break; + + case BHNDB_PCI_SPROM_SZ_16KB: + sprom_sz = (16 * 1024); + break; + + case BHNDB_PCI_SPROM_SZ_RESERVED: + default: + device_printf(sc->dev, "invalid PCI sprom size 0x%x\n", sctl); + return (0); + } + + if (sprom_sz > sprom_win->win_size) { + device_printf(sc->dev, + "PCI sprom size (0x%x) overruns defined register window\n", + sctl); + return (0); + } + + return (sprom_sz); +} + /* * On devices without a SROM, the PCI(e) cores will be initialized with * their Power-on-Reset defaults; this can leave two of the BAR0 PCI windows @@ -274,7 +398,7 @@ return (error); /* Disable PCI bus mastering */ - pci_disable_busmaster(device_get_parent(dev)); + pci_disable_busmaster(sc->parent); return (0); } @@ -301,19 +425,18 @@ bhndb_pci_compat_setregwin(struct bhndb_pci_softc *sc, const struct bhndb_regwin *rw, bhnd_addr_t addr) { - device_t parent; int error; - - parent = sc->bhndb.parent_dev; + int reg; if (rw->win_type != BHNDB_REGWIN_T_DYN) return (ENODEV); + reg = rw->d.dyn.cfg_offset; for (u_int i = 0; i < BHNDB_PCI_BARCTRL_WRITE_RETRY; i++) { if ((error = bhndb_pci_fast_setregwin(sc, rw, addr))) return (error); - if (pci_read_config(parent, rw->d.dyn.cfg_offset, 4) == addr) + if (pci_read_config(sc->parent, reg, 4) == addr) return (0); DELAY(10); @@ -330,8 +453,6 @@ bhndb_pci_fast_setregwin(struct bhndb_pci_softc *sc, const struct bhndb_regwin *rw, bhnd_addr_t addr) { - device_t parent = sc->bhndb.parent_dev; - /* The PCI bridge core only supports 32-bit addressing, regardless * of the bus' support for 64-bit addressing */ if (addr > UINT32_MAX) @@ -343,7 +464,7 @@ if (addr % rw->win_size != 0) return (EINVAL); - pci_write_config(parent, rw->d.dyn.cfg_offset, addr, 4); + pci_write_config(sc->parent, rw->d.dyn.cfg_offset, addr, 4); break; default: return (ENODEV); @@ -366,7 +487,6 @@ static int bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc) { - device_t pci_parent; uint32_t gpio_in, gpio_out, gpio_en; uint32_t gpio_flags; uint16_t pci_status; @@ -375,35 +495,33 @@ if (sc->pci_devclass != BHND_DEVCLASS_PCI) return (0); - pci_parent = device_get_parent(sc->dev); - /* Read state of XTAL pin */ - gpio_in = pci_read_config(pci_parent, BHNDB_PCI_GPIO_IN, 4); + gpio_in = pci_read_config(sc->parent, BHNDB_PCI_GPIO_IN, 4); if (gpio_in & BHNDB_PCI_GPIO_XTAL_ON) return (0); /* already enabled */ /* Fetch current config */ - gpio_out = pci_read_config(pci_parent, BHNDB_PCI_GPIO_OUT, 4); - gpio_en = pci_read_config(pci_parent, BHNDB_PCI_GPIO_OUTEN, 4); + gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4); + gpio_en = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, 4); /* Set PLL_OFF/XTAL_ON pins to HIGH and enable both pins */ gpio_flags = (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON); gpio_out |= gpio_flags; gpio_en |= gpio_flags; - pci_write_config(pci_parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4); - pci_write_config(pci_parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4); + pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4); + pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4); DELAY(1000); /* Reset PLL_OFF */ gpio_out &= ~BHNDB_PCI_GPIO_PLL_OFF; - pci_write_config(pci_parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4); + pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4); DELAY(5000); /* Clear any PCI 'sent target-abort' flag. */ - pci_status = pci_read_config(pci_parent, PCIR_STATUS, 2); + pci_status = pci_read_config(sc->parent, PCIR_STATUS, 2); pci_status &= ~PCIM_STATUS_STABORT; - pci_write_config(pci_parent, PCIR_STATUS, pci_status, 2); + pci_write_config(sc->parent, PCIR_STATUS, pci_status, 2); return (0); } @@ -416,31 +534,28 @@ static int bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc) { - device_t parent_dev; uint32_t gpio_out, gpio_en; /* Only supported and required on PCI devices */ if (sc->pci_devclass != BHND_DEVCLASS_PCI) return (0); - parent_dev = device_get_parent(sc->dev); - // TODO: Check board flags for BFL2_XTALBUFOUTEN? // TODO: Check PCI core revision? // TODO: Switch to 'slow' clock? /* Fetch current config */ - gpio_out = pci_read_config(parent_dev, BHNDB_PCI_GPIO_OUT, 4); - gpio_en = pci_read_config(parent_dev, BHNDB_PCI_GPIO_OUTEN, 4); + gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4); + gpio_en = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, 4); /* Set PLL_OFF to HIGH, XTAL_ON to LOW. */ gpio_out &= ~BHNDB_PCI_GPIO_XTAL_ON; gpio_out |= BHNDB_PCI_GPIO_PLL_OFF; - pci_write_config(parent_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4); + pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4); /* Enable both output pins */ gpio_en |= (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON); - pci_write_config(parent_dev, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4); + pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4); return (0); } Index: head/sys/dev/bhnd/bhndb/bhndb_pci_sprom.c =================================================================== --- head/sys/dev/bhnd/bhndb/bhndb_pci_sprom.c +++ head/sys/dev/bhnd/bhndb/bhndb_pci_sprom.c @@ -0,0 +1,210 @@ +/*- + * Copyright (c) 2015-2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * BHNDB PCI SPROM driver. + * + * Provides support for early PCI bridge cores that vend SPROM CSRs + * via PCI configuration space. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "bhnd_nvram_if.h" +#include "bhndb_pcireg.h" +#include "bhndb_pcivar.h" + +struct bhndb_pci_sprom_softc { + device_t dev; + struct bhnd_resource *sprom_res; /**< SPROM resource */ + int sprom_rid; /**< SPROM RID */ + struct bhnd_sprom shadow; /**< SPROM shadow */ + struct mtx mtx; /**< SPROM shadow mutex */ +}; + +#define SPROM_LOCK_INIT(sc) \ + mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ + "BHND PCI SPROM lock", MTX_DEF) +#define SPROM_LOCK(sc) mtx_lock(&(sc)->mtx) +#define SPROM_UNLOCK(sc) mtx_unlock(&(sc)->mtx) +#define SPROM_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what) +#define SPROM_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx) + +static int +bhndb_pci_sprom_probe(device_t dev) +{ + device_t bridge, bus; + + /* Our parent must be a PCI-BHND bridge with an attached bhnd bus */ + bridge = device_get_parent(dev); + if (device_get_driver(bridge) != &bhndb_pci_driver) + return (ENXIO); + + bus = device_find_child(bridge, devclass_get_name(bhnd_devclass), 0); + if (bus == NULL) + return (ENXIO); + + /* Found */ + device_set_desc(dev, "PCI-BHNDB SPROM/OTP"); + if (!bootverbose) + device_quiet(dev); + + /* Refuse wildcard attachments */ + return (BUS_PROBE_NOWILDCARD); +} + +static int +bhndb_pci_sprom_attach(device_t dev) +{ + struct bhndb_pci_sprom_softc *sc; + int error; + + sc = device_get_softc(dev); + sc->dev = dev; + + /* Allocate SPROM resource */ + sc->sprom_rid = 0; + sc->sprom_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->sprom_rid, RF_ACTIVE); + if (sc->sprom_res == NULL) { + device_printf(dev, "failed to allocate resources\n"); + return (ENXIO); + } + + /* Initialize SPROM shadow */ + if ((error = bhnd_sprom_init(&sc->shadow, sc->sprom_res, 0))) { + device_printf(dev, "unrecognized SPROM format\n"); + goto failed; + } + + /* Initialize mutex */ + SPROM_LOCK_INIT(sc); + + return (0); + +failed: + bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid, + sc->sprom_res); + return (error); +} + +static int +bhndb_pci_sprom_resume(device_t dev) +{ + return (0); +} + +static int +bhndb_pci_sprom_suspend(device_t dev) +{ + return (0); +} + +static int +bhndb_pci_sprom_detach(device_t dev) +{ + struct bhndb_pci_sprom_softc *sc; + + sc = device_get_softc(dev); + + bhnd_release_resource(dev, SYS_RES_MEMORY, sc->sprom_rid, + sc->sprom_res); + bhnd_sprom_fini(&sc->shadow); + SPROM_LOCK_DESTROY(sc); + + return (0); +} + +static int +bhndb_pci_sprom_getvar(device_t dev, const char *name, void *buf, size_t *len) +{ + struct bhndb_pci_sprom_softc *sc; + int error; + + sc = device_get_softc(dev); + + SPROM_LOCK(sc); + error = bhnd_sprom_getvar(&sc->shadow, name, buf, len); + SPROM_UNLOCK(sc); + + return (error); +} + +static int +bhndb_pci_sprom_setvar(device_t dev, const char *name, const void *buf, + size_t len) +{ + struct bhndb_pci_sprom_softc *sc; + int error; + + sc = device_get_softc(dev); + + SPROM_LOCK(sc); + error = bhnd_sprom_setvar(&sc->shadow, name, buf, len); + SPROM_UNLOCK(sc); + + return (error); +} + +static device_method_t bhndb_pci_sprom_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, bhndb_pci_sprom_probe), + DEVMETHOD(device_attach, bhndb_pci_sprom_attach), + DEVMETHOD(device_resume, bhndb_pci_sprom_resume), + DEVMETHOD(device_suspend, bhndb_pci_sprom_suspend), + DEVMETHOD(device_detach, bhndb_pci_sprom_detach), + + /* NVRAM interface */ + DEVMETHOD(bhnd_nvram_getvar, bhndb_pci_sprom_getvar), + DEVMETHOD(bhnd_nvram_setvar, bhndb_pci_sprom_setvar), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(bhnd_nvram, bhndb_pci_sprom_driver, bhndb_pci_sprom_methods, sizeof(struct bhndb_pci_sprom_softc)); + +DRIVER_MODULE(bhndb_pci_sprom, bhndb, bhndb_pci_sprom_driver, bhnd_nvram_devclass, NULL, NULL); +MODULE_DEPEND(bhndb_pci_sprom, bhnd, 1, 1, 1); +MODULE_VERSION(bhndb_pci_sprom, 1); Index: head/sys/dev/bhnd/bhndb/bhndb_pcireg.h =================================================================== --- head/sys/dev/bhnd/bhndb/bhndb_pcireg.h +++ head/sys/dev/bhnd/bhndb/bhndb_pcireg.h @@ -205,13 +205,17 @@ #define BHNDB_PCI_SBIM_MASK_SERR 0x4 /* backplane SBErr interrupt mask */ /* BHNDB_PCI_SPROM_CONTROL */ -#define BHNDB_PCI_SPROM_SZ_MSK 0x02 /* SPROM Size Mask */ -#define BHNDB_PCI_SPROM_LOCKED 0x08 /* SPROM Locked */ -#define BHNDB_PCI_SPROM_BLANK 0x04 /* indicating a blank SPROM */ -#define BHNDB_PCI_SPROM_WRITEEN 0x10 /* SPROM write enable */ -#define BHNDB_PCI_SPROM_BOOTROM_WE 0x20 /* external bootrom write enable */ -#define BHNDB_PCI_SPROM_BACKPLANE_EN 0x40 /* Enable indirect backplane access */ -#define BHNDB_PCI_SPROM_OTPIN_USE 0x80 /* device OTP In use */ +#define BHNDB_PCI_SPROM_SZ_MASK 0x03 /**< sprom size mask */ +#define BHNDB_PCI_SPROM_SZ_1KB 0x00 /**< 1KB sprom size */ +#define BHNDB_PCI_SPROM_SZ_4KB 0x01 /**< 4KB sprom size */ +#define BHNDB_PCI_SPROM_SZ_16KB 0x02 /**< 16KB sprom size */ +#define BHNDB_PCI_SPROM_SZ_RESERVED 0x03 /**< unsupported sprom size */ +#define BHNDB_PCI_SPROM_LOCKED 0x08 /**< sprom locked */ +#define BHNDB_PCI_SPROM_BLANK 0x04 /**< sprom blank */ +#define BHNDB_PCI_SPROM_WRITEEN 0x10 /**< sprom write enable */ +#define BHNDB_PCI_SPROM_BOOTROM_WE 0x20 /**< external bootrom write enable */ +#define BHNDB_PCI_SPROM_BACKPLANE_EN 0x40 /**< enable indirect backplane access (BHNDB_PCI_BACKPLANE_*) */ +#define BHNDB_PCI_SPROM_OTPIN_USE 0x80 /**< device OTP in use */ /* PCI (non-PCIe) BHNDB_PCI_GPIO_OUTEN */ Index: head/sys/dev/bhnd/bhndb/bhndb_pcivar.h =================================================================== --- head/sys/dev/bhnd/bhndb/bhndb_pcivar.h +++ head/sys/dev/bhnd/bhndb/bhndb_pcivar.h @@ -51,6 +51,7 @@ struct bhndb_pci_softc { struct bhndb_softc bhndb; /**< parent softc */ device_t dev; /**< bridge device */ + device_t parent; /**< parent PCI device */ bhnd_devclass_t pci_devclass; /**< PCI core's devclass */ bhndb_pci_set_regwin_t set_regwin; /**< regwin handler */ }; Index: head/sys/dev/bhnd/cores/chipc/chipc.c =================================================================== --- head/sys/dev/bhnd/cores/chipc/chipc.c +++ head/sys/dev/bhnd/cores/chipc/chipc.c @@ -52,6 +52,8 @@ #include +#include "bhnd_nvram_if.h" + #include "chipcreg.h" #include "chipcvar.h" @@ -73,13 +75,44 @@ /* Device quirks table */ static struct bhnd_device_quirk chipc_quirks[] = { - { BHND_HWREV_RANGE (0, 21), CHIPC_QUIRK_ALWAYS_HAS_SPROM }, - { BHND_HWREV_EQ (22), CHIPC_QUIRK_SPROM_CHECK_CST_R22 }, - { BHND_HWREV_RANGE (23, 31), CHIPC_QUIRK_SPROM_CHECK_CST_R23 }, - { BHND_HWREV_GTE (35), CHIPC_QUIRK_SUPPORTS_NFLASH }, + { BHND_HWREV_GTE (32), CHIPC_QUIRK_SUPPORTS_SPROM }, + { BHND_HWREV_GTE (35), CHIPC_QUIRK_SUPPORTS_NFLASH }, BHND_DEVICE_QUIRK_END }; +/* Chip-specific quirks table */ +static struct bhnd_chip_quirk chipc_chip_quirks[] = { + /* 4331 12x9 packages */ + {{ BHND_CHIP_IP(4331, 4331TN) }, + CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM + }, + {{ BHND_CHIP_IP(4331, 4331TNA0) }, + CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM + }, + + /* 4331 12x12 packages */ + {{ BHND_CHIP_IPR(4331, 4331TT, HWREV_GTE(1)) }, + CHIPC_QUIRK_4331_EXTPA2_MUX_SPROM + }, + + /* 4331 (all packages/revisions) */ + {{ BHND_CHIP_ID(4331) }, + CHIPC_QUIRK_4331_EXTPA_MUX_SPROM + }, + + /* 4360 family (all revs <= 2) */ + {{ BHND_CHIP_IR(4352, HWREV_LTE(2)) }, + CHIPC_QUIRK_4360_FEM_MUX_SPROM }, + {{ BHND_CHIP_IR(43460, HWREV_LTE(2)) }, + CHIPC_QUIRK_4360_FEM_MUX_SPROM }, + {{ BHND_CHIP_IR(43462, HWREV_LTE(2)) }, + CHIPC_QUIRK_4360_FEM_MUX_SPROM }, + {{ BHND_CHIP_IR(43602, HWREV_LTE(2)) }, + CHIPC_QUIRK_4360_FEM_MUX_SPROM }, + + BHND_CHIP_QUIRK_END +}; + /* quirk and capability flag convenience macros */ #define CHIPC_QUIRK(_sc, _name) \ ((_sc)->quirks & CHIPC_QUIRK_ ## _name) @@ -91,7 +124,13 @@ KASSERT(CHIPC_QUIRK((_sc), name), ("quirk " __STRING(_name) " not set")) #define CHIPC_ASSERT_CAP(_sc, name) \ - KASSERT(CHIPC_CAP((_sc), name), ("capability " __STRING(_name) " not set")) + KASSERT(CHIPC_CAP((_sc), name), ("capability " __STRING(_name) " not set")) + +static bhnd_nvram_src_t chipc_nvram_identify(struct chipc_softc *sc); +static int chipc_sprom_init(struct chipc_softc *); +static int chipc_enable_sprom_pins(struct chipc_softc *); +static int chipc_disable_sprom_pins(struct chipc_softc *); + static int chipc_probe(device_t dev) @@ -119,6 +158,9 @@ sc->dev = dev; sc->quirks = bhnd_device_quirks(dev, chipc_devices, sizeof(chipc_devices[0])); + sc->quirks |= bhnd_chip_quirks(dev, chipc_chip_quirks); + + CHIPC_LOCK_INIT(sc); /* Allocate bus resources */ memcpy(sc->rspec, chipc_rspec, sizeof(sc->rspec)); @@ -152,22 +194,28 @@ sc->caps = bhnd_bus_read_4(sc->core, CHIPC_CAPABILITIES); sc->cst = bhnd_bus_read_4(sc->core, CHIPC_CHIPST); - // TODO - switch (bhnd_chipc_nvram_src(dev)) { - case BHND_NVRAM_SRC_CIS: - device_printf(dev, "NVRAM source: CIS\n"); - break; - case BHND_NVRAM_SRC_SPROM: - device_printf(dev, "NVRAM source: SPROM\n"); - break; + /* Identify NVRAM source */ + sc->nvram_src = chipc_nvram_identify(sc); + + /* Read NVRAM data */ + switch (sc->nvram_src) { case BHND_NVRAM_SRC_OTP: - device_printf(dev, "NVRAM source: OTP\n"); + // TODO (requires access to OTP hardware) + device_printf(sc->dev, "NVRAM-OTP unsupported\n"); break; + case BHND_NVRAM_SRC_NFLASH: - device_printf(dev, "NVRAM source: NFLASH\n"); + // TODO (requires access to NFLASH hardware) + device_printf(sc->dev, "NVRAM-NFLASH unsupported\n"); + break; + + case BHND_NVRAM_SRC_SPROM: + if ((error = chipc_sprom_init(sc))) + goto cleanup; break; - case BHND_NVRAM_SRC_NONE: - device_printf(dev, "NVRAM source: NONE\n"); + + case BHND_NVRAM_SRC_UNKNOWN: + /* Handled externally */ break; } @@ -175,6 +223,7 @@ cleanup: bhnd_release_resources(dev, sc->rspec, sc->res); + CHIPC_LOCK_DESTROY(sc); return (error); } @@ -185,6 +234,9 @@ sc = device_get_softc(dev); bhnd_release_resources(dev, sc->rspec, sc->res); + bhnd_sprom_fini(&sc->sprom); + + CHIPC_LOCK_DESTROY(sc); return (0); } @@ -202,68 +254,64 @@ } /** - * Use device-specific ChipStatus flags to determine the preferred NVRAM - * data source. + * Initialize local SPROM shadow, if required. + * + * @param sc chipc driver state. */ -static bhnd_nvram_src_t -chipc_nvram_src_chipst(struct chipc_softc *sc) +static int +chipc_sprom_init(struct chipc_softc *sc) { - uint8_t nvram_sel; + int error; - CHIPC_ASSERT_QUIRK(sc, SPROM_CHECK_CHIPST); + KASSERT(sc->nvram_src == BHND_NVRAM_SRC_SPROM, + ("non-SPROM source (%u)\n", sc->nvram_src)); - if (CHIPC_QUIRK(sc, SPROM_CHECK_CST_R22)) { - // TODO: On these devices, the official driver code always - // assumes SPROM availability if CHIPC_CST_OTP_SEL is not - // set; we must review against the actual behavior of our - // BCM4312 hardware - nvram_sel = CHIPC_GET_ATTR(sc->cst, CST_SPROM_OTP_SEL_R22); - } else if (CHIPC_QUIRK(sc, SPROM_CHECK_CST_R23)) { - nvram_sel = CHIPC_GET_ATTR(sc->cst, CST_SPROM_OTP_SEL_R23); - } else { - panic("invalid CST OTP/SPROM chipc quirk flags"); - } - device_printf(sc->dev, "querying chipst for 0x%x, 0x%x\n", sc->ccid.chip_id, sc->cst); - - switch (nvram_sel) { - case CHIPC_CST_DEFCIS_SEL: - return (BHND_NVRAM_SRC_CIS); - - case CHIPC_CST_SPROM_SEL: - case CHIPC_CST_OTP_PWRDN: - return (BHND_NVRAM_SRC_SPROM); + /* Enable access to the SPROM */ + CHIPC_LOCK(sc); + if ((error = chipc_enable_sprom_pins(sc))) + goto failed; + + /* Initialize SPROM parser */ + error = bhnd_sprom_init(&sc->sprom, sc->core, CHIPC_SPROM_OTP); + if (error) { + device_printf(sc->dev, "SPROM identification failed: %d\n", + error); - case CHIPC_CST_OTP_SEL: - return (BHND_NVRAM_SRC_OTP); + chipc_disable_sprom_pins(sc); + goto failed; + } - default: - device_printf(sc->dev, "unrecognized OTP/SPROM type 0x%hhx", - nvram_sel); - return (BHND_NVRAM_SRC_NONE); + /* Drop access to the SPROM lines */ + if ((error = chipc_disable_sprom_pins(sc))) { + bhnd_sprom_fini(&sc->sprom); + goto failed; } + CHIPC_UNLOCK(sc); + + return (0); + +failed: + CHIPC_UNLOCK(sc); + return (error); } /** - * Determine the preferred NVRAM data source. + * Determine the NVRAM data source for this device. + * + * @param sc chipc driver state. */ static bhnd_nvram_src_t -chipc_nvram_src(device_t dev) +chipc_nvram_identify(struct chipc_softc *sc) { - struct chipc_softc *sc; uint32_t srom_ctrl; - sc = device_get_softc(dev); - - /* Very early devices always included a SPROM */ - if (CHIPC_QUIRK(sc, ALWAYS_HAS_SPROM)) - return (BHND_NVRAM_SRC_SPROM); - - /* Most other early devices require checking ChipStatus flags */ - if (CHIPC_QUIRK(sc, SPROM_CHECK_CHIPST)) - return (chipc_nvram_src_chipst(sc)); + /* Very early devices vend SPROM/OTP/CIS (if at all) via the + * host bridge interface instead of ChipCommon. */ + if (!CHIPC_QUIRK(sc, SUPPORTS_SPROM)) + return (BHND_NVRAM_SRC_UNKNOWN); /* - * Later chipset revisions standardized the NVRAM capability flags and + * Later chipset revisions standardized the SPROM capability flags and * register interfaces. * * We check for hardware presence in order of precedence. For example, @@ -287,7 +335,158 @@ return (BHND_NVRAM_SRC_NFLASH); /* No NVRAM hardware capability declared */ - return (BHND_NVRAM_SRC_NONE); + return (BHND_NVRAM_SRC_UNKNOWN); +} + + +/** + * If required by this device, enable access to the SPROM. + * + * @param sc chipc driver state. + */ +static int +chipc_enable_sprom_pins(struct chipc_softc *sc) +{ + uint32_t cctrl; + + CHIPC_LOCK_ASSERT(sc, MA_OWNED); + + /* Nothing to do? */ + if (!CHIPC_QUIRK(sc, MUX_SPROM)) + return (0); + + cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL); + + /* 4331 devices */ + if (CHIPC_QUIRK(sc, 4331_EXTPA_MUX_SPROM)) { + cctrl &= ~CHIPC_CCTRL4331_EXTPA_EN; + + if (CHIPC_QUIRK(sc, 4331_GPIO2_5_MUX_SPROM)) + cctrl &= ~CHIPC_CCTRL4331_EXTPA_ON_GPIO2_5; + + if (CHIPC_QUIRK(sc, 4331_EXTPA2_MUX_SPROM)) + cctrl &= ~CHIPC_CCTRL4331_EXTPA_EN2; + + bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl); + return (0); + } + + /* 4360 devices */ + if (CHIPC_QUIRK(sc, 4360_FEM_MUX_SPROM)) { + /* Unimplemented */ + } + + /* Refuse to proceed on unsupported devices with muxed SPROM pins */ + device_printf(sc->dev, "muxed sprom lines on unrecognized device\n"); + return (ENXIO); +} + +/** + * If required by this device, revert any GPIO/pin configuration applied + * to allow SPROM access. + * + * @param sc chipc driver state. + */ +static int +chipc_disable_sprom_pins(struct chipc_softc *sc) +{ + uint32_t cctrl; + + CHIPC_LOCK_ASSERT(sc, MA_OWNED); + + /* Nothing to do? */ + if (!CHIPC_QUIRK(sc, MUX_SPROM)) + return (0); + + cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL); + + /* 4331 devices */ + if (CHIPC_QUIRK(sc, 4331_EXTPA_MUX_SPROM)) { + cctrl |= CHIPC_CCTRL4331_EXTPA_EN; + + if (CHIPC_QUIRK(sc, 4331_GPIO2_5_MUX_SPROM)) + cctrl |= CHIPC_CCTRL4331_EXTPA_ON_GPIO2_5; + + if (CHIPC_QUIRK(sc, 4331_EXTPA2_MUX_SPROM)) + cctrl |= CHIPC_CCTRL4331_EXTPA_EN2; + + bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl); + return (0); + } + + /* 4360 devices */ + if (CHIPC_QUIRK(sc, 4360_FEM_MUX_SPROM)) { + /* Unimplemented */ + } + + /* Refuse to proceed on unsupported devices with muxed SPROM pins */ + device_printf(sc->dev, "muxed sprom lines on unrecognized device\n"); + return (ENXIO); +} + +static bhnd_nvram_src_t +chipc_nvram_src(device_t dev) +{ + struct chipc_softc *sc = device_get_softc(dev); + return (sc->nvram_src); +} + +static int +chipc_nvram_getvar(device_t dev, const char *name, void *buf, size_t *len) +{ + struct chipc_softc *sc; + int error; + + sc = device_get_softc(dev); + + switch (sc->nvram_src) { + case BHND_NVRAM_SRC_SPROM: + CHIPC_LOCK(sc); + error = bhnd_sprom_getvar(&sc->sprom, name, buf, len); + CHIPC_UNLOCK(sc); + return (error); + + case BHND_NVRAM_SRC_OTP: + case BHND_NVRAM_SRC_NFLASH: + /* Currently unsupported */ + return (ENXIO); + + case BHND_NVRAM_SRC_UNKNOWN: + return (ENODEV); + } + + /* Unknown NVRAM source */ + return (ENODEV); +} + +static int +chipc_nvram_setvar(device_t dev, const char *name, const void *buf, + size_t len) +{ + struct chipc_softc *sc; + int error; + + sc = device_get_softc(dev); + + switch (sc->nvram_src) { + case BHND_NVRAM_SRC_SPROM: + CHIPC_LOCK(sc); + error = bhnd_sprom_setvar(&sc->sprom, name, buf, len); + CHIPC_UNLOCK(sc); + return (error); + + case BHND_NVRAM_SRC_OTP: + case BHND_NVRAM_SRC_NFLASH: + /* Currently unsupported */ + return (ENXIO); + + case BHND_NVRAM_SRC_UNKNOWN: + default: + return (ENODEV); + } + + /* Unknown NVRAM source */ + return (ENODEV); } static device_method_t chipc_methods[] = { @@ -301,6 +500,10 @@ /* ChipCommon interface */ DEVMETHOD(bhnd_chipc_nvram_src, chipc_nvram_src), + /* NVRAM interface */ + DEVMETHOD(bhnd_nvram_getvar, chipc_nvram_getvar), + DEVMETHOD(bhnd_nvram_setvar, chipc_nvram_setvar), + DEVMETHOD_END }; Index: head/sys/dev/bhnd/cores/chipc/chipcreg.h =================================================================== --- head/sys/dev/bhnd/cores/chipc/chipcreg.h +++ head/sys/dev/bhnd/cores/chipc/chipcreg.h @@ -36,26 +36,12 @@ #define CHIPC_GET_ATTR(_entry, _attr) \ ((_entry & CHIPC_ ## _attr ## _MASK) >> CHIPC_ ## _attr ## _SHIFT) -#define CHIPC_ID 0x0 -#define CHIPC_CAPABILITIES 0x04 -#define CHIPC_CHIPST 0x2c -#define CHIPC_EROMPTR 0xfc /**< 32-bit EROM base address - * on BCMA devices */ - -/** chipid */ -#define CHIPC_ID 0x0 /**< identification register */ -#define CHIPC_ID_CHIP_MASK 0x0000FFFF /**< chip id */ -#define CHIPC_ID_CHIP_SHIFT 0 -#define CHIPC_ID_REV_MASK 0x000F0000 /**< chip revision */ -#define CHIPC_ID_REV_SHIFT 16 -#define CHIPC_ID_PKG_MASK 0x00F00000 /**< physical package ID */ -#define CHIPC_ID_PKG_SHIFT 20 -#define CHIPC_ID_NUMCORE_MASK 0x0F000000 /**< number of cores on chip (rev >= 4) */ -#define CHIPC_ID_NUMCORE_SHIFT 24 -#define CHIPC_ID_BUS_MASK 0xF0000000 /**< chip/interconnect type (BHND_CHIPTYPE_*) */ -#define CHIPC_ID_BUS_SHIFT 28 +#define CHIPC_ID 0x0 +#define CHIPC_CAPABILITIES 0x04 #define CHIPC_OTPST 0x10 +#define CHIPC_CHIPCTRL 0x28 /**< chip control */ +#define CHIPC_CHIPST 0x2c /**< chip status */ #define CHIPC_JTAGCMD 0x30 #define CHIPC_JTAGIR 0x34 #define CHIPC_JTAGDR 0x38 @@ -76,6 +62,8 @@ #define CHIPC_CLKC_M3 0xa0 #define CHIPC_CLKDIV 0xa4 #define CHIPC_SYS_CLK_CTL 0xc0 +#define CHIPC_EROMPTR 0xfc /**< 32-bit EROM base address + * on BCMA devices */ #define CHIPC_SPROM_CTRL 0x190 /**< SPROM interface (rev >= 32) */ #define CHIPC_SPROM_ADDR 0x194 #define CHIPC_SPROM_DATA 0x198 @@ -95,6 +83,19 @@ #define CHIPC_PMU_PLL_CONTROL_DATA 0x664 #define CHIPC_SPROM_OTP 0x800 /* SPROM/OTP address space */ +/** chipid */ +#define CHIPC_ID 0x0 /**< identification register */ +#define CHIPC_ID_CHIP_MASK 0x0000FFFF /**< chip id */ +#define CHIPC_ID_CHIP_SHIFT 0 +#define CHIPC_ID_REV_MASK 0x000F0000 /**< chip revision */ +#define CHIPC_ID_REV_SHIFT 16 +#define CHIPC_ID_PKG_MASK 0x00F00000 /**< physical package ID */ +#define CHIPC_ID_PKG_SHIFT 20 +#define CHIPC_ID_NUMCORE_MASK 0x0F000000 /**< number of cores on chip (rev >= 4) */ +#define CHIPC_ID_NUMCORE_SHIFT 24 +#define CHIPC_ID_BUS_MASK 0xF0000000 /**< chip/interconnect type (BHND_CHIPTYPE_*) */ +#define CHIPC_ID_BUS_SHIFT 28 + /* capabilities */ #define CHIPC_CAP_UARTS_MASK 0x00000003 /* Number of UARTs */ #define CHIPC_CAP_MIPSEB 0x00000004 /* MIPS is in big-endian mode */ @@ -1124,6 +1125,7 @@ #define CHIPC_CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /* override core control on pipe_AuxPowerDown */ #define CHIPC_CCTRL4331_PCIE_AUXCLKEN (1<<10) /* pcie_auxclkenable */ #define CHIPC_CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /* pcie_pipe_pllpowerdown */ +#define CHIPC_CCTRL4331_EXTPA_EN2 (1<<12) /* 0 ext pa2 disable, 1 ext pa2 enabled */ #define CHIPC_CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /* enable bt_shd0 at gpio4 */ #define CHIPC_CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /* enable bt_shd1 at gpio5 */ Index: head/sys/dev/bhnd/cores/chipc/chipcvar.h =================================================================== --- head/sys/dev/bhnd/cores/chipc/chipcvar.h +++ head/sys/dev/bhnd/cores/chipc/chipcvar.h @@ -32,6 +32,8 @@ #ifndef _BHND_CORES_CHIPC_CHIPCVAR_H_ #define _BHND_CORES_CHIPC_CHIPCVAR_H_ +#include + #include "chipc.h" DECLARE_CLASS(bhnd_chipc); @@ -45,37 +47,64 @@ */ enum { /** No quirks */ - CHIPC_QUIRK_NONE = 0, + CHIPC_QUIRK_NONE = 0, /** - * The device always provides an external SROM. + * ChipCommon-controlled SPROM/OTP is supported, along with the + * CHIPC_CAP_SPROM capability flag. */ - CHIPC_QUIRK_ALWAYS_HAS_SPROM = (1<<1), - - + CHIPC_QUIRK_SUPPORTS_SPROM = (1<<1), + /** - * SROM availability must be determined through chip-specific - * ChipStatus flags. + * External NAND NVRAM is supported, along with the CHIPC_CAP_NFLASH + * capability flag. */ - CHIPC_QUIRK_SPROM_CHECK_CHIPST = (1<<3), + CHIPC_QUIRK_SUPPORTS_NFLASH = (1<<2), /** - * Use the rev22 chipstatus register format when determining SPROM - * availability. + * The SPROM is attached via muxed pins. The pins must be switched + * to allow reading/writing. */ - CHIPC_QUIRK_SPROM_CHECK_CST_R22 = (1<<4)|CHIPC_QUIRK_SPROM_CHECK_CHIPST, + CHIPC_QUIRK_MUX_SPROM = (1<<3), /** - * Use the rev23 chipstatus register format when determining SPROM - * availability. + * Access to the SPROM uses pins shared with the 802.11a external PA. + * + * On modules using these 4331 packages, the CCTRL4331_EXTPA_EN flag + * must be cleared to allow SPROM access. */ - CHIPC_QUIRK_SPROM_CHECK_CST_R23 = (1<<5)|CHIPC_QUIRK_SPROM_CHECK_CHIPST, + CHIPC_QUIRK_4331_EXTPA_MUX_SPROM = (1<<4) | + CHIPC_QUIRK_MUX_SPROM, /** - * External NAND NVRAM is supported, along with the CHIPC_CAP_NFLASH - * capability flag. + * Access to the SPROM uses pins shared with the 802.11a external PA. + * + * On modules using these 4331 chip packages, the external PA is + * attached via GPIO 2, 5, and sprom_dout pins. + * + * When enabling and disabling EXTPA to allow SPROM access, the + * CCTRL4331_EXTPA_ON_GPIO2_5 flag must also be set or cleared, + * respectively. + */ + CHIPC_QUIRK_4331_GPIO2_5_MUX_SPROM = (1<<5) | + CHIPC_QUIRK_4331_EXTPA_MUX_SPROM, + + /** + * Access to the SPROM uses pins shared with two 802.11a external PAs. + * + * When enabling and disabling EXTPA, the CCTRL4331_EXTPA_EN2 must also + * be cleared to allow SPROM access. */ - CHIPC_QUIRK_SUPPORTS_NFLASH = (1<<6), + CHIPC_QUIRK_4331_EXTPA2_MUX_SPROM = (1<<6) | + CHIPC_QUIRK_4331_EXTPA_MUX_SPROM, + + + /** + * SPROM pins are muxed with the FEM control lines on this 4360-family + * device. The muxed pins must be switched to allow reading/writing + * the SPROM. + */ + CHIPC_QUIRK_4360_FEM_MUX_SPROM = (1<<5) | CHIPC_QUIRK_MUX_SPROM }; struct chipc_softc { @@ -89,6 +118,19 @@ uint32_t quirks; /**< CHIPC_QUIRK_* quirk flags */ uint32_t caps; /**< CHIPC_CAP_* capability register flags */ uint32_t cst; /**< CHIPC_CST* status register flags */ + bhnd_nvram_src_t nvram_src; /**< NVRAM source */ + + struct mtx mtx; /**< state mutex. */ + + struct bhnd_sprom sprom; /**< OTP/SPROM shadow, if any */ }; +#define CHIPC_LOCK_INIT(sc) \ + mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \ + "BHND chipc driver lock", MTX_DEF) +#define CHIPC_LOCK(sc) mtx_lock(&(sc)->mtx) +#define CHIPC_UNLOCK(sc) mtx_unlock(&(sc)->mtx) +#define CHIPC_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what) +#define CHIPC_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx) + #endif /* _BHND_CORES_CHIPC_CHIPCVAR_H_ */ \ No newline at end of file Index: head/sys/dev/bhnd/nvram/bhnd_nvram.h =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_nvram.h +++ head/sys/dev/bhnd/nvram/bhnd_nvram.h @@ -36,10 +36,6 @@ * NVRAM data sources supported by bhnd(4) devices. */ typedef enum { - BHND_NVRAM_SRC_CIS, /**< Default CIS source; this may - * apply, for example, to PCMCIA cards - * vending Broadcom NVRAM data via - * their standard CIS table. */ BHND_NVRAM_SRC_OTP, /**< On-chip one-time-programmable * memory. */ @@ -51,15 +47,36 @@ * NVRAM. */ BHND_NVRAM_SRC_SPROM, /**< External serial EEPROM. */ - BHND_NVRAM_SRC_NONE /**< No NVRAM source is directly - * attached. This is used on devices - * attached via PCI(e) to BHND SoCs, - * where to avoid unnecessary flash - * hardware, NVRAM configuration for - * individual devices is provided by - * hardware attached to the SoC - * itself. + BHND_NVRAM_SRC_UNKNOWN /**< No NVRAM source is directly + * attached. + * + * This will be returned by ChipCommon + * revisions (rev <= 31) used in early + * chipsets that vend SPROM/OTP via the + * native host bridge interface. + * + * For example, PCMCIA cards may vend + * Broadcom NVRAM data via their standard CIS + * table, and earlier PCI(e) devices map + * SPROM statically into PCI BARs, and the + * control registers into PCI config space. + + * This will also be returned on later + * devices that are attached via PCI(e) to + * BHND SoCs, but do not include an attached + * SPROM, or programmed OTP. On such SoCs, + * NVRAM configuration for individual devices + * is provided by a common platform NVRAM + * device. */ } bhnd_nvram_src_t; +/** + * Evaluates to true if the given NVRAM data source is accessible via + * ChipCommon. + */ +#define BHND_NVRAM_SRC_CC(_src) \ + ((_src) == BHND_NVRAM_SRC_OTP || (_src) == BHND_NVRAM_SRC_SPROM) + + #endif /* _BHND_NVRAM_BHND_NVRAM_H_ */ \ No newline at end of file Index: head/sys/dev/bhnd/nvram/bhnd_nvram_if.m =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_nvram_if.m +++ head/sys/dev/bhnd/nvram/bhnd_nvram_if.m @@ -46,13 +46,16 @@ * @param[out] buf On success, the requested value will be written * to this buffer. This argment may be NULL if * the value is not desired. - * @param[in,out] size The capacity of @p buf. On success, will be set - * to the actual size of the requested value. + * @param[in,out] len The maximum capacity of @p buf. On success, + * will be set to the actual size of the requested + * value. * * @retval 0 success * @retval ENOENT The requested variable was not found. - * @retval ENOMEM If @p buf is non-NULL and a buffer of @p size is too + * @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too * small to hold the requested value. + * @retval ENODEV If no supported NVRAM hardware is accessible via this + * device. * @retval non-zero If reading @p name otherwise fails, a regular unix * error code will be returned. */ @@ -60,5 +63,30 @@ device_t dev; const char *name; void *buf; - size_t *size; -}; \ No newline at end of file + size_t *len; +}; + +/** + * Set an NVRAM variable's local value. + * + * No changes should be written to non-volatile storage. + * + * @param dev The NVRAM device. + * @param name The NVRAM variable name. + * @param buf The new value. + * @param len The size of @p buf. + * + * @retval 0 success + * @retval ENOENT The specified variable name is not recognized. + * @retval EINVAL If @p len does not match the expected variable size. + * @retval ENODEV If no supported NVRAM hardware is accessible via this + * device. + * @retval non-zero If reading @p name otherwise fails, a regular unix + * error code will be returned. + */ +METHOD int setvar { + device_t dev; + const char *name; + const void *buf; + size_t len; +}; Index: head/sys/dev/bhnd/nvram/bhnd_sprom.c =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_sprom.c +++ head/sys/dev/bhnd/nvram/bhnd_sprom.c @@ -0,0 +1,572 @@ +/*- + * Copyright (c) 2015 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "nvramvar.h" + +#include "bhnd_spromreg.h" +#include "bhnd_spromvar.h" + +/* + * BHND SPROM Parsing + * + * Provides identification and parsing of BHND SPROM data. + */ + +static int sprom_direct_read(struct bhnd_sprom *sc, size_t offset, + void *buf, size_t nbytes, uint8_t *crc); +static int sprom_extend_shadow(struct bhnd_sprom *sc, size_t image_size, + uint8_t *crc); +static int sprom_populate_shadow(struct bhnd_sprom *sc); + +static int sprom_var_defn(struct bhnd_sprom *sc, const char *name, + const struct bhnd_nvram_var **var, + const struct bhnd_sprom_var **sprom, size_t *size); + +/* SPROM revision is always located at the second-to-last byte */ +#define SPROM_REV(_sc) SPROM_READ_1((_sc), (_sc)->sp_size - 2) + +/* SPROM CRC is always located at the last byte */ +#define SPROM_CRC_OFF(_sc) SPROM_CRC_LEN(_sc) + +/* SPROM CRC covers all but the final CRC byte */ +#define SPROM_CRC_LEN(_sc) ((_sc)->sp_size - 1) + +/* SPROM shadow I/O (with byte-order translation) */ +#define SPROM_READ_1(_sc, _off) SPROM_READ_ENC_1(_sc, _off) +#define SPROM_READ_2(_sc, _off) le16toh(SPROM_READ_ENC_2(_sc, _off)) +#define SPROM_READ_4(_sc, _off) le32toh(SPROM_READ_ENC_4(_sc, _off)) + +#define SPROM_WRITE_1(_sc, _off, _v) SPROM_WRITE_ENC_1(_sc, _off, (_v)) +#define SPROM_WRITE_2(_sc, _off, _v) SPROM_WRITE_ENC_2(_sc, _off, \ + htole16(_v)) +#define SPROM_WRITE_4(_sc, _off, _v) SPROM_WRITE_ENC_4(_sc, _off, \ + htole32(_v)) + +/* SPROM shadow I/O (without byte-order translation) */ +#define SPROM_READ_ENC_1(_sc, _off) (*(uint8_t *)((_sc)->sp_shadow + _off)) +#define SPROM_READ_ENC_2(_sc, _off) (*(uint16_t *)((_sc)->sp_shadow + _off)) +#define SPROM_READ_ENC_4(_sc, _off) (*(uint32_t *)((_sc)->sp_shadow + _off)) + +#define SPROM_WRITE_ENC_1(_sc, _off, _v) \ + *((uint8_t *)((_sc)->sp_shadow + _off)) = (_v) +#define SPROM_WRITE_ENC_2(_sc, _off, _v) \ + *((uint16_t *)((_sc)->sp_shadow + _off)) = (_v) +#define SPROM_WRITE_ENC_4(_sc, _off, _v) \ + *((uint32_t *)((_sc)->sp_shadow + _off)) = (_v) + +/* Call @p _next macro with the C type, widened (signed or unsigned) C + * type, and width associated with @p _dtype */ +#define SPROM_SWITCH_TYPE(_dtype, _next, ...) \ +do { \ + switch (_dtype) { \ + case BHND_NVRAM_DT_UINT8: \ + _next (uint8_t, uint32_t, 1, \ + ## __VA_ARGS__); \ + break; \ + case BHND_NVRAM_DT_UINT16: \ + _next (uint16_t, uint32_t, 2, \ + ## __VA_ARGS__); \ + break; \ + case BHND_NVRAM_DT_UINT32: \ + _next (uint32_t, uint32_t, 4, \ + ## __VA_ARGS__); \ + break; \ + case BHND_NVRAM_DT_INT8: \ + _next (int8_t, int32_t, 1, \ + ## __VA_ARGS__); \ + break; \ + case BHND_NVRAM_DT_INT16: \ + _next (int16_t, int32_t, 2, \ + ## __VA_ARGS__); \ + break; \ + case BHND_NVRAM_DT_INT32: \ + _next (int32_t, int32_t, 4, \ + ## __VA_ARGS__); \ + break; \ + case BHND_NVRAM_DT_CHAR: \ + _next (uint8_t, uint32_t, 1, \ + ## __VA_ARGS__); \ + break; \ + } \ +} while (0) + +/* + * Table of supported SPROM image formats, sorted by image size, ascending. + */ +#define SPROM_FMT(_sz, _revmin, _revmax, _sig) \ + { SPROM_SZ_ ## _sz, _revmin, _revmax, \ + SPROM_SIG_ ## _sig ## _OFF, \ + SPROM_SIG_ ## _sig } + +static const struct sprom_fmt { + size_t size; + uint8_t rev_min; + uint8_t rev_max; + size_t sig_offset; + uint16_t sig_req; +} sprom_fmts[] = { + SPROM_FMT(R1_3, 1, 3, NONE), + SPROM_FMT(R4_8_9, 4, 4, R4), + SPROM_FMT(R4_8_9, 8, 9, R8_9), + SPROM_FMT(R10, 10, 10, R10), + SPROM_FMT(R11, 11, 11, R11) +}; + +/** + * Identify the SPROM format at @p offset within @p r, verify the CRC, + * and allocate a local shadow copy of the SPROM data. + * + * After successful initialization, @p r will not be accessed; any pin + * configuration required for SPROM access may be reset. + * + * @param[out] sprom On success, will be initialized with shadow of the SPROM + * data. + * @param r An active resource mapping the SPROM data. + * @param offset Offset of the SPROM data within @p resource. + */ +int +bhnd_sprom_init(struct bhnd_sprom *sprom, struct bhnd_resource *r, + bus_size_t offset) +{ + bus_size_t res_size; + int error; + + sprom->dev = rman_get_device(r->res); + sprom->sp_res = r; + sprom->sp_res_off = offset; + + /* Determine maximum possible SPROM image size */ + res_size = rman_get_size(r->res); + if (offset >= res_size) + return (EINVAL); + + sprom->sp_size_max = MIN(res_size - offset, SPROM_SZ_MAX); + + /* Allocate and populate SPROM shadow */ + sprom->sp_size = 0; + sprom->sp_capacity = sprom->sp_size_max; + sprom->sp_shadow = malloc(sprom->sp_capacity, M_BHND, M_NOWAIT); + if (sprom->sp_shadow == NULL) + return (ENOMEM); + + /* Read and identify SPROM image */ + if ((error = sprom_populate_shadow(sprom))) + return (error); + + return (0); +} + +/** + * Release all resources held by @p sprom. + * + * @param sprom A SPROM instance previously initialized via bhnd_sprom_init(). + */ +void +bhnd_sprom_fini(struct bhnd_sprom *sprom) +{ + free(sprom->sp_shadow, M_BHND); +} + +/* Perform a read using a SPROM offset descriptor, safely widening the + * result to its 32-bit representation before assigning it to @p _dest. */ +#define SPROM_GETVAR_READ(_type, _widen, _width, _sc, _off, _dest) \ +do { \ + _type _v = (_type)SPROM_READ_ ## _width(_sc, _off->offset); \ + if (_off->shift > 0) { \ + _v >>= _off->shift; \ + } else if (off->shift < 0) { \ + _v <<= -_off->shift; \ + } \ + _dest = ((uint32_t) (_widen) _v) & _off->mask; \ +} while(0) + +/* Emit a value read using a SPROM offset descriptor, narrowing the + * result output representation and, if necessary, OR'ing it with the + * previously read value from @p _buf. */ +#define SPROM_GETVAR_WRITE(_type, _widen, _width, _off, _src, _buf) \ +do { \ + _type _v = (_type) (_widen) _src; \ + if (_off->cont) \ + _v |= *((_type *)_buf); \ + *((_type *)_buf) = _v; \ +} while(0) + +/** + * Read a SPROM variable, performing conversion to host byte order. + * + * @param sc The SPROM parser state. + * @param name The SPROM variable name. + * @param[out] buf On success, the requested value will be written + * to this buffer. This argment may be NULL if + * the value is not desired. + * @param[in,out] len The capacity of @p buf. On success, will be set + * to the actual size of the requested value. + * + * @retval 0 success + * @retval ENOENT The requested variable was not found. + * @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too + * small to hold the requested value. + * @retval non-zero If reading @p name otherwise fails, a regular unix + * error code will be returned. + */ +int +bhnd_sprom_getvar(struct bhnd_sprom *sc, const char *name, void *buf, + size_t *len) +{ + const struct bhnd_nvram_var *nv; + const struct bhnd_sprom_var *sv; + size_t all1_offs; + size_t req_size; + int error; + + if ((error = sprom_var_defn(sc, name, &nv, &sv, &req_size))) + return (error); + + /* Provide required size */ + if (buf == NULL) { + *len = req_size; + return (0); + } + + /* Check (and update) target buffer len */ + if (*len < req_size) + return (ENOMEM); + else + *len = req_size; + + /* Read data */ + all1_offs = 0; + for (size_t i = 0; i < sv->num_offsets; i++) { + const struct bhnd_sprom_offset *off; + uint32_t val; + + off = &sv->offsets[i]; + KASSERT(!off->cont || i > 0, ("cont marked on first offset")); + + /* If not a continuation, advance the output buffer */ + if (i > 0 && !off->cont) { + buf = ((uint8_t *)buf) + + bhnd_nvram_type_width(sv->offsets[i-1].type); + } + + /* Read the value, widening to a common uint32 + * representation */ + SPROM_SWITCH_TYPE(off->type, SPROM_GETVAR_READ, sc, off, val); + + /* If IGNALL1, record whether value has all bits set. */ + if (nv->flags & BHND_NVRAM_VF_IGNALL1) { + uint32_t all1; + + all1 = off->mask; + if (off->shift > 0) + all1 >>= off->shift; + else if (off->shift < 0) + all1 <<= -off->shift; + + if ((val & all1) == all1) + all1_offs++; + } + + /* Write the value, narrowing to the appropriate output + * width. */ + SPROM_SWITCH_TYPE(nv->type, SPROM_GETVAR_WRITE, off, val, buf); + } + + /* Should value should be treated as uninitialized? */ + if (nv->flags & BHND_NVRAM_VF_IGNALL1 && all1_offs == sv->num_offsets) + return (ENOENT); + + return (0); +} + +/* Perform a read of a variable offset from _src, safely widening the result + * to its 32-bit representation before assigning it to @p + * _dest. */ +#define SPROM_SETVAR_READ(_type, _widen, _width, _off, _src, _dest) \ +do { \ + _type _v = *(const _type *)_src; \ + if (_off->shift > 0) { \ + _v <<= _off->shift; \ + } else if (off->shift < 0) { \ + _v >>= -_off->shift; \ + } \ + _dest = ((uint32_t) (_widen) _v) & _off->mask; \ +} while(0) + + +/* Emit a value read using a SPROM offset descriptor, narrowing the + * result output representation and, if necessary, OR'ing it with the + * previously read value from @p _buf. */ +#define SPROM_SETVAR_WRITE(_type, _widen, _width, _sc, _off, _src) \ +do { \ + _type _v = (_type) (_widen) _src; \ + if (_off->cont) \ + _v |= SPROM_READ_ ## _width(_sc, _off->offset); \ + SPROM_WRITE_ ## _width(_sc, _off->offset, _v); \ +} while(0) + +/** + * Set a local value for a SPROM variable, performing conversion to SPROM byte + * order. + * + * The new value will be written to the backing SPROM shadow. + * + * @param sc The SPROM parser state. + * @param name The SPROM variable name. + * @param[out] buf The new value. + * @param[in,out] len The size of @p buf. + * + * @retval 0 success + * @retval ENOENT The requested variable was not found. + * @retval EINVAL If @p len does not match the expected variable size. + */ +int +bhnd_sprom_setvar(struct bhnd_sprom *sc, const char *name, const void *buf, + size_t len) +{ + const struct bhnd_nvram_var *nv; + const struct bhnd_sprom_var *sv; + size_t req_size; + int error; + uint8_t crc; + + if ((error = sprom_var_defn(sc, name, &nv, &sv, &req_size))) + return (error); + + /* Provide required size */ + if (len != req_size) + return (EINVAL); + + /* Write data */ + for (size_t i = 0; i < sv->num_offsets; i++) { + const struct bhnd_sprom_offset *off; + uint32_t val; + + off = &sv->offsets[i]; + KASSERT(!off->cont || i > 0, ("cont marked on first offset")); + + /* If not a continuation, advance the input pointer */ + if (i > 0 && !off->cont) { + buf = ((const uint8_t *)buf) + + bhnd_nvram_type_width(sv->offsets[i-1].type); + } + + /* Read the value, widening to a common uint32 + * representation */ + SPROM_SWITCH_TYPE(nv->type, SPROM_SETVAR_READ, off, buf, val); + + /* Write the value, narrowing to the appropriate output + * width. */ + SPROM_SWITCH_TYPE(off->type, SPROM_SETVAR_WRITE, sc, off, val); + } + + /* Update CRC */ + crc = ~bhnd_nvram_crc8(sc->sp_shadow, SPROM_CRC_LEN(sc), + BHND_NVRAM_CRC8_INITIAL); + SPROM_WRITE_1(sc, SPROM_CRC_OFF(sc), crc); + + return (0); +} + +/* Read and identify the SPROM image by incrementally performing + * read + CRC of all supported image formats */ +static int +sprom_populate_shadow(struct bhnd_sprom *sc) +{ + const struct sprom_fmt *fmt; + int error; + uint16_t sig; + uint8_t srom_rev; + uint8_t crc; + + crc = BHND_NVRAM_CRC8_INITIAL; + + /* Identify the SPROM revision (and populate the SPROM shadow) */ + for (size_t i = 0; i < nitems(sprom_fmts); i++) { + fmt = &sprom_fmts[i]; + + /* Read image data and check CRC */ + if ((error = sprom_extend_shadow(sc, fmt->size, &crc))) + return (error); + + /* Skip on invalid CRC */ + if (crc != BHND_NVRAM_CRC8_VALID) + continue; + + /* Fetch SROM revision */ + srom_rev = SPROM_REV(sc); + + /* Early sromrev 1 devices (specifically some BCM440x enet + * cards) are reported to have been incorrectly programmed + * with a revision of 0x10. */ + if (fmt->size == SPROM_SZ_R1_3 && srom_rev == 0x10) + srom_rev = 0x1; + + /* Verify revision range */ + if (srom_rev < fmt->rev_min || srom_rev > fmt->rev_max) + continue; + + /* Verify signature (if any) */ + sig = SPROM_SIG_NONE; + if (fmt->sig_offset != SPROM_SIG_NONE_OFF) + sig = SPROM_READ_2(sc, fmt->sig_offset); + + if (sig != fmt->sig_req) { + device_printf(sc->dev, + "invalid sprom %hhu signature: 0x%hx " + "(expected 0x%hx)\n", + srom_rev, sig, fmt->sig_req); + return (EINVAL); + } + + /* Identified */ + sc->sp_rev = srom_rev; + return (0); + } + + /* identification failed */ + device_printf(sc->dev, "unrecognized sprom format\n"); + return (EINVAL); +} + +/* + * Extend the shadowed SPROM buffer to image_size, reading any required + * data from the backing SPROM resource and updating the CRC. + */ +static int +sprom_extend_shadow(struct bhnd_sprom *sc, size_t image_size, + uint8_t *crc) +{ + int error; + + KASSERT(image_size >= sc->sp_size, (("shadow truncation unsupported"))); + + /* Verify the request fits within our shadow buffer */ + if (image_size > sc->sp_capacity) + return (ENOSPC); + + /* Skip no-op requests */ + if (sc->sp_size == image_size) + return (0); + + /* Populate the extended range */ + error = sprom_direct_read(sc, sc->sp_size, sc->sp_shadow + sc->sp_size, + image_size - sc->sp_size, crc); + if (error) + return (error); + + sc->sp_size = image_size; + return (0); +} + +/** + * Read nbytes at the given offset from the backing SPROM resource, and + * update the CRC. + */ +static int +sprom_direct_read(struct bhnd_sprom *sc, size_t offset, void *buf, + size_t nbytes, uint8_t *crc) +{ + bus_size_t res_offset; + size_t nread; + uint16_t *p; + + KASSERT(nbytes % sizeof(uint16_t) == 0, ("unaligned sprom size")); + KASSERT(offset % sizeof(uint16_t) == 0, ("unaligned sprom offset")); + + /* Check for read overrun */ + if (offset >= sc->sp_size_max || sc->sp_size_max - offset < nbytes) { + device_printf(sc->dev, "requested SPROM read would overrun\n"); + return (EINVAL); + } + + p = (uint16_t *)buf; + res_offset = sc->sp_res_off + offset; + + /* Perform read */ + for (nread = 0; nread < nbytes; nread += 2) { + *p = bhnd_bus_read_stream_2(sc->sp_res, res_offset+nread); + *crc = bhnd_nvram_crc8(p, sizeof(*p), *crc); + p++; + }; + + return (0); +} + + +/** + * Locate the variable and SPROM revision-specific definitions + * for variable with @p name. + */ +static int +sprom_var_defn(struct bhnd_sprom *sc, const char *name, + const struct bhnd_nvram_var **var, + const struct bhnd_sprom_var **sprom, + size_t *size) +{ + /* Find variable definition */ + *var = bhnd_nvram_var_defn(name); + if (*var == NULL) + return (ENOENT); + + /* Find revision-specific SPROM definition */ + for (size_t i = 0; i < (*var)->num_sp_descs; i++) { + const struct bhnd_sprom_var *sp = &(*var)->sprom_descs[i]; + + if (sc->sp_rev < sp->compat.first) + continue; + + if (sc->sp_rev > sp->compat.last) + continue; + + /* Found */ + *sprom = sp; + + /* Calculate size in bytes */ + *size = bhnd_nvram_type_width((*var)->type) * sp->num_offsets; + return (0); + } + + /* Not supported by this SPROM revision */ + return (ENOENT); +} \ No newline at end of file Index: head/sys/dev/bhnd/nvram/bhnd_spromreg.h =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_spromreg.h +++ head/sys/dev/bhnd/nvram/bhnd_spromreg.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _BHND_NVRAM_SPROMREG_H_ +#define _BHND_NVRAM_SPROMREG_H_ + +#define SPROM_SZ_R1_3 128 /**< SPROM image size (rev 1-3) */ +#define SPROM_SZ_R4_8_9 440 /**< SPROM image size (rev 4, 8-9) */ +#define SPROM_SZ_R10 460 /**< SPROM image size (rev 10) */ +#define SPROM_SZ_R11 468 /**< SPROM image size (rev 11) */ + +/** Maximum supported SPROM image size */ +#define SPROM_SZ_MAX SPROM_SZ_R11 + +#define SPROM_SIG_NONE 0x0 +#define SPROM_SIG_NONE_OFF 0x0 + +/** SPROM signature (rev 4) */ +#define SPROM_SIG_R4 0x5372 +#define SPROM_SIG_R4_OFF 64 /**< SPROM signature offset (rev 4) */ + +/** SPROM signature (rev 8, 9) */ +#define SPROM_SIG_R8_9 SPROM_SIG_R4 +#define SPROM_SIG_R8_9_OFF 128 /**< SPROM signature offset (rev 8-9) */ + +/** SPROM signature (rev 10) */ +#define SPROM_SIG_R10 SPROM_SIG_R4 +#define SPROM_SIG_R10_OFF 438 /**< SPROM signature offset (rev 10) */ + +/** SPROM signature (rev 11) */ +#define SPROM_SIG_R11 0x0634 +#define SPROM_SIG_R11_OFF 128 /**< SPROM signature offset (rev 11) */ + + +#endif /* _BHND_NVRAM_SPROMREG_H_ */ Index: head/sys/dev/bhnd/nvram/bhnd_spromvar.h =================================================================== --- head/sys/dev/bhnd/nvram/bhnd_spromvar.h +++ head/sys/dev/bhnd/nvram/bhnd_spromvar.h @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2015-2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _BHND_NVRAM_BHND_SPROM_H_ +#define _BHND_NVRAM_BHND_SPROM_H_ + +struct bhnd_sprom { + device_t dev; /**< sprom parent device */ + + uint8_t sp_rev; /**< sprom revision */ + + struct bhnd_resource *sp_res; /**< sprom resource. */ + bus_size_t sp_res_off; /**< offset to sprom image */ + + uint8_t *sp_shadow; /**< sprom shadow */ + bus_size_t sp_size_max; /**< maximum possible sprom length */ + size_t sp_size; /**< shadow size */ + size_t sp_capacity; /**< shadow buffer capacity */ +}; + +int bhnd_sprom_init(struct bhnd_sprom *sprom, struct bhnd_resource *r, + bus_size_t offset); +void bhnd_sprom_fini(struct bhnd_sprom *sprom); + +int bhnd_sprom_getvar(struct bhnd_sprom *sc, const char *name, void *buf, + size_t *len); +int bhnd_sprom_setvar(struct bhnd_sprom *sc, const char *name, + const void *buf, size_t len); + +#endif /* _BHND_NVRAM_BHND_SPROM_H_ */ Index: head/sys/dev/bhnd/nvram/nvram_map =================================================================== --- head/sys/dev/bhnd/nvram/nvram_map +++ head/sys/dev/bhnd/nvram/nvram_map @@ -0,0 +1,1445 @@ +#- +# Copyright (c) 2015-2016 Landon Fuller +# Copyright (C) 2008-2015, Broadcom Corporation. +# All Rights Reserved. +# +# The contents of this file (variable names, descriptions, and offsets) were +# extracted or derived from Broadcom's ISC-licensed sources. +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# $FreeBSD$ + +# +# NVRAM variable definitions and revision-specific SPROM offsets. +# +# Processed by nvram_map_gen.awk to produce bhnd_nvram_map.h +# +# NOTE: file was originally generated automatically by using libclang +# to analyze and extract format information and descriptions from Broadcom's +# available ISC-licensed CIS and SROM code and associated headers. +# + +# Antennas available +u8 aa2g { + srom 1-3 0x5C (&0x30, >>4) + srom 4-7 0x5D + srom 8-10 0x9D + srom >= 11 0xA1 +} +u8 aa5g { + srom 1-3 0x5C (&0xC0, >>6) + srom 4-7 0x5C + srom 8-10 0x9C + srom >= 11 0xA0 +} + +# ACPHY PA trimming parameters: 40 +u16[12] pa5gbw40a0 { + srom >= 11 0x110 +} + +# ACPHY PA trimming parameters: 80 +u16[12] pa5gbw80a0 { + srom >= 11 0x138 +} + +# ACPHY PA trimming parameters: 40/80 +u16[12] pa5gbw4080a0 { + srom >= 11 0x138 +} +u16[12] pa5gbw4080a1 { + srom >= 11 u16 0xB6, u16 0xBC, u16 0xCE, u16 0xD4, u16[8] 0x128 +} + +# ACPHY PA trimming parameters: CCK +u16[3] pa2gccka0 { + srom >= 11 0x102 +} + +# ACPHY Power-per-rate 2gpo +u16 dot11agofdmhrbw202gpo { + srom >= 11 0x15C +} +u16 ofdmlrbw202gpo { + srom >= 11 0x15E +} + +# ACPHY Power-per-rate 5gpo +u32 mcsbw805glpo { + srom >= 11 0x168 +} +u32 mcsbw805gmpo { + srom >= 11 0x178 +} +u32 mcsbw805ghpo { + srom >= 11 0x188 +} +u16 mcslr5glpo { + srom >= 11 0x190 (&0xFFF) +} +u16 mcslr5gmpo { + srom >= 11 0x192 +} +u16 mcslr5ghpo { + srom >= 11 0x194 +} + +# ACPHY Power-per-rate sbpo +u16 sb20in40hrpo { + srom >= 11 0x196 +} +u16 sb20in80and160hr5glpo { + srom >= 11 0x198 +} +u16 sb40and80hr5glpo { + srom >= 11 0x19A +} +u16 sb20in80and160hr5gmpo { + srom >= 11 0x19C +} +u16 sb40and80hr5gmpo { + srom >= 11 0x19E +} +u16 sb20in80and160hr5ghpo { + srom >= 11 0x1A0 +} +u16 sb40and80hr5ghpo { + srom >= 11 0x1A2 +} +u16 sb20in40lrpo { + srom >= 11 0x1A4 +} +u16 sb20in80and160lr5glpo { + srom >= 11 0x1A6 +} +u16 sb40and80lr5glpo { + srom >= 11 0x1A8 +} +u16 sb20in80and160lr5gmpo { + srom >= 11 0x1AA +} +u16 sb40and80lr5gmpo { + srom >= 11 0x1AC +} +u16 sb20in80and160lr5ghpo { + srom >= 11 0x1AE +} +u16 sb40and80lr5ghpo { + srom >= 11 0x1B0 +} +u16 dot11agduphrpo { + srom >= 11 0x1B2 +} +u16 dot11agduplrpo { + srom >= 11 0x1B4 +} + +# Antenna gain +u8 ag0 { + srom 1-3 0x75 + srom 4-7 0x5F + srom 8-10 0x9F +} +u8 ag1 { + srom 1-3 0x74 + srom 4-7 0x5E + srom 8-10 0x9E +} +u8 ag2 { + srom 4-7 0x61 + srom 8-10 0xA1 +} +u8 ag3 { + srom 4-7 0x60 + srom 8-10 0xA0 +} + +u8 agbg0 { + srom >= 11 0xA2 +} +u8 agbg1 { + srom >= 11 0xA3 +} +u8 agbg2 { + srom >= 11 0xA4 +} +u8 aga0 { + srom >= 11 0xA5 +} +u8 aga1 { + srom >= 11 0xA6 +} +u8 aga2 { + srom >= 11 0xA7 +} + +# board flags +u32 boardflags { + srom 1 u16 0x72 + srom 2 u16 0x72 | u16 0x38 (<<16) + srom 3 u16 0x72 | u16 0x7A (<<16) + srom 4 0x44 + srom 5-7 0x4A + srom >= 8 0x84 +} +u32 boardflags2 { + srom 4 0x48 + srom 5-7 0x4E + srom >= 8 0x88 +} +u32 boardflags3 { + srom >= 11 0x8C +} + +# board serial number, independent of mac addr +u16 boardnum { + srom 1-2 0x4C + srom 3 0x4E + srom 4 0x50 + srom 5-7 0x56 + srom 8-10 0x90 + srom >= 11 0x94 +} + +# One byte board revision +u16 boardrev { + srom 1-3 u8 0x5D + srom 4-7 0x42 + srom >= 8 0x82 +} + +# 2 bytes; boardtype +u16 boardtype { + srom >= 2 0x4 +} + +# Default country code (sromrev == 1) +u8 cc { + srom 1 0x5C (&0xF) +} + +# 2 bytes each +# CCK Power offsets for 20 MHz rates (11, 5.5, 2, 1Mbps) +# cckbw202gpo cckbw20ul2gpo +# +u16 cckbw202gpo { + srom 9-10 0x140 + srom >= 11 0x150 +} +u16 cckbw20ul2gpo { + srom 9-10 0x142 + srom >= 11 0x152 +} + +# Country code (2 bytes ascii + 1 byte cctl) +# in rev 2 +# +char[2] ccode { + sfmt ccode + srom 0-3 0x76 + srom 4 0x52 + srom 5-7 0x44 + srom 8-10 0x92 + srom >= 11 0x96 +} + +# 2 byte; txchain, rxchain +u8 txchain { + all1 ignore + srom 4-7 0x7B (&0xF) + srom 8-10 0xA3 (&0xF) + srom >= 11 0xA9 (&0xF) +} +u8 rxchain { + all1 ignore + srom 4-7 0x7B (&0xF0, >>4) + srom 8-10 0xA3 (&0xF0, >>4) + srom >= 11 0xA9 (&0xF0, >>4) +} +u16 antswitch { + all1 ignore + srom 4-7 u8 0x7A + srom 8-10 u8 0xA2 + srom >= 11 u8 0xA8 +} + +# PCI device id +private u16 devid { + srom >= 8 u16 0x60 +} + +u8 elna2g { + srom 8-10 0xBB +} + +u8 elna5g { + srom 8-10 0xBA +} + +# 11n front-end specification +u8 antswctl2g { + srom 8-10 0xAE (&0xF8, >>3) +} +u8 triso2g { + srom 8-10 0xAE (&0x7) +} +u8 pdetrange2g { + srom 8-10 0xAF (&0xF8, >>3) +} +u8 extpagain2g { + srom 8-10 0xAF (&0x6, >>1) +} +u8 tssipos2g { + srom 8-10 0xAF (&0x1) +} +u8 antswctl5g { + srom 8-10 0xB0 (&0xF8, >>3) +} +u8 triso5g { + srom 8-10 0xB0 (&0x7) +} +u8 pdetrange5g { + srom 8-10 0xB1 (&0xF8, >>3) +} +u8 extpagain5g { + srom 8-10 0xB1 (&0x6, >>1) +} +u8 tssipos5g { + srom 8-10 0xB1 (&0x1) +} + +# FEM config +u8 femctrl { + sfmt decimal + srom >= 11 0xAA (&0xF8, >>3) +} +u8 papdcap2g { + sfmt decimal + srom >= 11 0xAA (&0x4, >>2) +} +u8 tworangetssi2g { + sfmt decimal + srom >= 11 0xAA (&0x2, >>1) +} +u8 pdgain2g { + sfmt decimal + srom >= 11 u16 0xAA (&0x1F0, >>4) +} +u8 epagain2g { + sfmt decimal + srom >= 11 0xAB (&0xE, >>1) +} +u8 tssiposslope2g { + sfmt decimal + srom >= 11 0xAB (&0x1) +} +u8 gainctrlsph { + sfmt decimal + srom >= 11 0xAC (&0xF8, >>3) +} +u8 papdcap5g { + sfmt decimal + srom >= 11 0xAC (&0x4, >>2) +} +u8 tworangetssi5g { + sfmt decimal + srom >= 11 0xAC (&0x2, >>1) +} +u8 pdgain5g { + sfmt decimal + srom >= 11 u16 0xAC (&0x1F0, >>4) +} +u8 epagain5g { + sfmt decimal + srom >= 11 0xAD (&0xE, >>1) +} +u8 tssiposslope5g { + sfmt decimal + srom >= 11 0xAD (&0x1) +} + +# LED duty cycle +u8[2] leddc { + sfmt led_dc + all1 ignore + srom 3 0x7C + srom 4 0x5A + srom 5-7 0x5A + srom 8-10 0x9A + srom >= 11 0x9E +} + +# LED set +u8 ledbh0 { + all1 ignore + srom 1-3 0x65 + srom 4 0x57 + srom 5-7 0x77 + srom 8-10 0x97 + srom >= 11 0x9B +} +u8 ledbh1 { + all1 ignore + srom 1-3 0x64 + srom 4 0x56 + srom 5-7 0x76 + srom 8-10 0x96 + srom >= 11 0x9A +} +u8 ledbh2 { + all1 ignore + srom 1-3 0x67 + srom 4 0x59 + srom 5-7 0x79 + srom 8-10 0x99 + srom >= 11 0x9D +} +u8 ledbh3 { + all1 ignore + srom 1-3 0x66 + srom 4 0x58 + srom 5-7 0x78 + srom 8-10 0x98 + srom >= 11 0x9C +} + +# 2 bytes total +# Additional power offset for Legacy Dup40 transmissions. +# Applied in addition to legofdmbw20ulXpo, X=2g, 5gl, 5gm, or 5gh. +# LSB nibble: 2G band, MSB nibble: 5G band high subband. +# leg40dup5ghpo, leg40dup5gmpo, leg40dup5glpo, leg40dup2gpo +# +u16 legofdm40duppo { + srom 9-10 0x196 +} + +# 4 bytes each +# OFDM power offsets for 20 MHz Legacy rates +# (54, 48, 36, 24, 18, 12, 9, 6 Mbps) +# legofdmbw202gpo legofdmbw20ul2gpo +# +u32 legofdmbw202gpo { + srom 9-10 0x144 +} +u32 legofdmbw20ul2gpo { + srom 9-10 0x148 +} + +# 4 bytes each +# 5G band: OFDM power offsets for 20 MHz Legacy rates +# (54, 48, 36, 24, 18, 12, 9, 6 Mbps) +# low subband : legofdmbw205glpo legofdmbw20ul2glpo +# mid subband :legofdmbw205gmpo legofdmbw20ul2gmpo +# high subband :legofdmbw205ghpo legofdmbw20ul2ghpo +# +u32 legofdmbw205glpo { + srom 9-10 0x14C +} +u32 legofdmbw20ul5glpo { + srom 9-10 0x150 +} +u32 legofdmbw205gmpo { + srom 9-10 0x154 +} +u32 legofdmbw20ul5gmpo { + srom 9-10 0x158 +} +u32 legofdmbw205ghpo { + srom 9-10 0x15C +} +u32 legofdmbw20ul5ghpo { + srom 9-10 0x160 +} + +# mac addr override for the standard CIS LAN_NID +u8[6] macaddr { + sfmt macaddr + srom 3 u8 0x4B, u8 0x4A, u8 0x4D, u8 0x4C, u8 0x4F, u8 0x4E + srom 4 u8 0x4D, u8 0x4C, u8 0x4F, u8 0x4E, u8 0x51, u8 0x50 + srom 5-7 u8 0x53, u8 0x52, u8 0x55, u8 0x54, u8 0x57, u8 0x56 + srom 8-10 u8 0x8D, u8 0x8C, u8 0x8F, u8 0x8E, u8 0x91, u8 0x90 + srom >= 11 u8 0x91, u8 0x90, u8 0x93, u8 0x92, u8 0x95, u8 0x94 +} + +# 4 bytes each +# mcs 0-7 power-offset. LSB nibble: m0, MSB nibble: m7 +# mcsbw202gpo mcsbw20ul2gpo mcsbw402gpo +# +u32 mcsbw202gpo { + srom 9-10 0x164 + srom >= 11 0x154 +} +u32 mcsbw20ul2gpo { + srom 9-10 0x168 +} +u32 mcsbw402gpo { + srom 9-10 0x16C + srom >= 11 0x158 +} + +# 4 bytes each +# 5G high subband mcs 0-7 power-offset. +# LSB nibble: m0, MSB nibble: m7 +# mcsbw205ghpo mcsbw20ul5ghpo mcsbw405ghpo +# +u32 mcsbw205ghpo { + srom 9-10 0x188 + srom >= 11 0x180 +} +u32 mcsbw20ul5ghpo { + srom 9-10 0x18C +} +u32 mcsbw405ghpo { + srom 9-10 0x190 + srom >= 11 0x184 +} + +# 4 bytes each +# 5G low subband mcs 0-7 power-offset. +# LSB nibble: m0, MSB nibble: m7 +# mcsbw205glpo mcsbw20ul5glpo mcsbw405glpo +# +u32 mcsbw205glpo { + srom 9-10 0x170 + srom >= 11 0x160 +} +u32 mcsbw20ul5glpo { + srom 9-10 0x174 +} +u32 mcsbw405glpo { + srom 9-10 0x178 + srom >= 11 0x164 +} + +# 4 bytes each +# 5G mid subband mcs 0-7 power-offset. +# LSB nibble: m0, MSB nibble: m7 +# mcsbw205gmpo mcsbw20ul5gmpo mcsbw405gmpo +# +u32 mcsbw205gmpo { + srom 9-10 0x17C + srom >= 11 0x170 +} +u32 mcsbw20ul5gmpo { + srom 9-10 0x180 +} +u32 mcsbw405gmpo { + srom 9-10 0x184 + srom >= 11 0x174 +} + +# 2 bytes total +# mcs-32 power offset for each band/subband. +# LSB nibble: 2G band, MSB nibble: +# mcs322ghpo, mcs325gmpo, mcs325glpo, mcs322gpo +# +u16 mcs32po { + srom 9-10 0x194 +} + +u8 measpower { + srom 8-10 0xB4 (&0xFE, >>1) + srom >= 11 0xB0 (&0xFE, >>1) +} +u8 measpower1 { + srom 8-10 0xBF (&0x7F) + srom >= 11 0xBB (&0x7F) +} +u8 measpower2 { + srom 8-10 u16 0xBE (&0x3F80, >>7) + srom >= 11 u16 0xBA (&0x3F80, >>7) +} +u16 rawtempsense { + srom 8-10 0xB4 (&0x1FF) + srom >= 11 0xB0 (&0x1FF) +} + +u8 noiselvl2ga0 { + sfmt decimal + srom 8-10 0x1AB (&0x1F) + srom >= 11 0x1BD (&0x1F) +} +u8 noiselvl2ga1 { + sfmt decimal + srom 8-10 u16 0x1AA (&0x3E0, >>5) + srom >= 11 u16 0x1BC (&0x3E0, >>5) +} +u8 noiselvl2ga2 { + sfmt decimal + srom 8-10 0x1AA (&0x7C, >>2) + srom >= 11 0x1BC (&0x7C, >>2) +} +u8[4] noiselvl5ga0 { + sfmt decimal + srom >= 11 u8 0x1BF (&0x1F), u8 0x1C1 (&0x1F), u8 0x1C3 (&0x1F), u8 0x1C5 (&0x1F) +} +u8[4] noiselvl5ga1 { + sfmt decimal + srom >= 11 u16[4] 0x1BE (&0x3E0, >>5) +} +u8[4] noiselvl5ga2 { + sfmt decimal + srom >= 11 u8 0x1BE (&0x7C, >>2), u8 0x1C0 (&0x7C, >>2), u8 0x1C2 (&0x7C, >>2), u8 0x1C4 (&0x7C, >>2) +} + +# paparambwver +u8 paparambwver { + sfmt decimal + srom >= 11 0x190 (&0xF0, >>4) +} + +# PA parameters: 8 (sromrev == 1) +# or 9 (sromrev > 1) bytes +# +u16 pa0b0 { + sfmt decimal + srom 1-3 0x5E + srom 8-10 0xC2 +} +u16 pa0b1 { + sfmt decimal + srom 1-3 0x60 + srom 8-10 0xC4 +} +u16 pa0b2 { + sfmt decimal + srom 1-3 0x62 + srom 8-10 0xC6 +} +u8 pa0itssit { + sfmt decimal + srom 1-3 0x71 + srom 8-10 0xC0 +} +u8 pa0maxpwr { + sfmt decimal + srom 1-3 0x69 + srom 8-10 0xC1 +} +u8 opo { + srom 2-3 0x79 + srom 8-10 0x143 +} + +# 5G PA params +u16 pa1b0 { + sfmt decimal + srom 1-3 0x6A + srom 8-10 0xCC +} +u16 pa1b1 { + sfmt decimal + srom 1-3 0x6C + srom 8-10 0xCE +} +u16 pa1b2 { + sfmt decimal + srom 1-3 0x6E + srom 8-10 0xD0 +} +u16 pa1lob0 { + sfmt decimal + srom 2-3 0x3C + srom 8-10 0xD2 +} +u16 pa1lob1 { + sfmt decimal + srom 2-3 0x3E + srom 8-10 0xD4 +} +u16 pa1lob2 { + sfmt decimal + srom 2-3 0x40 + srom 8-10 0xD6 +} +u16 pa1hib0 { + sfmt decimal + srom 2-3 0x42 + srom 8-10 0xD8 +} +u16 pa1hib1 { + sfmt decimal + srom 2-3 0x44 + srom 8-10 0xDA +} +u16 pa1hib2 { + sfmt decimal + srom 2-3 0x46 + srom 8-10 0xDC +} +u8 pa1itssit { + sfmt decimal + srom 1-3 0x70 + srom 8-10 0xC8 +} +u8 pa1maxpwr { + sfmt decimal + srom 1-3 0x68 + srom 8-10 0xC9 +} +u8 pa1lomaxpwr { + sfmt decimal + srom 2-3 0x3A + srom 8-10 0xCA +} +u8 pa1himaxpwr { + sfmt decimal + srom 2-3 0x3B + srom 8-10 0xCB +} + +u16 pdoffset40ma0 { + srom >= 11 0xCA +} +u16 pdoffset40ma1 { + srom >= 11 0xCC +} +u16 pdoffset40ma2 { + srom >= 11 0xCE +} +u16 pdoffset80ma0 { + srom >= 11 0xD0 +} +u16 pdoffset80ma1 { + srom >= 11 0xD2 +} +u16 pdoffset80ma2 { + srom >= 11 0xD4 +} + +u8 pdoffset2g40ma0 { + srom >= 11 0xC9 (&0xF) +} +u8 pdoffset2g40ma1 { + srom >= 11 0xC9 (&0xF0, >>4) +} +u8 pdoffset2g40ma2 { + srom >= 11 0xC8 (&0xF) +} +u8 pdoffset2g40mvalid { + srom >= 11 0xC8 (&0x80, >>7) +} + +# 40Mhz channel 2g/5g power offset +u16 bw40po { + srom 4-7 0x18E + srom 8 0x196 +} + +# 40Mhz channel dup 2g/5g power offset +u16 bwduppo { + srom 4-7 0x190 + srom 8 0x198 +} + +# cck2g/ofdm2g/ofdm5g power offset +u16 cck2gpo { + srom 4-7 0x138 + srom 8 0x140 +} +u32 ofdm2gpo { + srom 4-7 0x13A + srom 8 0x142 +} +u32 ofdm5gpo { + srom 4-7 0x13E + srom 8 0x146 +} +u32 ofdm5glpo { + srom 4-7 0x142 + srom 8 0x14A +} +u32 ofdm5ghpo { + srom 4-7 0x146 + srom 8 0x14E +} + +# cdd2g/5g power offset +u16 cddpo { + srom 4-7 0x18A + srom 8 0x192 +} + +# mcs2g power offset +u16 mcs2gpo0 { + srom 4-7 0x14A + srom 8 0x152 +} +u16 mcs2gpo1 { + srom 4-7 0x14C + srom 8 0x154 +} +u16 mcs2gpo2 { + srom 4-7 0x14E + srom 8 0x156 +} +u16 mcs2gpo3 { + srom 4-7 0x150 + srom 8 0x158 +} +u16 mcs2gpo4 { + srom 4-7 0x152 + srom 8 0x15A +} +u16 mcs2gpo5 { + srom 4-7 0x154 + srom 8 0x15C +} +u16 mcs2gpo6 { + srom 4-7 0x156 + srom 8 0x15E +} +u16 mcs2gpo7 { + srom 4-7 0x158 + srom 8 0x160 +} + +# mcs5g low-high band power offset +u16 mcs5glpo0 { + srom 4-7 0x16A + srom 8 0x172 +} +u16 mcs5glpo1 { + srom 4-7 0x16C + srom 8 0x174 +} +u16 mcs5glpo2 { + srom 4-7 0x16E + srom 8 0x176 +} +u16 mcs5glpo3 { + srom 4-7 0x170 + srom 8 0x178 +} +u16 mcs5glpo4 { + srom 4-7 0x172 + srom 8 0x17A +} +u16 mcs5glpo5 { + srom 4-7 0x174 + srom 8 0x17C +} +u16 mcs5glpo6 { + srom 4-7 0x176 + srom 8 0x17E +} +u16 mcs5glpo7 { + srom 4-7 0x178 + srom 8 0x180 +} +u16 mcs5ghpo0 { + srom 4-7 0x17A + srom 8 0x182 +} +u16 mcs5ghpo1 { + srom 4-7 0x17C + srom 8 0x184 +} +u16 mcs5ghpo2 { + srom 4-7 0x17E + srom 8 0x186 +} +u16 mcs5ghpo3 { + srom 4-7 0x180 + srom 8 0x188 +} +u16 mcs5ghpo4 { + srom 4-7 0x182 + srom 8 0x18A +} +u16 mcs5ghpo5 { + srom 4-7 0x184 + srom 8 0x18C +} +u16 mcs5ghpo6 { + srom 4-7 0x186 + srom 8 0x18E +} +u16 mcs5ghpo7 { + srom 4-7 0x188 + srom 8 0x190 +} + +# mcs5g mid band power offset +u16 mcs5gpo0 { + srom 4-7 0x15A + srom 8 0x162 +} +u16 mcs5gpo1 { + srom 4-7 0x15C + srom 8 0x164 +} +u16 mcs5gpo2 { + srom 4-7 0x15E + srom 8 0x166 +} +u16 mcs5gpo3 { + srom 4-7 0x160 + srom 8 0x168 +} +u16 mcs5gpo4 { + srom 4-7 0x162 + srom 8 0x16A +} +u16 mcs5gpo5 { + srom 4-7 0x164 + srom 8 0x16C +} +u16 mcs5gpo6 { + srom 4-7 0x166 + srom 8 0x16E +} +u16 mcs5gpo7 { + srom 4-7 0x168 + srom 8 0x170 +} + +# stbc2g/5g power offset +u16 stbcpo { + srom 4-7 0x18C + srom 8 0x194 +} + +u8 regrev { + srom 3 0x78 + srom 4 0x55 + srom 5-7 0x47 + srom 8-10 0x95 + srom >= 11 0x99 +} + +# 4328 2G RSSI mid pt sel & board switch arch, +# 2 bytes, rev 3. +# +u8 rssismf2g { + srom 3 0x51 (&0xF) + srom 8-10 0xA5 (&0xF) +} +u8 rssismc2g { + srom 3 0x51 (&0xF0, >>4) + srom 8-10 0xA5 (&0xF0, >>4) +} +u8 rssisav2g { + srom 3 0x50 (&0x7) + srom 8-10 0xA4 (&0x7) +} +u8 bxa2g { + srom 3 0x50 (&0x18, >>3) + srom 8-10 0xA4 (&0x18, >>3) +} + +# 4328 5G RSSI mid pt sel & board switch arch, +# 2 bytes, rev 3. +# +u8 rssismf5g { + srom 3 0x53 (&0xF) + srom 8-10 0xA7 (&0xF) +} +u8 rssismc5g { + srom 3 0x53 (&0xF0, >>4) + srom 8-10 0xA7 (&0xF0, >>4) +} +u8 rssisav5g { + srom 3 0x52 (&0x7) + srom 8-10 0xA6 (&0x7) +} +u8 bxa5g { + srom 3 0x52 (&0x18, >>3) + srom 8-10 0xA6 (&0x18, >>3) +} + +u8 rxgainerr2ga0 { + srom 8-10 0x19B (&0x3F) + srom >= 11 0x1C7 (&0x3F) +} +u8 rxgainerr2ga1 { + srom 8-10 u16 0x19A (&0x7C0, >>6) + srom >= 11 u16 0x1C6 (&0x7C0, >>6) +} +u8 rxgainerr2ga2 { + srom 8-10 0x19A (&0xF8, >>3) + srom >= 11 0x1C6 (&0xF8, >>3) +} +u8[4] rxgainerr5ga0 { + srom >= 11 u8 0x1C9 (&0x3F), u8 0x1CB (&0x3F), u8 0x1CD (&0x3F), u8 0x1CF (&0x3F) +} +u8[4] rxgainerr5ga1 { + srom >= 11 u16[4] 0x1C8 (&0x7C0, >>6) +} +u8[4] rxgainerr5ga2 { + srom >= 11 u8 0x1C8 (&0xF8, >>3), u8 0x1CA (&0xF8, >>3), u8 0x1CC (&0xF8, >>3), u8 0x1CE (&0xF8, >>3) +} +u8 rxgainerr5gha0 { + srom 8-10 0x1A1 (&0x3F) +} +u8 rxgainerr5gha1 { + srom 8-10 u16 0x1A0 (&0x7C0, >>6) +} +u8 rxgainerr5gha2 { + srom 8-10 0x1A0 (&0xF8, >>3) +} +u8 rxgainerr5gla0 { + srom 8-10 0x19D (&0x3F) +} +u8 rxgainerr5gla1 { + srom 8-10 u16 0x19C (&0x7C0, >>6) +} +u8 rxgainerr5gla2 { + srom 8-10 0x19C (&0xF8, >>3) +} +u8 rxgainerr5gma0 { + srom 8-10 0x19F (&0x3F) +} +u8 rxgainerr5gma1 { + srom 8-10 u16 0x19E (&0x7C0, >>6) +} +u8 rxgainerr5gma2 { + srom 8-10 0x19E (&0xF8, >>3) +} +u8 rxgainerr5gua0 { + srom 8-10 0x1A3 (&0x3F) +} +u8 rxgainerr5gua1 { + srom 8-10 u16 0x1A2 (&0x7C0, >>6) +} +u8 rxgainerr5gua2 { + srom 8-10 0x1A2 (&0xF8, >>3) +} + +# 4328 2G RX power offset +i8 rxpo2g { + sfmt decimal + srom 3 0x5B + srom 8-10 0xAD +} + +# 4328 5G RX power offset +i8 rxpo5g { + sfmt decimal + srom 3 0x5A + srom 8-10 0xAC +} + +u16 subband5gver { + srom 8-10 u8 0x1A5 (&0x7) + srom >= 11 0xD6 +} + +# 2 bytes +# byte1 tempthresh +# byte2 period(msb 4 bits) | hysterisis(lsb 4 bits) +# +u8 tempthresh { + srom 8-10 0xB2 + srom >= 11 0xAE +} +u8 temps_period { + sfmt decimal + srom 8-10 0xBC (&0xF) + srom >= 11 0xB8 (&0xF) +} +u8 temps_hysteresis { + sfmt decimal + srom 8-10 0xBC (&0xF0, >>4) + srom >= 11 0xB8 (&0xF0, >>4) +} +u8 tempoffset { + sfmt decimal + srom 8-10 0xB3 + srom >= 11 0xAF +} +u8 tempsense_slope { + srom 8-10 0xB7 + srom >= 11 0xB3 +} +u8 tempcorrx { + srom 8-10 0xB6 (&0xFC, >>2) + srom >= 11 0xB2 (&0xFC, >>2) +} +u8 tempsense_option { + srom 8-10 0xB6 (&0x3) + srom >= 11 0xB2 (&0x3) +} +u8 phycal_tempdelta { + sfmt decimal + srom 8-10 0xBD + srom >= 11 0xB9 +} + +# 4328 2G TR isolation, 1 byte +u8 tri2g { + srom 3 0x55 + srom 8-10 0xA9 +} + +# 4328 5G TR isolation, 3 bytes +u8 tri5gl { + srom 3 0x57 + srom 8-10 0xAB +} +u8 tri5g { + srom 3 0x54 + srom 8-10 0xA8 +} +u8 tri5gh { + srom 3 0x56 + srom 8-10 0xAA +} + +# phy txbf rpcalvars +u16 rpcal2g { + srom >= 11 0x16C +} +u16 rpcal5gb0 { + srom >= 11 0x16E +} +u16 rpcal5gb1 { + srom >= 11 0x17C +} +u16 rpcal5gb2 { + srom >= 11 0x17E +} +u16 rpcal5gb3 { + srom >= 11 0x18C +} + +# Crystal frequency in kilohertz +u32 xtalfreq { + sfmt decimal + srom >= 11 u16 0xB4 +} + +# N-PHY tx power workaround +u8 txpid2ga0 { + srom 4-7 0x63 +} +u8 txpid2ga1 { + srom 4-7 0x62 +} +u8 txpid2ga2 { + srom 4-7 0x65 +} +u8 txpid2ga3 { + srom 4-7 0x64 +} +u8 txpid5ga0 { + srom 4-7 0x67 +} +u8 txpid5ga1 { + srom 4-7 0x66 +} +u8 txpid5ga2 { + srom 4-7 0x69 +} +u8 txpid5ga3 { + srom 4-7 0x68 +} +u8 txpid5gha0 { + srom 4-7 0x6F +} +u8 txpid5gha1 { + srom 4-7 0x6E +} +u8 txpid5gha2 { + srom 4-7 0x71 +} +u8 txpid5gha3 { + srom 4-7 0x70 +} +u8 txpid5gla0 { + srom 4-7 0x6B +} +u8 txpid5gla1 { + srom 4-7 0x6A +} +u8 txpid5gla2 { + srom 4-7 0x6D +} +u8 txpid5gla3 { + srom 4-7 0x6C +} + +u16 cckPwrOffset { + srom 10 0x1B4 +} +u8[6] et1macaddr { + sfmt macaddr + srom 0-2 u8 0x55, u8 0x54, u8 0x57, u8 0x56, u8 0x59, u8 0x58 +} +u8 eu_edthresh2g { + srom 8 0x1A9 + srom 9 0x199 + srom 10 0x199 + srom 11 0x1D1 +} +u8 eu_edthresh5g { + srom 8 0x1A8 + srom 9 0x198 + srom 10 0x198 + srom 11 0x1D0 +} +u8 freqoffset_corr { + srom 8-10 0xB9 (&0xF) +} +u8 hw_iqcal_en { + srom 8-10 0xB9 (&0x20, >>5) +} +u8[6] il0macaddr { + sfmt macaddr + srom 0-2 u8 0x49, u8 0x48, u8 0x51, u8 0x50, u8 0x53, u8 0x52 +} +u8 iqcal_swp_dis { + srom 8-10 0xB9 (&0x10, >>4) +} + +u8 noisecaloffset { + srom 8-9 0x1B5 +} +u8 noisecaloffset5g { + srom 8-9 0x1B4 +} +u8 noiselvl5gha0 { + srom 8-10 0x1B1 (&0x1F) +} +u8 noiselvl5gha1 { + srom 8-10 u16 0x1B0 (&0x3E0, >>5) +} +u8 noiselvl5gha2 { + srom 8-10 0x1B0 (&0x7C, >>2) +} +u8 noiselvl5gla0 { + srom 8-10 0x1AD (&0x1F) +} +u8 noiselvl5gla1 { + srom 8-10 u16 0x1AC (&0x3E0, >>5) +} +u8 noiselvl5gla2 { + srom 8-10 0x1AC (&0x7C, >>2) +} +u8 noiselvl5gma0 { + srom 8-10 0x1AF (&0x1F) +} +u8 noiselvl5gma1 { + srom 8-10 u16 0x1AE (&0x3E0, >>5) +} +u8 noiselvl5gma2 { + srom 8-10 0x1AE (&0x7C, >>2) +} +u8 noiselvl5gua0 { + srom 8-10 0x1B3 (&0x1F) +} +u8 noiselvl5gua1 { + srom 8-10 u16 0x1B2 (&0x3E0, >>5) +} +u8 noiselvl5gua2 { + srom 8-10 0x1B2 (&0x7C, >>2) +} + +u8 pcieingress_war { + srom 8-10 0x1A7 (&0xF) +} + +u8 pdoffsetcckma0 { + srom >= 11 0x18F (&0xF) +} +u8 pdoffsetcckma1 { + srom >= 11 0x18F (&0xF0, >>4) +} +u8 pdoffsetcckma2 { + srom >= 11 0x18E (&0xF) +} + +u8 sar2g { + srom 9-10 0x1A9 + srom >= 11 0x1BB +} +u8 sar5g { + srom 9-10 0x1A8 + srom >= 11 0x1BA +} + +u16 subvid { + srom >= 2 0x6 +} + +u32[5] swctrlmap_2g { + srom 10 u32[4] 0x1B8, u16 0x1C8 +} + +u16 tssifloor2g { + srom >= 11 0xBE (&0x3FF) +} +u16[4] tssifloor5g { + srom >= 11 0xC0 (&0x3FF) +} + +u8 txidxcap2g { + srom >= 11 u16 0x1A8 (&0xFF0, >>4) +} +u8 txidxcap5g { + srom >= 11 u16 0x1AC (&0xFF0, >>4) +} + +# +# Any variables defined within a `struct` block will be interpreted relative to +# the provided array of SPROM base addresses; this is used to define +# a common layout defined at the given base addresses. +# +# To produce SPROM variable names matching those used in the Broadcom HND +# ASCII 'key=value\0' NVRAM, the index number of the variable's +# struct instance will be appended (e.g., given a variable of noiselvl5ga, the +# generated variable instances will be named noiselvl5ga0, noiselvl5ga1, +# noiselvl5ga2, noiselvl5ga3 ...) +# + +# PHY chain[0-4] parameters +struct phy_chains[] { + srom 4-7 [0x080, 0x0AE, 0x0DC, 0x10A] + srom 8-10 [0x0C0, 0x0E0, 0x100, 0x120] + srom >= 11 [0x0D8, 0x100, 0x128] + + # AC-PHY PA parameters + u8[4] maxp5ga { + srom 4-7 u8 0xB + srom 8-10 u8 0x9 + srom >= 11 u8 0xD, u8 0xC, u8 0xF, u8 0xE + } + u16[3] pa2ga { + srom >= 11 0x2 + } + u8 maxp2ga { + srom 4-7 0x1 + srom 8-10 0x1 + srom >= 11 0x1 + } + u16[12] pa5ga { + srom >= 11 0x10 + } + + # AC-PHY rxgains + u8 rxgains5ghtrelnabypa { + srom >= 11 0x8 (&0x80, >>7) + } + u8 rxgains5ghelnagaina { + srom >= 11 0x8 (&0x7) + } + u8 rxgains5gelnagaina { + srom >= 11 0xA (&0x7) + } + u8 rxgains5gmtrelnabypa { + srom >= 11 0x9 (&0x80, >>7) + } + u8 rxgains2gtrelnabypa { + srom >= 11 0xB (&0x80, >>7) + } + u8 rxgains5gmtrisoa { + srom >= 11 0x9 (&0x78, >>3) + } + u8 rxgains5gmelnagaina { + srom >= 11 0x9 (&0x7) + } + u8 rxgains2gelnagaina { + srom >= 11 0xB (&0x7) + } + u8 rxgains5gtrisoa { + srom >= 11 0xA (&0x78, >>3) + } + u8 rxgains5gtrelnabypa { + srom >= 11 0xA (&0x80, >>7) + } + u8 rxgains2gtrisoa { + srom >= 11 0xB (&0x78, >>3) + } + u8 rxgains5ghtrisoa { + srom >= 11 0x8 (&0x78, >>3) + } + + # 11n PA parameters + u16 pa5gw2a { + srom 4-7 0x12 + srom 8-10 0x10 + } + u16 pa5ghw1a { + srom 4-7 0x20 + srom 8-10 0x1A + } + u16 pa5glw3a { + srom 4-7 0x1C + } + u16 pa5glw1a { + srom 4-7 0x18 + srom 8-10 0x14 + } + u16 pa5gw1a { + srom 4-7 0x10 + srom 8-10 0xE + } + u16 pa5glw0a { + srom 4-7 0x16 + srom 8-10 0x12 + } + u16 pa5gw3a { + srom 4-7 0x14 + } + u16 pa5glw2a { + srom 4-7 0x1A + srom 8-10 0x16 + } + u16 pa5ghw3a { + srom 4-7 0x24 + } + u16 pa5gw0a { + srom 4-7 0xE + srom 8-10 0xC + } + u8 maxp5gha { + srom 4-7 0xD + srom 8-10 0xB + } + u16 pa5ghw2a { + srom 4-7 0x22 + srom 8-10 0x1C + } + u16 pa5ghw0a { + srom 4-7 0x1E + srom 8-10 0x18 + } + u16 pa2gw3a { + srom 4-7 0x8 + } + u16 pa2gw2a { + srom 4-7 0x6 + srom 8-10 0x6 + } + u16 pa2gw1a { + srom 4-7 0x4 + srom 8-10 0x4 + } + u16 pa2gw0a { + srom 4-7 0x2 + srom 8-10 0x2 + } + u8 maxp5gla { + srom 4-7 0xC + srom 8-10 0xA + } + u8 itt5ga { + srom 4-7 0xA + srom 8-10 0x8 + } + u8 itt2ga { + srom 4-7 0x0 + srom 8-10 0x0 + } +} Index: head/sys/dev/bhnd/nvram/nvram_subr.c =================================================================== --- head/sys/dev/bhnd/nvram/nvram_subr.c +++ head/sys/dev/bhnd/nvram/nvram_subr.c @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include "bhnd_nvram_map_data.h" + +/* + * CRC-8 lookup table used to checksum SPROM and NVRAM data via + * bhnd_nvram_crc8(). + * + * Generated with following parameters: + * polynomial: CRC-8 (x^8 + x^7 + x^6 + x^4 + x^2 + 1) + * reflected bits: false + * reversed: true + */ +const uint8_t bhnd_nvram_crc8_tab[] = { + 0x00, 0xf7, 0xb9, 0x4e, 0x25, 0xd2, 0x9c, 0x6b, 0x4a, 0xbd, 0xf3, + 0x04, 0x6f, 0x98, 0xd6, 0x21, 0x94, 0x63, 0x2d, 0xda, 0xb1, 0x46, + 0x08, 0xff, 0xde, 0x29, 0x67, 0x90, 0xfb, 0x0c, 0x42, 0xb5, 0x7f, + 0x88, 0xc6, 0x31, 0x5a, 0xad, 0xe3, 0x14, 0x35, 0xc2, 0x8c, 0x7b, + 0x10, 0xe7, 0xa9, 0x5e, 0xeb, 0x1c, 0x52, 0xa5, 0xce, 0x39, 0x77, + 0x80, 0xa1, 0x56, 0x18, 0xef, 0x84, 0x73, 0x3d, 0xca, 0xfe, 0x09, + 0x47, 0xb0, 0xdb, 0x2c, 0x62, 0x95, 0xb4, 0x43, 0x0d, 0xfa, 0x91, + 0x66, 0x28, 0xdf, 0x6a, 0x9d, 0xd3, 0x24, 0x4f, 0xb8, 0xf6, 0x01, + 0x20, 0xd7, 0x99, 0x6e, 0x05, 0xf2, 0xbc, 0x4b, 0x81, 0x76, 0x38, + 0xcf, 0xa4, 0x53, 0x1d, 0xea, 0xcb, 0x3c, 0x72, 0x85, 0xee, 0x19, + 0x57, 0xa0, 0x15, 0xe2, 0xac, 0x5b, 0x30, 0xc7, 0x89, 0x7e, 0x5f, + 0xa8, 0xe6, 0x11, 0x7a, 0x8d, 0xc3, 0x34, 0xab, 0x5c, 0x12, 0xe5, + 0x8e, 0x79, 0x37, 0xc0, 0xe1, 0x16, 0x58, 0xaf, 0xc4, 0x33, 0x7d, + 0x8a, 0x3f, 0xc8, 0x86, 0x71, 0x1a, 0xed, 0xa3, 0x54, 0x75, 0x82, + 0xcc, 0x3b, 0x50, 0xa7, 0xe9, 0x1e, 0xd4, 0x23, 0x6d, 0x9a, 0xf1, + 0x06, 0x48, 0xbf, 0x9e, 0x69, 0x27, 0xd0, 0xbb, 0x4c, 0x02, 0xf5, + 0x40, 0xb7, 0xf9, 0x0e, 0x65, 0x92, 0xdc, 0x2b, 0x0a, 0xfd, 0xb3, + 0x44, 0x2f, 0xd8, 0x96, 0x61, 0x55, 0xa2, 0xec, 0x1b, 0x70, 0x87, + 0xc9, 0x3e, 0x1f, 0xe8, 0xa6, 0x51, 0x3a, 0xcd, 0x83, 0x74, 0xc1, + 0x36, 0x78, 0x8f, 0xe4, 0x13, 0x5d, 0xaa, 0x8b, 0x7c, 0x32, 0xc5, + 0xae, 0x59, 0x17, 0xe0, 0x2a, 0xdd, 0x93, 0x64, 0x0f, 0xf8, 0xb6, + 0x41, 0x60, 0x97, 0xd9, 0x2e, 0x45, 0xb2, 0xfc, 0x0b, 0xbe, 0x49, + 0x07, 0xf0, 0x9b, 0x6c, 0x22, 0xd5, 0xf4, 0x03, 0x4d, 0xba, 0xd1, + 0x26, 0x68, 0x9f +}; + + +/** + * Return the size of type @p dt. + * + * @param dt NVRAM data type. + * @result the byte width of @p dt. + */ +size_t +bhnd_nvram_type_width(bhnd_nvram_dt dt) +{ + switch (dt) { + case BHND_NVRAM_DT_INT8: + case BHND_NVRAM_DT_UINT8: + case BHND_NVRAM_DT_CHAR: + return (sizeof(uint8_t)); + + case BHND_NVRAM_DT_INT16: + case BHND_NVRAM_DT_UINT16: + return (sizeof(uint16_t)); + + case BHND_NVRAM_DT_INT32: + case BHND_NVRAM_DT_UINT32: + return (sizeof(uint32_t)); + } + + /* Quiesce gcc4.2 */ + panic("bhnd nvram data type %u unknown", dt); +} + + +/** + * Return the variable definition for @p varname, if any. + * + * @param varname variable name + * + * @retval bhnd_nvram_var If a valid definition for @p varname is found. + * @retval NULL If no definition for @p varname is found. + */ +const struct bhnd_nvram_var * +bhnd_nvram_var_defn(const char *varname) +{ + size_t min, mid, max; + int order; + + /* + * Locate the requested variable using a binary search. + * + * The variable table is guaranteed to be sorted in lexicographical + * order (using the 'C' locale for collation rules) + */ + min = 0; + mid = 0; + max = nitems(bhnd_nvram_vars) - 1; + + while (max >= min) { + /* Select midpoint */ + mid = (min + max) / 2; + + /* Determine which side of the partition to search */ + order = strcmp(bhnd_nvram_vars[mid].name, varname); + if (order < 0) { + /* Search upper partition */ + min = mid + 1; + } else if (order > 0) { + /* Search lower partition */ + max = mid - 1; + } else if (order == 0) { + /* Match found */ + return (&bhnd_nvram_vars[mid]); + } + } + + /* Not found */ + return (NULL); +} Index: head/sys/dev/bhnd/nvram/nvramvar.h =================================================================== --- head/sys/dev/bhnd/nvram/nvramvar.h +++ head/sys/dev/bhnd/nvram/nvramvar.h @@ -0,0 +1,128 @@ +/*- + * Copyright (c) 2015-2016 Landon Fuller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ + +#ifndef _BHND_NVRAM_BHND_NVRAMVAR_H_ +#define _BHND_NVRAM_BHND_NVRAMVAR_H_ + +/** NVRAM Primitive data types */ +typedef enum { + BHND_NVRAM_DT_UINT8 = 0, /**< unsigned 8-bit integer */ + BHND_NVRAM_DT_UINT16 = 1, /**< unsigned 16-bit integer */ + BHND_NVRAM_DT_UINT32 = 2, /**< unsigned 32-bit integer */ + BHND_NVRAM_DT_INT8 = 3, /**< signed 8-bit integer */ + BHND_NVRAM_DT_INT16 = 4, /**< signed 16-bit integer */ + BHND_NVRAM_DT_INT32 = 5, /**< signed 32-bit integer */ + BHND_NVRAM_DT_CHAR = 6, /**< ASCII char */ +} bhnd_nvram_dt; + +/** NVRAM data type string representations */ +typedef enum { + BHND_NVRAM_VFMT_HEX = 1, /**< hex format */ + BHND_NVRAM_VFMT_DEC = 2, /**< decimal format */ + BHND_NVRAM_VFMT_MACADDR = 3, /**< mac address (canonical form, hex octets, + separated with ':') */ + BHND_NVRAM_VFMT_LEDDC = 4, /**< LED PWM duty-cycle (2 bytes -- on/off) */ + BHND_NVRAM_VFMT_CCODE = 5 /**< count code format (2-3 ASCII chars, or hex string) */ +} bhnd_nvram_fmt; + +/** NVRAM variable flags */ +enum { + BHND_NVRAM_VF_ARRAY = (1<<0), /**< variable is an array */ + BHND_NVRAM_VF_MFGINT = (1<<1), /**< mfg-internal variable; should not be externally visible */ + BHND_NVRAM_VF_IGNALL1 = (1<<2) /**< hide variable if its value has all bits set. */ +}; + +#define BHND_SPROMREV_MAX UINT8_MAX /**< maximum supported SPROM revision */ + +/** SPROM revision compatibility declaration */ +struct bhnd_sprom_compat { + uint8_t first; /**< first compatible SPROM revision */ + uint8_t last; /**< last compatible SPROM revision, or BHND_SPROMREV_MAX */ +}; + +/** SPROM value descriptor */ +struct bhnd_sprom_offset { + uint16_t offset; /**< byte offset within SPROM */ + bool cont:1; /**< value should be bitwise OR'd with the + * previous offset descriptor */ + bhnd_nvram_dt type:7; /**< data type */ + int8_t shift; /**< shift to be applied to the value */ + uint32_t mask; /**< mask to be applied to the value(s) */ +}; + +/** SPROM-specific variable definition */ +struct bhnd_sprom_var { + struct bhnd_sprom_compat compat; /**< sprom compatibility declaration */ + const struct bhnd_sprom_offset *offsets; /**< offset descriptors */ + size_t num_offsets; /**< number of offset descriptors */ +}; + +/** NVRAM variable definition */ +struct bhnd_nvram_var { + const char *name; /**< variable name */ + bhnd_nvram_dt type; /**< base data type */ + bhnd_nvram_fmt fmt; /**< string format */ + uint32_t flags; /**< BHND_NVRAM_VF_* flags */ + + const struct bhnd_sprom_var *sprom_descs; /**< SPROM-specific variable descriptors */ + size_t num_sp_descs; /**< number of sprom descriptors */ +}; + +size_t bhnd_nvram_type_width(bhnd_nvram_dt dt); +const struct bhnd_nvram_var *bhnd_nvram_var_defn(const char *varname); + +/** Initial bhnd_nvram_crc8 value */ +#define BHND_NVRAM_CRC8_INITIAL 0xFF + +/** Valid CRC-8 checksum */ +#define BHND_NVRAM_CRC8_VALID 0x9F + +extern const uint8_t bhnd_nvram_crc8_tab[]; + +/** + * Calculate CRC-8 over @p buf. + * + * @param buf input buffer + * @param size buffer size + * @param crc last computed crc, or BHND_NVRAM_CRC8_INITIAL + */ +static inline uint8_t +bhnd_nvram_crc8(const void *buf, size_t size, uint8_t crc) +{ + const uint8_t *p = (const uint8_t *)buf; + while (size--) + crc = bhnd_nvram_crc8_tab[(crc ^ *p++)]; + + return (crc); +} + + +#endif /* _BHND_NVRAM_BHND_NVRAMVAR_H_ */ \ No newline at end of file Index: head/sys/dev/bhnd/tools/nvram_map_gen.awk =================================================================== --- head/sys/dev/bhnd/tools/nvram_map_gen.awk +++ head/sys/dev/bhnd/tools/nvram_map_gen.awk @@ -0,0 +1,1162 @@ +#!/usr/bin/awk -f + +#- +# Copyright (c) 2015-2016 Landon Fuller +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer, +# without modification. +# 2. Redistributions in binary form must reproduce at minimum a disclaimer +# similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any +# redistribution must be conditioned upon including a substantially +# similar Disclaimer requirement for further binary redistribution. +# +# NO WARRANTY +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY +# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +# THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGES. +# +# $FreeBSD$ + +BEGIN { + RS="\n" + + depth = 0 + symbols[depth,"_file"] = FILENAME + num_output_vars = 0 + OUTPUT_FILE = null + + # Seed rand() + srand() + + # Output type + OUT_T = null + OUT_T_HEADER = "HEADER" + OUT_T_DATA = "DATA" + + # Enable debug output + DEBUG = 0 + + # Maximum revision + REV_MAX = 255 + + # Parse arguments + if (ARGC < 2) + usage() + + for (i = 1; i < ARGC; i++) { + if (ARGV[i] == "--debug") { + DEBUG = 1 + } else if (ARGV[i] == "-d" && OUT_T == null) { + OUT_T = OUT_T_DATA + } else if (ARGV[i] == "-h" && OUT_T == null) { + OUT_T = OUT_T_HEADER + } else if (ARGV[i] == "-o") { + i++ + if (i >= ARGC) + usage() + + OUTPUT_FILE = ARGV[i] + } else if (ARGV[i] == "--") { + i++ + break + } else if (ARGV[i] !~ /^-/) { + FILENAME = ARGV[i] + } else { + print "unknown option " ARGV[i] + usage() + } + } + + ARGC=2 + + if (OUT_T == null) { + print("error: one of -d or -h required") + usage() + } + + if (FILENAME == null) { + print("error: no input file specified") + usage() + } + + if (OUTPUT_FILE == "-") { + OUTPUT_FILE = "/dev/stdout" + } else if (OUTPUT_FILE == null) { + _bi = split(FILENAME, _paths, "/") + OUTPUT_FILE = _paths[_bi] + + if (OUTPUT_FILE !~ /^bhnd_/) + OUTPUT_FILE = "bhnd_" OUTPUT_FILE + + if (OUT_T == OUT_T_HEADER) + OUTPUT_FILE = OUTPUT_FILE ".h" + else + OUTPUT_FILE = OUTPUT_FILE "_data.h" + } + + # Format Constants + FMT["hex"] = "BHND_NVRAM_VFMT_HEX" + FMT["decimal"] = "BHND_NVRAM_VFMT_DEC" + FMT["ccode"] = "BHND_NVRAM_VFMT_CCODE" + FMT["macaddr"] = "BHND_NVRAM_VFMT_MACADDR" + FMT["led_dc"] = "BHND_NVRAM_VFMT_LEDDC" + + # Data Type Constants + DTYPE["u8"] = "BHND_NVRAM_DT_UINT8" + DTYPE["u16"] = "BHND_NVRAM_DT_UINT16" + DTYPE["u32"] = "BHND_NVRAM_DT_UINT32" + DTYPE["i8"] = "BHND_NVRAM_DT_INT8" + DTYPE["i16"] = "BHND_NVRAM_DT_INT16" + DTYPE["i32"] = "BHND_NVRAM_DT_INT32" + DTYPE["char"] = "BHND_NVRAM_DT_CHAR" + + # Default masking for standard types + TMASK["u8"] = "0x000000FF" + TMASK["u16"] = "0x0000FFFF" + TMASK["u32"] = "0xFFFFFFFF" + TMASK["i8"] = TMASK["u8"] + TMASK["i16"] = TMASK["u16"] + TMASK["i32"] = TMASK["u32"] + TMASK["char"] = TMASK["u8"] + + # Byte sizes for standard types + TSIZE["u8"] = "1" + TSIZE["u16"] = "2" + TSIZE["u32"] = "4" + TSIZE["i8"] = TSIZE["u8"] + TSIZE["i16"] = TSIZE["u8"] + TSIZE["i32"] = TSIZE["u8"] + TSIZE["char"] = "1" + + # Common Regexs + INT_REGEX = "^(0|[1-9][0-9]*),?$" + HEX_REGEX = "^0x[A-Fa-f0-9]+,?$" + + ARRAY_REGEX = "\\[(0|[1-9][0-9]*)\\]" + TYPES_REGEX = "^(((u|i)(8|16|32))|char)("ARRAY_REGEX")?,?$" + + IDENT_REGEX = "^[A-Za-z_][A-Za-z0-9_]*,?$" + SROM_OFF_REGEX = "("TYPES_REGEX"|"HEX_REGEX")" + + # Parser states types + ST_STRUCT_BLOCK = "struct" # struct block + ST_VAR_BLOCK = "var" # variable block + ST_SROM_DEFN = "srom" # srom offset defn + ST_NONE = "NONE" # default state + + # Property types + PROP_T_SFMT = "sfmt" + PROP_T_ALL1 = "all1" + + # Internal variables used for parser state + # tracking + STATE_TYPE = "_state_type" + STATE_IDENT = "_state_block_name" + STATE_LINENO = "_state_first_line" + STATE_ISBLOCK = "_state_is_block" + + # Common array keys + DEF_LINE = "def_line" + NUM_REVS = "num_revs" + REV = "rev" + + # Revision array keys + REV_START = "rev_start" + REV_END = "rev_end" + REV_DESC = "rev_decl" + REV_NUM_OFFS = "num_offs" + + # Offset array keys + OFF = "off" + OFF_NUM_SEGS = "off_num_segs" + OFF_SEG = "off_seg" + + # Segment array keys + SEG_ADDR = "seg_addr" + SEG_COUNT = "seg_count" + SEG_TYPE = "seg_type" + SEG_MASK = "seg_mask" + SEG_SHIFT = "seg_shift" + + # Variable array keys + VAR_NAME = "v_name" + VAR_TYPE = "v_type" + VAR_BASE_TYPE = "v_base_type" + VAR_FMT = "v_fmt" + VAR_STRUCT = "v_parent_struct" + VAR_PRIVATE = "v_private" + VAR_ARRAY = "v_array" + VAR_IGNALL1 = "v_ignall1" +} + +# return the flag definition for variable `v` +function gen_var_flags (v) +{ + _num_flags = 0; + if (vars[v,VAR_ARRAY]) + _flags[_num_flags++] = "BHND_NVRAM_VF_ARRAY" + + if (vars[v,VAR_PRIVATE]) + _flags[_num_flags++] = "BHND_NVRAM_VF_MFGINT" + + if (vars[v,VAR_IGNALL1]) + _flags[_num_flags++] = "BHND_NVRAM_VF_IGNALL1" + + if (_num_flags == 0) + _flags[_num_flags++] = "0" + + return (join(_flags, "|", _num_flags)) +} + +# emit the bhnd_sprom_offsets for a given variable revision key +function emit_var_sprom_offsets (v, revk) +{ + emit(sprintf("{{%u, %u}, (struct bhnd_sprom_offset[]) {\n", + vars[revk,REV_START], + vars[revk,REV_END])) + output_depth++ + + num_offs = vars[revk,REV_NUM_OFFS] + num_offs_written = 0 + elem_count = 0 + for (offset = 0; offset < num_offs; offset++) { + offk = subkey(revk, OFF, offset"") + num_segs = vars[offk,OFF_NUM_SEGS] + + for (seg = 0; seg < num_segs; seg++) { + segk = subkey(offk, OFF_SEG, seg"") + + for (seg_n = 0; seg_n < vars[segk,SEG_COUNT]; seg_n++) { + seg_addr = vars[segk,SEG_ADDR] + seg_addr += TSIZE[vars[segk,SEG_TYPE]] * seg_n + + emit(sprintf("{%s, %s, %s, %s, %s},\n", + seg_addr, + (seg > 0) ? "true" : "false", + DTYPE[vars[segk,SEG_TYPE]], + vars[segk,SEG_SHIFT], + vars[segk,SEG_MASK])) + + num_offs_written++ + } + } + } + + output_depth-- + emit("}, " num_offs_written "},\n") +} + +# emit the bhnd_nvram_var definition for variable name `v` +function emit_var_defn (v) +{ + emit(sprintf("{\"%s\", %s, %s, %s, (struct bhnd_sprom_var[]) {\n", + v suffix, + DTYPE[vars[v,VAR_BASE_TYPE]], + FMT[vars[v,VAR_FMT]], + gen_var_flags(v))) + output_depth++ + + for (rev = 0; rev < vars[v,NUM_REVS]; rev++) { + revk = subkey(v, REV, rev"") + emit_var_sprom_offsets(v, revk) + } + + output_depth-- + emit("}, " vars[v,NUM_REVS] "},\n") +} + +# emit a header name #define for variable `v` +function emit_var_namedef (v) +{ + emit("#define\tBHND_NVAR_" toupper(v) "\t\"" v "\"\n") +} + +# generate a set of var offset definitions for struct variable `st_vid` +function gen_struct_var_offsets (vid, revk, st_vid, st_revk, base_addr) +{ + # Copy all offsets to the new variable + for (offset = 0; offset < vars[v,REV_NUM_OFFS]; offset++) { + st_offk = subkey(st_revk, OFF, offset"") + offk = subkey(revk, OFF, offset"") + + # Copy all segments to the new variable, applying base + # address adjustment + num_segs = vars[st_offk,OFF_NUM_SEGS] + vars[offk,OFF_NUM_SEGS] = num_segs + + for (seg = 0; seg < num_segs; seg++) { + st_segk = subkey(st_offk, OFF_SEG, seg"") + segk = subkey(offk, OFF_SEG, seg"") + + vars[segk,SEG_ADDR] = vars[st_segk,SEG_ADDR] + \ + base_addr"" + vars[segk,SEG_COUNT] = vars[st_segk,SEG_COUNT] + vars[segk,SEG_TYPE] = vars[st_segk,SEG_TYPE] + vars[segk,SEG_MASK] = vars[st_segk,SEG_MASK] + vars[segk,SEG_SHIFT] = vars[st_segk,SEG_SHIFT] + } + } +} + +# generate a complete set of variable definitions for struct variable `st_vid`. +function gen_struct_vars (st_vid) +{ + st = vars[st_vid,VAR_STRUCT] + st_max_off = 0 + + # determine the total number of variables to generate + for (st_rev = 0; st_rev < structs[st,NUM_REVS]; st_rev++) { + srevk = subkey(st, REV, st_rev"") + for (off = 0; off < structs[srevk,REV_NUM_OFFS]; off++) { + if (off > st_max_off) + st_max_off = off + } + } + + # generate variable records for each defined struct offset + for (off = 0; off < st_max_off; off++) { + # Construct basic variable definition + v = st_vid off"" + vars[v,VAR_TYPE] = vars[st_vid,VAR_TYPE] + vars[v,VAR_BASE_TYPE] = vars[st_vid,VAR_BASE_TYPE] + vars[v,VAR_FMT] = vars[st_vid,VAR_FMT] + vars[v,VAR_PRIVATE] = vars[st_vid,VAR_PRIVATE] + vars[v,VAR_ARRAY] = vars[st_vid,VAR_ARRAY] + vars[v,VAR_IGNALL1] = vars[st_vid,VAR_IGNALL1] + vars[v,NUM_REVS] = 0 + + # Add to output variable list + output_vars[num_output_vars++] = v + + # Construct revision / offset entries + for (srev = 0; srev < structs[st,NUM_REVS]; srev++) { + # Struct revision key + st_revk = subkey(st, REV, srev"") + + # Skip offsets not defined for this revision + if (off > structs[st_revk,REV_NUM_OFFS]) + continue + + # Strut offset key and associated base address */ + offk = subkey(st_revk, OFF, off"") + base_addr = structs[offk,SEG_ADDR] + + for (vrev = 0; vrev < vars[st_vid,NUM_REVS]; vrev++) { + st_var_revk = subkey(st_vid, REV, vrev"") + v_start = vars[st_var_revk,REV_START] + v_end = vars[st_var_revk,REV_END] + s_start = structs[st_revk,REV_START] + s_end = structs[st_revk,REV_END] + + # We don't support computing the union + # of partially overlapping ranges + if ((v_start < s_start && v_end >= s_start) || + (v_start <= s_end && v_end > s_end)) + { + errorx("partially overlapping " \ + "revision ranges are not supported") + } + + # skip variables revs that are not within + # the struct offset's compatibility range + if (v_start < s_start || v_start > s_end || + v_end < s_start || v_end > s_end) + continue + + # Generate the new revision record + rev = vars[v,NUM_REVS] "" + revk = subkey(v, REV, rev) + vars[v,NUM_REVS]++ + + vars[revk,DEF_LINE] = vars[st_revk,DEF_LINE] + vars[revk,REV_START] = v_start + vars[revk,REV_END] = v_end + vars[revk,REV_NUM_OFFS] = \ + vars[st_var_revk,REV_NUM_OFFS] + + gen_struct_var_offsets(v, revk, st_vid, st_revk, + base_addr) + } + } + } +} + + +END { + # Skip completion handling if exiting from an error + if (_EARLY_EXIT) + exit 1 + + # Check for complete block closure + if (depth > 0) { + block_start = g(STATE_LINENO) + errorx("missing '}' for block opened on line " block_start "") + } + + # Generate concrete variable definitions for all struct variables + for (v in var_names) { + if (vars[v,VAR_STRUCT] != null) { + gen_struct_vars(v) + } else { + output_vars[num_output_vars++] = v + } + } + + # Apply lexicographical sorting. To support more effecient table + # searching, we guarantee a stable sort order (using C collation). + sort(output_vars) + + # Truncate output file and write common header + printf("") > OUTPUT_FILE + emit("/*\n") + emit(" * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.\n") + emit(" *\n") + emit(" * generated from nvram map: " FILENAME "\n") + emit(" */\n") + emit("\n") + + # Emit all variable definitions + if (OUT_T == OUT_T_DATA) { + emit("#include \n") + emit("static const struct bhnd_nvram_var bhnd_nvram_vars[] = "\ + "{\n") + output_depth++ + for (i = 0; i < num_output_vars; i++) + emit_var_defn(output_vars[i]) + output_depth-- + emit("};\n") + } else if (OUT_T == OUT_T_HEADER) { + for (i = 0; i < num_output_vars; i++) + emit_var_namedef(output_vars[i]) + } + + printf("%u variable records written to %s\n", num_output_vars, + OUTPUT_FILE) >> "/dev/stderr" +} + + +# +# Print usage +# +function usage () +{ + print "usage: bhnd_nvram_map.awk [-hd] [-o output file]" + _EARLY_EXIT = 1 + exit 1 +} + +# +# Join all array elements with the given separator +# +function join (array, sep, count) +{ + if (count == 0) + return ("") + + _result = array[0] + for (_ji = 1; _ji < count; _ji++) + _result = _result sep array[_ji] + + return (_result) +} + +# +# Sort a contiguous integer-indexed array, using standard awk comparison +# operators over its values. +# +function sort (array) { + # determine array size + _sort_alen = 0 + + for (_ssort_key in array) + _sort_alen++ + + if (_sort_alen <= 1) + return + + # perform sort + _qsort(array, 0, _sort_alen-1) +} + +function _qsort (array, first, last) +{ + if (first >= last) + return + + # select pivot element + _qpivot = int(first + int((last-first+1) * rand())) + _qleft = first + _qright = last + + _qpivot_val = array[_qpivot] + + # partition + while (_qleft <= _qright) { + while (array[_qleft] < _qpivot_val) + _qleft++ + + while (array[_qright] > _qpivot_val) + _qright-- + + # swap + if (_qleft <= _qright) { + _qleft_val = array[_qleft] + _qright_val = array[_qright] + + array[_qleft] = _qright_val + array[_qright] = _qleft_val + + _qleft++ + _qright-- + } + } + + # sort the partitions + _qsort(array, first, _qright) + _qsort(array, _qleft, last) +} + +# +# Print msg to output file, without indentation +# +function emit_ni (msg) +{ + printf("%s", msg) >> OUTPUT_FILE +} + +# +# Print msg to output file, indented for the current `output_depth` +# +function emit (msg) +{ + for (_ind = 0; _ind < output_depth; _ind++) + emit_ni("\t") + + emit_ni(msg) +} + +# +# Print a warning to stderr +# +function warn (msg) +{ + print "warning:", msg, "at", FILENAME, "line", NR > "/dev/stderr" +} + +# +# Print a compiler error to stderr +# +function error (msg) +{ + errorx(msg " at " FILENAME " line " NR ":\n\t" $0) +} + +# +# Print an error message without including the source line information +# +function errorx (msg) +{ + print "error:", msg > "/dev/stderr" + _EARLY_EXIT=1 + exit 1 +} + +# +# Print a debug output message +# +function debug (msg) +{ + if (!DEBUG) + return + for (_di = 0; _di < depth; _di++) + printf("\t") > "/dev/stderr" + print msg > "/dev/stderr" +} + +# +# Return an array key composed of the given (parent, selector, child) +# tuple. +# The child argument is optional and may be omitted. +# +function subkey (parent, selector, child) +{ + if (child != null) + return (parent SUBSEP selector SUBSEP child) + else + return (parent SUBSEP selector) +} + +# +# Advance to the next non-comment input record +# +function next_line () +{ + do { + _result = getline + } while (_result > 0 && $0 ~ /^[ \t]*#.*/) # skip comment lines + return (_result) +} + +# +# Advance to the next input record and verify that it matches @p regex +# +function getline_matching (regex) +{ + _result = next_line() + if (_result <= 0) + return (_result) + + if ($0 ~ regex) + return (1) + + return (-1) +} + +# +# Shift the current fields left by `n`. +# +# If all fields are consumed and the optional do_getline argument is true, +# read the next line. +# +function shiftf (n, do_getline) +{ + if (n > NF) error("shift past end of line") + for (_si = 1; _si <= NF-n; _si++) { + $(_si) = $(_si+n) + } + NF = NF - n + + if (NF == 0 && do_getline) + next_line() +} + +# +# Parse a revision descriptor from the current line. +# +function parse_revdesc (result) +{ + _rstart = 0 + _rend = 0 + + if ($2 ~ "[0-9]*-[0-9*]") { + split($2, _revrange, "[ \t]*-[ \t]*") + _rstart = _revrange[1] + _rend = _revrange[2] + } else if ($2 ~ "(>|>=|<|<=)" && $3 ~ "[1-9][0-9]*") { + if ($2 == ">") { + _rstart = int($3)+1 + _rend = REV_MAX + } else if ($2 == ">=") { + _rstart = int($3) + _rend = REV_MAX + } else if ($2 == "<" && int($3) > 0) { + _rstart = 0 + _rend = int($3)-1 + } else if ($2 == "<=") { + _rstart = 0 + _rend = int($3)-1 + } else { + error("invalid revision descriptor") + } + } else if ($2 ~ "[1-9][0-9]*") { + _rstart = int($2) + _rend = int($2) + } else { + error("invalid revision descriptor") + } + + result[REV_START] = _rstart + result[REV_END] = _rend +} + +# +# Push a new parser state. +# +# The name may be null, in which case the STATE_IDENT variable will not be +# defined in this scope +# +function push_state (type, name, block) { + depth++ + push(STATE_LINENO, NR) + if (name != null) + push(STATE_IDENT, name) + push(STATE_TYPE, type) + push(STATE_ISBLOCK, block) +} + +# +# Pop the top of the parser state stack. +# +function pop_state () { + # drop all symbols defined at this depth + for (s in symbols) { + if (s ~ "^"depth"[^0-9]") + delete symbols[s] + } + depth-- +} + +# +# Find opening brace and push a new parser state for a brace-delimited block. +# +# The name may be null, in which case the STATE_IDENT variable will not be +# defined in this scope +# +function open_block (type, name) +{ + if ($0 ~ "{" || getline_matching("^[ \t]*{") > 0) { + push_state(type, name, 1) + sub("^[^{]+{", "", $0) + return + } + + error("found '"$1 "' instead of expected '{' for '" name "'") +} + +# +# Find closing brace and pop parser states until the first +# brace-delimited block is discarded. +# +function close_block () +{ + if ($0 !~ "}") + error("internal error - no closing brace") + + # pop states until we exit the first enclosing block + do { + _closed_block = g(STATE_ISBLOCK) + pop_state() + } while (!_closed_block) + + # strip everything prior to the block closure + sub("^[^}]*}", "", $0) +} + +# Internal symbol table lookup function. Returns the symbol depth if +# name is found at or above scope; if scope is null, it defauls to 0 +function _find_sym (name, scope) +{ + if (scope == null) + scope = 0; + + for (i = scope; i < depth; i++) { + if ((depth-i,name) in symbols) + return (depth-i) + } + + return (-1) +} + +# +# Look up a variable in the symbol table with `name` and return its value. +# +# If `scope` is not null, the variable search will start at the provided +# scope level -- 0 is the current scope, 1 is the parent's scope, etc. +# +function g (name, scope) +{ + _g_depth = _find_sym(name, scope) + if (_g_depth < 0) + error("'" name "' is undefined") + + return (symbols[_g_depth,name]) +} + +function is_defined (name, scope) +{ + return (_find_sym(name, scope) >= 0) +} + +# Define a new variable in the symbol table's current scope, +# with the given value +function push (name, value) +{ + symbols[depth,name] = value +} + +# Set an existing variable's value in the symbol table; if not yet defined, +# will trigger an error +function set (name, value, scope) +{ + for (i = 0; i < depth; i++) { + if ((depth-i,name) in symbols) { + symbols[depth-i,name] = value + return + } + } + # No existing value, cannot define + error("'" name "' is undefined") +} + +# Evaluates to true if immediately within a block scope of the given type +function in_state (type) +{ + if (!is_defined(STATE_TYPE)) + return (type == ST_NONE) + + return (type == g(STATE_TYPE)) +} + +# Evaluates to true if within an immediate or non-immediate block scope of the +# given type +function in_nested_state (type) +{ + for (i = 0; i < depth; i++) { + if ((depth-i,STATE_TYPE) in symbols) { + if (symbols[depth-i,STATE_TYPE] == type) + return (1) + } + } + return (0) +} + +# Evaluates to true if definitions of the given type are permitted within +# the current scope +function allow_def (type) +{ + if (type == ST_VAR_BLOCK) { + return (in_state(ST_NONE) || in_state(ST_STRUCT_BLOCK)) + } else if (type == ST_STRUCT_BLOCK) { + return (in_state(ST_NONE)) + } else if (type == ST_SROM_DEFN) { + return (in_state(ST_VAR_BLOCK) || in_state(ST_STRUCT_BLOCK)) + } + + error("unknown type '" type "'") +} + +# struct definition +$1 == ST_STRUCT_BLOCK && allow_def($1) { + name = $2 + + # Remove array[] specifier + if (sub(/\[\]$/, "", name) == 0) + error("expected '" name "[]', not '" name "'") + + if (name !~ IDENT_REGEX || name ~ TYPES_REGEX) + error("invalid identifier '" name "'") + + # Add top-level struct entry + if ((name,DEF_LINE) in structs) + error("struct identifier '" name "' previously defined on " \ + "line " structs[name,DEF_LINE]) + structs[name,DEF_LINE] = NR + structs[name,NUM_REVS] = 0 + + # Open the block + debug("struct " name " {") + open_block(ST_STRUCT_BLOCK, name) +} + +# struct srom descriptor +$1 == ST_SROM_DEFN && allow_def(ST_SROM_DEFN) && in_state(ST_STRUCT_BLOCK) { + sid = g(STATE_IDENT) + + # parse revision descriptor + rev_desc[REV_START] = 0 + parse_revdesc(rev_desc) + + # assign revision id + rev = structs[sid,NUM_REVS] "" + revk = subkey(sid, REV, rev) + structs[sid,NUM_REVS]++ + + # init basic revision state + structs[revk,REV_START] = rev_desc[REV_START] + structs[revk,REV_END] = rev_desc[REV_END] + + if (match($0, "\\[[^]]*\\]") <= 0) + error("expected base address array") + + addrs_str = substr($0, RSTART+1, RLENGTH-2) + num_offs = split(addrs_str, addrs, ",[ \t]*") + structs[revk, REV_NUM_OFFS] = num_offs + for (i = 1; i <= num_offs; i++) { + offk = subkey(revk, OFF, (i-1) "") + + if (addrs[i] !~ HEX_REGEX) + error("invalid base address '" addrs[i] "'") + + structs[offk,SEG_ADDR] = addrs[i] + } + + debug("struct_srom " structs[revk,REV_START] "... [" addrs_str "]") + next +} + +# close any previous srom revision descriptor +$1 == ST_SROM_DEFN && in_state(ST_SROM_DEFN) { + pop_state() +} + +# open a new srom revision descriptor +$1 == ST_SROM_DEFN && allow_def(ST_SROM_DEFN) { + # parse revision descriptor + parse_revdesc(rev_desc) + + # assign revision id + vid = g(STATE_IDENT) + rev = vars[vid,NUM_REVS] "" + revk = subkey(vid, REV, rev) + vars[vid,NUM_REVS]++ + + # vend scoped rev/revk variables for use in the + # revision offset block + push("rev_id", rev) + push("rev_key", revk) + + # init basic revision state + vars[revk,DEF_LINE] = NR + vars[revk,REV_START] = rev_desc[REV_START] + vars[revk,REV_END] = rev_desc[REV_END] + vars[revk,REV_NUM_OFFS] = 0 + + debug("srom " rev_desc[REV_START] "-" rev_desc[REV_END] " {") + push_state(ST_SROM_DEFN, null, 0) + + # seek to the first offset definition + do { + shiftf(1) + } while ($1 !~ SROM_OFF_REGEX && NF > 0) +} + +# +# Extract and return the array length from the given type string. +# Returns -1 if the type is not an array. +# +function type_array_len (type) +{ + # extract byte count[] and width + if (match(type, ARRAY_REGEX"$") > 0) { + return (substr(type, RSTART+1, RLENGTH-2)) + } else { + return (-1) + } +} + +# +# Parse an offset declaration from the current line. +# +function parse_offset_segment (revk, offk) +{ + vid = g(STATE_IDENT) + + # use explicit type if specified, otherwise use the variable's + # common type + if ($1 !~ HEX_REGEX) { + type = $1 + if (type !~ TYPES_REGEX) + error("unknown field type '" type "'") + + shiftf(1) + } else { + type = vars[vid,VAR_TYPE] + } + + # read offset value + offset = $1 + if (offset !~ HEX_REGEX) + error("invalid offset value '" offset "'") + + # extract byte count[], base type, and width + if (match(type, ARRAY_REGEX"$") > 0) { + count = int(substr(type, RSTART+1, RLENGTH-2)) + type = substr(type, 1, RSTART-1) + } else { + count = 1 + } + width = TSIZE[type] + + # seek to attributes or end of the offset expr + sub("^[^,(|){}]+", "", $0) + + # parse attributes + mask=TMASK[type] + shift=0 + + if ($1 ~ "^\\(") { + # extract attribute list + if (match($0, "\\([^|\(\)]*\\)") <= 0) + error("expected attribute list") + attr_str = substr($0, RSTART+1, RLENGTH-2) + + # drop from input line + $0 = substr($0, RSTART+RLENGTH, length($0) - RSTART+RLENGTH) + + # parse attributes + num_attr = split(attr_str, attrs, ",[ \t]*") + for (i = 1; i <= num_attr; i++) { + attr = attrs[i] + if (sub("^&[ \t]*", "", attr) > 0) { + mask = attr + } else if (sub("^<<[ \t]*", "", attr) > 0) { + shift = "-"attr + } else if (sub("^>>[ \t]*", "", attr) > 0) { + shift = attr + } else { + error("unknown attribute '" attr "'") + } + } + } + + # assign segment id + seg = vars[offk,OFF_NUM_SEGS] "" + segk = subkey(offk, OFF_SEG, seg) + vars[offk,OFF_NUM_SEGS]++ + + vars[segk,SEG_ADDR] = offset + (width * _oi) + vars[segk,SEG_COUNT] = count + vars[segk,SEG_TYPE] = type + vars[segk,SEG_MASK] = mask + vars[segk,SEG_SHIFT] = shift + + debug("{"vars[segk,SEG_ADDR]", "type", "mask", "shift"}" \ + _comma) +} + +# revision offset definition +$1 ~ SROM_OFF_REGEX && in_state(ST_SROM_DEFN) { + vid = g(STATE_IDENT) + + # fetch rev id/key defined by our parent block + rev = g("rev_id") + revk = g("rev_key") + + # parse all offsets + do { + # assign offset id + off = vars[revk,REV_NUM_OFFS] "" + offk = subkey(revk, OFF, off) + vars[revk,REV_NUM_OFFS]++ + + # initialize segment count + vars[offk,DEF_LINE] = NR + vars[offk,OFF_NUM_SEGS] = 0 + + debug("[") + # parse all segments + do { + parse_offset_segment(revk, offk) + _more_seg = ($1 == "|") + if (_more_seg) + shiftf(1, 1) + } while (_more_seg) + debug("],") + _more_vals = ($1 == ",") + if (_more_vals) + shiftf(1, 1) + } while (_more_vals) +} + +# variable definition +(($1 == "private" && $2 ~ TYPES_REGEX) || $1 ~ TYPES_REGEX) && + allow_def(ST_VAR_BLOCK) \ +{ + # check for 'private' flag + if ($1 == "private") { + private = 1 + shiftf(1) + } else { + private = 0 + } + + type = $1 + name = $2 + array = 0 + debug(type " " name " {") + + # Check for and remove any array[] specifier + base_type = type + if (sub(ARRAY_REGEX"$", "", base_type) > 0) + array = 1 + + # verify type + if (!base_type in DTYPE) + error("unknown type '" $1 "'") + + # Add top-level variable entry + if (name in var_names) + error("variable identifier '" name "' previously defined on " \ + "line " vars[name,DEF_LINE]) + + var_names[name] = 0 + vars[name,VAR_NAME] = name + vars[name,DEF_LINE] = NR + vars[name,VAR_TYPE] = type + vars[name,VAR_BASE_TYPE] = base_type + vars[name,NUM_REVS] = 0 + vars[name,VAR_PRIVATE] = private + vars[name,VAR_ARRAY] = array + vars[name,VAR_FMT] = "hex" # default if not specified + + open_block(ST_VAR_BLOCK, name) + + debug("type=" DTYPE[base_type]) + + if (in_nested_state(ST_STRUCT_BLOCK)) { + # Fetch the enclosing struct's name + sid = g(STATE_IDENT, 1) + + # Mark as a struct-based variable + vars[name,VAR_STRUCT] = sid + } +} + +# variable parameters +$1 ~ IDENT_REGEX && $2 ~ IDENT_REGEX && in_state(ST_VAR_BLOCK) { + vid = g(STATE_IDENT) + if ($1 == PROP_T_SFMT) { + if (!$2 in FMT) + error("invalid fmt '" $2 "'") + + vars[vid,VAR_FMT] = $2 + debug($1 "=" FMT[$2]) + } else if ($1 == PROP_T_ALL1 && $2 == "ignore") { + vars[vid,VAR_IGNALL1] = 1 + } else { + error("unknown parameter " $1) + } + next +} + +# Skip comments and blank lines +/^[ \t]*#/ || /^$/ { + next +} + +# Close blocks +/}/ && !in_state(ST_NONE) { + while (!in_state(ST_NONE) && $0 ~ "}") { + close_block(); + debug("}") + } + next +} + +# Report unbalanced '}' +/}/ && in_state(ST_NONE) { + error("extra '}'") +} + +# Invalid variable type +$1 && allow_def(ST_VAR_BLOCK) { + error("unknown type '" $1 "'") +} + +# Generic parse failure +{ + error("unrecognized statement") +} Index: head/sys/dev/bhnd/tools/nvram_map_gen.sh =================================================================== --- head/sys/dev/bhnd/tools/nvram_map_gen.sh +++ head/sys/dev/bhnd/tools/nvram_map_gen.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# Use C locale to ensure AWK string comparisons always produce +# a stable sort order. + +# $FreeBSD$ + +BHND_TOOLDIR="$(dirname $0)/" + +LC_ALL=C; export LC_ALL + +"$BHND_TOOLDIR/nvram_map_gen.awk" $@ Index: head/sys/dev/bwn/bwn_mac.c =================================================================== --- head/sys/dev/bwn/bwn_mac.c +++ head/sys/dev/bwn/bwn_mac.c @@ -42,6 +42,8 @@ #include #include +#include "bhnd_nvram_map.h" + static const struct resource_spec bwn_rspec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { -1, -1, 0 } @@ -97,6 +99,14 @@ r = sc->res[0]; device_printf(dev, "got rid=%d res=%p\n", sc->rspec[0].rid, r); + uint8_t macaddr[6]; + error = bhnd_nvram_getvar(dev, BHND_NVAR_MACADDR, macaddr, + sizeof(macaddr)); + if (error) + return (error); + + device_printf(dev, "got macaddr %6D\n", macaddr, ":"); + return (0); } Index: head/sys/modules/bhnd/Makefile =================================================================== --- head/sys/modules/bhnd/Makefile +++ head/sys/modules/bhnd/Makefile @@ -1,10 +1,16 @@ # $FreeBSD$ .PATH: ${.CURDIR}/../../dev/bhnd +.PATH: ${.CURDIR}/../../dev/bhnd/nvram KMOD= bhnd SRCS= bhnd.c bhnd_subr.c \ - bhnd_bus_if.c bhnd_bus_if.h bhnd_nvram_if.h + bhnd_sprom.c nvram_subr.c \ + bhnd_nvram_map.h bhnd_nvram_map_data.h + +SRCS+= bhnd_bus_if.c bhnd_bus_if.h \ + bhnd_chipc_if.c bhnd_chipc_if.h \ + bhnd_nvram_if.c bhnd_nvram_if.h SRCS+= device_if.h bus_if.h @@ -13,7 +19,6 @@ bhndb \ bhndb_pci \ cores \ - nvram \ siba \ siba_bhndb Index: head/sys/modules/bhnd/bhndb/Makefile =================================================================== --- head/sys/modules/bhnd/bhndb/Makefile +++ head/sys/modules/bhnd/bhndb/Makefile @@ -5,8 +5,10 @@ KMOD= bhndb SRCS= bhndb.c bhndb_subr.c bhndb_hwdata.c \ bhndb_bus_if.c bhndb_bus_if.h \ - bhndb_if.c bhndb_if.h \ - bhnd_bus_if.h + bhndb_if.c bhndb_if.h +SRCS+= bhnd_bus_if.h \ + bhnd_chipc_if.h \ + bhnd_nvram_if.h SRCS+= device_if.h bus_if.h pci_if.h Index: head/sys/modules/bhnd/bhndb_pci/Makefile =================================================================== --- head/sys/modules/bhnd/bhndb_pci/Makefile +++ head/sys/modules/bhnd/bhndb_pci/Makefile @@ -3,8 +3,10 @@ .PATH: ${.CURDIR}/../../../dev/bhnd/bhndb KMOD= bhndb_pci -SRCS= bhndb_pci.c bhndb_pci_hwdata.c +SRCS= bhndb_pci.c bhndb_pci_hwdata.c \ + bhndb_pci_sprom.c SRCS+= bhnd_bus_if.h bhndb_bus_if.h bhndb_if.h +SRCS+= bhnd_nvram_if.h SRCS+= device_if.h bus_if.h pci_if.h Index: head/sys/modules/bhnd/cores/bhnd_chipc/Makefile =================================================================== --- head/sys/modules/bhnd/cores/bhnd_chipc/Makefile +++ head/sys/modules/bhnd/cores/bhnd_chipc/Makefile @@ -3,8 +3,8 @@ .PATH: ${.CURDIR}/../../../../dev/bhnd/cores/chipc KMOD= bhnd_chipc -SRCS= chipc.c \ - bhnd_chipc_if.c bhnd_chipc_if.h -SRCS+= device_if.h bus_if.h bhnd_bus_if.h +SRCS= chipc.c +SRCS+= device_if.h bus_if.h bhnd_bus_if.h \ + bhnd_chipc_if.h bhnd_nvram_if.h .include Index: head/sys/modules/bhnd/nvram/Makefile =================================================================== --- head/sys/modules/bhnd/nvram/Makefile +++ head/sys/modules/bhnd/nvram/Makefile @@ -1,10 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../../dev/bhnd/nvram - -KMOD= bhnd_nvram -SRCS= bhnd_nvram_if.c bhnd_nvram_if.h bhnd_bus_if.h - -SRCS+= device_if.h bus_if.h - -.include Index: head/sys/modules/bwn_pci/Makefile =================================================================== --- head/sys/modules/bwn_pci/Makefile +++ head/sys/modules/bwn_pci/Makefile @@ -4,8 +4,8 @@ KMOD= if_bwn_pci SRCS= if_bwn_pci.c bwn_mac.c +SRCS+= bhnd_bus_if.h bhndb_bus_if.h \ + bhndb_if.h bhnd_nvram_map.h SRCS+= device_if.h bus_if.h pci_if.h \ - bhnd_bus_if.h bhndb_bus_if.h \ - bhndb_if.h .include