- Fix incorrect values in the computation of transmit power for the
authorkevlo <kevlo@openbsd.org>
Fri, 16 Jun 2017 14:57:51 +0000 (14:57 +0000)
committerkevlo <kevlo@openbsd.org>
Fri, 16 Jun 2017 14:57:51 +0000 (14:57 +0000)
  rtl8188eu chipset.
- Small code refactoring:
  - replace hardcoded rate indexes with their name, like athn(4).
  - replace fields offsets with the structure; from FreeBSD r294198.
  - be compliant with definitions of the efuse in vendor hal_pg.h and
    rename struct r92c_rom member names: s/channel_plan/reserved5/,
    s/xtal_calib/channel_plan.
  - no need to disable HWPDN twice in urtwn_r88e_power_on().

Tested by stsp@ and myself with RTL8188CUS, RTL8192CU, RTL8188EU, and
RTL8188CE devices.

ok stsp@

sys/dev/ic/r92creg.h
sys/dev/ic/rtwn.c
sys/dev/ic/rtwnvar.h
sys/dev/pci/if_rtwn.c
sys/dev/usb/if_urtwn.c

index eaa1dc6..7d8d044 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: r92creg.h,v 1.9 2017/05/19 18:15:15 stsp Exp $        */
+/*     $OpenBSD: r92creg.h,v 1.10 2017/06/16 14:57:51 kevlo Exp $      */
 
 /*-
  * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -1015,7 +1015,7 @@ struct r92c_rom {
        uint16_t        reserved3;
        uint8_t         usb_phy;
        uint8_t         reserved4[3];
-       uint8_t         macaddr[6];
+       uint8_t         macaddr[IEEE80211_ADDR_LEN];
        uint8_t         string[61];     /* "Realtek" */
        uint8_t         subcustomer_id;
        uint8_t         cck_tx_pwr[R92C_MAX_CHAINS][3];
@@ -1025,7 +1025,7 @@ struct r92c_rom {
        uint8_t         ofdm_tx_pwr_diff[3];
        uint8_t         ht40_max_pwr[3];
        uint8_t         ht20_max_pwr[3];
-       uint8_t         xtal_calib;
+       uint8_t         channel_plan;
        uint8_t         tssi[R92C_MAX_CHAINS];
        uint8_t         thermal_meter;
        uint8_t         rf_opt1;
@@ -1042,11 +1042,51 @@ struct r92c_rom {
        uint8_t         rf_opt2;
        uint8_t         rf_opt3;
        uint8_t         rf_opt4;
-       uint8_t         channel_plan;
+       uint8_t         reserved5;
        uint8_t         version;
        uint8_t         curstomer_id;
 } __packed;
 
+struct r88e_tx_pwr {
+       uint8_t         cck_tx_pwr[6];
+       uint8_t         ht40_tx_pwr[5];
+       uint8_t         ht20_ofdm_tx_pwr_diff;
+#define R88E_ROM_TXPWR_HT20_DIFF_M     0xf0
+#define R88E_ROM_TXPWR_HT20_DIFF_S     4
+#define R88E_ROM_TXPWR_OFDM_DIFF_M     0x0f
+#define R88E_ROM_TXPWR_OFDM_DIFF_S     0
+
+} __packed;
+
+/*
+ * RTL8188EU ROM image.
+ */
+struct r88e_rom {
+       uint8_t                 reserved1[16];
+       struct r88e_tx_pwr      txpwr;
+       uint8_t                 reserved2[156];
+       uint8_t                 channel_plan;
+       uint8_t                 xtal;
+       uint8_t                 thermal_meter;
+       uint8_t                 reserved3[6];
+       uint8_t                 rf_board_opt;
+       uint8_t                 rf_feature_opt;
+       uint8_t                 rf_bt_opt;
+       uint8_t                 version;
+       uint8_t                 customer_id;
+       uint8_t                 reserved4[3];
+       uint8_t                 rf_ant_opt;
+       uint8_t                 reserved5[6];
+       uint16_t                vid;
+       uint16_t                pid;
+       uint8_t                 usb_opt;
+       uint8_t                 reserved6[2];
+       uint8_t                 macaddr[IEEE80211_ADDR_LEN];
+       uint8_t                 reserved7[2];
+       uint8_t                 string[33];     /* "Realtek" */
+       uint8_t                 reserved8[256];
+} __packed;
+
 /* Rx PHY descriptor. */
 struct r92c_rx_phystat {
        uint32_t        phydw0;
@@ -2272,10 +2312,6 @@ struct r92c_txpwr {
        uint8_t pwr[3][28];
 };
 
-struct r88e_txpwr {
-       uint8_t pwr[6][28];
-};
-
 /*
  * Per RF chain/group/rate Tx gain values.
  */
@@ -2344,44 +2380,3 @@ static const struct r92c_txpwr rtl8188ru_txagc[] = {
        }
        } }
 };
-
-static const struct r88e_txpwr rtl8188eu_txagc[] = {
-       { {     /* Chain 0. */
-       {       /* Group 0. */
-       0x00, 0x00, 0x00, 0x00,                         /* CCK1~11. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* MCS8~15. */
-       },
-       {       /* Group 1. */
-       0x00, 0x00, 0x00, 0x00,                         /* CCK1~11. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* MCS8~15. */
-       },
-       {       /* Group 2. */
-       0x00, 0x00, 0x00, 0x00,                         /* CCK1~11. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* MCS8~15. */
-       },
-       {       /* Group 3. */
-       0x00, 0x00, 0x00, 0x00,                         /* CCK1~11. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* MCS8~15. */
-       },
-       {       /* Group 4. */
-       0x00, 0x00, 0x00, 0x00,                         /* CCK1~11. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* MCS8~15. */
-       },
-       {       /* Group 5. */
-       0x00, 0x00, 0x00, 0x00,                         /* CCK1~11. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* MCS8~15. */
-       }
-       } }
-};
index 75baea2..bca14ca 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rtwn.c,v 1.21 2017/05/19 18:15:15 stsp Exp $  */
+/*     $OpenBSD: rtwn.c,v 1.22 2017/06/16 14:57:51 kevlo Exp $ */
 
 /*-
  * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -18,7 +18,7 @@
  */
 
 /*
- * Driver for Realtek RTL8188CE
+ * Driver for Realtek 802.11b/g/n chipsets.
  */
 
 #include "bpfilter.h"
 #include <dev/ic/r92creg.h>
 #include <dev/ic/rtwnvar.h>
 
-#define RTWN_RIDX_COUNT        28
+#define RTWN_RIDX_CCK1         0
+#define RTWN_RIDX_CCK2         1
+#define RTWN_RIDX_CCK11                3
+#define RTWN_RIDX_OFDM6                4
+#define RTWN_RIDX_OFDM54       11
+#define RTWN_RIDX_MCS0         12
+#define RTWN_RIDX_MCS8         (RTWN_RIDX_MCS0 + 8)
+#define RTWN_RIDX_MCS15                27
+#define RTWN_RIDX_MAX          27
+
+#define RTWN_POWER_CCK1                0
+#define RTWN_POWER_CCK2                1
+#define RTWN_POWER_CCK55       2
+#define RTWN_POWER_CCK11       3
+#define RTWN_POWER_OFDM6       4
+#define RTWN_POWER_OFDM9       5
+#define RTWN_POWER_OFDM12      6
+#define RTWN_POWER_OFDM18      7
+#define RTWN_POWER_OFDM24      8
+#define RTWN_POWER_OFDM36      9
+#define RTWN_POWER_OFDM48      10 
+#define RTWN_POWER_OFDM54      11
+#define RTWN_POWER_MCS(mcs)    (12 + (mcs))
+#define RTWN_POWER_COUNT       28
+
 
 #ifdef RTWN_DEBUG
 #define DPRINTF(x)     do { if (rtwn_debug) printf x; } while (0)
