svn commit: r291264 - head/sys/dev/usb/wlan
Andriy Voskoboinyk
avos at FreeBSD.org
Tue Nov 24 19:20:47 UTC 2015
Author: avos
Date: Tue Nov 24 19:20:45 2015
New Revision: 291264
URL: https://svnweb.freebsd.org/changeset/base/291264
Log:
urtwn(4): rework ROM reading.
- Add error handling for urtwn_(r88e_)read_rom() and
urtwn_efuse_*() functions.
- Remove code duplication between urtwn_efuse_read() and
urtwn_r88e_read_rom().
- Merge r88e_rom and (r92c_)rom structures
(only one of them can be used at the same time).
- Other minor fixes / improvements.
Tested with RTL8188EU, STA mode
(URTWN_DEBUG + USB_DEBUG, hw.usb.urtwn.debug=3, no visual differences).
Reviewed by: kevlo
Approved by: adrian (mentor)
Differential Revision: https://reviews.freebsd.org/D4253
Modified:
head/sys/dev/usb/wlan/if_urtwn.c
head/sys/dev/usb/wlan/if_urtwnreg.h
head/sys/dev/usb/wlan/if_urtwnvar.h
Modified: head/sys/dev/usb/wlan/if_urtwn.c
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwn.c Tue Nov 24 18:51:17 2015 (r291263)
+++ head/sys/dev/usb/wlan/if_urtwn.c Tue Nov 24 19:20:45 2015 (r291264)
@@ -214,12 +214,19 @@ static void urtwn_r88e_rf_write(struct
static uint32_t urtwn_rf_read(struct urtwn_softc *, int, uint8_t);
static int urtwn_llt_write(struct urtwn_softc *, uint32_t,
uint32_t);
-static uint8_t urtwn_efuse_read_1(struct urtwn_softc *, uint16_t);
-static void urtwn_efuse_read(struct urtwn_softc *);
+static int urtwn_efuse_read_next(struct urtwn_softc *, uint8_t *);
+static int urtwn_efuse_read_data(struct urtwn_softc *, uint8_t *,
+ uint8_t, uint8_t);
+#ifdef URTWN_DEBUG
+static void urtwn_dump_rom_contents(struct urtwn_softc *,
+ uint8_t *, uint16_t);
+#endif
+static int urtwn_efuse_read(struct urtwn_softc *, uint8_t *,
+ uint16_t);
static void urtwn_efuse_switch_power(struct urtwn_softc *);
static int urtwn_read_chipid(struct urtwn_softc *);
-static void urtwn_read_rom(struct urtwn_softc *);
-static void urtwn_r88e_read_rom(struct urtwn_softc *);
+static int urtwn_read_rom(struct urtwn_softc *);
+static int urtwn_r88e_read_rom(struct urtwn_softc *);
static int urtwn_ra_init(struct urtwn_softc *);
static void urtwn_init_beacon(struct urtwn_softc *,
struct urtwn_vap *);
@@ -431,9 +438,15 @@ urtwn_attach(device_t self)
}
if (sc->chip & URTWN_CHIP_88E)
- urtwn_r88e_read_rom(sc);
+ error = urtwn_r88e_read_rom(sc);
else
- urtwn_read_rom(sc);
+ error = urtwn_read_rom(sc);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "%s: cannot read rom, error %d\n",
+ __func__, error);
+ URTWN_UNLOCK(sc);
+ goto detach;
+ }
device_printf(sc->sc_dev, "MAC/BB RTL%s, RF 6052 %dT%dR\n",
(sc->chip & URTWN_CHIP_92C) ? "8192CU" :
@@ -1224,68 +1237,137 @@ urtwn_llt_write(struct urtwn_softc *sc,
return (ETIMEDOUT);
}
-static uint8_t
-urtwn_efuse_read_1(struct urtwn_softc *sc, uint16_t addr)
+static int
+urtwn_efuse_read_next(struct urtwn_softc *sc, uint8_t *val)
{
uint32_t reg;
int ntries;
+ if (sc->last_rom_addr >= URTWN_EFUSE_MAX_LEN)
+ return (EFAULT);
+
reg = urtwn_read_4(sc, R92C_EFUSE_CTRL);
- reg = RW(reg, R92C_EFUSE_CTRL_ADDR, addr);
+ reg = RW(reg, R92C_EFUSE_CTRL_ADDR, sc->last_rom_addr);
reg &= ~R92C_EFUSE_CTRL_VALID;
+
urtwn_write_4(sc, R92C_EFUSE_CTRL, reg);
/* Wait for read operation to complete. */
for (ntries = 0; ntries < 100; ntries++) {
reg = urtwn_read_4(sc, R92C_EFUSE_CTRL);
if (reg & R92C_EFUSE_CTRL_VALID)
- return (MS(reg, R92C_EFUSE_CTRL_DATA));
+ break;
urtwn_ms_delay(sc);
}
- device_printf(sc->sc_dev,
- "could not read efuse byte at address 0x%x\n", addr);
- return (0xff);
+ if (ntries == 100) {
+ device_printf(sc->sc_dev,
+ "could not read efuse byte at address 0x%x\n",
+ sc->last_rom_addr);
+ return (ETIMEDOUT);
+ }
+
+ *val = MS(reg, R92C_EFUSE_CTRL_DATA);
+ sc->last_rom_addr++;
+
+ return (0);
}
+static int
+urtwn_efuse_read_data(struct urtwn_softc *sc, uint8_t *rom, uint8_t off,
+ uint8_t msk)
+{
+ uint8_t reg;
+ int i, error;
+
+ for (i = 0; i < 4; i++) {
+ if (msk & (1 << i))
+ continue;
+ error = urtwn_efuse_read_next(sc, ®);
+ if (error != 0)
+ return (error);
+ DPRINTF("rom[0x%03X] == 0x%02X\n", off * 8 + i * 2, reg);
+ rom[off * 8 + i * 2 + 0] = reg;
+
+ error = urtwn_efuse_read_next(sc, ®);
+ if (error != 0)
+ return (error);
+ DPRINTF("rom[0x%03X] == 0x%02X\n", off * 8 + i * 2 + 1, reg);
+ rom[off * 8 + i * 2 + 1] = reg;
+ }
+
+ return (0);
+}
+
+#ifdef URTWN_DEBUG
static void
-urtwn_efuse_read(struct urtwn_softc *sc)
+urtwn_dump_rom_contents(struct urtwn_softc *sc, uint8_t *rom, uint16_t size)
{
- uint8_t *rom = (uint8_t *)&sc->rom;
- uint16_t addr = 0;
- uint32_t reg;
- uint8_t off, msk;
int i;
+ /* Dump ROM contents. */
+ device_printf(sc->sc_dev, "%s:", __func__);
+ for (i = 0; i < size; i++) {
+ if (i % 32 == 0)
+ printf("\n%03X: ", i);
+ else if (i % 4 == 0)
+ printf(" ");
+
+ printf("%02X", rom[i]);
+ }
+ printf("\n");
+}
+#endif
+
+static int
+urtwn_efuse_read(struct urtwn_softc *sc, uint8_t *rom, uint16_t size)
+{
+#define URTWN_CHK(res) do { \
+ if ((error = res) != 0) \
+ goto end; \
+} while(0)
+ uint8_t msk, off, reg;
+ int error;
+
urtwn_efuse_switch_power(sc);
- memset(&sc->rom, 0xff, sizeof(sc->rom));
- while (addr < 512) {
- reg = urtwn_efuse_read_1(sc, addr);
- if (reg == 0xff)
- break;
- addr++;
- off = reg >> 4;
- msk = reg & 0xf;
- for (i = 0; i < 4; i++) {
- if (msk & (1 << i))
+ /* Read full ROM image. */
+ sc->last_rom_addr = 0;
+ memset(rom, 0xff, size);
+
+ URTWN_CHK(urtwn_efuse_read_next(sc, ®));
+ while (reg != 0xff) {
+ /* check for extended header */
+ if ((sc->chip & URTWN_CHIP_88E) && (reg & 0x1f) == 0x0f) {
+ off = reg >> 5;
+ URTWN_CHK(urtwn_efuse_read_next(sc, ®));
+
+ if ((reg & 0x0f) != 0x0f)
+ off = ((reg & 0xf0) >> 1) | off;
+ else
continue;
- rom[off * 8 + i * 2 + 0] =
- urtwn_efuse_read_1(sc, addr);
- addr++;
- rom[off * 8 + i * 2 + 1] =
- urtwn_efuse_read_1(sc, addr);
- addr++;
- }
+ } else
+ off = reg >> 4;
+ msk = reg & 0xf;
+
+ URTWN_CHK(urtwn_efuse_read_data(sc, rom, off, msk));
+ URTWN_CHK(urtwn_efuse_read_next(sc, ®));
}
+
+end:
+
#ifdef URTWN_DEBUG
- if (urtwn_debug >= 2) {
- /* Dump ROM content. */
- printf("\n");
- for (i = 0; i < sizeof(sc->rom); i++)
- printf("%02x:", rom[i]);
- printf("\n");
- }
+ if (urtwn_debug >= 2)
+ urtwn_dump_rom_contents(sc, rom, size);
#endif
+
urtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
+
+ if (error != 0) {
+ device_printf(sc->sc_dev, "%s: error while reading ROM\n",
+ __func__);
+ }
+
+ return (error);
+#undef URTWN_CHK
}
static void
@@ -1341,16 +1423,22 @@ urtwn_read_chipid(struct urtwn_softc *sc
return (0);
}
-static void
+static int
urtwn_read_rom(struct urtwn_softc *sc)
{
- struct r92c_rom *rom = &sc->rom;
+ struct r92c_rom *rom = &sc->rom.r92c_rom;
+ int error;
/* Read full ROM image. */
- urtwn_efuse_read(sc);
+ error = urtwn_efuse_read(sc, (uint8_t *)rom, sizeof(*rom));
+ if (error != 0)
+ return (error);
/* XXX Weird but this is what the vendor driver does. */
- sc->pa_setting = urtwn_efuse_read_1(sc, 0x1fa);
+ sc->last_rom_addr = 0x1fa;
+ error = urtwn_efuse_read_next(sc, &sc->pa_setting);
+ if (error != 0)
+ return (error);
DPRINTF("PA setting=0x%x\n", sc->pa_setting);
sc->board_type = MS(rom->rf_opt1, R92C_ROM_RF1_BOARD_TYPE);
@@ -1362,67 +1450,40 @@ urtwn_read_rom(struct urtwn_softc *sc)
sc->sc_rf_write = urtwn_r92c_rf_write;
sc->sc_power_on = urtwn_r92c_power_on;
sc->sc_dma_init = urtwn_r92c_dma_init;
+
+ return (0);
}
-static void
+static int
urtwn_r88e_read_rom(struct urtwn_softc *sc)
{
- uint8_t *rom = sc->r88e_rom;
- uint16_t addr = 0;
- uint32_t reg;
- uint8_t off, msk, tmp;
- int i;
-
- off = 0;
- urtwn_efuse_switch_power(sc);
-
- /* Read full ROM image. */
- memset(&sc->r88e_rom, 0xff, sizeof(sc->r88e_rom));
- while (addr < 512) {
- reg = urtwn_efuse_read_1(sc, addr);
- if (reg == 0xff)
- break;
- addr++;
- if ((reg & 0x1f) == 0x0f) {
- tmp = (reg & 0xe0) >> 5;
- reg = urtwn_efuse_read_1(sc, addr);
- if ((reg & 0x0f) != 0x0f)
- off = ((reg & 0xf0) >> 1) | tmp;
- addr++;
- } else
- off = reg >> 4;
- msk = reg & 0xf;
- for (i = 0; i < 4; i++) {
- if (msk & (1 << i))
- continue;
- rom[off * 8 + i * 2 + 0] =
- urtwn_efuse_read_1(sc, addr);
- addr++;
- rom[off * 8 + i * 2 + 1] =
- urtwn_efuse_read_1(sc, addr);
- addr++;
- }
- }
+ uint8_t *rom = sc->rom.r88e_rom;
+ uint16_t addr;
+ int error, i;
- urtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
+ error = urtwn_efuse_read(sc, rom, sizeof(sc->rom.r88e_rom));
+ if (error != 0)
+ return (error);
addr = 0x10;
for (i = 0; i < 6; i++)
- sc->cck_tx_pwr[i] = sc->r88e_rom[addr++];
+ sc->cck_tx_pwr[i] = rom[addr++];
for (i = 0; i < 5; i++)
- sc->ht40_tx_pwr[i] = sc->r88e_rom[addr++];
- sc->bw20_tx_pwr_diff = (sc->r88e_rom[addr] & 0xf0) >> 4;
+ sc->ht40_tx_pwr[i] = rom[addr++];
+ sc->bw20_tx_pwr_diff = (rom[addr] & 0xf0) >> 4;
if (sc->bw20_tx_pwr_diff & 0x08)
sc->bw20_tx_pwr_diff |= 0xf0;
- sc->ofdm_tx_pwr_diff = (sc->r88e_rom[addr] & 0xf);
+ sc->ofdm_tx_pwr_diff = (rom[addr] & 0xf);
if (sc->ofdm_tx_pwr_diff & 0x08)
sc->ofdm_tx_pwr_diff |= 0xf0;
- sc->regulatory = MS(sc->r88e_rom[0xc1], R92C_ROM_RF1_REGULATORY);
- IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, &sc->r88e_rom[0xd7]);
+ sc->regulatory = MS(rom[0xc1], R92C_ROM_RF1_REGULATORY);
+ IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, &rom[0xd7]);
sc->sc_rf_write = urtwn_r88e_rf_write;
sc->sc_power_on = urtwn_r88e_power_on;
sc->sc_dma_init = urtwn_r88e_dma_init;
+
+ return (0);
}
/*
@@ -2944,7 +3005,7 @@ urtwn_bb_init(struct urtwn_softc *sc)
urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420);
urtwn_ms_delay(sc);
- crystalcap = sc->r88e_rom[0xb9];
+ crystalcap = sc->rom.r88e_rom[0xb9];
if (crystalcap == 0xff)
crystalcap = 0x20;
crystalcap &= 0x3f;
@@ -3210,7 +3271,7 @@ urtwn_get_txpower(struct urtwn_softc *sc
uint16_t power[URTWN_RIDX_COUNT])
{
struct ieee80211com *ic = &sc->sc_ic;
- struct r92c_rom *rom = &sc->rom;
+ struct r92c_rom *rom = &sc->rom.r92c_rom;
uint16_t cckpow, ofdmpow, htpow, diff, max;
const struct urtwn_txpwr *base;
int ridx, chan, group;
Modified: head/sys/dev/usb/wlan/if_urtwnreg.h
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwnreg.h Tue Nov 24 18:51:17 2015 (r291263)
+++ head/sys/dev/usb/wlan/if_urtwnreg.h Tue Nov 24 19:20:45 2015 (r291264)
@@ -938,6 +938,8 @@ struct r92c_rom {
uint8_t curstomer_id;
} __packed;
+#define URTWN_EFUSE_MAX_LEN 512
+
/* Rx MAC descriptor. */
struct r92c_rx_stat {
uint32_t rxdw0;
Modified: head/sys/dev/usb/wlan/if_urtwnvar.h
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwnvar.h Tue Nov 24 18:51:17 2015 (r291263)
+++ head/sys/dev/usb/wlan/if_urtwnvar.h Tue Nov 24 19:20:45 2015 (r291264)
@@ -128,6 +128,11 @@ enum {
#define URTWN_EP_QUEUES URTWN_BULK_RX
+union urtwn_rom {
+ struct r92c_rom r92c_rom;
+ uint8_t r88e_rom[URTWN_EFUSE_MAX_LEN];
+};
+
struct urtwn_softc {
struct ieee80211com sc_ic;
struct mbufq sc_snd;
@@ -177,12 +182,12 @@ struct urtwn_softc {
struct urtwn_fw_info fw;
void *fw_virtaddr;
- struct r92c_rom rom;
- uint8_t r88e_rom[512];
+ union urtwn_rom rom;
uint8_t cck_tx_pwr[6];
uint8_t ht40_tx_pwr[5];
int8_t bw20_tx_pwr_diff;
int8_t ofdm_tx_pwr_diff;
+ uint16_t last_rom_addr;
struct callout sc_watchdog_ch;
struct mtx sc_mtx;
More information about the svn-src-head
mailing list