diff options
author | Martynas Venckus <martynas@cvs.openbsd.org> | 2009-06-06 12:06:29 +0000 |
---|---|---|
committer | Martynas Venckus <martynas@cvs.openbsd.org> | 2009-06-06 12:06:29 +0000 |
commit | 4cb110240acd5065ff89e41d8ce6f711d496579d (patch) | |
tree | 0beda13bb0d4a90c6bd11fdfd7fd36c4877cff1a | |
parent | 88882c002d203afe3b942846fc83f707bc1a75e2 (diff) |
- implement support for rtl8187b
- change state properly in urtw_stop. disable interrupts, rx, and
tx. fixes scanning, ifconfig down, and some other issues
- fix rxgain; for ver. 2
- remove delays; that have been removed 8185 -> 8187
new one tested by jsg@, a bunch of people on tech@, and myself
old one tested by nick@
-rw-r--r-- | sys/dev/usb/if_urtw.c | 929 | ||||
-rw-r--r-- | sys/dev/usb/if_urtwreg.h | 36 |
2 files changed, 878 insertions, 87 deletions
diff --git a/sys/dev/usb/if_urtw.c b/sys/dev/usb/if_urtw.c index 9c266781e9b..dd99db414e0 100644 --- a/sys/dev/usb/if_urtw.c +++ b/sys/dev/usb/if_urtw.c @@ -1,6 +1,7 @@ -/* $OpenBSD: if_urtw.c,v 1.20 2009/06/05 01:21:02 martynas Exp $ */ +/* $OpenBSD: if_urtw.c,v 1.21 2009/06/06 12:06:28 martynas Exp $ */ /*- + * Copyright (c) 2009 Martynas Venckus <martynas@openbsd.org> * Copyright (c) 2008 Weongyo Jeong <weongyo@FreeBSD.org> * * Permission to use, copy, modify, and distribute this software for any @@ -79,6 +80,8 @@ static const struct urtw_type { } urtw_devs[] = { #define URTW_DEV_RTL8187(v, p) \ { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, URTW_HWREV_8187 } +#define URTW_DEV_RTL8187B(v, p) \ + { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, URTW_HWREV_8187B } /* Realtek RTL8187 devices. */ URTW_DEV_RTL8187(DICKSMITH, RTL8187), URTW_DEV_RTL8187(LOGITEC, RTL8187), @@ -86,7 +89,15 @@ static const struct urtw_type { URTW_DEV_RTL8187(REALTEK, RTL8187), URTW_DEV_RTL8187(SPHAIRON, RTL8187), URTW_DEV_RTL8187(SURECOM, EP9001G2A), + /* Realtek RTL8187B devices. */ + URTW_DEV_RTL8187B(BELKIN, F5D7050E), + URTW_DEV_RTL8187B(NETGEAR, WG111V3), + URTW_DEV_RTL8187B(REALTEK, RTL8187B_0), + URTW_DEV_RTL8187B(REALTEK, RTL8187B_1), + URTW_DEV_RTL8187B(REALTEK, RTL8187B_2), + URTW_DEV_RTL8187B(SITECOMEU, WL168) #undef URTW_DEV_RTL8187 +#undef URTW_DEV_RTL8187B }; #define urtw_lookup(v, p) \ ((const struct urtw_type *)usb_lookup(urtw_devs, v, p)) @@ -175,6 +186,52 @@ struct urtw_pair { uint32_t val; }; +struct urtw_pair_idx { + uint8_t reg; + uint8_t val; + uint8_t idx; +}; + +static struct urtw_pair_idx urtw_8187b_regtbl[] = { + { 0xf0, 0x32, 0 }, { 0xf1, 0x32, 0 }, { 0xf2, 0x00, 0 }, + { 0xf3, 0x00, 0 }, { 0xf4, 0x32, 0 }, { 0xf5, 0x43, 0 }, + { 0xf6, 0x00, 0 }, { 0xf7, 0x00, 0 }, { 0xf8, 0x46, 0 }, + { 0xf9, 0xa4, 0 }, { 0xfa, 0x00, 0 }, { 0xfb, 0x00, 0 }, + { 0xfc, 0x96, 0 }, { 0xfd, 0xa4, 0 }, { 0xfe, 0x00, 0 }, + { 0xff, 0x00, 0 }, + + { 0x58, 0x4b, 1 }, { 0x59, 0x00, 1 }, { 0x5a, 0x4b, 1 }, + { 0x5b, 0x00, 1 }, { 0x60, 0x4b, 1 }, { 0x61, 0x09, 1 }, + { 0x62, 0x4b, 1 }, { 0x63, 0x09, 1 }, { 0xce, 0x0f, 1 }, + { 0xcf, 0x00, 1 }, { 0xe0, 0xff, 1 }, { 0xe1, 0x0f, 1 }, + { 0xe2, 0x00, 1 }, { 0xf0, 0x4e, 1 }, { 0xf1, 0x01, 1 }, + { 0xf2, 0x02, 1 }, { 0xf3, 0x03, 1 }, { 0xf4, 0x04, 1 }, + { 0xf5, 0x05, 1 }, { 0xf6, 0x06, 1 }, { 0xf7, 0x07, 1 }, + { 0xf8, 0x08, 1 }, + + { 0x4e, 0x00, 2 }, { 0x0c, 0x04, 2 }, { 0x21, 0x61, 2 }, + { 0x22, 0x68, 2 }, { 0x23, 0x6f, 2 }, { 0x24, 0x76, 2 }, + { 0x25, 0x7d, 2 }, { 0x26, 0x84, 2 }, { 0x27, 0x8d, 2 }, + { 0x4d, 0x08, 2 }, { 0x50, 0x05, 2 }, { 0x51, 0xf5, 2 }, + { 0x52, 0x04, 2 }, { 0x53, 0xa0, 2 }, { 0x54, 0x1f, 2 }, + { 0x55, 0x23, 2 }, { 0x56, 0x45, 2 }, { 0x57, 0x67, 2 }, + { 0x58, 0x08, 2 }, { 0x59, 0x08, 2 }, { 0x5a, 0x08, 2 }, + { 0x5b, 0x08, 2 }, { 0x60, 0x08, 2 }, { 0x61, 0x08, 2 }, + { 0x62, 0x08, 2 }, { 0x63, 0x08, 2 }, { 0x64, 0xcf, 2 }, + { 0x72, 0x56, 2 }, { 0x73, 0x9a, 2 }, + + { 0x34, 0xf0, 0 }, { 0x35, 0x0f, 0 }, { 0x5b, 0x40, 0 }, + { 0x84, 0x88, 0 }, { 0x85, 0x24, 0 }, { 0x88, 0x54, 0 }, + { 0x8b, 0xb8, 0 }, { 0x8c, 0x07, 0 }, { 0x8d, 0x00, 0 }, + { 0x94, 0x1b, 0 }, { 0x95, 0x12, 0 }, { 0x96, 0x00, 0 }, + { 0x97, 0x06, 0 }, { 0x9d, 0x1a, 0 }, { 0x9f, 0x10, 0 }, + { 0xb4, 0x22, 0 }, { 0xbe, 0x80, 0 }, { 0xdb, 0x00, 0 }, + { 0xee, 0x00, 0 }, { 0x91, 0x03, 0 }, + + { 0x4c, 0x00, 2 }, { 0x9f, 0x00, 3 }, { 0x8c, 0x01, 0 }, + { 0x8d, 0x10, 0 }, { 0x8e, 0x08, 0 }, { 0x8f, 0x00, 0 } +}; + static uint8_t urtw_8225_agc[] = { 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, @@ -293,6 +350,36 @@ static uint8_t urtw_8225_txpwr_ofdm[] = { 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 }; +static uint8_t urtw_8225v2_agc[] = { + 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, + 0x55, 0x53, 0x51, 0x4f, 0x4d, 0x4b, 0x49, 0x47, + 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37, + 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, + 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1b, 0x19, 0x17, + 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07, + 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2a, + 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, + 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 +}; + +static uint8_t urtw_8225v2_ofdm[] = { + 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, + 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26, + 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3, + 0x0a, 0xe1, 0x2c, 0x8a, 0x86, 0x83, 0x34, 0x0f, + 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00, + 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e, + 0x6d, 0x3c, 0xfb, 0x07 +}; + static uint8_t urtw_8225v2_gain_bg[] = { 0x23, 0x15, 0xa5, /* -82-1dbm */ 0x23, 0x15, 0xb5, /* -82-2dbm */ @@ -335,16 +422,16 @@ static struct urtw_pair urtw_8225v2_rf_part3[] = { }; static uint16_t urtw_8225v2_rxgain[] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009, - 0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141, - 0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183, - 0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244, - 0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288, - 0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345, - 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389, - 0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393, - 0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, - 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, + 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, + 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, + 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, + 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, + 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, + 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, + 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, + 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, + 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb }; @@ -359,11 +446,25 @@ static uint8_t urtw_8225v2_tx_gain_cck_ofdm[] = { }; static uint8_t urtw_8225v2_txpwr_cck[] = { - 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 + 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04, + 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03, + 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03, + 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 }; static uint8_t urtw_8225v2_txpwr_cck_ch14[] = { - 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 + 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00 +}; + +static struct urtw_pair urtw_8225v2_b_rf[] = { + { 0x00, 0x00b7 }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, + { 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a }, + { 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb }, + { 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 }, + { 0x00, 0x01b7 } }; static struct urtw_pair urtw_ratetable[] = { @@ -461,6 +562,15 @@ usbd_status urtw_led_mode3(struct urtw_softc *, int); usbd_status urtw_rx_setconf(struct urtw_softc *); usbd_status urtw_rx_enable(struct urtw_softc *); usbd_status urtw_tx_enable(struct urtw_softc *); +usbd_status urtw_8187b_update_wmm(struct urtw_softc *); +usbd_status urtw_8187b_reset(struct urtw_softc *); +int urtw_8187b_init(struct ifnet *); +usbd_status urtw_8225v2_b_config_mac(struct urtw_softc *); +usbd_status urtw_8225v2_b_init_rfe(struct urtw_softc *); +usbd_status urtw_8225v2_b_update_chan(struct urtw_softc *); +usbd_status urtw_8225v2_b_rf_init(struct urtw_rf *); +usbd_status urtw_8225v2_b_rf_set_chan(struct urtw_rf *, int); +usbd_status urtw_8225v2_b_set_txpwrlvl(struct urtw_softc *, int); int urtw_match(struct device *, void *, void *); void urtw_attach(struct device *, struct device *, void *); @@ -499,6 +609,7 @@ urtw_attach(struct device *parent, struct device *self, void *aux) struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; usbd_status error; + uint8_t data8; uint32_t data; int i; const char *urtw_name = NULL; @@ -520,7 +631,8 @@ urtw_attach(struct device *parent, struct device *self, void *aux) * Detect Realtek RTL8187B devices that use * USB IDs of RTL8187. */ - urtw_name = "RTL8187B rev. B (not supported)"; + sc->sc_hwrev = URTW_HWREV_8187B | URTW_HWREV_8187B_B; + urtw_name = "RTL8187B rev. B (early)"; break; default: sc->sc_hwrev |= URTW_HWREV_8187_B; @@ -528,7 +640,26 @@ urtw_attach(struct device *parent, struct device *self, void *aux) break; } } else { - urtw_name = "RTL8187B (not supported)"; + /* RTL8187B hwrev register. */ + urtw_read8_m(sc, URTW_8187B_HWREV, &data8); + switch (data8) { + case URTW_8187B_HWREV_8187B_B: + sc->sc_hwrev |= URTW_HWREV_8187B_B; + urtw_name = "RTL8187B rev. B"; + break; + case URTW_8187B_HWREV_8187B_D: + sc->sc_hwrev |= URTW_HWREV_8187B_D; + urtw_name = "RTL8187B rev. D"; + break; + case URTW_8187B_HWREV_8187B_E: + sc->sc_hwrev |= URTW_HWREV_8187B_E; + urtw_name = "RTL8187B rev. E"; + break; + default: + sc->sc_hwrev |= URTW_HWREV_8187B_B; + urtw_name = "RTL8187B rev. B (default)"; + break; + } } printf("%s: %s", sc->sc_dev.dv_xname, urtw_name); @@ -589,7 +720,11 @@ urtw_attach(struct device *parent, struct device *self, void *aux) ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_init = urtw_init; + if (sc->sc_hwrev & URTW_HWREV_8187) { + ifp->if_init = urtw_init; + } else { + ifp->if_init = urtw_8187b_init; + } ifp->if_ioctl = urtw_ioctl; ifp->if_start = urtw_start; ifp->if_watchdog = urtw_watchdog; @@ -708,24 +843,36 @@ urtw_open_pipes(struct urtw_softc *sc) */ /* tx pipe - low priority packets */ - error = usbd_open_pipe(sc->sc_iface, 0x2, USBD_EXCLUSIVE_USE, - &sc->sc_txpipe_low); + if (sc->sc_hwrev & URTW_HWREV_8187) + error = usbd_open_pipe(sc->sc_iface, 0x2, + USBD_EXCLUSIVE_USE, &sc->sc_txpipe_low); + else + error = usbd_open_pipe(sc->sc_iface, 0x6, + USBD_EXCLUSIVE_USE, &sc->sc_txpipe_low); if (error != 0) { printf("%s: could not open Tx low pipe: %s\n", sc->sc_dev.dv_xname, usbd_errstr(error)); goto fail; } /* tx pipe - normal priority packets */ - error = usbd_open_pipe(sc->sc_iface, 0x3, USBD_EXCLUSIVE_USE, - &sc->sc_txpipe_normal); + if (sc->sc_hwrev & URTW_HWREV_8187) + error = usbd_open_pipe(sc->sc_iface, 0x3, + USBD_EXCLUSIVE_USE, &sc->sc_txpipe_normal); + else + error = usbd_open_pipe(sc->sc_iface, 0x7, + USBD_EXCLUSIVE_USE, &sc->sc_txpipe_normal); if (error != 0) { printf("%s: could not open Tx normal pipe: %s\n", sc->sc_dev.dv_xname, usbd_errstr(error)); goto fail; } /* rx pipe */ - error = usbd_open_pipe(sc->sc_iface, 0x81, USBD_EXCLUSIVE_USE, - &sc->sc_rxpipe); + if (sc->sc_hwrev & URTW_HWREV_8187) + error = usbd_open_pipe(sc->sc_iface, 0x81, + USBD_EXCLUSIVE_USE, &sc->sc_rxpipe); + else + error = usbd_open_pipe(sc->sc_iface, 0x83, + USBD_EXCLUSIVE_USE, &sc->sc_rxpipe); if (error != 0) { printf("%s: could not open Rx pipe: %s\n", sc->sc_dev.dv_xname, usbd_errstr(error)); @@ -1147,33 +1294,43 @@ urtw_get_rfchip(struct urtw_softc *sc) rf->rf_sc = sc; - error = urtw_eprom_read32(sc, URTW_EPROM_RFCHIPID, &data); - if (error != 0) - goto fail; - switch (data & 0xff) { - case URTW_EPROM_RFCHIPID_RTL8225U: - error = urtw_8225_isv2(sc, &ret); + if (sc->sc_hwrev & URTW_HWREV_8187) { + error = urtw_eprom_read32(sc, URTW_EPROM_RFCHIPID, &data); if (error != 0) + panic("unsupported RF chip"); + /* NOTREACHED */ + switch (data & 0xff) { + case URTW_EPROM_RFCHIPID_RTL8225U: + error = urtw_8225_isv2(sc, &ret); + if (error != 0) + goto fail; + if (ret == 0) { + rf->init = urtw_8225_rf_init; + rf->set_chan = urtw_8225_rf_set_chan; + rf->set_sens = urtw_8225_rf_set_sens; + } else { + rf->init = urtw_8225v2_rf_init; + rf->set_chan = urtw_8225v2_rf_set_chan; + rf->set_sens = NULL; + } + break; + default: goto fail; - if (ret == 0) { - rf->init = urtw_8225_rf_init; - rf->set_sens = urtw_8225_rf_set_sens; - rf->set_chan = urtw_8225_rf_set_chan; - } else { - rf->init = urtw_8225v2_rf_init; - rf->set_chan = urtw_8225v2_rf_set_chan; - rf->set_sens = NULL; } - rf->max_sens = URTW_8225_RF_MAX_SENS; - rf->sens = URTW_8225_RF_DEF_SENS; - break; - default: - panic("unsupported RF chip %d\n", data & 0xff); - /* NOTREACHED */ + } else { + rf->init = urtw_8225v2_b_rf_init; + rf->set_chan = urtw_8225v2_b_rf_set_chan; + rf->set_sens = NULL; } + rf->max_sens = URTW_8225_RF_MAX_SENS; + rf->sens = URTW_8225_RF_DEF_SENS; + + return (0); + fail: - return (error); + panic("unsupported RF chip %d\n", data & 0xff); + /* NOTREACHED */ } usbd_status @@ -1207,14 +1364,41 @@ urtw_get_txpwr(struct urtw_softc *sc) sc->sc_txpwr_ofdm[i + 6] = (data & 0xf0) >> 4; sc->sc_txpwr_ofdm[i + 6 + 1] = (data & 0xf000) >> 12; } - for (i = 1, j = 0; i < 4; i += 2, j++) { - error = urtw_eprom_read32(sc, URTW_EPROM_TXPW2 + j, &data); + if (sc->sc_hwrev & URTW_HWREV_8187) { + for (i = 1, j = 0; i < 4; i += 2, j++) { + error = urtw_eprom_read32(sc, URTW_EPROM_TXPW2 + j, + &data); + if (error != 0) + goto fail; + sc->sc_txpwr_cck[i + 6 + 4] = data & 0xf; + sc->sc_txpwr_cck[i + 6 + 4 + 1] = (data & 0xf00) >> 8; + sc->sc_txpwr_ofdm[i + 6 + 4] = (data & 0xf0) >> 4; + sc->sc_txpwr_ofdm[i + 6 + 4 + 1] = + (data & 0xf000) >> 12; + } + } else { + /* Channel 11. */ + error = urtw_eprom_read32(sc, 0x1b, &data); + if (error != 0) + goto fail; + sc->sc_txpwr_cck[11] = data & 0xf; + sc->sc_txpwr_ofdm[11] = (data & 0xf0) >> 4; + + /* Channel 12. */ + error = urtw_eprom_read32(sc, 0xa, &data); if (error != 0) goto fail; - sc->sc_txpwr_cck[i + 6 + 4] = data & 0xf; - sc->sc_txpwr_cck[i + 6 + 4 + 1] = (data & 0xf00) >> 8; - sc->sc_txpwr_ofdm[i + 6 + 4] = (data & 0xf0) >> 4; - sc->sc_txpwr_ofdm[i + 6 + 4 + 1] = (data & 0xf000) >> 12; + sc->sc_txpwr_cck[12] = data & 0xf; + sc->sc_txpwr_ofdm[12] = (data & 0xf0) >> 4; + + /* Channel 13, 14. */ + error = urtw_eprom_read32(sc, 0x1c, &data); + if (error != 0) + goto fail; + sc->sc_txpwr_cck[13] = data & 0xf; + sc->sc_txpwr_ofdm[13] = (data & 0xf0) >> 4; + sc->sc_txpwr_cck[14] = (data & 0xf00) >> 8; + sc->sc_txpwr_ofdm[14] = (data & 0xf000) >> 12; } fail: return (error); @@ -1880,6 +2064,10 @@ urtw_update_msr(struct urtw_softc *sc) urtw_read8_m(sc, URTW_MSR, &data); data &= ~URTW_MSR_LINK_MASK; + /* Should always be set. */ + if (sc->sc_hwrev & URTW_HWREV_8187B) + data |= URTW_MSR_LINK_ENEDCA; + if (sc->sc_state == IEEE80211_S_RUN) { switch (ic->ic_opmode) { case IEEE80211_M_STA: @@ -2044,27 +2232,35 @@ urtw_tx_enable(struct urtw_softc *sc) uint32_t data; usbd_status error; - urtw_read8_m(sc, URTW_CW_CONF, &data8); - data8 &= ~(URTW_CW_CONF_PERPACKET_CW | URTW_CW_CONF_PERPACKET_RETRY); - urtw_write8_m(sc, URTW_CW_CONF, data8); + if (sc->sc_hwrev & URTW_HWREV_8187) { + urtw_read8_m(sc, URTW_CW_CONF, &data8); + data8 &= ~(URTW_CW_CONF_PERPACKET_CW | + URTW_CW_CONF_PERPACKET_RETRY); + urtw_write8_m(sc, URTW_CW_CONF, data8); - urtw_read8_m(sc, URTW_TX_AGC_CTL, &data8); - data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN; - data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL; - data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT; - urtw_write8_m(sc, URTW_TX_AGC_CTL, data8); + urtw_read8_m(sc, URTW_TX_AGC_CTL, &data8); + data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN; + data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL; + data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT; + urtw_write8_m(sc, URTW_TX_AGC_CTL, data8); - urtw_read32_m(sc, URTW_TX_CONF, &data); - data &= ~URTW_TX_LOOPBACK_MASK; - data |= URTW_TX_LOOPBACK_NONE; - data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK); - data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT; - data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT; - data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK); - data |= URTW_TX_MXDMA_2048 | URTW_TX_CWMIN | URTW_TX_DISCW; - data &= ~URTW_TX_SWPLCPLEN; - data |= URTW_TX_NOICV; - urtw_write32_m(sc, URTW_TX_CONF, data); + urtw_read32_m(sc, URTW_TX_CONF, &data); + data &= ~URTW_TX_LOOPBACK_MASK; + data |= URTW_TX_LOOPBACK_NONE; + data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK); + data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT; + data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT; + data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK); + data |= URTW_TX_MXDMA_2048 | URTW_TX_CWMIN | URTW_TX_DISCW; + data &= ~URTW_TX_SWPLCPLEN; + data |= URTW_TX_NOICV; + urtw_write32_m(sc, URTW_TX_CONF, data); + } else { + data = URTW_TX_DURPROCMODE | URTW_TX_DISREQQSIZE | + URTW_TX_MXDMA_2048 | URTW_TX_SHORTRETRY | + URTW_TX_LONGRETRY; + urtw_write32_m(sc, URTW_TX_CONF, data); + } urtw_read8_m(sc, URTW_CMD, &data8); urtw_write8_m(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE); @@ -2497,7 +2693,11 @@ urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, } #endif - xferlen = m0->m_pkthdr.len + 4 * 3; + if (sc->sc_hwrev & URTW_HWREV_8187) + xferlen = m0->m_pkthdr.len + 4 * 3; + else + xferlen = m0->m_pkthdr.len + 4 * 8; + if ((0 == xferlen % 64) || (0 == xferlen % 512)) xferlen += 1; @@ -2533,11 +2733,17 @@ urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, else if (ic->ic_fixed_rate != -1) data->buf[3] = urtw_rate2rtl(ic->ic_fixed_rate); } - data->buf[8] = 3; /* CW minimum */ - data->buf[8] |= (7 << 4); /* CW maximum */ - data->buf[9] |= 11; /* retry limitation */ - m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)&data->buf[12]); + if (sc->sc_hwrev & URTW_HWREV_8187) { + data->buf[8] = 3; /* CW minimum */ + data->buf[8] |= (7 << 4); /* CW maximum */ + data->buf[9] |= 11; /* retry limitation */ + m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)&data->buf[12]); + } else { + data->buf[21] |= 11; /* retry limitation */ + m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)&data->buf[32]); + } + data->ni = ni; /* mbuf is no longer needed. */ @@ -2616,7 +2822,10 @@ urtw_8187_write_phy(struct urtw_softc *sc, uint8_t addr, uint32_t data) urtw_write8_m(sc, 0x7e, ((phyw & 0x00ff0000) >> 16)); urtw_write8_m(sc, 0x7d, ((phyw & 0x0000ff00) >> 8)); urtw_write8_m(sc, 0x7c, ((phyw & 0x000000ff))); - usbd_delay_ms(sc->sc_udev, 1); + /* + * Delay removed from 8185 to 8187. + * usbd_delay_ms(sc->sc_udev, 1); + */ fail: return (error); } @@ -2874,18 +3083,32 @@ void urtw_stop(struct ifnet *ifp, int disable) { struct urtw_softc *sc = ifp->if_softc; + struct ieee80211com *ic = &sc->sc_ic; + uint8_t data; + usbd_status error; ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + ieee80211_new_state(ic, IEEE80211_S_INIT, -1); + timeout_del(&sc->scan_to); timeout_del(&sc->sc_led_ch); + urtw_intr_disable(sc); + urtw_read8_m(sc, URTW_CMD, &data); + data &= ~URTW_CMD_TX_ENABLE; + data &= ~URTW_CMD_RX_ENABLE; + urtw_write8_m(sc, URTW_CMD, data); + if (sc->sc_rxpipe != NULL) usbd_abort_pipe(sc->sc_rxpipe); if (sc->sc_txpipe_low != NULL) usbd_abort_pipe(sc->sc_txpipe_low); if (sc->sc_txpipe_normal != NULL) usbd_abort_pipe(sc->sc_txpipe_normal); + +fail: + return; } int @@ -2927,8 +3150,13 @@ urtw_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) goto skip; } - /* 4 dword and 4 byte CRC */ - len = actlen - (4 * 4); + if (sc->sc_hwrev & URTW_HWREV_8187) + /* 4 dword and 4 byte CRC */ + len = actlen - (4 * 4); + else + /* 5 dword and 4 byte CRC */ + len = actlen - (4 * 5); + desc = data->buf + len; flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff); if (flen > actlen) { @@ -2937,15 +3165,21 @@ urtw_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) } rate = (desc[2] & 0xf0) >> 4; - quality = desc[4] & 0xff; - /* XXX correct? */ - rssi = (desc[6] & 0xfe) >> 1; - if (!urtw_isbmode(rate)) { - rssi = (rssi > 90) ? 90 : ((rssi < 25) ? 25 : rssi); - rssi = ((90 - rssi) * 100) / 65; + if (sc->sc_hwrev & URTW_HWREV_8187) { + quality = desc[4] & 0xff; + rssi = (desc[6] & 0xfe) >> 1; + + /* XXX correct? */ + if (!urtw_isbmode(rate)) { + rssi = (rssi > 90) ? 90 : ((rssi < 25) ? 25 : rssi); + rssi = ((90 - rssi) * 100) / 65; + } else { + rssi = (rssi > 90) ? 95 : ((rssi < 30) ? 30 : rssi); + rssi = ((95 - rssi) * 100) / 65; + } } else { - rssi = (rssi > 90) ? 95 : ((rssi < 30) ? 30 : rssi); - rssi = ((95 - rssi) * 100) / 65; + quality = desc[12]; + rssi = 14 - desc[14] / 2; } MGETHDR(mnew, M_DONTWAIT, MT_DATA); @@ -2999,7 +3233,17 @@ urtw_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) ni = ieee80211_find_rxnode(ic, wh); /* XXX correct? */ - nf = (quality > 64) ? 0 : ((64 - quality) * 100) / 64; + if (!urtw_isbmode(rate)) { + if (quality > 127) + quality = 0; + else if (quality < 27) + quality = 100; + else + quality = 127 - quality; + } else + quality = (quality > 64) ? 0 : ((64 - quality) * 100) / 64; + + nf = quality; /* send the frame to the 802.11 layer */ rxi.rxi_flags = 0; @@ -3324,7 +3568,7 @@ urtw_task(void *arg) urtw_write16_m(sc, URTW_ATIM_WND, 2); urtw_write16_m(sc, URTW_ATIM_TR_ITV, 100); urtw_write16_m(sc, URTW_BEACON_INTERVAL, 0x64); - urtw_write16_m(sc, URTW_BEACON_INTERVAL_TIME, 100); + urtw_write16_m(sc, URTW_BEACON_INTERVAL_TIME, 0x3ff); error = urtw_led_ctl(sc, URTW_LED_CTL_LINK); if (error != 0) printf("%s: could not control LED (%d)\n", @@ -3340,3 +3584,516 @@ fail: sc->sc_dev.dv_xname)); } +usbd_status +urtw_8187b_update_wmm(struct urtw_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211_channel *c = ic->ic_ibss_chan; + uint32_t data; + uint8_t aifs, sifs, slot, ecwmin, ecwmax; + usbd_status error; + + sifs = 0xa; + if (IEEE80211_IS_CHAN_G(c)) + slot = 0x9; + else + slot = 0x14; + + aifs = (2 * slot) + sifs; + ecwmin = 3; + ecwmax = 7; + + data = ((uint32_t)aifs << 0) | /* AIFS, offset 0 */ + ((uint32_t)ecwmin << 8) | /* ECW minimum, offset 8 */ + ((uint32_t)ecwmax << 12); /* ECW maximum, offset 16 */ + + urtw_write32_m(sc, URTW_AC_VO, data); + urtw_write32_m(sc, URTW_AC_VI, data); + urtw_write32_m(sc, URTW_AC_BE, data); + urtw_write32_m(sc, URTW_AC_BK, data); + +fail: + return (error); +} + +usbd_status +urtw_8187b_reset(struct urtw_softc *sc) +{ + uint8_t data; + usbd_status error; + + error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); + if (error) + goto fail; + + urtw_read8_m(sc, URTW_CONFIG3, &data); + urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE | + URTW_CONFIG3_GNT_SELECT); + + urtw_write32_m(sc, URTW_ANAPARAM2, URTW_8187B_8225_ANAPARAM2_ON); + urtw_write32_m(sc, URTW_ANAPARAM, URTW_8187B_8225_ANAPARAM_ON); + urtw_write8_m(sc, URTW_ANAPARAM3, URTW_8187B_8225_ANAPARAM3_ON); + + urtw_write8_m(sc, 0x61, 0x10); + urtw_read8_m(sc, 0x62, &data); + urtw_write8_m(sc, 0x62, data & ~(1 << 5)); + urtw_write8_m(sc, 0x62, data | (1 << 5)); + + urtw_read8_m(sc, URTW_CONFIG3, &data); + urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE); + + error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); + if (error) + goto fail; + + urtw_read8_m(sc, URTW_CMD, &data); + data = (data & 2) | URTW_CMD_RST; + urtw_write8_m(sc, URTW_CMD, data); + usbd_delay_ms(sc->sc_udev, 100); + + urtw_read8_m(sc, URTW_CMD, &data); + if (data & URTW_CMD_RST) { + printf("%s: reset timeout\n", sc->sc_dev.dv_xname); + goto fail; + } + +fail: + return (error); +} + +int +urtw_8187b_init(struct ifnet *ifp) +{ + struct urtw_softc *sc = ifp->if_softc; + struct urtw_rf *rf = &sc->sc_rf; + struct ieee80211com *ic = &sc->sc_ic; + int ret; + uint8_t data; + usbd_status error; + + urtw_stop(ifp, 0); + + error = urtw_8187b_update_wmm(sc); + if (error != 0) + goto fail; + error = urtw_8187b_reset(sc); + if (error) + goto fail; + + /* Applying MAC address again. */ + error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); + if (error) + goto fail; + IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl)); + urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_myaddr)[0]); + urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_myaddr)[1] & 0xffff); + error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); + if (error) + goto fail; + + error = urtw_update_msr(sc); + if (error) + goto fail; + + error = rf->init(rf); + if (error != 0) + goto fail; + + urtw_write8_m(sc, URTW_CMD, URTW_CMD_TX_ENABLE | + URTW_CMD_RX_ENABLE); + error = urtw_intr_enable(sc); + if (error != 0) + goto fail; + + error = urtw_write8e(sc, 0x41, 0xf4); + if (error != 0) + goto fail; + error = urtw_write8e(sc, 0x40, 0x00); + if (error != 0) + goto fail; + error = urtw_write8e(sc, 0x42, 0x00); + if (error != 0) + goto fail; + error = urtw_write8e(sc, 0x42, 0x01); + if (error != 0) + goto fail; + error = urtw_write8e(sc, 0x40, 0x0f); + if (error != 0) + goto fail; + error = urtw_write8e(sc, 0x42, 0x00); + if (error != 0) + goto fail; + error = urtw_write8e(sc, 0x42, 0x01); + if (error != 0) + goto fail; + + urtw_read8_m(sc, 0xdb, &data); + urtw_write8_m(sc, 0xdb, data | (1 << 2)); + urtw_write16_idx_m(sc, 0x72, 0x59fa, 3); + urtw_write16_idx_m(sc, 0x74, 0x59d2, 3); + urtw_write16_idx_m(sc, 0x76, 0x59d2, 3); + urtw_write16_idx_m(sc, 0x78, 0x19fa, 3); + urtw_write16_idx_m(sc, 0x7a, 0x19fa, 3); + urtw_write16_idx_m(sc, 0x7c, 0x00d0, 3); + urtw_write8_m(sc, 0x61, 0); + urtw_write8_idx_m(sc, 0x80, 0x0f, 1); + urtw_write8_idx_m(sc, 0x83, 0x03, 1); + urtw_write8_m(sc, 0xda, 0x10); + urtw_write8_idx_m(sc, 0x4d, 0x08, 2); + + urtw_write32_m(sc, URTW_HSSI_PARA, 0x0600321b); + + urtw_write16_idx_m(sc, 0xec, 0x0800, 1); + + urtw_write8_m(sc, URTW_ACM_CONTROL, 0); + + /* Reset softc variables. */ + sc->sc_txidx = sc->sc_tx_low_queued = sc->sc_tx_normal_queued = 0; + sc->sc_txtimer = 0; + + if (!(sc->sc_flags & URTW_INIT_ONCE)) { + error = usbd_set_config_no(sc->sc_udev, URTW_CONFIG_NO, 0); + if (error != 0) { + printf("%s: could not set configuration no\n", + sc->sc_dev.dv_xname); + goto fail; + } + /* Get the first interface handle. */ + error = usbd_device2interface_handle(sc->sc_udev, + URTW_IFACE_INDEX, &sc->sc_iface); + if (error != 0) { + printf("%s: could not get interface handle\n", + sc->sc_dev.dv_xname); + goto fail; + } + error = urtw_open_pipes(sc); + if (error != 0) + goto fail; + ret = urtw_alloc_rx_data_list(sc); + if (error != 0) + goto fail; + ret = urtw_alloc_tx_data_list(sc); + if (error != 0) + goto fail; + sc->sc_flags |= URTW_INIT_ONCE; + } + + error = urtw_rx_enable(sc); + if (error != 0) + goto fail; + error = urtw_tx_enable(sc); + if (error != 0) + goto fail; + + ifp->if_flags &= ~IFF_OACTIVE; + ifp->if_flags |= IFF_RUNNING; + + ifp->if_timer = 1; + + if (ic->ic_opmode == IEEE80211_M_MONITOR) + ieee80211_new_state(ic, IEEE80211_S_RUN, -1); + else + ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); + +fail: + return (error); +} + +usbd_status +urtw_8225v2_b_config_mac(struct urtw_softc *sc) +{ + int i; + usbd_status error; + + for (i = 0; i < nitems(urtw_8187b_regtbl); i++) { + urtw_write8_idx_m(sc, urtw_8187b_regtbl[i].reg, + urtw_8187b_regtbl[i].val, urtw_8187b_regtbl[i].idx); + } + + urtw_write16_m(sc, URTW_TID_AC_MAP, 0xfa50); + urtw_write16_m(sc, URTW_INT_MIG, 0); + + urtw_write32_idx_m(sc, 0xf0, 0, 1); + urtw_write32_idx_m(sc, 0xf4, 0, 1); + urtw_write8_idx_m(sc, 0xf8, 0, 1); + + urtw_write32_m(sc, URTW_RF_TIMING, 0x00004001); + +fail: + return (error); +} + +usbd_status +urtw_8225v2_b_init_rfe(struct urtw_softc *sc) +{ + usbd_status error; + + urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, 0x0480); + urtw_write16_m(sc, URTW_RF_PINS_SELECT, 0x2488); + urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1fff); + usbd_delay_ms(sc->sc_udev, 100); + +fail: + return (error); +} + +usbd_status +urtw_8225v2_b_update_chan(struct urtw_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211_channel *c = ic->ic_ibss_chan; + uint8_t aifs, difs, eifs, sifs, slot; + usbd_status error; + + urtw_write8_m(sc, URTW_SIFS, 0x22); + + sifs = 0xa; + if (IEEE80211_IS_CHAN_G(c)) { + slot = 0x9; + difs = 0x1c; + eifs = 0x5b; + } else { + slot = 0x14; + difs = 0x32; + eifs = 0x5b; + } + aifs = (2 * slot) + sifs; + + urtw_write8_m(sc, URTW_SLOT, slot); + + urtw_write8_m(sc, URTW_AC_VO, aifs); + urtw_write8_m(sc, URTW_AC_VI, aifs); + urtw_write8_m(sc, URTW_AC_BE, aifs); + urtw_write8_m(sc, URTW_AC_BK, aifs); + + urtw_write8_m(sc, URTW_DIFS, difs); + urtw_write8_m(sc, URTW_8187B_EIFS, eifs); + +fail: + return (error); +} + +usbd_status +urtw_8225v2_b_rf_init(struct urtw_rf *rf) +{ + struct urtw_softc *sc = rf->rf_sc; + int i; + uint8_t data; + usbd_status error; + + /* Set up ACK rate, retry limit, TX AGC, TX antenna. */ + urtw_write16_m(sc, URTW_8187B_BRSR, 0x0fff); + urtw_read8_m(sc, URTW_CW_CONF, &data); + urtw_write8_m(sc, URTW_CW_CONF, data | + URTW_CW_CONF_PERPACKET_RETRY); + urtw_read8_m(sc, URTW_TX_AGC_CTL, &data); + urtw_write8_m(sc, URTW_TX_AGC_CTL, data | + URTW_TX_AGC_CTL_PERPACKET_GAIN | + URTW_TX_AGC_CTL_PERPACKET_ANTSEL); + + /* Auto rate fallback control. */ + urtw_write16_idx_m(sc, URTW_ARFR, 0x0fff, 1); /* 1M ~ 54M */ + urtw_read8_m(sc, URTW_RATE_FALLBACK, &data); + urtw_write8_m(sc, URTW_RATE_FALLBACK, data | + URTW_RATE_FALLBACK_ENABLE); + + urtw_write16_m(sc, URTW_BEACON_INTERVAL, 100); + urtw_write16_m(sc, URTW_ATIM_WND, 2); + urtw_write16_idx_m(sc, URTW_FEMR, 0xffff, 1); + + error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); + if (error) + goto fail; + urtw_read8_m(sc, URTW_CONFIG1, &data); + urtw_write8_m(sc, URTW_CONFIG1, (data & 0x3f) | 0x80); + error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); + if (error) + goto fail; + + urtw_write8_m(sc, URTW_WPA_CONFIG, 0); + urtw_8225v2_b_config_mac(sc); + urtw_write16_idx_m(sc, URTW_RFSW_CTRL, 0x569a, 2); + + error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); + if (error) + goto fail; + urtw_read8_m(sc, URTW_CONFIG3, &data); + urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE); + error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); + if (error) + goto fail; + + urtw_8225v2_b_init_rfe(sc); + + for (i = 0; i < nitems(urtw_8225v2_b_rf); i++) { + urtw_8225_write(sc, urtw_8225v2_b_rf[i].reg, + urtw_8225v2_b_rf[i].val); + } + + for (i = 0; i < nitems(urtw_8225v2_rxgain); i++) { + urtw_8225_write(sc, 0x1, (uint8_t)(i + 1)); + urtw_8225_write(sc, 0x2, urtw_8225v2_rxgain[i]); + } + + urtw_8225_write(sc, 0x03, 0x080); + urtw_8225_write(sc, 0x05, 0x004); + urtw_8225_write(sc, 0x00, 0x0b7); + urtw_8225_write(sc, 0x02, 0xc4d); + urtw_8225_write(sc, 0x02, 0x44d); + urtw_8225_write(sc, 0x00, 0x2bf); + + urtw_write8_m(sc, URTW_TX_GAIN_CCK, 0x03); + urtw_write8_m(sc, URTW_TX_GAIN_OFDM, 0x07); + urtw_write8_m(sc, URTW_TX_ANTENNA, 0x03); + + urtw_8187_write_phy_ofdm(sc, 0x80, 0x12); + for (i = 0; i < nitems(urtw_8225v2_agc); i++) { + urtw_8187_write_phy_ofdm(sc, 0x0f, urtw_8225v2_agc[i]); + urtw_8187_write_phy_ofdm(sc, 0x0e, (uint8_t)i + 0x80); + urtw_8187_write_phy_ofdm(sc, 0x0e, 0); + } + urtw_8187_write_phy_ofdm(sc, 0x80, 0x10); + + for (i = 0; i < nitems(urtw_8225v2_ofdm); i++) + urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2_ofdm[i]); + + urtw_8225v2_b_update_chan(sc); + + urtw_8187_write_phy_ofdm(sc, 0x97, 0x46); + urtw_8187_write_phy_ofdm(sc, 0xa4, 0xb6); + urtw_8187_write_phy_ofdm(sc, 0x85, 0xfc); + urtw_8187_write_phy_cck(sc, 0xc1, 0x88); + + error = urtw_8225v2_b_rf_set_chan(rf, 1); +fail: + return (error); +} + +usbd_status +urtw_8225v2_b_rf_set_chan(struct urtw_rf *rf, int chan) +{ + struct urtw_softc *sc = rf->rf_sc; + usbd_status error; + + error = urtw_8225v2_b_set_txpwrlvl(sc, chan); + if (error) + goto fail; + + urtw_8225_write(sc, 0x7, urtw_8225_channel[chan]); + /* + * Delay removed from 8185 to 8187. + * usbd_delay_ms(sc->sc_udev, 10); + */ + + urtw_write16_m(sc, URTW_AC_VO, 0x5114); + urtw_write16_m(sc, URTW_AC_VI, 0x5114); + urtw_write16_m(sc, URTW_AC_BE, 0x5114); + urtw_write16_m(sc, URTW_AC_BK, 0x5114); + +fail: + return (error); +} + +usbd_status +urtw_8225v2_b_set_txpwrlvl(struct urtw_softc *sc, int chan) +{ + int i; + uint8_t *cck_pwrtable; + uint8_t cck_pwrlvl_min, cck_pwrlvl_max, ofdm_pwrlvl_min, + ofdm_pwrlvl_max; + int8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; + int8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; + usbd_status error; + + if (sc->sc_hwrev & URTW_HWREV_8187B_B) { + cck_pwrlvl_min = 0; + cck_pwrlvl_max = 15; + ofdm_pwrlvl_min = 2; + ofdm_pwrlvl_max = 17; + } else { + cck_pwrlvl_min = 7; + cck_pwrlvl_max = 22; + ofdm_pwrlvl_min = 10; + ofdm_pwrlvl_max = 25; + } + + /* CCK power setting */ + cck_pwrlvl = (cck_pwrlvl > (cck_pwrlvl_max - cck_pwrlvl_min)) ? + cck_pwrlvl_max : (cck_pwrlvl + cck_pwrlvl_min); + + cck_pwrlvl += sc->sc_txpwr_cck_base; + cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl; + cck_pwrlvl = (cck_pwrlvl < 0) ? 0 : cck_pwrlvl; + + cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 : + urtw_8225v2_txpwr_cck; + + if (sc->sc_hwrev & URTW_HWREV_8187B_B) { + if (cck_pwrlvl <= 6) + ; /* do nothing */ + else if (cck_pwrlvl <= 11) + cck_pwrtable += 8; + else + cck_pwrtable += 16; + } else { + if (cck_pwrlvl <= 5) + ; /* do nothing */ + else if (cck_pwrlvl <= 11) + cck_pwrtable += 8; + else if (cck_pwrlvl <= 17) + cck_pwrtable += 16; + else + cck_pwrtable += 24; + } + + for (i = 0; i < 8; i++) { + urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]); + } + + urtw_write8_m(sc, URTW_TX_GAIN_CCK, + urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl] << 1); + /* + * Delay removed from 8185 to 8187. + * usbd_delay_ms(sc->sc_udev, 1); + */ + + /* OFDM power setting */ + ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ? + ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min; + + ofdm_pwrlvl += sc->sc_txpwr_ofdm_base; + ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; + ofdm_pwrlvl = (ofdm_pwrlvl < 0) ? 0 : ofdm_pwrlvl; + + urtw_write8_m(sc, URTW_TX_GAIN_OFDM, + urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl] << 1); + + if (sc->sc_hwrev & URTW_HWREV_8187B_B) { + if (ofdm_pwrlvl <= 11) { + urtw_8187_write_phy_ofdm(sc, 0x87, 0x60); + urtw_8187_write_phy_ofdm(sc, 0x89, 0x60); + } else { + urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c); + urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c); + } + } else { + if (ofdm_pwrlvl <= 11) { + urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c); + urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c); + } else if (ofdm_pwrlvl <= 17) { + urtw_8187_write_phy_ofdm(sc, 0x87, 0x54); + urtw_8187_write_phy_ofdm(sc, 0x89, 0x54); + } else { + urtw_8187_write_phy_ofdm(sc, 0x87, 0x50); + urtw_8187_write_phy_ofdm(sc, 0x89, 0x50); + } + } + + /* + * Delay removed from 8185 to 8187. + * usbd_delay_ms(sc->sc_udev, 1); + */ +fail: + return (error); +} + diff --git a/sys/dev/usb/if_urtwreg.h b/sys/dev/usb/if_urtwreg.h index a1d79f4085a..b6e0ee16e59 100644 --- a/sys/dev/usb/if_urtwreg.h +++ b/sys/dev/usb/if_urtwreg.h @@ -1,6 +1,7 @@ -/* $OpenBSD: if_urtwreg.h,v 1.11 2009/06/05 01:21:54 martynas Exp $ */ +/* $OpenBSD: if_urtwreg.h,v 1.12 2009/06/06 12:06:28 martynas Exp $ */ /*- + * Copyright (c) 2009 Martynas Venckus <martynas@openbsd.org> * Copyright (c) 2008 Weongyo Jeong <weongyo@FreeBSD.org> * * Permission to use, copy, modify, and distribute this software for any @@ -25,6 +26,10 @@ #define URTW_HWREV_8187 0x01 #define URTW_HWREV_8187_B 0x02 #define URTW_HWREV_8187_D 0x04 +#define URTW_HWREV_8187B 0x08 +#define URTW_HWREV_8187B_B 0x10 +#define URTW_HWREV_8187B_D 0x20 +#define URTW_HWREV_8187B_E 0x40 /* * Registers specific to RTL8187 and RTL8187B. @@ -37,8 +42,10 @@ #define URTW_MAC5 0x0005 /* 1 byte */ #define URTW_8187_BRSR 0x002c /* 2 byte */ #define URTW_BRSR_MBR_8185 (0x0fff) +#define URTW_8187B_EIFS 0x002d /* 1 byte */ #define URTW_BSSID 0x002e /* 6 byte */ #define URTW_RESP_RATE 0x0034 /* 1 byte */ +#define URTW_8187B_BRSR 0x0034 /* 2 byte */ #define URTW_RESP_MAX_RATE_SHIFT (4) #define URTW_RESP_MIN_RATE_SHIFT (0) #define URTW_8187_EIFS 0x0035 /* 1 byte */ @@ -51,6 +58,10 @@ #define URTW_TX_HWREV_MASK (7 << 25) #define URTW_TX_HWREV_8187_D (5 << 25) #define URTW_TX_HWREV_8187B_D (6 << 25) +#define URTW_TX_DURPROCMODE (1 << 30) +#define URTW_TX_DISREQQSIZE (1 << 28) +#define URTW_TX_SHORTRETRY (7 << 8) +#define URTW_TX_LONGRETRY (7 << 0) #define URTW_TX_LOOPBACK_SHIFT (17) #define URTW_TX_LOOPBACK_NONE (0 << URTW_TX_LOOPBACK_SHIFT) #define URTW_TX_LOOPBACK_MAC (1 << URTW_TX_LOOPBACK_SHIFT) @@ -119,9 +130,11 @@ #define URTW_EPROM_WRITEBIT (0x2) #define URTW_EPROM_CK (0x4) #define URTW_EPROM_CS (0x8) +#define URTW_CONFIG1 0x0052 /* 1 byte */ #define URTW_CONFIG2 0x0053 /* 1 byte */ #define URTW_ANAPARAM 0x0054 /* 4 byte */ #define URTW_8187_8225_ANAPARAM_ON (0xa0000a59) +#define URTW_8187B_8225_ANAPARAM_ON (0x45090658) #define URTW_MSR 0x0058 /* 1 byte */ #define URTW_MSR_LINK_MASK ((1 << 2) | (1 << 3)) #define URTW_MSR_LINK_SHIFT (2) @@ -129,12 +142,15 @@ #define URTW_MSR_LINK_ADHOC (1 << URTW_MSR_LINK_SHIFT) #define URTW_MSR_LINK_STA (2 << URTW_MSR_LINK_SHIFT) #define URTW_MSR_LINK_HOSTAP (3 << URTW_MSR_LINK_SHIFT) +#define URTW_MSR_LINK_ENEDCA (4 << URTW_MSR_LINK_SHIFT) #define URTW_CONFIG3 0x0059 /* 1 byte */ #define URTW_CONFIG3_ANAPARAM_WRITE (0x40) #define URTW_CONFIG3_ANAPARAM_W_SHIFT (6) +#define URTW_CONFIG3_GNT_SELECT (0x80) #define URTW_PSR 0x005e /* 1 byte */ #define URTW_ANAPARAM2 0x0060 /* 4 byte */ #define URTW_8187_8225_ANAPARAM2_ON (0x860c7312) +#define URTW_8187B_8225_ANAPARAM2_ON (0x727f3f52) #define URTW_BEACON_INTERVAL 0x0070 /* 2 byte */ #define URTW_ATIM_WND 0x0072 /* 2 byte */ #define URTW_BEACON_INTERVAL_TIME 0x0074 /* 2 byte */ @@ -150,6 +166,7 @@ #define URTW_RF_TIMING 0x008c /* 4 byte */ #define URTW_GP_ENABLE 0x0090 /* 1 byte */ #define URTW_GPIO 0x0091 /* 1 byte */ +#define URTW_HSSI_PARA 0x0094 /* 4 byte */ #define URTW_TX_AGC_CTL 0x009c /* 1 byte */ #define URTW_TX_AGC_CTL_PERPACKET_GAIN (0x1) #define URTW_TX_AGC_CTL_PERPACKET_ANTSEL (0x2) @@ -166,7 +183,24 @@ #define URTW_CW_CONF_PERPACKET_CW (0x1) #define URTW_CW_VAL 0x00bd /* 1 byte */ #define URTW_RATE_FALLBACK 0x00be /* 1 byte */ +#define URTW_RATE_FALLBACK_ENABLE (0x80) +#define URTW_ACM_CONTROL 0x00bf /* 1 byte */ +#define URTW_8187B_HWREV 0x00e1 /* 1 byte */ +#define URTW_8187B_HWREV_8187B_B (0x0) +#define URTW_8187B_HWREV_8187B_D (0x1) +#define URTW_8187B_HWREV_8187B_E (0x2) +#define URTW_INT_MIG 0x00e2 /* 2 byte */ +#define URTW_TID_AC_MAP 0x00e8 /* 2 byte */ +#define URTW_ANAPARAM3 0x00ee /* 4 byte */ +#define URTW_8187B_8225_ANAPARAM3_ON (0x0) #define URTW_TALLY_SEL 0x00fc /* 1 byte */ +#define URTW_AC_VO 0x00f0 /* 1 byte */ +#define URTW_AC_VI 0x00f4 /* 1 byte */ +#define URTW_AC_BE 0x00f8 /* 1 byte */ +#define URTW_AC_BK 0x00fc /* 1 byte */ +#define URTW_FEMR 0x01d4 /* 2 byte */ +#define URTW_ARFR 0x01e0 /* 2 byte */ +#define URTW_RFSW_CTRL 0x0272 /* 2 byte */ /* for EEPROM */ #define URTW_EPROM_TXPW_BASE 0x05 |