@@ -76,10 +100,11 @@ void               rtwn_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t);
 uint32_t       rtwn_rf_read(struct rtwn_softc *, int, uint8_t);
 void           rtwn_cam_write(struct rtwn_softc *, uint32_t, uint32_t);
 uint8_t                rtwn_efuse_read_1(struct rtwn_softc *, uint16_t);
-void           rtwn_efuse_read(struct rtwn_softc *);
+void           rtwn_efuse_read(struct rtwn_softc *, uint8_t *, size_t);
 void           rtwn_efuse_switch_power(struct rtwn_softc *);
-int            rtwn_read_chipid(struct rtwn_softc *, uint32_t);
-void           rtwn_read_rom(struct rtwn_softc *);
+int            rtwn_read_chipid(struct rtwn_softc *);
+void           rtwn_read_rom(void *);
+void           rtwn_r92c_read_rom(struct rtwn_softc *);
 void           rtwn_r88e_read_rom(struct rtwn_softc *);
 int            rtwn_media_change(struct ifnet *);
 int            rtwn_ra_init(struct rtwn_softc *);
@@ -101,7 +126,9 @@ void                rtwn_pa_bias_init(struct rtwn_softc *);
 void           rtwn_rxfilter_init(struct rtwn_softc *);
 void           rtwn_edca_init(struct rtwn_softc *);
 void           rtwn_write_txpower(struct rtwn_softc *, int, uint16_t[]);
-void           rtwn_get_txpower(struct rtwn_softc *, int,
+void           rtwn_get_txpower(void *, int, struct ieee80211_channel *,
+                   struct ieee80211_channel *, uint16_t[]);
+void           rtwn_r92c_get_txpower(struct rtwn_softc *, int,
                    struct ieee80211_channel *, struct ieee80211_channel *,
                    uint16_t[]);
 void           rtwn_r88e_get_txpower(struct rtwn_softc *, int,
@@ -132,8 +159,13 @@ void               rtwn_stop(struct ifnet *);
 #define        rtwn_bb_write   rtwn_write_4
 #define rtwn_bb_read   rtwn_read_4
 
+/* 
+ * Macro to convert 4-bit signed integer to 8-bit signed integer.
+ */
+#define RTWN_SIGN4TO8(val)     (((val) & 0x08) ? (val) | 0xf0 : (val))
+
 int
-rtwn_attach(struct device *pdev, struct rtwn_softc *sc, uint32_t chip_type)
+rtwn_attach(struct device *pdev, struct rtwn_softc *sc)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -143,13 +175,15 @@ rtwn_attach(struct device *pdev, struct rtwn_softc *sc, uint32_t chip_type)
 
        task_set(&sc->init_task, rtwn_init_task, sc);
 
-       sc->chip = 0;
-       error = rtwn_read_chipid(sc, chip_type);
+       error = rtwn_read_chipid(sc);
        if (error != 0) {
                printf("%s: unsupported chip\n", sc->sc_pdev->dv_xname);
                return (ENXIO);
        }
 
+       sc->sc_ops.get_txpower = rtwn_get_txpower;
+       sc->sc_ops.read_rom = rtwn_read_rom;
+
        /* Determine number of Tx/Rx chains. */
        if (sc->chip & RTWN_CHIP_92C) {
                sc->ntxchains = (sc->chip & RTWN_CHIP_92C_1T2R) ? 1 : 2;
@@ -159,10 +193,7 @@ rtwn_attach(struct device *pdev, struct rtwn_softc *sc, uint32_t chip_type)
                sc->nrxchains = 1;
        }
 
-       if (sc->chip & RTWN_CHIP_88E)
-               rtwn_r88e_read_rom(sc);
-       else
-               rtwn_read_rom(sc);
+       rtwn_read_rom(sc);
 
        if (sc->chip & RTWN_CHIP_PCI) {
                printf("%s: MAC/BB RTL%s, RF 6052 %dT%dR, address %s\n",
@@ -438,24 +469,34 @@ rtwn_efuse_read_1(struct rtwn_softc *sc, uint16_t addr)
 }
 
 void
-rtwn_efuse_read(struct rtwn_softc *sc)
+rtwn_efuse_read(struct rtwn_softc *sc, uint8_t *rom, size_t size)
 {
-       uint8_t *rom = (uint8_t *)&sc->rom;
+       uint8_t off, msk, tmp;
        uint16_t addr = 0;
        uint32_t reg;
-       uint8_t off, msk;
-       int i;
+       int i, len;
 
        rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON);
        rtwn_efuse_switch_power(sc);
 
-       memset(&sc->rom, 0xff, sizeof(sc->rom));
-       while (addr < 512) {
+       memset(rom, 0xff, size);
+       len = (sc->chip & RTWN_CHIP_88E) ? 256 : 512;
+       while (addr < len) {
                reg = rtwn_efuse_read_1(sc, addr);
                if (reg == 0xff)
                        break;
                addr++;
-               off = reg >> 4;
+
+               /* Check for extended header. */
+               if ((sc->sc_flags & RTWN_FLAG_EXT_HDR) &&
+                   (reg & 0x1f) == 0x0f) {
+                       tmp = (reg & 0xe0) >> 5;
+                       reg = rtwn_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))
@@ -472,7 +513,7 @@ rtwn_efuse_read(struct rtwn_softc *sc)
        if (rtwn_debug >= 2) {
                /* Dump ROM content. */
                printf("\n");
-               for (i = 0; i < sizeof(sc->rom); i++)
+               for (i = 0; i < size); i++)
                        printf("%02x:", rom[i]);
                printf("\n");
        }
@@ -504,12 +545,12 @@ rtwn_efuse_switch_power(struct rtwn_softc *sc)
 }
 
 int
-rtwn_read_chipid(struct rtwn_softc *sc, uint32_t chip_type)
+rtwn_read_chipid(struct rtwn_softc *sc)
 {
        uint32_t reg;
 
-       if (chip_type & RTWN_CHIP_88E) {
-               sc->chip = chip_type;
+       if (sc->chip & RTWN_CHIP_88E) {
+               sc->sc_flags |= RTWN_FLAG_EXT_HDR;
                return (0);
        }
 
@@ -518,16 +559,16 @@ rtwn_read_chipid(struct rtwn_softc *sc, uint32_t chip_type)
                /* Unsupported test chip. */
                return (EIO);
 
-       if ((chip_type & (RTWN_CHIP_92C | RTWN_CHIP_88C)) != 0) {
+       if ((sc->chip & (RTWN_CHIP_92C | RTWN_CHIP_88C)) != 0) {
                if (reg & R92C_SYS_CFG_TYPE_92C) {
-                       sc->chip = RTWN_CHIP_92C;
+                       sc->chip &= ~RTWN_CHIP_88C;
                        /* Check if it is a castrated 8192C. */
                        if (MS(rtwn_read_4(sc, R92C_HPON_FSM),
                            R92C_HPON_FSM_CHIP_BONDING_ID) ==
                            R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R)
                                sc->chip |= RTWN_CHIP_92C_1T2R;
                } else
-                       sc->chip = RTWN_CHIP_88C;
+                       sc->chip &= ~RTWN_CHIP_92C;
 
                if (reg & R92C_SYS_CFG_VENDOR_UMC) {
                        sc->chip |= RTWN_CHIP_UMC;
@@ -535,7 +576,6 @@ rtwn_read_chipid(struct rtwn_softc *sc, uint32_t chip_type)
                                sc->chip |= RTWN_CHIP_UMC_A_CUT;
                }
 
-               sc->chip |= (chip_type & (RTWN_CHIP_USB | RTWN_CHIP_PCI));
                return (0);
        }
 
@@ -543,13 +583,25 @@ rtwn_read_chipid(struct rtwn_softc *sc, uint32_t chip_type)
 }
 
 void
-rtwn_read_rom(struct rtwn_softc *sc)
+rtwn_read_rom(void *cookie)
+{
+       struct rtwn_softc *sc = cookie;
+
+       if (sc->chip & RTWN_CHIP_88E)
+               rtwn_r88e_read_rom(sc);
+       else
+               rtwn_r92c_read_rom(sc);
+}
+
+void
+rtwn_r92c_read_rom(struct rtwn_softc *sc)
 {
        struct ieee80211com *ic = &sc->sc_ic;
-       struct r92c_rom *rom = &sc->rom;
+       struct r92c_rom *rom = &sc->sc_r92c_rom;
 
        /* Read full ROM image. */
-       rtwn_efuse_read(sc);
+       rtwn_efuse_read(sc, (uint8_t *)&sc->sc_r92c_rom,
+           sizeof(sc->sc_r92c_rom));
 
        /* XXX Weird but this is what the vendor driver does. */
        sc->pa_setting = rtwn_efuse_read_1(sc, 0x1fa);
@@ -568,60 +620,19 @@ void
 rtwn_r88e_read_rom(struct rtwn_softc *sc)
 {
        struct ieee80211com *ic = &sc->sc_ic;
-       uint8_t *rom = sc->r88e_rom;
-       uint16_t addr = 0;
-       uint32_t reg;
-       uint8_t off, msk, tmp;
-       int i;
-
-       off = 0;
-
-       rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON);
-       rtwn_efuse_switch_power(sc);
+       struct r88e_rom *rom = &sc->sc_r88e_rom;
 
        /* Read full ROM image. */
-       memset(&sc->r88e_rom, 0xff, sizeof(sc->r88e_rom));
-       while (addr < 512) {
-               reg = rtwn_efuse_read_1(sc, addr);
-               if (reg == 0xff)
-                       break;
-               addr++;
-               if ((reg & 0x1f) == 0x0f) {
-                       tmp = (reg & 0xe0) >> 5;
-                       reg = rtwn_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] =
-                           rtwn_efuse_read_1(sc, addr);
-                       addr++;
-                       rom[off * 8 + i * 2 + 1] =
-                           rtwn_efuse_read_1(sc, addr);
-                       addr++;
-               }
-       }
+       rtwn_efuse_read(sc, (uint8_t *)&sc->sc_r88e_rom,
+           sizeof(sc->sc_r88e_rom));
 
-       rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF);
+       sc->crystal_cap = rom->xtal;
+       DPRINTF(("Crystal cap=0x%x\n", sc->crystal_cap));
+
+       sc->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY);
+       DPRINTF(("regulatory type=%d\n", sc->regulatory));
 
-       addr = 0x10;
-       for (i = 0; i < 6; i++)
-               sc->cck_tx_pwr[i] = sc->r88e_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;
-       if (sc->bw20_tx_pwr_diff & 0x08)
-               sc->bw20_tx_pwr_diff |= 0xf0;
-       sc->ofdm_tx_pwr_diff = (sc->r88e_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(ic->ic_myaddr, &sc->r88e_rom[0xd7]);
+       IEEE80211_ADDR_COPY(ic->ic_myaddr, rom->macaddr);
 }
 
 int
@@ -1763,71 +1774,83 @@ rtwn_edca_init(struct rtwn_softc *sc)
 
 void
 rtwn_write_txpower(struct rtwn_softc *sc, int chain,
-    uint16_t power[RTWN_RIDX_COUNT])
+    uint16_t power[RTWN_POWER_COUNT])
 {
        uint32_t reg;
 
        /* Write per-CCK rate Tx power. */
        if (chain == 0) {
                reg = rtwn_bb_read(sc, R92C_TXAGC_A_CCK1_MCS32);
-               reg = RW(reg, R92C_TXAGC_A_CCK1,  power[0]);
+               reg = RW(reg, R92C_TXAGC_A_CCK1,  power[RTWN_POWER_CCK1]);
                rtwn_bb_write(sc, R92C_TXAGC_A_CCK1_MCS32, reg);
                reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
-               reg = RW(reg, R92C_TXAGC_A_CCK2,  power[1]);
-               reg = RW(reg, R92C_TXAGC_A_CCK55, power[2]);
-               reg = RW(reg, R92C_TXAGC_A_CCK11, power[3]);
+               reg = RW(reg, R92C_TXAGC_A_CCK2,  power[RTWN_POWER_CCK2]);
+               reg = RW(reg, R92C_TXAGC_A_CCK55, power[RTWN_POWER_CCK55]);
+               reg = RW(reg, R92C_TXAGC_A_CCK11, power[RTWN_POWER_CCK11]);
                rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
        } else {
                reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK1_55_MCS32);
-               reg = RW(reg, R92C_TXAGC_B_CCK1,  power[0]);
-               reg = RW(reg, R92C_TXAGC_B_CCK2,  power[1]);
-               reg = RW(reg, R92C_TXAGC_B_CCK55, power[2]);
+               reg = RW(reg, R92C_TXAGC_B_CCK1,  power[RTWN_POWER_CCK1]);
+               reg = RW(reg, R92C_TXAGC_B_CCK2,  power[RTWN_POWER_CCK2]);
+               reg = RW(reg, R92C_TXAGC_B_CCK55, power[RTWN_POWER_CCK55]);
                rtwn_bb_write(sc, R92C_TXAGC_B_CCK1_55_MCS32, reg);
                reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
-               reg = RW(reg, R92C_TXAGC_B_CCK11, power[3]);
+               reg = RW(reg, R92C_TXAGC_B_CCK11, power[RTWN_POWER_CCK11]);
                rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
        }
        /* Write per-OFDM rate Tx power. */
        rtwn_bb_write(sc, R92C_TXAGC_RATE18_06(chain),
-           SM(R92C_TXAGC_RATE06, power[ 4]) |
-           SM(R92C_TXAGC_RATE09, power[ 5]) |
-           SM(R92C_TXAGC_RATE12, power[ 6]) |
-           SM(R92C_TXAGC_RATE18, power[ 7]));
+           SM(R92C_TXAGC_RATE06, power[RTWN_POWER_OFDM6]) |
+           SM(R92C_TXAGC_RATE09, power[RTWN_POWER_OFDM9]) |
+           SM(R92C_TXAGC_RATE12, power[RTWN_POWER_OFDM12]) |
+           SM(R92C_TXAGC_RATE18, power[RTWN_POWER_OFDM18]));
        rtwn_bb_write(sc, R92C_TXAGC_RATE54_24(chain),
-           SM(R92C_TXAGC_RATE24, power[ 8]) |
-           SM(R92C_TXAGC_RATE36, power[ 9]) |
-           SM(R92C_TXAGC_RATE48, power[10]) |
-           SM(R92C_TXAGC_RATE54, power[11]));
+           SM(R92C_TXAGC_RATE24, power[RTWN_POWER_OFDM24]) |
+           SM(R92C_TXAGC_RATE36, power[RTWN_POWER_OFDM36]) |
+           SM(R92C_TXAGC_RATE48, power[RTWN_POWER_OFDM48]) |
+           SM(R92C_TXAGC_RATE54, power[RTWN_POWER_OFDM54]));
        /* Write per-MCS Tx power. */
        rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain),
-           SM(R92C_TXAGC_MCS00,  power[12]) |
-           SM(R92C_TXAGC_MCS01,  power[13]) |
-           SM(R92C_TXAGC_MCS02,  power[14]) |
-           SM(R92C_TXAGC_MCS03,  power[15]));
+           SM(R92C_TXAGC_MCS00,  power[RTWN_POWER_MCS( 0)]) |
+           SM(R92C_TXAGC_MCS01,  power[RTWN_POWER_MCS( 1)]) |
+           SM(R92C_TXAGC_MCS02,  power[RTWN_POWER_MCS( 2)]) |
+           SM(R92C_TXAGC_MCS03,  power[RTWN_POWER_MCS( 3)]));
        rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain),
-           SM(R92C_TXAGC_MCS04,  power[16]) |
-           SM(R92C_TXAGC_MCS05,  power[17]) |
-           SM(R92C_TXAGC_MCS06,  power[18]) |
-           SM(R92C_TXAGC_MCS07,  power[19]));
+           SM(R92C_TXAGC_MCS04,  power[RTWN_POWER_MCS( 4)]) |
+           SM(R92C_TXAGC_MCS05,  power[RTWN_POWER_MCS( 5)]) |
+           SM(R92C_TXAGC_MCS06,  power[RTWN_POWER_MCS( 6)]) |
+           SM(R92C_TXAGC_MCS07,  power[RTWN_POWER_MCS( 7)]));
        rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain),
-           SM(R92C_TXAGC_MCS08,  power[20]) |
-           SM(R92C_TXAGC_MCS09,  power[21]) |
-           SM(R92C_TXAGC_MCS10,  power[22]) |
-           SM(R92C_TXAGC_MCS11,  power[23]));
+           SM(R92C_TXAGC_MCS08,  power[RTWN_POWER_MCS( 8)]) |
+           SM(R92C_TXAGC_MCS09,  power[RTWN_POWER_MCS( 9)]) |
+           SM(R92C_TXAGC_MCS10,  power[RTWN_POWER_MCS(10)]) |
+           SM(R92C_TXAGC_MCS11,  power[RTWN_POWER_MCS(11)]));
        rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain),
-           SM(R92C_TXAGC_MCS12,  power[24]) |
-           SM(R92C_TXAGC_MCS13,  power[25]) |
-           SM(R92C_TXAGC_MCS14,  power[26]) |
-           SM(R92C_TXAGC_MCS15,  power[27]));
+           SM(R92C_TXAGC_MCS12,  power[RTWN_POWER_MCS(12)]) |
+           SM(R92C_TXAGC_MCS13,  power[RTWN_POWER_MCS(13)]) |
+           SM(R92C_TXAGC_MCS14,  power[RTWN_POWER_MCS(14)]) |
+           SM(R92C_TXAGC_MCS15,  power[RTWN_POWER_MCS(15)]));
 }
 
 void
-rtwn_get_txpower(struct rtwn_softc *sc, int chain,
+rtwn_get_txpower(void *cookie, int chain, struct ieee80211_channel *c,
+    struct ieee80211_channel *extc, uint16_t power[RTWN_POWER_COUNT])
+{
+       struct rtwn_softc *sc = cookie;
+
+       if (sc->chip & RTWN_CHIP_88E)
+               rtwn_r88e_get_txpower(sc, chain, c, extc, power);
+       else
+               rtwn_r92c_get_txpower(sc, chain, c, extc, power);
+}
+
+void
+rtwn_r92c_get_txpower(struct rtwn_softc *sc, int chain,
     struct ieee80211_channel *c, struct ieee80211_channel *extc,
-    uint16_t power[RTWN_RIDX_COUNT])
+    uint16_t power[RTWN_POWER_COUNT])
 {
        struct ieee80211com *ic = &sc->sc_ic;
-       struct r92c_rom *rom = &sc->rom;
+       struct r92c_rom *rom = &sc->sc_r92c_rom;
        uint16_t cckpow, ofdmpow, htpow, diff, max;
        const struct r92c_txpwr *base;
        int ridx, chan, group;
@@ -1850,12 +1873,12 @@ rtwn_get_txpower(struct rtwn_softc *sc, int chain,
        } else
                base = &rtl8192cu_txagc[chain];
 
-       memset(power, 0, RTWN_RIDX_COUNT * sizeof(power[0]));
+       memset(power, 0, RTWN_POWER_COUNT * sizeof(power[0]));
        if (sc->regulatory == 0) {
-               for (ridx = 0; ridx <= 3; ridx++)
+               for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++)
                        power[ridx] = base->pwr[0][ridx];
        }
-       for (ridx = 4; ridx < RTWN_RIDX_COUNT; ridx++) {
+       for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_MAX; ridx++) {
                if (sc->regulatory == 3) {
                        power[ridx] = base->pwr[0][ridx];
                        /* Apply vendor limits. */
@@ -1875,7 +1898,7 @@ rtwn_get_txpower(struct rtwn_softc *sc, int chain,
 
        /* Compute per-CCK rate Tx power. */
        cckpow = rom->cck_tx_pwr[chain][group];
-       for (ridx = 0; ridx <= 3; ridx++) {
+       for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) {
                power[ridx] += cckpow;
                if (power[ridx] > R92C_MAX_TX_PWR)
                        power[ridx] = R92C_MAX_TX_PWR;
@@ -1893,7 +1916,7 @@ rtwn_get_txpower(struct rtwn_softc *sc, int chain,
        diff = rom->ofdm_tx_pwr_diff[group];
        diff = (diff >> (chain * 4)) & 0xf;
        ofdmpow = htpow + diff; /* HT->OFDM correction. */
-       for (ridx = 4; ridx <= 11; ridx++) {
+       for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) {
                power[ridx] += ofdmpow;
                if (power[ridx] > R92C_MAX_TX_PWR)
                        power[ridx] = R92C_MAX_TX_PWR;
@@ -1905,7 +1928,7 @@ rtwn_get_txpower(struct rtwn_softc *sc, int chain,
                diff = (diff >> (chain * 4)) & 0xf;
                htpow += diff;  /* HT40->HT20 correction. */
        }
-       for (ridx = 12; ridx <= 27; ridx++) {
+       for (ridx = RTWN_RIDX_MCS0; ridx <= RTWN_RIDX_MCS15; ridx++) {
                power[ridx] += htpow;
                if (power[ridx] > R92C_MAX_TX_PWR)
                        power[ridx] = R92C_MAX_TX_PWR;
@@ -1914,7 +1937,7 @@ rtwn_get_txpower(struct rtwn_softc *sc, int chain,
        if (rtwn_debug >= 4) {
                /* Dump per-rate Tx power values. */
                printf("Tx power for chain %d:\n", chain);
-               for (ridx = 0; ridx < RTWN_RIDX_COUNT; ridx++)
+               for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_MAX; ridx++)
                        printf("Rate %d = %u\n", ridx, power[ridx]);
        }
 #endif
@@ -1923,11 +1946,12 @@ rtwn_get_txpower(struct rtwn_softc *sc, int chain,
 void
 rtwn_r88e_get_txpower(struct rtwn_softc *sc, int chain,
     struct ieee80211_channel *c, struct ieee80211_channel *extc,
-    uint16_t power[RTWN_RIDX_COUNT])
+    uint16_t power[RTWN_POWER_COUNT])
 {
        struct ieee80211com *ic = &sc->sc_ic;
-       uint16_t cckpow, ofdmpow, bw20pow, htpow;
-       const struct r88e_txpwr *base;
+       struct r88e_rom *rom = &sc->sc_r88e_rom;
+       uint8_t cckpow, htpow, ofdmpow;
+       int8_t diff;
        int ridx, chan, group;
 
        /* Determine channel group. */
@@ -1945,45 +1969,37 @@ rtwn_r88e_get_txpower(struct rtwn_softc *sc, int chain,
        else
                group = 5;
 
-       /* Get original Tx power based on board type and RF chain. */
-       base = &rtl8188eu_txagc[chain];
-
-       memset(power, 0, RTWN_RIDX_COUNT * sizeof(power[0]));
-       if (sc->regulatory == 0) {
-               for (ridx = 0; ridx <= 3; ridx++)
-                       power[ridx] = base->pwr[0][ridx];
-       }
-       for (ridx = 4; ridx < RTWN_RIDX_COUNT; ridx++) {
-               if (sc->regulatory == 3)
-                       power[ridx] = base->pwr[0][ridx];
-               else if (sc->regulatory == 1) {
-                       if (extc == NULL)
-                               power[ridx] = base->pwr[group][ridx];
-               } else if (sc->regulatory != 2)
-                       power[ridx] = base->pwr[0][ridx];
-       }
+       memset(power, 0, RTWN_POWER_COUNT * sizeof(power[0]));
 
        /* Compute per-CCK rate Tx power. */
-       cckpow = sc->cck_tx_pwr[group];
-       for (ridx = 0; ridx <= 3; ridx++) {
-               power[ridx] += cckpow;
+       cckpow = rom->txpwr.cck_tx_pwr[group];
+       for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) {
+               power[ridx] = (ridx == RTWN_RIDX_CCK2) ? cckpow - 9 : cckpow;
                if (power[ridx] > R92C_MAX_TX_PWR)
                        power[ridx] = R92C_MAX_TX_PWR;
        }
 
-       htpow = sc->ht40_tx_pwr[group];
+       if (group < 5)
+               htpow = rom->txpwr.ht40_tx_pwr[group];
 
        /* Compute per-OFDM rate Tx power. */
-       ofdmpow = htpow + sc->ofdm_tx_pwr_diff;
-       for (ridx = 4; ridx <= 11; ridx++) {
-               power[ridx] += ofdmpow;
+       diff = RTWN_SIGN4TO8(MS(rom->txpwr.ht20_ofdm_tx_pwr_diff,
+           R88E_ROM_TXPWR_OFDM_DIFF));
+       ofdmpow = htpow + diff;
+       for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) {
+               power[ridx] = ofdmpow; 
                if (power[ridx] > R92C_MAX_TX_PWR)
                        power[ridx] = R92C_MAX_TX_PWR;
        }
 
-       bw20pow = htpow + sc->bw20_tx_pwr_diff;
-       for (ridx = 12; ridx <= 27; ridx++) {
-               power[ridx] += bw20pow;
+       /* Compute per-MCS Tx power. */
+       if (extc == NULL) {
+               diff = RTWN_SIGN4TO8(MS(rom->txpwr.ht20_ofdm_tx_pwr_diff,
+                   R88E_ROM_TXPWR_HT20_DIFF));
+               htpow += diff;
+       }
+       for (ridx = RTWN_RIDX_MCS0; ridx < RTWN_RIDX_MCS8; ridx++) {
+               power[ridx] = htpow;
                if (power[ridx] > R92C_MAX_TX_PWR)
                        power[ridx] = R92C_MAX_TX_PWR;
        }
@@ -1993,15 +2009,12 @@ void
 rtwn_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c,
     struct ieee80211_channel *extc)
 {
-       uint16_t power[RTWN_RIDX_COUNT];
+       uint16_t power[RTWN_POWER_COUNT];
        int i;
 
        for (i = 0; i < sc->ntxchains; i++) {
                /* Compute per-rate Tx power values. */
-               if (sc->chip & RTWN_CHIP_88E)
-                       rtwn_r88e_get_txpower(sc, i, c, extc, power);
-               else
-                       rtwn_get_txpower(sc, i, c, extc, power);
+               rtwn_get_txpower(sc, i, c, extc, power);
                /* Write per-rate Tx power values to hardware. */
                rtwn_write_txpower(sc, i, power);
        }
index f7c57c6..6165b04 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rtwnvar.h,v 1.8 2017/01/30 21:54:30 stsp Exp $        */
+/*     $OpenBSD: rtwnvar.h,v 1.9 2017/06/16 14:57:51 kevlo Exp $       */
 
 /*-
  * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -43,6 +43,10 @@ struct rtwn_ops {
        void            (*next_scan)(void *);
        void            (*cancel_scan)(void *);
        void            (*wait_async)(void *);
+
+       void            (*get_txpower)(void *, int, struct ieee80211_channel *,
+                           struct ieee80211_channel *, uint16_t[]);
+       void            (*read_rom)(void *);
 };
 
 #define RTWN_LED_LINK  0
@@ -67,6 +71,7 @@ struct rtwn_softc {
 #define RTWN_FLAG_CCK_HIPWR            0x01
 #define RTWN_FLAG_BUSY                 0x02
 #define RTWN_FLAG_FORCE_RAID_11B       0x04
+#define RTWN_FLAG_EXT_HDR              0x08
 
        uint32_t                chip;
 #define RTWN_CHIP_92C          0x00000001
@@ -80,6 +85,7 @@ struct rtwn_softc {
 #define RTWN_CHIP_USB          0x80000000
 
        uint8_t                         board_type;
+       uint8_t                         crystal_cap;
        uint8_t                         regulatory;
        uint8_t                         pa_setting;
        int                             avg_pwdb;
@@ -91,18 +97,17 @@ struct rtwn_softc {
 
        int                             sc_tx_timer;
        int                             fwcur;
-       struct r92c_rom                 rom;
-
-       uint8_t                         r88e_rom[512];
-       uint8_t                         cck_tx_pwr[6];
-       uint8_t                         ht40_tx_pwr[5];
-       int8_t                          bw20_tx_pwr_diff;
-       int8_t                          ofdm_tx_pwr_diff;
+       union {
+               struct r92c_rom         r92c_rom;
+               struct r88e_rom         r88e_rom;
+       } u;
+#define sc_r92c_rom    u.r92c_rom
+#define sc_r88e_rom    u.r88e_rom
 
        uint32_t                        rf_chnlbw[R92C_MAX_CHAINS];
 };
 
-int            rtwn_attach(struct device *, struct rtwn_softc *, uint32_t);
+int            rtwn_attach(struct device *, struct rtwn_softc *);
 int            rtwn_detach(struct rtwn_softc *, int);
 int            rtwn_activate(struct rtwn_softc *, int);
 int8_t         rtwn_get_rssi(struct rtwn_softc *, int, void *);
index 754af77..1a74b76 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_rtwn.c,v 1.28 2017/05/19 11:30:40 stsp Exp $       */
+/*     $OpenBSD: if_rtwn.c,v 1.29 2017/06/16 14:57:51 kevlo Exp $      */
 
 /*-
  * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -371,8 +371,10 @@ rtwn_pci_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_sc.sc_ops.next_scan = rtwn_pci_next_scan;
        sc->sc_sc.sc_ops.cancel_scan = rtwn_cancel_scan;
        sc->sc_sc.sc_ops.wait_async = rtwn_wait_async;
-       error = rtwn_attach(&sc->sc_dev, &sc->sc_sc,
-           RTWN_CHIP_88C | RTWN_CHIP_PCI);
+
+       sc->sc_sc.chip = RTWN_CHIP_88C | RTWN_CHIP_PCI;
+
+       error = rtwn_attach(&sc->sc_dev, &sc->sc_sc);
        if (error != 0) {
                rtwn_free_rx_list(sc);
                for (i = 0; i < RTWN_NTXQUEUES; i++)
index a22be51..039f4d1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_urtwn.c,v 1.70 2017/05/08 12:28:39 stsp Exp $      */
+/*     $OpenBSD: if_urtwn.c,v 1.71 2017/06/16 14:57:51 kevlo Exp $     */
 
 /*-
  * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -204,96 +204,110 @@ int urtwn_debug = 4;
 #define DPRINTFN(n, x)
 #endif
 
-static const struct usb_devno urtwn_devs[] = {
-       { USB_VENDOR_ABOCOM,    USB_PRODUCT_ABOCOM_RTL8188CU_1 },
-       { USB_VENDOR_ABOCOM,    USB_PRODUCT_ABOCOM_RTL8188CU_2 },
-       { USB_VENDOR_ABOCOM,    USB_PRODUCT_ABOCOM_RTL8192CU },
-       { USB_VENDOR_ASUS,      USB_PRODUCT_ASUS_RTL8192CU },
-       { USB_VENDOR_ASUS,      USB_PRODUCT_ASUS_RTL8192CU_2 },
-       { USB_VENDOR_ASUS,      USB_PRODUCT_ASUS_RTL8192CU_3 },
-       { USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RTL8188CE_1 },
-       { USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RTL8188CE_2 },
-       { USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RTL8188CU },
-       { USB_VENDOR_BELKIN,    USB_PRODUCT_BELKIN_F7D2102 },
-       { USB_VENDOR_BELKIN,    USB_PRODUCT_BELKIN_F9L1004V1 },
-       { USB_VENDOR_BELKIN,    USB_PRODUCT_BELKIN_RTL8188CU },
-       { USB_VENDOR_BELKIN,    USB_PRODUCT_BELKIN_RTL8188CUS },
-       { USB_VENDOR_BELKIN,    USB_PRODUCT_BELKIN_RTL8192CU },
-       { USB_VENDOR_BELKIN,    USB_PRODUCT_BELKIN_RTL8192CU_1 },
-       { USB_VENDOR_BELKIN,    USB_PRODUCT_BELKIN_RTL8192CU_2 },
-       { USB_VENDOR_CHICONY,   USB_PRODUCT_CHICONY_RTL8188CUS_1 },
-       { USB_VENDOR_CHICONY,   USB_PRODUCT_CHICONY_RTL8188CUS_2 },
-       { USB_VENDOR_CHICONY,   USB_PRODUCT_CHICONY_RTL8188CUS_3 },
-       { USB_VENDOR_CHICONY,   USB_PRODUCT_CHICONY_RTL8188CUS_4 },
-       { USB_VENDOR_CHICONY,   USB_PRODUCT_CHICONY_RTL8188CUS_5 },
-       { USB_VENDOR_CHICONY,   USB_PRODUCT_CHICONY_RTL8188CUS_6 },
-       { USB_VENDOR_COMPARE,   USB_PRODUCT_COMPARE_RTL8192CU },
-       { USB_VENDOR_COREGA,    USB_PRODUCT_COREGA_RTL8192CU },
-       { USB_VENDOR_DLINK,     USB_PRODUCT_DLINK_DWA131B },
-       { USB_VENDOR_DLINK,     USB_PRODUCT_DLINK_RTL8188CU },
-       { USB_VENDOR_DLINK,     USB_PRODUCT_DLINK_RTL8192CU_1 },
-       { USB_VENDOR_DLINK,     USB_PRODUCT_DLINK_RTL8192CU_2 },
-       { USB_VENDOR_DLINK,     USB_PRODUCT_DLINK_RTL8192CU_3 },
-       { USB_VENDOR_DLINK,     USB_PRODUCT_DLINK_RTL8192CU_4 },
-       { USB_VENDOR_EDIMAX,    USB_PRODUCT_EDIMAX_EW7811UN },
-       { USB_VENDOR_EDIMAX,    USB_PRODUCT_EDIMAX_RTL8192CU },
-       { USB_VENDOR_FEIXUN,    USB_PRODUCT_FEIXUN_RTL8188CU },
-       { USB_VENDOR_FEIXUN,    USB_PRODUCT_FEIXUN_RTL8192CU },
-       { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWNUP150 },
-       { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_RTL8192CU },
-       { USB_VENDOR_HAWKING,   USB_PRODUCT_HAWKING_RTL8192CU },
-       { USB_VENDOR_HAWKING,   USB_PRODUCT_HAWKING_RTL8192CU_2 },
-       { USB_VENDOR_HP3,       USB_PRODUCT_HP3_RTL8188CU },
-       { USB_VENDOR_IODATA,    USB_PRODUCT_IODATA_WNG150UM },
-       { USB_VENDOR_IODATA,    USB_PRODUCT_IODATA_RTL8192CU },
-       { USB_VENDOR_NETGEAR,   USB_PRODUCT_NETGEAR_N300MA },
-       { USB_VENDOR_NETGEAR,   USB_PRODUCT_NETGEAR_WNA1000M },
-       { USB_VENDOR_NETGEAR,   USB_PRODUCT_NETGEAR_WNA1000Mv2 },
-       { USB_VENDOR_NETGEAR,   USB_PRODUCT_NETGEAR_RTL8192CU },
-       { USB_VENDOR_NETGEAR4,  USB_PRODUCT_NETGEAR4_RTL8188CU },
-       { USB_VENDOR_NETWEEN,   USB_PRODUCT_NETWEEN_RTL8192CU },
-       { USB_VENDOR_NOVATECH,  USB_PRODUCT_NOVATECH_RTL8188CU },
-       { USB_VENDOR_PLANEX2,   USB_PRODUCT_PLANEX2_RTL8188CU_1 },
-       { USB_VENDOR_PLANEX2,   USB_PRODUCT_PLANEX2_RTL8188CU_2 },
-       { USB_VENDOR_PLANEX2,   USB_PRODUCT_PLANEX2_RTL8188CU_3 },
-       { USB_VENDOR_PLANEX2,   USB_PRODUCT_PLANEX2_RTL8188CU_4 },
-       { USB_VENDOR_PLANEX2,   USB_PRODUCT_PLANEX2_RTL8188CUS },
-       { USB_VENDOR_PLANEX2,   USB_PRODUCT_PLANEX2_RTL8192CU },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188CE_0 },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188CE_1 },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188CTV },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188CU_0 },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188CU_1 },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188CU_2 },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188CU_3 },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188CU_4 },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188CU_5 },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188CU_COMBO },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188CUS },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188RU },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188RU_2 },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188RU_3 },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8191CU },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8192CE },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8192CE_VAU },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8192CU },
-       { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RTL8188CU },
-       { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RTL8188CU_2 },
-       { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RTL8192CU },
-       { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RTL8192CU_2 },
-       { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WLA2100V2 },
-       { USB_VENDOR_TPLINK,    USB_PRODUCT_TPLINK_RTL8192CU },
-       { USB_VENDOR_TRENDNET,  USB_PRODUCT_TRENDNET_RTL8188CU },
-       { USB_VENDOR_TRENDNET,  USB_PRODUCT_TRENDNET_RTL8192CU },
-       { USB_VENDOR_ZYXEL,     USB_PRODUCT_ZYXEL_RTL8192CU },
+/*
+ * Various supported device vendors/products.
+ */
+#define URTWN_DEV(v, p, f)                                     \
+        { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, (f) | RTWN_CHIP_USB }
+#define URTWN_DEV_8192CU(v, p) URTWN_DEV(v, p, RTWN_CHIP_92C | RTWN_CHIP_88C)
+#define URTWN_DEV_8188EU(v, p) URTWN_DEV(v, p, RTWN_CHIP_88E)
+static const struct urtwn_type {
+       struct usb_devno        dev;
+       uint32_t                chip;
+} urtwn_devs[] = {
+       URTWN_DEV_8192CU(ABOCOM,        RTL8188CU_1),
+       URTWN_DEV_8192CU(ABOCOM,        RTL8188CU_1),
+       URTWN_DEV_8192CU(ABOCOM,        RTL8188CU_2),
+       URTWN_DEV_8192CU(ABOCOM,        RTL8192CU),
+       URTWN_DEV_8192CU(ASUS,          RTL8192CU),
+       URTWN_DEV_8192CU(ASUS,          RTL8192CU_2),
+       URTWN_DEV_8192CU(ASUS,          RTL8192CU_3),
+       URTWN_DEV_8192CU(AZUREWAVE,     RTL8188CE_1),
+       URTWN_DEV_8192CU(AZUREWAVE,     RTL8188CE_2),
+       URTWN_DEV_8192CU(AZUREWAVE,     RTL8188CU),
+       URTWN_DEV_8192CU(BELKIN,        F7D2102),
+       URTWN_DEV_8192CU(BELKIN,        F9L1004V1),
+       URTWN_DEV_8192CU(BELKIN,        RTL8188CU),
+       URTWN_DEV_8192CU(BELKIN,        RTL8188CUS),
+       URTWN_DEV_8192CU(BELKIN,        RTL8192CU),
+       URTWN_DEV_8192CU(BELKIN,        RTL8192CU_1),
+       URTWN_DEV_8192CU(BELKIN,        RTL8192CU_2),
+       URTWN_DEV_8192CU(CHICONY,       RTL8188CUS_1),
+       URTWN_DEV_8192CU(CHICONY,       RTL8188CUS_2),
+       URTWN_DEV_8192CU(CHICONY,       RTL8188CUS_3),
+       URTWN_DEV_8192CU(CHICONY,       RTL8188CUS_4),
+       URTWN_DEV_8192CU(CHICONY,       RTL8188CUS_5),
+       URTWN_DEV_8192CU(CHICONY,       RTL8188CUS_6),
+       URTWN_DEV_8192CU(COMPARE,       RTL8192CU),
+       URTWN_DEV_8192CU(COREGA,        RTL8192CU),
+       URTWN_DEV_8192CU(DLINK,         DWA131B),
+       URTWN_DEV_8192CU(DLINK,         RTL8188CU),
+       URTWN_DEV_8192CU(DLINK,         RTL8192CU_1),
+       URTWN_DEV_8192CU(DLINK,         RTL8192CU_2),
+       URTWN_DEV_8192CU(DLINK,         RTL8192CU_3),
+       URTWN_DEV_8192CU(DLINK,         RTL8192CU_4),
+       URTWN_DEV_8192CU(EDIMAX,        EW7811UN),
+       URTWN_DEV_8192CU(EDIMAX,        RTL8192CU),
+       URTWN_DEV_8192CU(FEIXUN,        RTL8188CU),
+       URTWN_DEV_8192CU(FEIXUN,        RTL8192CU),
+       URTWN_DEV_8192CU(GUILLEMOT,     HWNUP150),
+       URTWN_DEV_8192CU(GUILLEMOT,     RTL8192CU),
+       URTWN_DEV_8192CU(HAWKING,       RTL8192CU),
+       URTWN_DEV_8192CU(HAWKING,       RTL8192CU_2),
+       URTWN_DEV_8192CU(HP3,           RTL8188CU),
+       URTWN_DEV_8192CU(IODATA,        WNG150UM),
+       URTWN_DEV_8192CU(IODATA,        RTL8192CU),
+       URTWN_DEV_8192CU(NETGEAR,       N300MA),
+       URTWN_DEV_8192CU(NETGEAR,       WNA1000M),
+       URTWN_DEV_8192CU(NETGEAR,       WNA1000Mv2),
+       URTWN_DEV_8192CU(NETGEAR,       RTL8192CU),
+       URTWN_DEV_8192CU(NETGEAR4,      RTL8188CU),
+       URTWN_DEV_8192CU(NETWEEN,       RTL8192CU),
+       URTWN_DEV_8192CU(NOVATECH,      RTL8188CU),
+       URTWN_DEV_8192CU(PLANEX2,       RTL8188CU_1),
+       URTWN_DEV_8192CU(PLANEX2,       RTL8188CU_2),
+       URTWN_DEV_8192CU(PLANEX2,       RTL8188CU_3),
+       URTWN_DEV_8192CU(PLANEX2,       RTL8188CU_4),
+       URTWN_DEV_8192CU(PLANEX2,       RTL8188CUS),
+       URTWN_DEV_8192CU(PLANEX2,       RTL8192CU),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188CE_0),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188CE_1),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188CTV),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188CU_0),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188CU_1),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188CU_2),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188CU_3),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188CU_4),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188CU_5),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188CU_COMBO),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188CUS),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188RU),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188RU_2),
+       URTWN_DEV_8192CU(REALTEK,       RTL8188RU_3),
+       URTWN_DEV_8192CU(REALTEK,       RTL8191CU),
+       URTWN_DEV_8192CU(REALTEK,       RTL8192CE),
+       URTWN_DEV_8192CU(REALTEK,       RTL8192CE_VAU),
+       URTWN_DEV_8192CU(REALTEK,       RTL8192CU),
+       URTWN_DEV_8192CU(SITECOMEU,     RTL8188CU),
+       URTWN_DEV_8192CU(SITECOMEU,     RTL8188CU_2),
+       URTWN_DEV_8192CU(SITECOMEU,     RTL8192CU),
+       URTWN_DEV_8192CU(SITECOMEU,     RTL8192CU_2),
+       URTWN_DEV_8192CU(SITECOMEU,     WLA2100V2),
+       URTWN_DEV_8192CU(TPLINK,        RTL8192CU),
+       URTWN_DEV_8192CU(TRENDNET,      RTL8188CU),
+       URTWN_DEV_8192CU(TRENDNET,      RTL8192CU),
+       URTWN_DEV_8192CU(ZYXEL,         RTL8192CU),
        /* URTWN_RTL8188E */
-       { USB_VENDOR_DLINK,     USB_PRODUCT_DLINK_DWA123D1 },
-       { USB_VENDOR_DLINK,     USB_PRODUCT_DLINK_DWA125D1 },
-       { USB_VENDOR_ELECOM,    USB_PRODUCT_ELECOM_WDC150SU2M },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188ETV },
-       { USB_VENDOR_REALTEK,   USB_PRODUCT_REALTEK_RTL8188EU }
+       URTWN_DEV_8188EU(DLINK,         DWA123D1),
+       URTWN_DEV_8188EU(DLINK,         DWA125D1),
+       URTWN_DEV_8188EU(ELECOM,        WDC150SU2M),
+       URTWN_DEV_8188EU(REALTEK,       RTL8188ETV),
+       URTWN_DEV_8188EU(REALTEK,       RTL8188EU)
 };
 
+#define urtwn_lookup(v, p)     \
+       ((const struct urtwn_type *)usb_lookup(urtwn_devs, v, p))
+
 int            urtwn_match(struct device *, void *, void *);
 void           urtwn_attach(struct device *, struct device *, void *);
 int            urtwn_detach(struct device *, int);
@@ -381,7 +395,7 @@ urtwn_match(struct device *parent, void *match, void *aux)
        if (uaa->iface == NULL || uaa->configno != 1)
                return (UMATCH_NONE);
 
-       return ((usb_lookup(urtwn_devs, uaa->vendor, uaa->product) != NULL) ?
+       return ((urtwn_lookup(uaa->vendor, uaa->product) != NULL) ?
            UMATCH_VENDOR_PRODUCT_CONF_IFACE : UMATCH_NONE);
 }
 
@@ -392,27 +406,18 @@ urtwn_attach(struct device *parent, struct device *self, void *aux)
        struct usb_attach_arg *uaa = aux;
        struct ifnet *ifp;
        struct ieee80211com *ic = &sc->sc_sc.sc_ic;
-       uint32_t chip_type;
 
        sc->sc_udev = uaa->device;
        sc->sc_iface = uaa->iface;
 
+       sc->sc_sc.chip = urtwn_lookup(uaa->vendor, uaa->product)->chip;
+
        usb_init_task(&sc->sc_task, urtwn_task, sc, USB_TASK_TYPE_GENERIC);
        timeout_set(&sc->scan_to, urtwn_scan_to, sc);
        timeout_set(&sc->calib_to, urtwn_calib_to, sc);
        if (urtwn_open_pipes(sc) != 0)
                return;
 
-       chip_type = RTWN_CHIP_USB;
-       if (uaa->product == USB_PRODUCT_DLINK_DWA123D1 ||
-           uaa->product == USB_PRODUCT_DLINK_DWA125D1 ||
-           uaa->product == USB_PRODUCT_ELECOM_WDC150SU2M ||
-           uaa->product == USB_PRODUCT_REALTEK_RTL8188EU ||
-           uaa->product == USB_PRODUCT_REALTEK_RTL8188ETV)
-               chip_type |= RTWN_CHIP_88E;
-       else
-               chip_type |= (RTWN_CHIP_92C | RTWN_CHIP_88C);
-
        sc->amrr.amrr_min_success_threshold =  1;
        sc->amrr.amrr_max_success_threshold = 10;
 
@@ -440,7 +445,7 @@ urtwn_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_sc.sc_ops.next_scan = urtwn_next_scan;
        sc->sc_sc.sc_ops.cancel_scan = urtwn_cancel_scan;
        sc->sc_sc.sc_ops.wait_async = urtwn_wait_async;
-       if (rtwn_attach(&sc->sc_dev, &sc->sc_sc, chip_type) != 0) {
+       if (rtwn_attach(&sc->sc_dev, &sc->sc_sc) != 0) {
                urtwn_close_pipes(sc);
                return;
        }
@@ -1579,7 +1584,6 @@ urtwn_r88e_power_on(struct urtwn_softc *sc)
            urtwn_read_1(sc, R92C_AFE_XTAL_CTRL + 2) | 0x80);
 
        /* Disable HWPDN. */
-       urtwn_write_1(sc, 0x5, urtwn_read_1(sc, 0x5) & ~0x80);
        urtwn_write_2(sc, R92C_APS_FSMCO,
            urtwn_read_2(sc, R92C_APS_FSMCO) & ~R92C_APS_FSMCO_APDM_HPDN);
 
@@ -1862,7 +1866,7 @@ urtwn_bb_init(void *cookie)
        struct urtwn_softc *sc = cookie;
        const struct r92c_bb_prog *prog;
        uint32_t reg;
-       uint8_t crystalcap;
+       uint8_t xtal;
        int i;
 
        /* Enable BB and RF. */
@@ -1960,14 +1964,10 @@ urtwn_bb_init(void *cookie)
                urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420);
                DELAY(1);
 
-               crystalcap = sc->sc_sc.r88e_rom[0xb9];
-               if (crystalcap == 0xff)
-                       crystalcap = 0x20;
-               crystalcap &= 0x3f;
+               xtal = sc->sc_sc.crystal_cap & 0x3f;
                reg = urtwn_bb_read(sc, R92C_AFE_XTAL_CTRL);
                urtwn_bb_write(sc, R92C_AFE_XTAL_CTRL,
-                   RW(reg, R92C_AFE_XTAL_CTRL_ADDR,
-                   crystalcap | crystalcap << 6));
+                   RW(reg, R92C_AFE_XTAL_CTRL_ADDR, xtal | xtal << 6));
        }
 
        if (urtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & R92C_HSSI_PARAM2_CCK_HIPWR)
@@ -1980,9 +1980,9 @@ urtwn_power_on(void *cookie)
        struct urtwn_softc *sc = cookie;
 
        if (sc->sc_sc.chip & RTWN_CHIP_88E)
-               return urtwn_r88e_power_on(sc);
+               return (urtwn_r88e_power_on(sc));
 
-       return urtwn_r92c_power_on(sc);
+       return (urtwn_r92c_power_on(sc));
 }
 
 int