diff options
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/files.pci | 7 | ||||
-rw-r--r-- | sys/dev/pci/if_rtwn.c | 2880 |
2 files changed, 181 insertions, 2706 deletions
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 0614e568d71..cae5a3aae6f 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $OpenBSD: files.pci,v 1.322 2015/12/31 13:06:49 kettenis Exp $ +# $OpenBSD: files.pci,v 1.323 2016/03/09 18:18:28 stsp Exp $ # $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $ # # Config file and device description for machine-independent PCI code. @@ -677,9 +677,8 @@ attach rtw at pci with rtw_pci file dev/pci/if_rtw_pci.c rtw_pci # Realtek RTL8188CE Mini-PCI -device rtwn: ifnet, wlan, firmload -attach rtwn at pci -file dev/pci/if_rtwn.c rtwn +attach rtwn at pci with rtwn_pci +file dev/pci/if_rtwn.c rtwn_pci # Ralink RT2500 PCI/Mini-PCI attach ral at pci with ral_pci diff --git a/sys/dev/pci/if_rtwn.c b/sys/dev/pci/if_rtwn.c index b575193f7dd..fa84bbcbb70 100644 --- a/sys/dev/pci/if_rtwn.c +++ b/sys/dev/pci/if_rtwn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_rtwn.c,v 1.15 2016/03/07 19:41:49 stsp Exp $ */ +/* $OpenBSD: if_rtwn.c,v 1.16 2016/03/09 18:18:28 stsp Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> @@ -18,7 +18,7 @@ */ /* - * Driver for Realtek RTL8188CE + * PCI front-end for Realtek RTL8188CE driver. */ #include "bpfilter.h" @@ -56,14 +56,7 @@ #include <dev/pci/pcidevs.h> #include <dev/ic/r92creg.h> - -#define R92C_PUBQ_NPAGES 176 -#define R92C_HPQ_NPAGES 41 -#define R92C_LPQ_NPAGES 28 -#define R92C_TXPKTBUF_COUNT 256 -#define R92C_TX_PAGE_COUNT \ - (R92C_PUBQ_NPAGES + R92C_HPQ_NPAGES + R92C_LPQ_NPAGES) -#define R92C_TX_PAGE_BOUNDARY (R92C_TX_PAGE_COUNT + 1) +#include <dev/ic/rtwnvar.h> /* * Driver definitions. @@ -71,7 +64,6 @@ #define RTWN_NTXQUEUES 9 #define RTWN_RX_LIST_COUNT 256 #define RTWN_TX_LIST_COUNT 256 -#define RTWN_HOST_CMD_RING_COUNT 32 /* TX queue indices. */ #define RTWN_BK_QUEUE 0 @@ -84,19 +76,6 @@ #define RTWN_HIGH_QUEUE 7 #define RTWN_HCCA_QUEUE 8 -/* RX queue indices. */ -#define RTWN_RX_QUEUE 0 - -#define RTWN_RXBUFSZ (16 * 1024) -#define RTWN_TXBUFSZ (sizeof(struct r92c_tx_desc_pci) + IEEE80211_MAX_LEN) - -#define RTWN_RIDX_COUNT 28 - -#define RTWN_TX_TIMEOUT 5000 /* ms */ - -#define RTWN_LED_LINK 0 -#define RTWN_LED_DATA 1 - struct rtwn_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; uint8_t wr_flags; @@ -123,8 +102,6 @@ struct rtwn_tx_radiotap_header { (1 << IEEE80211_RADIOTAP_FLAGS | \ 1 << IEEE80211_RADIOTAP_CHANNEL) -struct rtwn_softc; - struct rtwn_rx_data { bus_dmamap_t map; struct mbuf *m; @@ -154,28 +131,13 @@ struct rtwn_tx_ring { int cur; }; -struct rtwn_host_cmd { - void (*cb)(struct rtwn_softc *, void *); - uint8_t data[256]; -}; +struct rtwn_pci_softc { + struct device sc_dev; + struct rtwn_softc sc_sc; -struct rtwn_cmd_key { - struct ieee80211_key key; - uint16_t associd; -}; - -struct rtwn_host_cmd_ring { - struct rtwn_host_cmd cmd[RTWN_HOST_CMD_RING_COUNT]; - int cur; - int next; - int queued; -}; - -struct rtwn_softc { - struct device sc_dev; - struct ieee80211com sc_ic; - int (*sc_newstate)(struct ieee80211com *, - enum ieee80211_state, int); + struct rtwn_rx_ring rx_ring; + struct rtwn_tx_ring tx_ring[RTWN_NTXQUEUES]; + uint32_t qfullmsk; /* PCI specific goo. */ bus_dma_tag_t sc_dmat; @@ -187,40 +149,6 @@ struct rtwn_softc { bus_size_t sc_mapsize; int sc_cap_off; - - struct timeout scan_to; - struct timeout calib_to; - struct task init_task; - int ac2idx[EDCA_NUM_AC]; - u_int sc_flags; -#define RTWN_FLAG_CCK_HIPWR 0x01 -#define RTWN_FLAG_BUSY 0x02 - - u_int chip; -#define RTWN_CHIP_88C 0x00 -#define RTWN_CHIP_92C 0x01 -#define RTWN_CHIP_92C_1T2R 0x02 -#define RTWN_CHIP_UMC 0x04 -#define RTWN_CHIP_UMC_A_CUT 0x08 - - uint8_t board_type; - uint8_t regulatory; - uint8_t pa_setting; - int avg_pwdb; - int thcal_state; - int thcal_lctemp; - int ntxchains; - int nrxchains; - int ledlink; - - int sc_tx_timer; - int fwcur; - struct rtwn_rx_ring rx_ring; - struct rtwn_tx_ring tx_ring[RTWN_NTXQUEUES]; - uint32_t qfullmsk; - struct r92c_rom rom; - - uint32_t rf_chnlbw[R92C_MAX_CHAINS]; #if NBPFILTER > 0 caddr_t sc_drvbpf; @@ -240,11 +168,10 @@ struct rtwn_softc { #endif }; - #ifdef RTWN_DEBUG #define DPRINTF(x) do { if (rtwn_debug) printf x; } while (0) #define DPRINTFN(n, x) do { if (rtwn_debug >= (n)) printf x; } while (0) -int rtwn_debug = 0; +extern int rtwn_debug; #else #define DPRINTF(x) #define DPRINTFN(n, x) @@ -265,123 +192,61 @@ static const struct pci_matchid rtwn_pci_devices[] = { { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8188 } }; -int rtwn_match(struct device *, void *, void *); -void rtwn_attach(struct device *, struct device *, void *); -int rtwn_detach(struct device *, int); -int rtwn_activate(struct device *, int); -int rtwn_alloc_rx_list(struct rtwn_softc *); -void rtwn_reset_rx_list(struct rtwn_softc *); -void rtwn_free_rx_list(struct rtwn_softc *); -void rtwn_setup_rx_desc(struct rtwn_softc *, +int rtwn_pci_match(struct device *, void *, void *); +void rtwn_pci_attach(struct device *, struct device *, void *); +int rtwn_pci_detach(struct device *, int); +int rtwn_pci_activate(struct device *, int); +int rtwn_alloc_rx_list(struct rtwn_pci_softc *); +void rtwn_reset_rx_list(struct rtwn_pci_softc *); +void rtwn_free_rx_list(struct rtwn_pci_softc *); +void rtwn_setup_rx_desc(struct rtwn_pci_softc *, struct r92c_rx_desc_pci *, bus_addr_t, size_t, int); -int rtwn_alloc_tx_list(struct rtwn_softc *, int); -void rtwn_reset_tx_list(struct rtwn_softc *, int); -void rtwn_free_tx_list(struct rtwn_softc *, int); -void rtwn_write_1(struct rtwn_softc *, uint16_t, uint8_t); -void rtwn_write_2(struct rtwn_softc *, uint16_t, uint16_t); -void rtwn_write_4(struct rtwn_softc *, uint16_t, uint32_t); -uint8_t rtwn_read_1(struct rtwn_softc *, uint16_t); -uint16_t rtwn_read_2(struct rtwn_softc *, uint16_t); -uint32_t rtwn_read_4(struct rtwn_softc *, uint16_t); -int rtwn_fw_cmd(struct rtwn_softc *, uint8_t, const void *, int); -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); -int rtwn_llt_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 *); -int rtwn_read_chipid(struct rtwn_softc *); -void rtwn_read_rom(struct rtwn_softc *); -int rtwn_media_change(struct ifnet *); -int rtwn_ra_init(struct rtwn_softc *); -void rtwn_tsf_sync_enable(struct rtwn_softc *); -void rtwn_set_led(struct rtwn_softc *, int, int); -void rtwn_calib_to(void *); -void rtwn_next_scan(void *); -int rtwn_newstate(struct ieee80211com *, enum ieee80211_state, - int); -void rtwn_updateedca(struct ieee80211com *); -int rtwn_set_key(struct ieee80211com *, struct ieee80211_node *, - struct ieee80211_key *); -void rtwn_delete_key(struct ieee80211com *, - struct ieee80211_node *, struct ieee80211_key *); -void rtwn_update_avgrssi(struct rtwn_softc *, int, int8_t); -int8_t rtwn_get_rssi(struct rtwn_softc *, int, void *); -void rtwn_rx_frame(struct rtwn_softc *, struct r92c_rx_desc_pci *, - struct rtwn_rx_data *, int); -int rtwn_tx(struct rtwn_softc *, struct mbuf *, - struct ieee80211_node *); -void rtwn_tx_done(struct rtwn_softc *, int); -void rtwn_start(struct ifnet *); -void rtwn_watchdog(struct ifnet *); -int rtwn_ioctl(struct ifnet *, u_long, caddr_t); -int rtwn_power_on(struct rtwn_softc *); -int rtwn_llt_init(struct rtwn_softc *); -void rtwn_fw_reset(struct rtwn_softc *); -int rtwn_fw_loadpage(struct rtwn_softc *, int, uint8_t *, int); -int rtwn_load_firmware(struct rtwn_softc *); -int rtwn_dma_init(struct rtwn_softc *); -void rtwn_mac_init(struct rtwn_softc *); -void rtwn_bb_init(struct rtwn_softc *); -void rtwn_rf_init(struct rtwn_softc *); -void rtwn_cam_init(struct rtwn_softc *); -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, - struct ieee80211_channel *, struct ieee80211_channel *, - uint16_t[]); -void rtwn_set_txpower(struct rtwn_softc *, - struct ieee80211_channel *, struct ieee80211_channel *); -void rtwn_set_chan(struct rtwn_softc *, - struct ieee80211_channel *, struct ieee80211_channel *); -int rtwn_iq_calib_chain(struct rtwn_softc *, int, uint16_t[2], - uint16_t[2]); -void rtwn_iq_calib_run(struct rtwn_softc *, int, uint16_t[2][2], - uint16_t[2][2]); -int rtwn_iq_calib_compare_results(uint16_t[2][2], uint16_t[2][2], - uint16_t[2][2], uint16_t[2][2], int); -void rtwn_iq_calib_write_results(struct rtwn_softc *, uint16_t[2], - uint16_t[2], int); -void rtwn_iq_calib(struct rtwn_softc *); -void rtwn_lc_calib(struct rtwn_softc *); -void rtwn_temp_calib(struct rtwn_softc *); -int rtwn_init(struct ifnet *); -void rtwn_init_task(void *); -void rtwn_stop(struct ifnet *); +int rtwn_alloc_tx_list(struct rtwn_pci_softc *, int); +void rtwn_reset_tx_list(struct rtwn_pci_softc *, int); +void rtwn_free_tx_list(struct rtwn_pci_softc *, int); +void rtwn_pci_write_1(void *, uint16_t, uint8_t); +void rtwn_pci_write_2(void *, uint16_t, uint16_t); +void rtwn_pci_write_4(void *, uint16_t, uint32_t); +uint8_t rtwn_pci_read_1(void *, uint16_t); +uint16_t rtwn_pci_read_2(void *, uint16_t); +uint32_t rtwn_pci_read_4(void *, uint16_t); +void rtwn_pci_next_scan(void *); +void rtwn_rx_frame(struct rtwn_pci_softc *, + struct r92c_rx_desc_pci *, struct rtwn_rx_data *, int); +int rtwn_tx(void *, struct mbuf *, struct ieee80211_node *); +void rtwn_tx_done(struct rtwn_pci_softc *, int); +void rtwn_pci_stop(void *); int rtwn_intr(void *); - -/* Aliases. */ -#define rtwn_bb_write rtwn_write_4 -#define rtwn_bb_read rtwn_read_4 +int rtwn_is_oactive(void *); +int rtwn_configure_dma(void *); +void rtwn_enable_intr(void *); +void rtwn_disable_intr(void *); struct cfdriver rtwn_cd = { NULL, "rtwn", DV_IFNET }; -const struct cfattach rtwn_ca = { - sizeof(struct rtwn_softc), - rtwn_match, - rtwn_attach, - rtwn_detach, - rtwn_activate +const struct cfattach rtwn_pci_ca = { + sizeof(struct rtwn_pci_softc), + rtwn_pci_match, + rtwn_pci_attach, + rtwn_pci_detach, + rtwn_pci_activate }; int -rtwn_match(struct device *parent, void *match, void *aux) +rtwn_pci_match(struct device *parent, void *match, void *aux) { return (pci_matchbyid(aux, rtwn_pci_devices, nitems(rtwn_pci_devices))); } void -rtwn_attach(struct device *parent, struct device *self, void *aux) +rtwn_pci_attach(struct device *parent, struct device *self, void *aux) { - struct rtwn_softc *sc = (struct rtwn_softc *)self; + struct rtwn_pci_softc *sc = (struct rtwn_pci_softc*)self; struct pci_attach_args *pa = aux; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; + struct ifnet *ifp; int i, error; pcireg_t memtype; pci_intr_handle_t ih; @@ -391,11 +256,6 @@ rtwn_attach(struct device *parent, struct device *self, void *aux) sc->sc_pc = pa->pa_pc; sc->sc_tag = pa->pa_tag; - timeout_set(&sc->scan_to, rtwn_next_scan, sc); - timeout_set(&sc->calib_to, rtwn_calib_to, sc); - - task_set(&sc->init_task, rtwn_init_task, sc); - pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0); /* Map control/status registers. */ @@ -423,12 +283,6 @@ rtwn_attach(struct device *parent, struct device *self, void *aux) } printf(": %s\n", intrstr); - error = rtwn_read_chipid(sc); - if (error != 0) { - printf("%s: unsupported test chip\n", sc->sc_dev.dv_xname); - return; - } - /* Disable PCIe Active State Power Management (ASPM). */ if (pci_get_capability(sc->sc_pc, sc->sc_tag, PCI_CAP_PCIEXPRESS, &sc->sc_cap_off, NULL)) { @@ -455,85 +309,25 @@ rtwn_attach(struct device *parent, struct device *self, void *aux) } } - /* Determine number of Tx/Rx chains. */ - if (sc->chip & RTWN_CHIP_92C) { - sc->ntxchains = (sc->chip & RTWN_CHIP_92C_1T2R) ? 1 : 2; - sc->nrxchains = 2; - } else { - sc->ntxchains = 1; - sc->nrxchains = 1; - } - rtwn_read_rom(sc); - - printf("%s: MAC/BB RTL%s, RF 6052 %dT%dR, address %s\n", - sc->sc_dev.dv_xname, - (sc->chip & RTWN_CHIP_92C) ? "8192CE" : "8188CE", - sc->ntxchains, sc->nrxchains, - ether_sprintf(ic->ic_myaddr)); - - ic->ic_phytype = IEEE80211_T_OFDM; /* Not only, but not used. */ - ic->ic_opmode = IEEE80211_M_STA; /* Default to BSS mode. */ - ic->ic_state = IEEE80211_S_INIT; - - /* Set device capabilities. */ - ic->ic_caps = - IEEE80211_C_MONITOR | /* Monitor mode supported. */ - IEEE80211_C_SHPREAMBLE | /* Short preamble supported. */ - IEEE80211_C_SHSLOT | /* Short slot time supported. */ - IEEE80211_C_WEP | /* WEP. */ - IEEE80211_C_RSN; /* WPA/RSN. */ - - /* Set HT capabilities. */ - ic->ic_htcaps = - IEEE80211_HTCAP_CBW20_40 | - IEEE80211_HTCAP_DSSSCCK40; - /* Set supported HT rates. */ - for (i = 0; i < sc->nrxchains; i++) - ic->ic_sup_mcs[i] = 0xff; - - /* Set supported .11b and .11g rates. */ - ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b; - ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g; - - /* Set supported .11b and .11g channels (1 through 14). */ - for (i = 1; i <= 14; i++) { - ic->ic_channels[i].ic_freq = - ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); - ic->ic_channels[i].ic_flags = - IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | - IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; - } - -#ifdef notyet - /* - * The number of STAs that we can support is limited by the number - * of CAM entries used for hardware crypto. - */ - ic->ic_max_nnodes = R92C_CAM_ENTRY_COUNT - 4; - if (ic->ic_max_nnodes > IEEE80211_CACHE_SIZE) - ic->ic_max_nnodes = IEEE80211_CACHE_SIZE; -#endif - - ifp->if_softc = sc; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = rtwn_ioctl; - ifp->if_start = rtwn_start; - ifp->if_watchdog = rtwn_watchdog; - IFQ_SET_READY(&ifp->if_snd); - memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); - - if_attach(ifp); - ieee80211_ifattach(ifp); - ic->ic_updateedca = rtwn_updateedca; -#ifdef notyet - ic->ic_set_key = rtwn_set_key; - ic->ic_delete_key = rtwn_delete_key; -#endif - /* Override state transition machine. */ - sc->sc_newstate = ic->ic_newstate; - ic->ic_newstate = rtwn_newstate; - ieee80211_media_init(ifp, rtwn_media_change, ieee80211_media_status); - + /* Attach the bus-agnostic driver. */ + sc->sc_sc.sc_ops.cookie = sc; + sc->sc_sc.sc_ops.write_1 = rtwn_pci_write_1; + sc->sc_sc.sc_ops.write_2 = rtwn_pci_write_2; + sc->sc_sc.sc_ops.write_4 = rtwn_pci_write_4; + sc->sc_sc.sc_ops.read_1 = rtwn_pci_read_1; + sc->sc_sc.sc_ops.read_2 = rtwn_pci_read_2; + sc->sc_sc.sc_ops.read_4 = rtwn_pci_read_4; + sc->sc_sc.sc_ops.next_scan = rtwn_pci_next_scan; + sc->sc_sc.sc_ops.tx = rtwn_tx; + sc->sc_sc.sc_ops.configure_dma = rtwn_configure_dma; + sc->sc_sc.sc_ops.enable_intr = rtwn_enable_intr; + sc->sc_sc.sc_ops.disable_intr = rtwn_disable_intr; + sc->sc_sc.sc_ops.stop = rtwn_pci_stop; + sc->sc_sc.sc_ops.is_oactive = rtwn_is_oactive; + rtwn_attach(&sc->sc_dev, &sc->sc_sc); + + /* ifp is now valid */ + ifp = &sc->sc_sc.sc_ic.ic_if; #if NBPFILTER > 0 bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO, sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN); @@ -549,26 +343,14 @@ rtwn_attach(struct device *parent, struct device *self, void *aux) } int -rtwn_detach(struct device *self, int flags) +rtwn_pci_detach(struct device *self, int flags) { - struct rtwn_softc *sc = (struct rtwn_softc *)self; - struct ifnet *ifp = &sc->sc_ic.ic_if; + struct rtwn_pci_softc *sc = (struct rtwn_pci_softc *)self; int s, i; - s = splnet(); - - if (timeout_initialized(&sc->scan_to)) - timeout_del(&sc->scan_to); - if (timeout_initialized(&sc->calib_to)) - timeout_del(&sc->calib_to); - - task_del(systq, &sc->init_task); - - if (ifp->if_softc != NULL) { - ieee80211_ifdetach(ifp); - if_detach(ifp); - } + rtwn_detach(&sc->sc_sc, flags); + s = splnet(); /* Free Tx/Rx buffers. */ for (i = 0; i < RTWN_NTXQUEUES; i++) rtwn_free_tx_list(sc, i); @@ -579,25 +361,15 @@ rtwn_detach(struct device *self, int flags) } int -rtwn_activate(struct device *self, int act) +rtwn_pci_activate(struct device *self, int act) { - struct rtwn_softc *sc = (struct rtwn_softc *)self; - struct ifnet *ifp = &sc->sc_ic.ic_if; - - switch (act) { - case DVACT_SUSPEND: - if (ifp->if_flags & IFF_RUNNING) - rtwn_stop(ifp); - break; - case DVACT_WAKEUP: - rtwn_init_task(sc); - break; - } - return (0); + struct rtwn_pci_softc *sc = (struct rtwn_pci_softc *)self; + + return rtwn_activate(&sc->sc_sc, act); } void -rtwn_setup_rx_desc(struct rtwn_softc *sc, struct r92c_rx_desc_pci *desc, +rtwn_setup_rx_desc(struct rtwn_pci_softc *sc, struct r92c_rx_desc_pci *desc, bus_addr_t addr, size_t len, int idx) { memset(desc, 0, sizeof(*desc)); @@ -610,7 +382,7 @@ rtwn_setup_rx_desc(struct rtwn_softc *sc, struct r92c_rx_desc_pci *desc, } int -rtwn_alloc_rx_list(struct rtwn_softc *sc) +rtwn_alloc_rx_list(struct rtwn_pci_softc *sc) { struct rtwn_rx_ring *rx_ring = &sc->rx_ring; struct rtwn_rx_data *rx_data; @@ -695,7 +467,7 @@ fail: if (error != 0) } void -rtwn_reset_rx_list(struct rtwn_softc *sc) +rtwn_reset_rx_list(struct rtwn_pci_softc *sc) { struct rtwn_rx_ring *rx_ring = &sc->rx_ring; struct rtwn_rx_data *rx_data; @@ -709,7 +481,7 @@ rtwn_reset_rx_list(struct rtwn_softc *sc) } void -rtwn_free_rx_list(struct rtwn_softc *sc) +rtwn_free_rx_list(struct rtwn_pci_softc *sc) { struct rtwn_rx_ring *rx_ring = &sc->rx_ring; struct rtwn_rx_data *rx_data; @@ -747,7 +519,7 @@ rtwn_free_rx_list(struct rtwn_softc *sc) } int -rtwn_alloc_tx_list(struct rtwn_softc *sc, int qid) +rtwn_alloc_tx_list(struct rtwn_pci_softc *sc, int qid) { struct rtwn_tx_ring *tx_ring = &sc->tx_ring[qid]; struct rtwn_tx_data *tx_data; @@ -817,9 +589,9 @@ fail: } void -rtwn_reset_tx_list(struct rtwn_softc *sc, int qid) +rtwn_reset_tx_list(struct rtwn_pci_softc *sc, int qid) { - struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211com *ic = &sc->sc_sc.sc_ic; struct rtwn_tx_ring *tx_ring = &sc->tx_ring[qid]; int i; @@ -849,7 +621,7 @@ rtwn_reset_tx_list(struct rtwn_softc *sc, int qid) } void -rtwn_free_tx_list(struct rtwn_softc *sc, int qid) +rtwn_free_tx_list(struct rtwn_pci_softc *sc, int qid) { struct rtwn_tx_ring *tx_ring = &sc->tx_ring[qid]; struct rtwn_tx_data *tx_data; @@ -883,442 +655,60 @@ rtwn_free_tx_list(struct rtwn_softc *sc, int qid) } void -rtwn_write_1(struct rtwn_softc *sc, uint16_t addr, uint8_t val) +rtwn_pci_write_1(void *cookie, uint16_t addr, uint8_t val) { + struct rtwn_pci_softc *sc = cookie; + bus_space_write_1(sc->sc_st, sc->sc_sh, addr, val); } void -rtwn_write_2(struct rtwn_softc *sc, uint16_t addr, uint16_t val) +rtwn_pci_write_2(void *cookie, uint16_t addr, uint16_t val) { + struct rtwn_pci_softc *sc = cookie; + val = htole16(val); bus_space_write_2(sc->sc_st, sc->sc_sh, addr, val); } void -rtwn_write_4(struct rtwn_softc *sc, uint16_t addr, uint32_t val) +rtwn_pci_write_4(void *cookie, uint16_t addr, uint32_t val) { + struct rtwn_pci_softc *sc = cookie; + val = htole32(val); bus_space_write_4(sc->sc_st, sc->sc_sh, addr, val); } uint8_t -rtwn_read_1(struct rtwn_softc *sc, uint16_t addr) +rtwn_pci_read_1(void *cookie, uint16_t addr) { + struct rtwn_pci_softc *sc = cookie; + return bus_space_read_1(sc->sc_st, sc->sc_sh, addr); } uint16_t -rtwn_read_2(struct rtwn_softc *sc, uint16_t addr) -{ - return bus_space_read_2(sc->sc_st, sc->sc_sh, addr); -} - -uint32_t -rtwn_read_4(struct rtwn_softc *sc, uint16_t addr) +rtwn_pci_read_2(void *cookie, uint16_t addr) { - return bus_space_read_4(sc->sc_st, sc->sc_sh, addr); -} - -int -rtwn_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len) -{ - struct r92c_fw_cmd cmd; - int ntries; + struct rtwn_pci_softc *sc = cookie; - /* Wait for current FW box to be empty. */ - for (ntries = 0; ntries < 100; ntries++) { - if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur))) - break; - DELAY(1); - } - if (ntries == 100) { - printf("%s: could not send firmware command %d\n", - sc->sc_dev.dv_xname, id); - return (ETIMEDOUT); - } - memset(&cmd, 0, sizeof(cmd)); - cmd.id = id; - if (len > 3) - cmd.id |= R92C_CMD_FLAG_EXT; - KASSERT(len <= sizeof(cmd.msg)); - memcpy(cmd.msg, buf, len); - - /* Write the first word last since that will trigger the FW. */ - rtwn_write_2(sc, R92C_HMEBOX_EXT(sc->fwcur), *((uint8_t *)&cmd + 4)); - rtwn_write_4(sc, R92C_HMEBOX(sc->fwcur), *((uint8_t *)&cmd + 0)); - - sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX; - - /* Give firmware some time for processing. */ - DELAY(2000); - - return (0); -} - -void -rtwn_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, uint32_t val) -{ - rtwn_bb_write(sc, R92C_LSSI_PARAM(chain), - SM(R92C_LSSI_PARAM_ADDR, addr) | - SM(R92C_LSSI_PARAM_DATA, val)); + return bus_space_read_2(sc->sc_st, sc->sc_sh, addr); } uint32_t -rtwn_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr) -{ - uint32_t reg[R92C_MAX_CHAINS], val; - - reg[0] = rtwn_bb_read(sc, R92C_HSSI_PARAM2(0)); - if (chain != 0) - reg[chain] = rtwn_bb_read(sc, R92C_HSSI_PARAM2(chain)); - - rtwn_bb_write(sc, R92C_HSSI_PARAM2(0), - reg[0] & ~R92C_HSSI_PARAM2_READ_EDGE); - DELAY(1000); - - rtwn_bb_write(sc, R92C_HSSI_PARAM2(chain), - RW(reg[chain], R92C_HSSI_PARAM2_READ_ADDR, addr) | - R92C_HSSI_PARAM2_READ_EDGE); - DELAY(1000); - - rtwn_bb_write(sc, R92C_HSSI_PARAM2(0), - reg[0] | R92C_HSSI_PARAM2_READ_EDGE); - DELAY(1000); - - if (rtwn_bb_read(sc, R92C_HSSI_PARAM1(chain)) & R92C_HSSI_PARAM1_PI) - val = rtwn_bb_read(sc, R92C_HSPI_READBACK(chain)); - else - val = rtwn_bb_read(sc, R92C_LSSI_READBACK(chain)); - return (MS(val, R92C_LSSI_READBACK_DATA)); -} - -void -rtwn_cam_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data) -{ - rtwn_write_4(sc, R92C_CAMWRITE, data); - rtwn_write_4(sc, R92C_CAMCMD, - R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE | - SM(R92C_CAMCMD_ADDR, addr)); -} - -int -rtwn_llt_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data) -{ - int ntries; - - rtwn_write_4(sc, R92C_LLT_INIT, - SM(R92C_LLT_INIT_OP, R92C_LLT_INIT_OP_WRITE) | - SM(R92C_LLT_INIT_ADDR, addr) | - SM(R92C_LLT_INIT_DATA, data)); - /* Wait for write operation to complete. */ - for (ntries = 0; ntries < 20; ntries++) { - if (MS(rtwn_read_4(sc, R92C_LLT_INIT), R92C_LLT_INIT_OP) == - R92C_LLT_INIT_OP_NO_ACTIVE) - return (0); - DELAY(5); - } - return (ETIMEDOUT); -} - -uint8_t -rtwn_efuse_read_1(struct rtwn_softc *sc, uint16_t addr) -{ - uint32_t reg; - int ntries; - - reg = rtwn_read_4(sc, R92C_EFUSE_CTRL); - reg = RW(reg, R92C_EFUSE_CTRL_ADDR, addr); - reg &= ~R92C_EFUSE_CTRL_VALID; - rtwn_write_4(sc, R92C_EFUSE_CTRL, reg); - /* Wait for read operation to complete. */ - for (ntries = 0; ntries < 100; ntries++) { - reg = rtwn_read_4(sc, R92C_EFUSE_CTRL); - if (reg & R92C_EFUSE_CTRL_VALID) - return (MS(reg, R92C_EFUSE_CTRL_DATA)); - DELAY(5); - } - printf("%s: could not read efuse byte at address 0x%x\n", - sc->sc_dev.dv_xname, addr); - return (0xff); -} - -void -rtwn_efuse_read(struct rtwn_softc *sc) -{ - uint8_t *rom = (uint8_t *)&sc->rom; - uint16_t addr = 0; - uint32_t reg; - uint8_t off, msk; - int i; - - reg = rtwn_read_2(sc, R92C_SYS_ISO_CTRL); - if (!(reg & R92C_SYS_ISO_CTRL_PWC_EV12V)) { - rtwn_write_2(sc, R92C_SYS_ISO_CTRL, - reg | R92C_SYS_ISO_CTRL_PWC_EV12V); - } - reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN); - if (!(reg & R92C_SYS_FUNC_EN_ELDR)) { - rtwn_write_2(sc, R92C_SYS_FUNC_EN, - reg | R92C_SYS_FUNC_EN_ELDR); - } - reg = rtwn_read_2(sc, R92C_SYS_CLKR); - if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) != - (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) { - rtwn_write_2(sc, R92C_SYS_CLKR, - reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M); - } - memset(&sc->rom, 0xff, sizeof(sc->rom)); - while (addr < 512) { - reg = rtwn_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)) - 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++; - } - } -#ifdef RTWN_DEBUG - if (rtwn_debug >= 2) { - /* Dump ROM content. */ - printf("\n"); - for (i = 0; i < sizeof(sc->rom); i++) - printf("%02x:", rom[i]); - printf("\n"); - } -#endif -} - -/* rtwn_read_chipid: reg=0x40073b chipid=0x0 */ -int -rtwn_read_chipid(struct rtwn_softc *sc) -{ - uint32_t reg; - - reg = rtwn_read_4(sc, R92C_SYS_CFG); - if (reg & R92C_SYS_CFG_TRP_VAUX_EN) - /* Unsupported test chip. */ - return (EIO); - - if (reg & R92C_SYS_CFG_TYPE_92C) { - sc->chip |= RTWN_CHIP_92C; - /* 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; - } - if (reg & R92C_SYS_CFG_VENDOR_UMC) { - sc->chip |= RTWN_CHIP_UMC; - if (MS(reg, R92C_SYS_CFG_CHIP_VER_RTL) == 0) - sc->chip |= RTWN_CHIP_UMC_A_CUT; - } - return (0); -} - -void -rtwn_read_rom(struct rtwn_softc *sc) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct r92c_rom *rom = &sc->rom; - - /* Read full ROM image. */ - rtwn_efuse_read(sc); - - if (rom->id != 0x8129) { - printf("%s: invalid EEPROM ID 0x%x\n", - sc->sc_dev.dv_xname, rom->id); - } - - /* XXX Weird but this is what the vendor driver does. */ - sc->pa_setting = rtwn_efuse_read_1(sc, 0x1fa); - DPRINTF(("PA setting=0x%x\n", sc->pa_setting)); - - sc->board_type = MS(rom->rf_opt1, R92C_ROM_RF1_BOARD_TYPE); - - sc->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY); - DPRINTF(("regulatory type=%d\n", sc->regulatory)); - - IEEE80211_ADDR_COPY(ic->ic_myaddr, rom->macaddr); -} - -int -rtwn_media_change(struct ifnet *ifp) -{ - int error; - - error = ieee80211_media_change(ifp); - if (error != ENETRESET) - return (error); - - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == - (IFF_UP | IFF_RUNNING)) { - rtwn_stop(ifp); - rtwn_init(ifp); - } - return (0); -} - -/* - * Initialize rate adaptation in firmware. - */ -int -rtwn_ra_init(struct rtwn_softc *sc) -{ - static const uint8_t map[] = - { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_node *ni = ic->ic_bss; - struct ieee80211_rateset *rs = &ni->ni_rates; - struct r92c_fw_cmd_macid_cfg cmd; - uint32_t rates, basicrates; - uint8_t mode; - int maxrate, maxbasicrate, error, i, j; - - /* Get normal and basic rates mask. */ - rates = basicrates = 0; - maxrate = maxbasicrate = 0; - for (i = 0; i < rs->rs_nrates; i++) { - /* Convert 802.11 rate to HW rate index. */ - for (j = 0; j < nitems(map); j++) - if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == map[j]) - break; - if (j == nitems(map)) /* Unknown rate, skip. */ - continue; - rates |= 1 << j; - if (j > maxrate) - maxrate = j; - if (rs->rs_rates[i] & IEEE80211_RATE_BASIC) { - basicrates |= 1 << j; - if (j > maxbasicrate) - maxbasicrate = j; - } - } - if (ic->ic_curmode == IEEE80211_MODE_11B) - mode = R92C_RAID_11B; - else - mode = R92C_RAID_11BG; - DPRINTF(("mode=0x%x rates=0x%08x, basicrates=0x%08x\n", - mode, rates, basicrates)); - - /* Set rates mask for group addressed frames. */ - cmd.macid = R92C_MACID_BC | R92C_MACID_VALID; - cmd.mask = htole32(mode << 28 | basicrates); - error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); - if (error != 0) { - printf("%s: could not add broadcast station\n", - sc->sc_dev.dv_xname); - return (error); - } - /* Set initial MRR rate. */ - DPRINTF(("maxbasicrate=%d\n", maxbasicrate)); - rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(R92C_MACID_BC), - maxbasicrate); - - /* Set rates mask for unicast frames. */ - cmd.macid = R92C_MACID_BSS | R92C_MACID_VALID; - cmd.mask = htole32(mode << 28 | rates); - error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); - if (error != 0) { - printf("%s: could not add BSS station\n", - sc->sc_dev.dv_xname); - return (error); - } - /* Set initial MRR rate. */ - DPRINTF(("maxrate=%d\n", maxrate)); - rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(R92C_MACID_BSS), - maxrate); - - /* Configure Automatic Rate Fallback Register. */ - if (ic->ic_curmode == IEEE80211_MODE_11B) { - if (rates & 0x0c) - rtwn_write_4(sc, R92C_ARFR(0), htole32(rates & 0x0d)); - else - rtwn_write_4(sc, R92C_ARFR(0), htole32(rates & 0x0f)); - } else - rtwn_write_4(sc, R92C_ARFR(0), htole32(rates & 0x0ff5)); - - /* Indicate highest supported rate. */ - ni->ni_txrate = rs->rs_nrates - 1; - return (0); -} - -void -rtwn_tsf_sync_enable(struct rtwn_softc *sc) -{ - struct ieee80211_node *ni = sc->sc_ic.ic_bss; - uint64_t tsf; - - /* Enable TSF synchronization. */ - rtwn_write_1(sc, R92C_BCN_CTRL, - rtwn_read_1(sc, R92C_BCN_CTRL) & ~R92C_BCN_CTRL_DIS_TSF_UDT0); - - rtwn_write_1(sc, R92C_BCN_CTRL, - rtwn_read_1(sc, R92C_BCN_CTRL) & ~R92C_BCN_CTRL_EN_BCN); - - /* Set initial TSF. */ - memcpy(&tsf, ni->ni_tstamp, 8); - tsf = letoh64(tsf); - tsf = tsf - (tsf % (ni->ni_intval * IEEE80211_DUR_TU)); - tsf -= IEEE80211_DUR_TU; - rtwn_write_4(sc, R92C_TSFTR + 0, tsf); - rtwn_write_4(sc, R92C_TSFTR + 4, tsf >> 32); - - rtwn_write_1(sc, R92C_BCN_CTRL, - rtwn_read_1(sc, R92C_BCN_CTRL) | R92C_BCN_CTRL_EN_BCN); -} - -void -rtwn_set_led(struct rtwn_softc *sc, int led, int on) -{ - uint8_t reg; - - if (led == RTWN_LED_LINK) { - reg = rtwn_read_1(sc, R92C_LEDCFG2) & 0xf0; - if (!on) - reg |= R92C_LEDCFG2_DIS; - else - reg |= R92C_LEDCFG2_EN; - rtwn_write_1(sc, R92C_LEDCFG2, reg); - sc->ledlink = on; /* Save LED state. */ - } -} - -void -rtwn_calib_to(void *arg) +rtwn_pci_read_4(void *cookie, uint16_t addr) { - struct rtwn_softc *sc = arg; - struct r92c_fw_cmd_rssi cmd; - - if (sc->avg_pwdb != -1) { - /* Indicate Rx signal strength to FW for rate adaptation. */ - memset(&cmd, 0, sizeof(cmd)); - cmd.macid = 0; /* BSS. */ - cmd.pwdb = sc->avg_pwdb; - DPRINTFN(3, ("sending RSSI command avg=%d\n", sc->avg_pwdb)); - rtwn_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd)); - } + struct rtwn_pci_softc *sc = cookie; - /* Do temperature compensation. */ - rtwn_temp_calib(sc); - - timeout_add_sec(&sc->calib_to, 2); + return bus_space_read_4(sc->sc_st, sc->sc_sh, addr); } void -rtwn_next_scan(void *arg) +rtwn_pci_next_scan(void *arg) { - struct rtwn_softc *sc = arg; - struct ieee80211com *ic = &sc->sc_ic; + struct rtwn_pci_softc *sc = arg; + struct ieee80211com *ic = &sc->sc_sc.sc_ic; int s; s = splnet(); @@ -1327,343 +717,11 @@ rtwn_next_scan(void *arg) splx(s); } -int -rtwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) -{ - struct rtwn_softc *sc = ic->ic_softc; - struct ieee80211_node *ni; - enum ieee80211_state ostate; - uint32_t reg; - int s; - - s = splnet(); - ostate = ic->ic_state; - - if (nstate != ostate) - DPRINTF(("newstate %s -> %s\n", - ieee80211_state_name[ostate], - ieee80211_state_name[nstate])); - - if (ostate == IEEE80211_S_RUN) { - /* Stop calibration. */ - timeout_del(&sc->calib_to); - - /* Turn link LED off. */ - rtwn_set_led(sc, RTWN_LED_LINK, 0); - - /* Set media status to 'No Link'. */ - reg = rtwn_read_4(sc, R92C_CR); - reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_NOLINK); - rtwn_write_4(sc, R92C_CR, reg); - - /* Stop Rx of data frames. */ - rtwn_write_2(sc, R92C_RXFLTMAP2, 0); - - /* Rest TSF. */ - rtwn_write_1(sc, R92C_DUAL_TSF_RST, 0x03); - - /* Disable TSF synchronization. */ - rtwn_write_1(sc, R92C_BCN_CTRL, - rtwn_read_1(sc, R92C_BCN_CTRL) | - R92C_BCN_CTRL_DIS_TSF_UDT0); - - /* Reset EDCA parameters. */ - rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3217); - rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4317); - rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x00105320); - rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a444); - } - switch (nstate) { - case IEEE80211_S_INIT: - /* Turn link LED off. */ - rtwn_set_led(sc, RTWN_LED_LINK, 0); - break; - case IEEE80211_S_SCAN: - if (ostate != IEEE80211_S_SCAN) { - /* Allow Rx from any BSSID. */ - rtwn_write_4(sc, R92C_RCR, - rtwn_read_4(sc, R92C_RCR) & - ~(R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN)); - - /* Set gain for scanning. */ - reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0)); - reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20); - rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1)); - reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20); - rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg); - } - - /* Make link LED blink during scan. */ - rtwn_set_led(sc, RTWN_LED_LINK, !sc->ledlink); - - /* Pause AC Tx queues. */ - rtwn_write_1(sc, R92C_TXPAUSE, - rtwn_read_1(sc, R92C_TXPAUSE) | 0x0f); - rtwn_set_chan(sc, ic->ic_bss->ni_chan, NULL); - timeout_add_msec(&sc->scan_to, 200); - break; - - case IEEE80211_S_AUTH: - /* Set initial gain under link. */ - reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0)); - reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32); - rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1)); - reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32); - rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg); - - rtwn_set_chan(sc, ic->ic_bss->ni_chan, NULL); - break; - case IEEE80211_S_ASSOC: - break; - case IEEE80211_S_RUN: - if (ic->ic_opmode == IEEE80211_M_MONITOR) { - rtwn_set_chan(sc, ic->ic_ibss_chan, NULL); - - /* Enable Rx of data frames. */ - rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff); - - /* Turn link LED on. */ - rtwn_set_led(sc, RTWN_LED_LINK, 1); - break; - } - ni = ic->ic_bss; - - /* Set media status to 'Associated'. */ - reg = rtwn_read_4(sc, R92C_CR); - reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_INFRA); - rtwn_write_4(sc, R92C_CR, reg); - - /* Set BSSID. */ - rtwn_write_4(sc, R92C_BSSID + 0, LE_READ_4(&ni->ni_bssid[0])); - rtwn_write_4(sc, R92C_BSSID + 4, LE_READ_2(&ni->ni_bssid[4])); - - if (ic->ic_curmode == IEEE80211_MODE_11B) - rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 0); - else /* 802.11b/g */ - rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 3); - - /* Enable Rx of data frames. */ - rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff); - - /* Flush all AC queues. */ - rtwn_write_1(sc, R92C_TXPAUSE, 0); - - /* Set beacon interval. */ - rtwn_write_2(sc, R92C_BCN_INTERVAL, ni->ni_intval); - - /* Allow Rx from our BSSID only. */ - rtwn_write_4(sc, R92C_RCR, - rtwn_read_4(sc, R92C_RCR) | - R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN); - - /* Enable TSF synchronization. */ - rtwn_tsf_sync_enable(sc); - - rtwn_write_1(sc, R92C_SIFS_CCK + 1, 10); - rtwn_write_1(sc, R92C_SIFS_OFDM + 1, 10); - rtwn_write_1(sc, R92C_SPEC_SIFS + 1, 10); - rtwn_write_1(sc, R92C_MAC_SPEC_SIFS + 1, 10); - rtwn_write_1(sc, R92C_R2T_SIFS + 1, 10); - rtwn_write_1(sc, R92C_T2T_SIFS + 1, 10); - - /* Intialize rate adaptation. */ - rtwn_ra_init(sc); - /* Turn link LED on. */ - rtwn_set_led(sc, RTWN_LED_LINK, 1); - - sc->avg_pwdb = -1; /* Reset average RSSI. */ - /* Reset temperature calibration state machine. */ - sc->thcal_state = 0; - sc->thcal_lctemp = 0; - /* Start periodic calibration. */ - timeout_add_sec(&sc->calib_to, 2); - break; - } - (void)sc->sc_newstate(ic, nstate, arg); - splx(s); - - return (0); -} - -void -rtwn_updateedca(struct ieee80211com *ic) -{ - struct rtwn_softc *sc = ic->ic_softc; - const uint16_t aci2reg[EDCA_NUM_AC] = { - R92C_EDCA_BE_PARAM, - R92C_EDCA_BK_PARAM, - R92C_EDCA_VI_PARAM, - R92C_EDCA_VO_PARAM - }; - struct ieee80211_edca_ac_params *ac; - int s, aci, aifs, slottime; - - s = splnet(); - slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; - for (aci = 0; aci < EDCA_NUM_AC; aci++) { - ac = &ic->ic_edca_ac[aci]; - /* AIFS[AC] = AIFSN[AC] * aSlotTime + aSIFSTime. */ - aifs = ac->ac_aifsn * slottime + 10; - rtwn_write_4(sc, aci2reg[aci], - SM(R92C_EDCA_PARAM_TXOP, ac->ac_txoplimit) | - SM(R92C_EDCA_PARAM_ECWMIN, ac->ac_ecwmin) | - SM(R92C_EDCA_PARAM_ECWMAX, ac->ac_ecwmax) | - SM(R92C_EDCA_PARAM_AIFS, aifs)); - } - splx(s); -} - -int -rtwn_set_key(struct ieee80211com *ic, struct ieee80211_node *ni, - struct ieee80211_key *k) -{ - struct rtwn_softc *sc = ic->ic_softc; - static const uint8_t etherzeroaddr[6] = { 0 }; - const uint8_t *macaddr; - uint8_t keybuf[16], algo; - int i, entry; - - /* Defer setting of WEP keys until interface is brought up. */ - if ((ic->ic_if.if_flags & (IFF_UP | IFF_RUNNING)) != - (IFF_UP | IFF_RUNNING)) - return (0); - - /* Map net80211 cipher to HW crypto algorithm. */ - switch (k->k_cipher) { - case IEEE80211_CIPHER_WEP40: - algo = R92C_CAM_ALGO_WEP40; - break; - case IEEE80211_CIPHER_WEP104: - algo = R92C_CAM_ALGO_WEP104; - break; - case IEEE80211_CIPHER_TKIP: - algo = R92C_CAM_ALGO_TKIP; - break; - case IEEE80211_CIPHER_CCMP: - algo = R92C_CAM_ALGO_AES; - break; - default: - /* Fallback to software crypto for other ciphers. */ - return (ieee80211_set_key(ic, ni, k)); - } - if (k->k_flags & IEEE80211_KEY_GROUP) { - macaddr = etherzeroaddr; - entry = k->k_id; - } else { - macaddr = ic->ic_bss->ni_macaddr; - entry = 4; - } - /* Write key. */ - memset(keybuf, 0, sizeof(keybuf)); - memcpy(keybuf, k->k_key, MIN(k->k_len, sizeof(keybuf))); - for (i = 0; i < 4; i++) { - rtwn_cam_write(sc, R92C_CAM_KEY(entry, i), - LE_READ_4(&keybuf[i * 4])); - } - /* Write CTL0 last since that will validate the CAM entry. */ - rtwn_cam_write(sc, R92C_CAM_CTL1(entry), - LE_READ_4(&macaddr[2])); - rtwn_cam_write(sc, R92C_CAM_CTL0(entry), - SM(R92C_CAM_ALGO, algo) | - SM(R92C_CAM_KEYID, k->k_id) | - SM(R92C_CAM_MACLO, LE_READ_2(&macaddr[0])) | - R92C_CAM_VALID); - - return (0); -} - -void -rtwn_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni, - struct ieee80211_key *k) -{ - struct rtwn_softc *sc = ic->ic_softc; - int i, entry; - - if (!(ic->ic_if.if_flags & IFF_RUNNING) || - ic->ic_state != IEEE80211_S_RUN) - return; /* Nothing to do. */ - - if (k->k_flags & IEEE80211_KEY_GROUP) - entry = k->k_id; - else - entry = 4; - rtwn_cam_write(sc, R92C_CAM_CTL0(entry), 0); - rtwn_cam_write(sc, R92C_CAM_CTL1(entry), 0); - /* Clear key. */ - for (i = 0; i < 4; i++) - rtwn_cam_write(sc, R92C_CAM_KEY(entry, i), 0); -} - -void -rtwn_update_avgrssi(struct rtwn_softc *sc, int rate, int8_t rssi) -{ - int pwdb; - - /* Convert antenna signal to percentage. */ - if (rssi <= -100 || rssi >= 20) - pwdb = 0; - else if (rssi >= 0) - pwdb = 100; - else - pwdb = 100 + rssi; - if (rate <= 3) { - /* CCK gain is smaller than OFDM/MCS gain. */ - pwdb += 6; - if (pwdb > 100) - pwdb = 100; - if (pwdb <= 14) - pwdb -= 4; - else if (pwdb <= 26) - pwdb -= 8; - else if (pwdb <= 34) - pwdb -= 6; - else if (pwdb <= 42) - pwdb -= 2; - } - if (sc->avg_pwdb == -1) /* Init. */ - sc->avg_pwdb = pwdb; - else if (sc->avg_pwdb < pwdb) - sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20) + 1; - else - sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20); - DPRINTFN(4, ("PWDB=%d EMA=%d\n", pwdb, sc->avg_pwdb)); -} - -int8_t -rtwn_get_rssi(struct rtwn_softc *sc, int rate, void *physt) -{ - static const int8_t cckoff[] = { 16, -12, -26, -46 }; - struct r92c_rx_phystat *phy; - struct r92c_rx_cck *cck; - uint8_t rpt; - int8_t rssi; - - if (rate <= 3) { - cck = (struct r92c_rx_cck *)physt; - if (sc->sc_flags & RTWN_FLAG_CCK_HIPWR) { - rpt = (cck->agc_rpt >> 5) & 0x3; - rssi = (cck->agc_rpt & 0x1f) << 1; - } else { - rpt = (cck->agc_rpt >> 6) & 0x3; - rssi = cck->agc_rpt & 0x3e; - } - rssi = cckoff[rpt] - rssi; - } else { /* OFDM/HT. */ - phy = (struct r92c_rx_phystat *)physt; - rssi = ((letoh32(phy->phydw1) >> 1) & 0x7f) - 110; - } - return (rssi); -} - void -rtwn_rx_frame(struct rtwn_softc *sc, struct r92c_rx_desc_pci *rx_desc, +rtwn_rx_frame(struct rtwn_pci_softc *sc, struct r92c_rx_desc_pci *rx_desc, struct rtwn_rx_data *rx_data, int desc_idx) { - struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211com *ic = &sc->sc_sc.sc_ic; struct ifnet *ifp = &ic->ic_if; struct ieee80211_rxinfo rxi; struct ieee80211_frame *wh; @@ -1702,9 +760,9 @@ rtwn_rx_frame(struct rtwn_softc *sc, struct r92c_rx_desc_pci *rx_desc, /* Get RSSI from PHY status descriptor if present. */ if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) { phy = mtod(rx_data->m, struct r92c_rx_phystat *); - rssi = rtwn_get_rssi(sc, rate, phy); + rssi = rtwn_get_rssi(&sc->sc_sc, rate, phy); /* Update our average RSSI. */ - rtwn_update_avgrssi(sc, rate, rssi); + rtwn_update_avgrssi(&sc->sc_sc, rate, rssi); } DPRINTFN(5, ("Rx frame len=%d rate=%d infosz=%d shift=%d rssi=%d\n", @@ -1804,9 +862,10 @@ rtwn_rx_frame(struct rtwn_softc *sc, struct r92c_rx_desc_pci *rx_desc, } int -rtwn_tx(struct rtwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) +rtwn_tx(void *cookie, struct mbuf *m, struct ieee80211_node *ni) { - struct ieee80211com *ic = &sc->sc_ic; + struct rtwn_pci_softc *sc = cookie; + struct ieee80211com *ic = &sc->sc_sc.sc_ic; struct ieee80211_frame *wh; struct ieee80211_key *k = NULL; struct rtwn_tx_ring *tx_ring; @@ -1989,15 +1048,15 @@ rtwn_tx(struct rtwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) sc->qfullmsk |= (1 << qid); /* Kick TX. */ - rtwn_write_2(sc, R92C_PCIE_CTRL_REG, (1 << qid)); + rtwn_pci_write_2(sc, R92C_PCIE_CTRL_REG, (1 << qid)); return (0); } void -rtwn_tx_done(struct rtwn_softc *sc, int qid) +rtwn_tx_done(struct rtwn_pci_softc *sc, int qid) { - struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211com *ic = &sc->sc_sc.sc_ic; struct ifnet *ifp = &ic->ic_if; struct rtwn_tx_ring *tx_ring = &sc->tx_ring[qid]; struct rtwn_tx_data *tx_data; @@ -2023,7 +1082,7 @@ rtwn_tx_done(struct rtwn_softc *sc, int qid) tx_data->ni = NULL; ifp->if_opackets++; - sc->sc_tx_timer = 0; + sc->sc_sc.sc_tx_timer = 0; tx_ring->queued--; } @@ -2037,1672 +1096,32 @@ rtwn_tx_done(struct rtwn_softc *sc, int qid) } void -rtwn_start(struct ifnet *ifp) -{ - struct rtwn_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_node *ni; - struct mbuf *m; - - if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) - return; - - for (;;) { - if (sc->qfullmsk != 0) { - ifq_set_oactive(&ifp->if_snd); - break; - } - /* Send pending management frames first. */ - m = mq_dequeue(&ic->ic_mgtq); - if (m != NULL) { - ni = m->m_pkthdr.ph_cookie; - goto sendit; - } - if (ic->ic_state != IEEE80211_S_RUN) - break; - - /* Encapsulate and send data frames. */ - IFQ_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; -#if NBPFILTER > 0 - if (ifp->if_bpf != NULL) - bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); -#endif - if ((m = ieee80211_encap(ifp, m, &ni)) == NULL) - continue; -sendit: -#if NBPFILTER > 0 - if (ic->ic_rawbpf != NULL) - bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT); -#endif - if (rtwn_tx(sc, m, ni) != 0) { - ieee80211_release_node(ic, ni); - ifp->if_oerrors++; - continue; - } - - sc->sc_tx_timer = 5; - ifp->if_timer = 1; - } -} - -void -rtwn_watchdog(struct ifnet *ifp) -{ - struct rtwn_softc *sc = ifp->if_softc; - - ifp->if_timer = 0; - - if (sc->sc_tx_timer > 0) { - if (--sc->sc_tx_timer == 0) { - printf("%s: device timeout\n", sc->sc_dev.dv_xname); - task_add(systq, &sc->init_task); - ifp->if_oerrors++; - return; - } - ifp->if_timer = 1; - } - ieee80211_watchdog(ifp); -} - -int -rtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct rtwn_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct ifreq *ifr; - int s, error = 0; - - s = splnet(); - /* - * Prevent processes from entering this function while another - * process is tsleep'ing in it. - */ - while ((sc->sc_flags & RTWN_FLAG_BUSY) && error == 0) - error = tsleep(&sc->sc_flags, PCATCH, "rtwnioc", 0); - if (error != 0) { - splx(s); - return error; - } - sc->sc_flags |= RTWN_FLAG_BUSY; - - switch (cmd) { - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - /* FALLTHROUGH */ - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_flags & IFF_RUNNING)) - rtwn_init(ifp); - } else { - if (ifp->if_flags & IFF_RUNNING) - rtwn_stop(ifp); - } - break; - case SIOCADDMULTI: - case SIOCDELMULTI: - ifr = (struct ifreq *)data; - error = (cmd == SIOCADDMULTI) ? - ether_addmulti(ifr, &ic->ic_ac) : - ether_delmulti(ifr, &ic->ic_ac); - if (error == ENETRESET) - error = 0; - break; - case SIOCS80211CHANNEL: - error = ieee80211_ioctl(ifp, cmd, data); - if (error == ENETRESET && - ic->ic_opmode == IEEE80211_M_MONITOR) { - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == - (IFF_UP | IFF_RUNNING)) - rtwn_set_chan(sc, ic->ic_ibss_chan, NULL); - error = 0; - } - break; - default: - error = ieee80211_ioctl(ifp, cmd, data); - } - - if (error == ENETRESET) { - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == - (IFF_UP | IFF_RUNNING)) { - rtwn_stop(ifp); - rtwn_init(ifp); - } - error = 0; - } - sc->sc_flags &= ~RTWN_FLAG_BUSY; - wakeup(&sc->sc_flags); - splx(s); - - return (error); -} - -int -rtwn_power_on(struct rtwn_softc *sc) -{ - uint32_t reg; - int ntries; - - /* Wait for autoload done bit. */ - for (ntries = 0; ntries < 1000; ntries++) { - if (rtwn_read_1(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_PFM_ALDN) - break; - DELAY(5); - } - if (ntries == 1000) { - printf("%s: timeout waiting for chip autoload\n", - sc->sc_dev.dv_xname); - return (ETIMEDOUT); - } - - /* Unlock ISO/CLK/Power control register. */ - rtwn_write_1(sc, R92C_RSV_CTRL, 0); - - /* TODO: check if we need this for 8188CE */ - if (sc->board_type != R92C_BOARD_TYPE_DONGLE) { - /* bt coex */ - reg = rtwn_read_4(sc, R92C_APS_FSMCO); - reg |= (R92C_APS_FSMCO_SOP_ABG | - R92C_APS_FSMCO_SOP_AMB | - R92C_APS_FSMCO_XOP_BTCK); - rtwn_write_4(sc, R92C_APS_FSMCO, reg); - } - - /* Move SPS into PWM mode. */ - rtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b); - - /* Set low byte to 0x0f, leave others unchanged. */ - rtwn_write_4(sc, R92C_AFE_XTAL_CTRL, - (rtwn_read_4(sc, R92C_AFE_XTAL_CTRL) & 0xffffff00) | 0x0f); - - /* TODO: check if we need this for 8188CE */ - if (sc->board_type != R92C_BOARD_TYPE_DONGLE) { - /* bt coex */ - reg = rtwn_read_4(sc, R92C_AFE_XTAL_CTRL); - reg &= (~0x00024800); /* XXX magic from linux */ - rtwn_write_4(sc, R92C_AFE_XTAL_CTRL, reg); - } - - rtwn_write_2(sc, R92C_SYS_ISO_CTRL, - (rtwn_read_2(sc, R92C_SYS_ISO_CTRL) & 0xff) | - R92C_SYS_ISO_CTRL_PWC_EV12V | R92C_SYS_ISO_CTRL_DIOR); - DELAY(200); - - /* TODO: linux does additional btcoex stuff here */ - - /* Auto enable WLAN. */ - rtwn_write_2(sc, R92C_APS_FSMCO, - rtwn_read_2(sc, R92C_APS_FSMCO) | R92C_APS_FSMCO_APFM_ONMAC); - for (ntries = 0; ntries < 1000; ntries++) { - if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & - R92C_APS_FSMCO_APFM_ONMAC)) - break; - DELAY(5); - } - if (ntries == 1000) { - printf("%s: timeout waiting for MAC auto ON\n", - sc->sc_dev.dv_xname); - return (ETIMEDOUT); - } - - /* Enable radio, GPIO and LED functions. */ - rtwn_write_2(sc, R92C_APS_FSMCO, - R92C_APS_FSMCO_AFSM_PCIE | - R92C_APS_FSMCO_PDN_EN | - R92C_APS_FSMCO_PFM_ALDN); - /* Release RF digital isolation. */ - rtwn_write_2(sc, R92C_SYS_ISO_CTRL, - rtwn_read_2(sc, R92C_SYS_ISO_CTRL) & ~R92C_SYS_ISO_CTRL_DIOR); - - if (sc->chip & RTWN_CHIP_92C) - rtwn_write_1(sc, R92C_PCIE_CTRL_REG + 3, 0x77); - else - rtwn_write_1(sc, R92C_PCIE_CTRL_REG + 3, 0x22); - - rtwn_write_4(sc, R92C_INT_MIG, 0); - - if (sc->board_type != R92C_BOARD_TYPE_DONGLE) { - /* bt coex */ - reg = rtwn_read_4(sc, R92C_AFE_XTAL_CTRL + 2); - reg &= 0xfd; /* XXX magic from linux */ - rtwn_write_4(sc, R92C_AFE_XTAL_CTRL + 2, reg); - } - - rtwn_write_1(sc, R92C_GPIO_MUXCFG, - rtwn_read_1(sc, R92C_GPIO_MUXCFG) & ~R92C_GPIO_MUXCFG_RFKILL); - - reg = rtwn_read_1(sc, R92C_GPIO_IO_SEL); - if (!(reg & R92C_GPIO_IO_SEL_RFKILL)) { - printf("%s: radio is disabled by hardware switch\n", - sc->sc_dev.dv_xname); - return (EPERM); /* :-) */ - } - - /* Initialize MAC. */ - reg = rtwn_read_1(sc, R92C_APSD_CTRL); - rtwn_write_1(sc, R92C_APSD_CTRL, - rtwn_read_1(sc, R92C_APSD_CTRL) & ~R92C_APSD_CTRL_OFF); - for (ntries = 0; ntries < 200; ntries++) { - if (!(rtwn_read_1(sc, R92C_APSD_CTRL) & - R92C_APSD_CTRL_OFF_STATUS)) - break; - DELAY(500); - } - if (ntries == 200) { - printf("%s: timeout waiting for MAC initialization\n", - sc->sc_dev.dv_xname); - return (ETIMEDOUT); - } - - /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ - reg = rtwn_read_2(sc, R92C_CR); - reg |= R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | - R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | - R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN | - R92C_CR_ENSEC; - rtwn_write_2(sc, R92C_CR, reg); - - rtwn_write_1(sc, 0xfe10, 0x19); - - return (0); -} - -int -rtwn_llt_init(struct rtwn_softc *sc) -{ - int i, error; - - /* Reserve pages [0; R92C_TX_PAGE_COUNT]. */ - for (i = 0; i < R92C_TX_PAGE_COUNT; i++) { - if ((error = rtwn_llt_write(sc, i, i + 1)) != 0) - return (error); - } - /* NB: 0xff indicates end-of-list. */ - if ((error = rtwn_llt_write(sc, i, 0xff)) != 0) - return (error); - /* - * Use pages [R92C_TX_PAGE_COUNT + 1; R92C_TXPKTBUF_COUNT - 1] - * as ring buffer. - */ - for (++i; i < R92C_TXPKTBUF_COUNT - 1; i++) { - if ((error = rtwn_llt_write(sc, i, i + 1)) != 0) - return (error); - } - /* Make the last page point to the beginning of the ring buffer. */ - error = rtwn_llt_write(sc, i, R92C_TX_PAGE_COUNT + 1); - return (error); -} - -void -rtwn_fw_reset(struct rtwn_softc *sc) -{ - uint16_t reg; - int ntries; - - /* Tell 8051 to reset itself. */ - rtwn_write_1(sc, R92C_HMETFR + 3, 0x20); - - /* Wait until 8051 resets by itself. */ - for (ntries = 0; ntries < 100; ntries++) { - reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN); - if (!(reg & R92C_SYS_FUNC_EN_CPUEN)) - goto sleep; - DELAY(50); - } - /* Force 8051 reset. */ - rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN); -sleep: - /* - * We must sleep for one second to let the firmware settle. - * Accessing registers too early will hang the whole system. - */ - tsleep(®, 0, "rtwnrst", hz); -} - -int -rtwn_fw_loadpage(struct rtwn_softc *sc, int page, uint8_t *buf, int len) -{ - uint32_t reg; - int off, mlen, error = 0, i; - - reg = rtwn_read_4(sc, R92C_MCUFWDL); - reg = RW(reg, R92C_MCUFWDL_PAGE, page); - rtwn_write_4(sc, R92C_MCUFWDL, reg); - - DELAY(5); - - off = R92C_FW_START_ADDR; - while (len > 0) { - if (len > 196) - mlen = 196; - else if (len > 4) - mlen = 4; - else - mlen = 1; - for (i = 0; i < mlen; i++) - rtwn_write_1(sc, off++, buf[i]); - buf += mlen; - len -= mlen; - } - - return (error); -} - -int -rtwn_load_firmware(struct rtwn_softc *sc) -{ - const struct r92c_fw_hdr *hdr; - const char *name; - u_char *fw, *ptr; - size_t len; - uint32_t reg; - int mlen, ntries, page, error; - - /* Read firmware image from the filesystem. */ - if ((sc->chip & (RTWN_CHIP_UMC_A_CUT | RTWN_CHIP_92C)) == - RTWN_CHIP_UMC_A_CUT) - name = "rtwn-rtl8192cfwU"; - else - name = "rtwn-rtl8192cfwU_B"; - if ((error = loadfirmware(name, &fw, &len)) != 0) { - printf("%s: could not read firmware %s (error %d)\n", - sc->sc_dev.dv_xname, name, error); - return (error); - } - if (len < sizeof(*hdr)) { - printf("%s: firmware too short\n", sc->sc_dev.dv_xname); - error = EINVAL; - goto fail; - } - ptr = fw; - hdr = (const struct r92c_fw_hdr *)ptr; - /* Check if there is a valid FW header and skip it. */ - if ((letoh16(hdr->signature) >> 4) == 0x88c || - (letoh16(hdr->signature) >> 4) == 0x92c) { - DPRINTF(("FW V%d.%d %02d-%02d %02d:%02d\n", - letoh16(hdr->version), letoh16(hdr->subversion), - hdr->month, hdr->date, hdr->hour, hdr->minute)); - ptr += sizeof(*hdr); - len -= sizeof(*hdr); - } - - if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) - rtwn_fw_reset(sc); - - /* Enable FW download. */ - rtwn_write_2(sc, R92C_SYS_FUNC_EN, - rtwn_read_2(sc, R92C_SYS_FUNC_EN) | - R92C_SYS_FUNC_EN_CPUEN); - rtwn_write_1(sc, R92C_MCUFWDL, - rtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_EN); - rtwn_write_1(sc, R92C_MCUFWDL + 2, - rtwn_read_1(sc, R92C_MCUFWDL + 2) & ~0x08); - - /* Reset the FWDL checksum. */ - rtwn_write_1(sc, R92C_MCUFWDL, - rtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_CHKSUM_RPT); - - for (page = 0; len > 0; page++) { - mlen = MIN(len, R92C_FW_PAGE_SIZE); - error = rtwn_fw_loadpage(sc, page, ptr, mlen); - if (error != 0) { - printf("%s: could not load firmware page %d\n", - sc->sc_dev.dv_xname, page); - goto fail; - } - ptr += mlen; - len -= mlen; - } - - /* Disable FW download. */ - rtwn_write_1(sc, R92C_MCUFWDL, - rtwn_read_1(sc, R92C_MCUFWDL) & ~R92C_MCUFWDL_EN); - rtwn_write_1(sc, R92C_MCUFWDL + 1, 0); - - /* Wait for checksum report. */ - for (ntries = 0; ntries < 1000; ntries++) { - if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_CHKSUM_RPT) - break; - DELAY(5); - } - if (ntries == 1000) { - printf("%s: timeout waiting for checksum report\n", - sc->sc_dev.dv_xname); - error = ETIMEDOUT; - goto fail; - } - - reg = rtwn_read_4(sc, R92C_MCUFWDL); - reg = (reg & ~R92C_MCUFWDL_WINTINI_RDY) | R92C_MCUFWDL_RDY; - rtwn_write_4(sc, R92C_MCUFWDL, reg); - /* Wait for firmware readiness. */ - for (ntries = 0; ntries < 1000; ntries++) { - if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_WINTINI_RDY) - break; - DELAY(5); - } - if (ntries == 1000) { - printf("%s: timeout waiting for firmware readiness\n", - sc->sc_dev.dv_xname); - error = ETIMEDOUT; - goto fail; - } - fail: - free(fw, M_DEVBUF, len); - return (error); -} - -int -rtwn_dma_init(struct rtwn_softc *sc) -{ - uint32_t reg; - int error; - - /* Initialize LLT table. */ - error = rtwn_llt_init(sc); - if (error != 0) - return error; - - /* Set number of pages for normal priority queue. */ - rtwn_write_2(sc, R92C_RQPN_NPQ, 0); - rtwn_write_4(sc, R92C_RQPN, - /* Set number of pages for public queue. */ - SM(R92C_RQPN_PUBQ, R92C_PUBQ_NPAGES) | - /* Set number of pages for high priority queue. */ - SM(R92C_RQPN_HPQ, R92C_HPQ_NPAGES) | - /* Set number of pages for low priority queue. */ - SM(R92C_RQPN_LPQ, R92C_LPQ_NPAGES) | - /* Load values. */ - R92C_RQPN_LD); - - rtwn_write_1(sc, R92C_TXPKTBUF_BCNQ_BDNY, R92C_TX_PAGE_BOUNDARY); - rtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, R92C_TX_PAGE_BOUNDARY); - rtwn_write_1(sc, R92C_TXPKTBUF_WMAC_LBK_BF_HD, R92C_TX_PAGE_BOUNDARY); - rtwn_write_1(sc, R92C_TRXFF_BNDY, R92C_TX_PAGE_BOUNDARY); - rtwn_write_1(sc, R92C_TDECTRL + 1, R92C_TX_PAGE_BOUNDARY); - - reg = rtwn_read_2(sc, R92C_TRXDMA_CTRL); - reg &= ~R92C_TRXDMA_CTRL_QMAP_M; - reg |= 0xF771; - rtwn_write_2(sc, R92C_TRXDMA_CTRL, reg); - - rtwn_write_4(sc, R92C_TCR, R92C_TCR_CFENDFORM | (1 << 12) | (1 << 13)); - - /* Configure Tx DMA. */ - rtwn_write_4(sc, R92C_BKQ_DESA, - sc->tx_ring[RTWN_BK_QUEUE].map->dm_segs[0].ds_addr); - rtwn_write_4(sc, R92C_BEQ_DESA, - sc->tx_ring[RTWN_BE_QUEUE].map->dm_segs[0].ds_addr); - rtwn_write_4(sc, R92C_VIQ_DESA, - sc->tx_ring[RTWN_VI_QUEUE].map->dm_segs[0].ds_addr); - rtwn_write_4(sc, R92C_VOQ_DESA, - sc->tx_ring[RTWN_VO_QUEUE].map->dm_segs[0].ds_addr); - rtwn_write_4(sc, R92C_BCNQ_DESA, - sc->tx_ring[RTWN_BEACON_QUEUE].map->dm_segs[0].ds_addr); - rtwn_write_4(sc, R92C_MGQ_DESA, - sc->tx_ring[RTWN_MGNT_QUEUE].map->dm_segs[0].ds_addr); - rtwn_write_4(sc, R92C_HQ_DESA, - sc->tx_ring[RTWN_HIGH_QUEUE].map->dm_segs[0].ds_addr); - - /* Configure Rx DMA. */ - rtwn_write_4(sc, R92C_RX_DESA, sc->rx_ring.map->dm_segs[0].ds_addr); - - /* Set Tx/Rx transfer page boundary. */ - rtwn_write_2(sc, R92C_TRXFF_BNDY + 2, 0x27ff); - - /* Set Tx/Rx transfer page size. */ - rtwn_write_1(sc, R92C_PBP, - SM(R92C_PBP_PSRX, R92C_PBP_128) | - SM(R92C_PBP_PSTX, R92C_PBP_128)); - return (0); -} - -void -rtwn_mac_init(struct rtwn_softc *sc) -{ - int i; - - /* Write MAC initialization values. */ - for (i = 0; i < nitems(rtl8192ce_mac); i++) - rtwn_write_1(sc, rtl8192ce_mac[i].reg, rtl8192ce_mac[i].val); -} - -void -rtwn_bb_init(struct rtwn_softc *sc) -{ - const struct r92c_bb_prog *prog; - uint32_t reg; - int i; - - /* Enable BB and RF. */ - rtwn_write_2(sc, R92C_SYS_FUNC_EN, - rtwn_read_2(sc, R92C_SYS_FUNC_EN) | - R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | - R92C_SYS_FUNC_EN_DIO_RF); - - rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0xdb83); - - rtwn_write_1(sc, R92C_RF_CTRL, - R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); - - rtwn_write_1(sc, R92C_SYS_FUNC_EN, - R92C_SYS_FUNC_EN_DIO_PCIE | R92C_SYS_FUNC_EN_PCIEA | - R92C_SYS_FUNC_EN_PPLL | R92C_SYS_FUNC_EN_BB_GLB_RST | - R92C_SYS_FUNC_EN_BBRSTB); - - rtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80); - - rtwn_write_4(sc, R92C_LEDCFG0, - rtwn_read_4(sc, R92C_LEDCFG0) | 0x00800000); - - /* Select BB programming. */ - prog = (sc->chip & RTWN_CHIP_92C) ? - &rtl8192ce_bb_prog_2t : &rtl8192ce_bb_prog_1t; - - /* Write BB initialization values. */ - for (i = 0; i < prog->count; i++) { - rtwn_bb_write(sc, prog->regs[i], prog->vals[i]); - DELAY(1); - } - - if (sc->chip & RTWN_CHIP_92C_1T2R) { - /* 8192C 1T only configuration. */ - reg = rtwn_bb_read(sc, R92C_FPGA0_TXINFO); - reg = (reg & ~0x00000003) | 0x2; - rtwn_bb_write(sc, R92C_FPGA0_TXINFO, reg); - - reg = rtwn_bb_read(sc, R92C_FPGA1_TXINFO); - reg = (reg & ~0x00300033) | 0x00200022; - rtwn_bb_write(sc, R92C_FPGA1_TXINFO, reg); - - reg = rtwn_bb_read(sc, R92C_CCK0_AFESETTING); - reg = (reg & ~0xff000000) | 0x45 << 24; - rtwn_bb_write(sc, R92C_CCK0_AFESETTING, reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA); - reg = (reg & ~0x000000ff) | 0x23; - rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_AGCPARAM1); - reg = (reg & ~0x00000030) | 1 << 4; - rtwn_bb_write(sc, R92C_OFDM0_AGCPARAM1, reg); - - reg = rtwn_bb_read(sc, 0xe74); - reg = (reg & ~0x0c000000) | 2 << 26; - rtwn_bb_write(sc, 0xe74, reg); - reg = rtwn_bb_read(sc, 0xe78); - reg = (reg & ~0x0c000000) | 2 << 26; - rtwn_bb_write(sc, 0xe78, reg); - reg = rtwn_bb_read(sc, 0xe7c); - reg = (reg & ~0x0c000000) | 2 << 26; - rtwn_bb_write(sc, 0xe7c, reg); - reg = rtwn_bb_read(sc, 0xe80); - reg = (reg & ~0x0c000000) | 2 << 26; - rtwn_bb_write(sc, 0xe80, reg); - reg = rtwn_bb_read(sc, 0xe88); - reg = (reg & ~0x0c000000) | 2 << 26; - rtwn_bb_write(sc, 0xe88, reg); - } - - /* Write AGC values. */ - for (i = 0; i < prog->agccount; i++) { - rtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE, - prog->agcvals[i]); - DELAY(1); - } - - if (rtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & - R92C_HSSI_PARAM2_CCK_HIPWR) - sc->sc_flags |= RTWN_FLAG_CCK_HIPWR; -} - -void -rtwn_rf_init(struct rtwn_softc *sc) -{ - const struct r92c_rf_prog *prog; - uint32_t reg, type; - int i, j, idx, off; - - /* Select RF programming based on board type. */ - if (!(sc->chip & RTWN_CHIP_92C)) { - if (sc->board_type == R92C_BOARD_TYPE_MINICARD) - prog = rtl8188ce_rf_prog; - else if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) - prog = rtl8188ru_rf_prog; - else - prog = rtl8188cu_rf_prog; - } else - prog = rtl8192ce_rf_prog; - - for (i = 0; i < sc->nrxchains; i++) { - /* Save RF_ENV control type. */ - idx = i / 2; - off = (i % 2) * 16; - reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx)); - type = (reg >> off) & 0x10; - - /* Set RF_ENV enable. */ - reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i)); - reg |= 0x100000; - rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg); - DELAY(1); - /* Set RF_ENV output high. */ - reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i)); - reg |= 0x10; - rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg); - DELAY(1); - /* Set address and data lengths of RF registers. */ - reg = rtwn_bb_read(sc, R92C_HSSI_PARAM2(i)); - reg &= ~R92C_HSSI_PARAM2_ADDR_LENGTH; - rtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg); - DELAY(1); - reg = rtwn_bb_read(sc, R92C_HSSI_PARAM2(i)); - reg &= ~R92C_HSSI_PARAM2_DATA_LENGTH; - rtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg); - DELAY(1); - - /* Write RF initialization values for this chain. */ - for (j = 0; j < prog[i].count; j++) { - if (prog[i].regs[j] >= 0xf9 && - prog[i].regs[j] <= 0xfe) { - /* - * These are fake RF registers offsets that - * indicate a delay is required. - */ - DELAY(50); - continue; - } - rtwn_rf_write(sc, i, prog[i].regs[j], - prog[i].vals[j]); - DELAY(1); - } - - /* Restore RF_ENV control type. */ - reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx)); - reg &= ~(0x10 << off) | (type << off); - rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(idx), reg); - - /* Cache RF register CHNLBW. */ - sc->rf_chnlbw[i] = rtwn_rf_read(sc, i, R92C_RF_CHNLBW); - } - - if ((sc->chip & (RTWN_CHIP_UMC_A_CUT | RTWN_CHIP_92C)) == - RTWN_CHIP_UMC_A_CUT) { - rtwn_rf_write(sc, 0, R92C_RF_RX_G1, 0x30255); - rtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x50a00); - } -} - -void -rtwn_cam_init(struct rtwn_softc *sc) -{ - /* Invalidate all CAM entries. */ - rtwn_write_4(sc, R92C_CAMCMD, - R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR); -} - -void -rtwn_pa_bias_init(struct rtwn_softc *sc) -{ - uint8_t reg; - int i; - - for (i = 0; i < sc->nrxchains; i++) { - if (sc->pa_setting & (1 << i)) - continue; - rtwn_rf_write(sc, i, R92C_RF_IPA, 0x0f406); - rtwn_rf_write(sc, i, R92C_RF_IPA, 0x4f406); - rtwn_rf_write(sc, i, R92C_RF_IPA, 0x8f406); - rtwn_rf_write(sc, i, R92C_RF_IPA, 0xcf406); - } - if (!(sc->pa_setting & 0x10)) { - reg = rtwn_read_1(sc, 0x16); - reg = (reg & ~0xf0) | 0x90; - rtwn_write_1(sc, 0x16, reg); - } -} - -void -rtwn_rxfilter_init(struct rtwn_softc *sc) -{ - /* Initialize Rx filter. */ - /* TODO: use better filter for monitor mode. */ - rtwn_write_4(sc, R92C_RCR, - R92C_RCR_AAP | R92C_RCR_APM | R92C_RCR_AM | R92C_RCR_AB | - R92C_RCR_APP_ICV | R92C_RCR_AMF | R92C_RCR_HTC_LOC_CTRL | - R92C_RCR_APP_MIC | R92C_RCR_APP_PHYSTS); - /* Accept all multicast frames. */ - rtwn_write_4(sc, R92C_MAR + 0, 0xffffffff); - rtwn_write_4(sc, R92C_MAR + 4, 0xffffffff); - /* Accept all management frames. */ - rtwn_write_2(sc, R92C_RXFLTMAP0, 0xffff); - /* Reject all control frames. */ - rtwn_write_2(sc, R92C_RXFLTMAP1, 0x0000); - /* Accept all data frames. */ - rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff); -} - -void -rtwn_edca_init(struct rtwn_softc *sc) -{ - rtwn_write_2(sc, R92C_SPEC_SIFS, 0x1010); - rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x1010); - rtwn_write_2(sc, R92C_SIFS_CCK, 0x1010); - rtwn_write_2(sc, R92C_SIFS_OFDM, 0x0e0e); - rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b); - rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f); - rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4322); - rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3222); -} - -void -rtwn_write_txpower(struct rtwn_softc *sc, int chain, - uint16_t power[RTWN_RIDX_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]); - 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]); - 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]); - 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]); - 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])); - 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])); - /* 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])); - 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])); - 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])); - 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])); -} - -void -rtwn_get_txpower(struct rtwn_softc *sc, int chain, - struct ieee80211_channel *c, struct ieee80211_channel *extc, - uint16_t power[RTWN_RIDX_COUNT]) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct r92c_rom *rom = &sc->rom; - uint16_t cckpow, ofdmpow, htpow, diff, max; - const struct r92c_txpwr *base; - int ridx, chan, group; - - /* Determine channel group. */ - chan = ieee80211_chan2ieee(ic, c); /* XXX center freq! */ - if (chan <= 3) - group = 0; - else if (chan <= 9) - group = 1; - else - group = 2; - - /* Get original Tx power based on board type and RF chain. */ - if (!(sc->chip & RTWN_CHIP_92C)) { - if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) - base = &rtl8188ru_txagc[chain]; - else - base = &rtl8192cu_txagc[chain]; - } else - base = &rtl8192cu_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]; - /* Apply vendor limits. */ - if (extc != NULL) - max = rom->ht40_max_pwr[group]; - else - max = rom->ht20_max_pwr[group]; - max = (max >> (chain * 4)) & 0xf; - if (power[ridx] > max) - power[ridx] = max; - } 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]; - } - - /* Compute per-CCK rate Tx power. */ - cckpow = rom->cck_tx_pwr[chain][group]; - for (ridx = 0; ridx <= 3; ridx++) { - power[ridx] += cckpow; - if (power[ridx] > R92C_MAX_TX_PWR) - power[ridx] = R92C_MAX_TX_PWR; - } - - htpow = rom->ht40_1s_tx_pwr[chain][group]; - if (sc->ntxchains > 1) { - /* Apply reduction for 2 spatial streams. */ - diff = rom->ht40_2s_tx_pwr_diff[group]; - diff = (diff >> (chain * 4)) & 0xf; - htpow = (htpow > diff) ? htpow - diff : 0; - } - - /* Compute per-OFDM rate Tx power. */ - diff = rom->ofdm_tx_pwr_diff[group]; - diff = (diff >> (chain * 4)) & 0xf; - ofdmpow = htpow + diff; /* HT->OFDM correction. */ - for (ridx = 4; ridx <= 11; ridx++) { - power[ridx] += ofdmpow; - if (power[ridx] > R92C_MAX_TX_PWR) - power[ridx] = R92C_MAX_TX_PWR; - } - - /* Compute per-MCS Tx power. */ - if (extc == NULL) { - diff = rom->ht20_tx_pwr_diff[group]; - diff = (diff >> (chain * 4)) & 0xf; - htpow += diff; /* HT40->HT20 correction. */ - } - for (ridx = 12; ridx <= 27; ridx++) { - power[ridx] += htpow; - if (power[ridx] > R92C_MAX_TX_PWR) - power[ridx] = R92C_MAX_TX_PWR; - } -#ifdef RTWN_DEBUG - 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++) - printf("Rate %d = %u\n", ridx, power[ridx]); - } -#endif -} - -void -rtwn_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c, - struct ieee80211_channel *extc) +rtwn_pci_stop(void *cookie) { - uint16_t power[RTWN_RIDX_COUNT]; + struct rtwn_pci_softc *sc = cookie; int i; - for (i = 0; i < sc->ntxchains; i++) { - /* Compute per-rate Tx power values. */ - rtwn_get_txpower(sc, i, c, extc, power); - /* Write per-rate Tx power values to hardware. */ - rtwn_write_txpower(sc, i, power); - } -} - -void -rtwn_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c, - struct ieee80211_channel *extc) -{ - struct ieee80211com *ic = &sc->sc_ic; - u_int chan; - int i; - - chan = ieee80211_chan2ieee(ic, c); /* XXX center freq! */ - - /* Set Tx power for this new channel. */ - rtwn_set_txpower(sc, c, extc); - - for (i = 0; i < sc->nrxchains; i++) { - rtwn_rf_write(sc, i, R92C_RF_CHNLBW, - RW(sc->rf_chnlbw[i], R92C_RF_CHNLBW_CHNL, chan)); - } - if (extc != NULL) { - uint32_t reg; - - /* Is secondary channel below or above primary? */ - int prichlo = c->ic_freq < extc->ic_freq; - - rtwn_write_1(sc, R92C_BWOPMODE, - rtwn_read_1(sc, R92C_BWOPMODE) & ~R92C_BWOPMODE_20MHZ); - - reg = rtwn_read_1(sc, R92C_RRSR + 2); - reg = (reg & ~0x6f) | (prichlo ? 1 : 2) << 5; - rtwn_write_1(sc, R92C_RRSR + 2, reg); - - rtwn_bb_write(sc, R92C_FPGA0_RFMOD, - rtwn_bb_read(sc, R92C_FPGA0_RFMOD) | R92C_RFMOD_40MHZ); - rtwn_bb_write(sc, R92C_FPGA1_RFMOD, - rtwn_bb_read(sc, R92C_FPGA1_RFMOD) | R92C_RFMOD_40MHZ); - - /* Set CCK side band. */ - reg = rtwn_bb_read(sc, R92C_CCK0_SYSTEM); - reg = (reg & ~0x00000010) | (prichlo ? 0 : 1) << 4; - rtwn_bb_write(sc, R92C_CCK0_SYSTEM, reg); - - reg = rtwn_bb_read(sc, R92C_OFDM1_LSTF); - reg = (reg & ~0x00000c00) | (prichlo ? 1 : 2) << 10; - rtwn_bb_write(sc, R92C_OFDM1_LSTF, reg); - - rtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2, - rtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) & - ~R92C_FPGA0_ANAPARAM2_CBW20); - - reg = rtwn_bb_read(sc, 0x818); - reg = (reg & ~0x0c000000) | (prichlo ? 2 : 1) << 26; - rtwn_bb_write(sc, 0x818, reg); - - /* Select 40MHz bandwidth. */ - rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, - (sc->rf_chnlbw[0] & ~0xfff) | chan); - } else { - rtwn_write_1(sc, R92C_BWOPMODE, - rtwn_read_1(sc, R92C_BWOPMODE) | R92C_BWOPMODE_20MHZ); - - rtwn_bb_write(sc, R92C_FPGA0_RFMOD, - rtwn_bb_read(sc, R92C_FPGA0_RFMOD) & ~R92C_RFMOD_40MHZ); - rtwn_bb_write(sc, R92C_FPGA1_RFMOD, - rtwn_bb_read(sc, R92C_FPGA1_RFMOD) & ~R92C_RFMOD_40MHZ); - - rtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2, - rtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) | - R92C_FPGA0_ANAPARAM2_CBW20); - - /* Select 20MHz bandwidth. */ - rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, - (sc->rf_chnlbw[0] & ~0xfff) | R92C_RF_CHNLBW_BW20 | chan); - } -} - -int -rtwn_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2], - uint16_t rx[2]) -{ - uint32_t status; - int offset = chain * 0x20; - - if (chain == 0) { /* IQ calibration for chain 0. */ - /* IQ calibration settings for chain 0. */ - rtwn_bb_write(sc, 0xe30, 0x10008c1f); - rtwn_bb_write(sc, 0xe34, 0x10008c1f); - rtwn_bb_write(sc, 0xe38, 0x82140102); - - if (sc->ntxchains > 1) { - rtwn_bb_write(sc, 0xe3c, 0x28160202); /* 2T */ - /* IQ calibration settings for chain 1. */ - rtwn_bb_write(sc, 0xe50, 0x10008c22); - rtwn_bb_write(sc, 0xe54, 0x10008c22); - rtwn_bb_write(sc, 0xe58, 0x82140102); - rtwn_bb_write(sc, 0xe5c, 0x28160202); - } else - rtwn_bb_write(sc, 0xe3c, 0x28160502); /* 1T */ - - /* LO calibration settings. */ - rtwn_bb_write(sc, 0xe4c, 0x001028d1); - /* We're doing LO and IQ calibration in one shot. */ - rtwn_bb_write(sc, 0xe48, 0xf9000000); - rtwn_bb_write(sc, 0xe48, 0xf8000000); - - } else { /* IQ calibration for chain 1. */ - /* We're doing LO and IQ calibration in one shot. */ - rtwn_bb_write(sc, 0xe60, 0x00000002); - rtwn_bb_write(sc, 0xe60, 0x00000000); - } - - /* Give LO and IQ calibrations the time to complete. */ - DELAY(1000); - - /* Read IQ calibration status. */ - status = rtwn_bb_read(sc, 0xeac); - - if (status & (1 << (28 + chain * 3))) - return (0); /* Tx failed. */ - /* Read Tx IQ calibration results. */ - tx[0] = (rtwn_bb_read(sc, 0xe94 + offset) >> 16) & 0x3ff; - tx[1] = (rtwn_bb_read(sc, 0xe9c + offset) >> 16) & 0x3ff; - if (tx[0] == 0x142 || tx[1] == 0x042) - return (0); /* Tx failed. */ - - if (status & (1 << (27 + chain * 3))) - return (1); /* Rx failed. */ - /* Read Rx IQ calibration results. */ - rx[0] = (rtwn_bb_read(sc, 0xea4 + offset) >> 16) & 0x3ff; - rx[1] = (rtwn_bb_read(sc, 0xeac + offset) >> 16) & 0x3ff; - if (rx[0] == 0x132 || rx[1] == 0x036) - return (1); /* Rx failed. */ - - return (3); /* Both Tx and Rx succeeded. */ -} - -void -rtwn_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2], - uint16_t rx[2][2]) -{ - /* Registers to save and restore during IQ calibration. */ - struct iq_cal_regs { - uint32_t adda[16]; - uint8_t txpause; - uint8_t bcn_ctrl; - uint8_t ustime_tsf; - uint32_t gpio_muxcfg; - uint32_t ofdm0_trxpathena; - uint32_t ofdm0_trmuxpar; - uint32_t fpga0_rfifacesw1; - } iq_cal_regs; - static const uint16_t reg_adda[16] = { - 0x85c, 0xe6c, 0xe70, 0xe74, - 0xe78, 0xe7c, 0xe80, 0xe84, - 0xe88, 0xe8c, 0xed0, 0xed4, - 0xed8, 0xedc, 0xee0, 0xeec - }; - int i, chain; - uint32_t hssi_param1; - - if (n == 0) { - for (i = 0; i < nitems(reg_adda); i++) - iq_cal_regs.adda[i] = rtwn_bb_read(sc, reg_adda[i]); - - iq_cal_regs.txpause = rtwn_read_1(sc, R92C_TXPAUSE); - iq_cal_regs.bcn_ctrl = rtwn_read_1(sc, R92C_BCN_CTRL); - iq_cal_regs.ustime_tsf = rtwn_read_1(sc, R92C_USTIME_TSF); - iq_cal_regs.gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG); - } - - if (sc->ntxchains == 1) { - rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0); - for (i = 1; i < nitems(reg_adda); i++) - rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0); - } else { - for (i = 0; i < nitems(reg_adda); i++) - rtwn_bb_write(sc, reg_adda[i], 0x04db25a4); - } - - hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0)); - if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) { - rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), - hssi_param1 | R92C_HSSI_PARAM1_PI); - rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), - hssi_param1 | R92C_HSSI_PARAM1_PI); - } - - if (n == 0) { - iq_cal_regs.ofdm0_trxpathena = - rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA); - iq_cal_regs.ofdm0_trmuxpar = - rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR); - iq_cal_regs.fpga0_rfifacesw1 = - rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1)); - } - - rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600); - rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4); - rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000); - if (sc->ntxchains > 1) { - rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000); - rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00010000); - } - - rtwn_write_1(sc, R92C_TXPAUSE, 0x3f); - rtwn_write_1(sc, R92C_BCN_CTRL, iq_cal_regs.bcn_ctrl & ~(0x08)); - rtwn_write_1(sc, R92C_USTIME_TSF, iq_cal_regs.ustime_tsf & ~(0x08)); - rtwn_write_1(sc, R92C_GPIO_MUXCFG, - iq_cal_regs.gpio_muxcfg & ~(0x20)); - - rtwn_bb_write(sc, 0x0b68, 0x00080000); - if (sc->ntxchains > 1) - rtwn_bb_write(sc, 0x0b6c, 0x00080000); - - rtwn_bb_write(sc, 0x0e28, 0x80800000); - rtwn_bb_write(sc, 0x0e40, 0x01007c00); - rtwn_bb_write(sc, 0x0e44, 0x01004800); - - rtwn_bb_write(sc, 0x0b68, 0x00080000); - - for (chain = 0; chain < sc->ntxchains; chain++) { - if (chain > 0) { - /* Put chain 0 on standby. */ - rtwn_bb_write(sc, 0x0e28, 0x00); - rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000); - rtwn_bb_write(sc, 0x0e28, 0x80800000); - - /* Enable chain 1. */ - for (i = 0; i < nitems(reg_adda); i++) - rtwn_bb_write(sc, reg_adda[i], 0x0b1b25a4); - } - - /* Run IQ calibration twice. */ - for (i = 0; i < 2; i++) { - int ret; - - ret = rtwn_iq_calib_chain(sc, chain, - tx[chain], rx[chain]); - if (ret == 0) { - DPRINTF(("%s: chain %d: Tx failed.\n", - __func__, chain)); - tx[chain][0] = 0xff; - tx[chain][1] = 0xff; - rx[chain][0] = 0xff; - rx[chain][1] = 0xff; - } else if (ret == 1) { - DPRINTF(("%s: chain %d: Rx failed.\n", - __func__, chain)); - rx[chain][0] = 0xff; - rx[chain][1] = 0xff; - } else if (ret == 3) { - DPRINTF(("%s: chain %d: Both Tx and Rx " - "succeeded.\n", __func__, chain)); - } - } - - DPRINTF(("%s: results for run %d chain %d: tx[0]=0x%x, " - "tx[1]=0x%x rx[0]=0x%x rx[1]=0x%x\n", __func__, n, chain, - tx[chain][0], tx[chain][1], rx[chain][0], rx[chain][1])); - } - - rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, - iq_cal_regs.ofdm0_trxpathena); - rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), - iq_cal_regs.fpga0_rfifacesw1); - rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, iq_cal_regs.ofdm0_trmuxpar); - - rtwn_bb_write(sc, 0x0e28, 0x00); - rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3); - if (sc->ntxchains > 1) - rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3); - - if (n != 0) { - if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) { - rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1); - rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1); - } - - for (i = 0; i < nitems(reg_adda); i++) - rtwn_bb_write(sc, reg_adda[i], iq_cal_regs.adda[i]); - - rtwn_write_1(sc, R92C_TXPAUSE, iq_cal_regs.txpause); - rtwn_write_1(sc, R92C_BCN_CTRL, iq_cal_regs.bcn_ctrl); - rtwn_write_1(sc, R92C_USTIME_TSF, iq_cal_regs.ustime_tsf); - rtwn_write_4(sc, R92C_GPIO_MUXCFG, iq_cal_regs.gpio_muxcfg); - } -} - -#define RTWN_IQ_CAL_MAX_TOLERANCE 5 -int -rtwn_iq_calib_compare_results(uint16_t tx1[2][2], uint16_t rx1[2][2], - uint16_t tx2[2][2], uint16_t rx2[2][2], int ntxchains) -{ - int chain, i, tx_ok[2], rx_ok[2]; - - tx_ok[0] = tx_ok[1] = rx_ok[0] = rx_ok[1] = 0; - for (chain = 0; chain < ntxchains; chain++) { - for (i = 0; i < 2; i++) { - if (tx1[chain][i] == 0xff || tx2[chain][i] == 0xff || - rx1[chain][i] == 0xff || rx2[chain][i] == 0xff) - continue; - - tx_ok[chain] = (abs(tx1[chain][i] - tx2[chain][i]) <= - RTWN_IQ_CAL_MAX_TOLERANCE); - - rx_ok[chain] = (abs(rx1[chain][i] - rx2[chain][i]) <= - RTWN_IQ_CAL_MAX_TOLERANCE); - } - } - - if (ntxchains > 1) - return (tx_ok[0] && tx_ok[1] && rx_ok[0] && rx_ok[1]); - else - return (tx_ok[0] && rx_ok[0]); -} -#undef RTWN_IQ_CAL_MAX_TOLERANCE - -void -rtwn_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2], - uint16_t rx[2], int chain) -{ - uint32_t reg, val, x; - long y, tx_c; - - if (tx[0] == 0xff || tx[1] == 0xff) - return; - - reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain)); - val = ((reg >> 22) & 0x3ff); - x = tx[0]; - if (x & 0x0200) - x |= 0xfc00; - reg = (((x * val) >> 8) & 0x3ff); - rtwn_bb_write(sc, R92C_OFDM0_TXIQIMBALANCE(chain), reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_ECCATHRESHOLD); - if (((x * val) >> 7) & 0x01) - reg |= 0x80000000; - else - reg &= ~0x80000000; - rtwn_bb_write(sc, R92C_OFDM0_ECCATHRESHOLD, reg); - - y = tx[1]; - if (y & 0x00000200) - y |= 0xfffffc00; - tx_c = (y * val) >> 8; - reg = rtwn_bb_read(sc, R92C_OFDM0_TXAFE(chain)); - reg |= ((((tx_c & 0x3c0) >> 6) << 24) & 0xf0000000); - rtwn_bb_write(sc, R92C_OFDM0_TXAFE(chain), reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain)); - reg |= (((tx_c & 0x3f) << 16) & 0x003F0000); - rtwn_bb_write(sc, R92C_OFDM0_TXIQIMBALANCE(chain), reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_ECCATHRESHOLD); - if (((y * val) >> 7) & 0x01) - reg |= 0x20000000; - else - reg &= ~0x20000000; - rtwn_bb_write(sc, R92C_OFDM0_ECCATHRESHOLD, reg); - - if (rx[0] == 0xff || rx[1] == 0xff) - return; - - reg = rtwn_bb_read(sc, R92C_OFDM0_RXIQIMBALANCE(chain)); - reg |= (rx[0] & 0x3ff); - rtwn_bb_write(sc, R92C_OFDM0_RXIQIMBALANCE(chain), reg); - reg |= (((rx[1] & 0x03f) << 8) & 0xFC00); - rtwn_bb_write(sc, R92C_OFDM0_RXIQIMBALANCE(chain), reg); - - if (chain == 0) { - reg = rtwn_bb_read(sc, R92C_OFDM0_RXIQEXTANTA); - reg |= (((rx[1] & 0xf) >> 6) & 0x000f); - rtwn_bb_write(sc, R92C_OFDM0_RXIQEXTANTA, reg); - } else { - reg = rtwn_bb_read(sc, R92C_OFDM0_AGCRSSITABLE); - reg |= ((((rx[1] & 0xf) >> 6) << 12) & 0xf000); - rtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE, reg); - } -} - -#define RTWN_IQ_CAL_NRUN 3 -void -rtwn_iq_calib(struct rtwn_softc *sc) -{ - uint16_t tx[RTWN_IQ_CAL_NRUN][2][2], rx[RTWN_IQ_CAL_NRUN][2][2]; - int n, valid; - - valid = 0; - for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) { - rtwn_iq_calib_run(sc, n, tx[n], rx[n]); - - if (n == 0) - continue; - - /* Valid results remain stable after consecutive runs. */ - valid = rtwn_iq_calib_compare_results(tx[n - 1], rx[n - 1], - tx[n], rx[n], sc->ntxchains); - if (valid) - break; - } - - if (valid) { - rtwn_iq_calib_write_results(sc, tx[n][0], rx[n][0], 0); - if (sc->ntxchains > 1) - rtwn_iq_calib_write_results(sc, tx[n][1], rx[n][1], 1); - } -} -#undef RTWN_IQ_CAL_NRUN - -void -rtwn_lc_calib(struct rtwn_softc *sc) -{ - uint32_t rf_ac[2]; - uint8_t txmode; - int i; - - txmode = rtwn_read_1(sc, R92C_OFDM1_LSTF + 3); - if ((txmode & 0x70) != 0) { - /* Disable all continuous Tx. */ - rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode & ~0x70); - - /* Set RF mode to standby mode. */ - for (i = 0; i < sc->nrxchains; i++) { - rf_ac[i] = rtwn_rf_read(sc, i, R92C_RF_AC); - rtwn_rf_write(sc, i, R92C_RF_AC, - RW(rf_ac[i], R92C_RF_AC_MODE, - R92C_RF_AC_MODE_STANDBY)); - } - } else { - /* Block all Tx queues. */ - rtwn_write_1(sc, R92C_TXPAUSE, 0xff); - } - /* Start calibration. */ - rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, - rtwn_rf_read(sc, 0, R92C_RF_CHNLBW) | R92C_RF_CHNLBW_LCSTART); - - /* Give calibration the time to complete. */ - DELAY(100); - - /* Restore configuration. */ - if ((txmode & 0x70) != 0) { - /* Restore Tx mode. */ - rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode); - /* Restore RF mode. */ - for (i = 0; i < sc->nrxchains; i++) - rtwn_rf_write(sc, i, R92C_RF_AC, rf_ac[i]); - } else { - /* Unblock all Tx queues. */ - rtwn_write_1(sc, R92C_TXPAUSE, 0x00); - } -} - -void -rtwn_temp_calib(struct rtwn_softc *sc) -{ - int temp; - - if (sc->thcal_state == 0) { - /* Start measuring temperature. */ - rtwn_rf_write(sc, 0, R92C_RF_T_METER, 0x60); - sc->thcal_state = 1; - return; - } - sc->thcal_state = 0; - - /* Read measured temperature. */ - temp = rtwn_rf_read(sc, 0, R92C_RF_T_METER) & 0x1f; - if (temp == 0) /* Read failed, skip. */ - return; - DPRINTFN(2, ("temperature=%d\n", temp)); - - /* - * Redo IQ and LC calibration if temperature changed significantly - * since last calibration. - */ - if (sc->thcal_lctemp == 0) { - /* First calibration is performed in rtwn_init(). */ - sc->thcal_lctemp = temp; - } else if (abs(temp - sc->thcal_lctemp) > 1) { - DPRINTF(("IQ/LC calib triggered by temp: %d -> %d\n", - sc->thcal_lctemp, temp)); - rtwn_iq_calib(sc); - rtwn_lc_calib(sc); - /* Record temperature of last calibration. */ - sc->thcal_lctemp = temp; - } -} - -int -rtwn_init(struct ifnet *ifp) -{ - struct rtwn_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - uint32_t reg; - int i, error; - - /* Init firmware commands ring. */ - sc->fwcur = 0; - - /* Power on adapter. */ - error = rtwn_power_on(sc); - if (error != 0) { - printf("%s: could not power on adapter\n", - sc->sc_dev.dv_xname); - goto fail; - } - - /* Initialize DMA. */ - error = rtwn_dma_init(sc); - if (error != 0) { - printf("%s: could not initialize DMA\n", - sc->sc_dev.dv_xname); - goto fail; - } - - /* Set info size in Rx descriptors (in 64-bit words). */ - rtwn_write_1(sc, R92C_RX_DRVINFO_SZ, 4); - - /* Disable interrupts. */ - rtwn_write_4(sc, R92C_HISR, 0x00000000); - rtwn_write_4(sc, R92C_HIMR, 0x00000000); - - /* Set MAC address. */ - IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl)); - for (i = 0; i < IEEE80211_ADDR_LEN; i++) - rtwn_write_1(sc, R92C_MACID + i, ic->ic_myaddr[i]); - - /* Set initial network type. */ - reg = rtwn_read_4(sc, R92C_CR); - reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_INFRA); - rtwn_write_4(sc, R92C_CR, reg); - - rtwn_rxfilter_init(sc); - - reg = rtwn_read_4(sc, R92C_RRSR); - reg = RW(reg, R92C_RRSR_RATE_BITMAP, R92C_RRSR_RATE_ALL); - rtwn_write_4(sc, R92C_RRSR, reg); - - /* Set short/long retry limits. */ - rtwn_write_2(sc, R92C_RL, - SM(R92C_RL_SRL, 0x07) | SM(R92C_RL_LRL, 0x07)); - - /* Initialize EDCA parameters. */ - rtwn_edca_init(sc); - - /* Set data and response automatic rate fallback retry counts. */ - rtwn_write_4(sc, R92C_DARFRC + 0, 0x01000000); - rtwn_write_4(sc, R92C_DARFRC + 4, 0x07060504); - rtwn_write_4(sc, R92C_RARFRC + 0, 0x01000000); - rtwn_write_4(sc, R92C_RARFRC + 4, 0x07060504); - - rtwn_write_2(sc, R92C_FWHW_TXQ_CTRL, 0x1f80); - - /* Set ACK timeout. */ - rtwn_write_1(sc, R92C_ACKTO, 0x40); - - /* Initialize beacon parameters. */ - rtwn_write_2(sc, R92C_TBTT_PROHIBIT, 0x6404); - rtwn_write_1(sc, R92C_DRVERLYINT, 0x05); - rtwn_write_1(sc, R92C_BCNDMATIM, 0x02); - rtwn_write_2(sc, R92C_BCNTCFG, 0x660f); - - /* Setup AMPDU aggregation. */ - rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */ - rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16); - - rtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff); - rtwn_write_1(sc, R92C_BCN_CTRL, R92C_BCN_CTRL_DIS_TSF_UDT0); - - rtwn_write_4(sc, R92C_PIFS, 0x1c); - rtwn_write_4(sc, R92C_MCUTST_1, 0x0); - - /* Load 8051 microcode. */ - error = rtwn_load_firmware(sc); - if (error != 0) - goto fail; - - /* Initialize MAC/BB/RF blocks. */ - rtwn_mac_init(sc); - rtwn_bb_init(sc); - rtwn_rf_init(sc); - - /* Turn CCK and OFDM blocks on. */ - reg = rtwn_bb_read(sc, R92C_FPGA0_RFMOD); - reg |= R92C_RFMOD_CCK_EN; - rtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg); - reg = rtwn_bb_read(sc, R92C_FPGA0_RFMOD); - reg |= R92C_RFMOD_OFDM_EN; - rtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg); - - /* Clear per-station keys table. */ - rtwn_cam_init(sc); - - /* Enable hardware sequence numbering. */ - rtwn_write_1(sc, R92C_HWSEQ_CTRL, 0xff); - - /* Perform LO and IQ calibrations. */ - rtwn_iq_calib(sc); - /* Perform LC calibration. */ - rtwn_lc_calib(sc); - - rtwn_pa_bias_init(sc); - - /* Initialize GPIO setting. */ - rtwn_write_1(sc, R92C_GPIO_MUXCFG, - rtwn_read_1(sc, R92C_GPIO_MUXCFG) & ~R92C_GPIO_MUXCFG_ENBT); - - /* Fix for lower temperature. */ - rtwn_write_1(sc, 0x15, 0xe9); - - /* Set default channel. */ - ic->ic_bss->ni_chan = ic->ic_ibss_chan; - rtwn_set_chan(sc, ic->ic_ibss_chan, NULL); - - /* CLear pending interrupts. */ - rtwn_write_4(sc, R92C_HISR, 0xffffffff); - - /* Enable interrupts. */ - rtwn_write_4(sc, R92C_HIMR, RTWN_INT_ENABLE); - - /* We're ready to go. */ - ifq_clr_oactive(&ifp->if_snd); - ifp->if_flags |= IFF_RUNNING; - -#ifdef notyet - if (ic->ic_flags & IEEE80211_F_WEPON) { - /* Install WEP keys. */ - for (i = 0; i < IEEE80211_WEP_NKID; i++) - rtwn_set_key(ic, NULL, &ic->ic_nw_keys[i]); - } -#endif - if (ic->ic_opmode == IEEE80211_M_MONITOR) - ieee80211_new_state(ic, IEEE80211_S_RUN, -1); - else - ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); - return (0); - fail: - rtwn_stop(ifp); - return (error); -} - -void -rtwn_init_task(void *arg1) -{ - struct rtwn_softc *sc = arg1; - struct ifnet *ifp = &sc->sc_ic.ic_if; - int s; - - s = splnet(); - while (sc->sc_flags & RTWN_FLAG_BUSY) - tsleep(&sc->sc_flags, 0, "rtwnpwr", 0); - sc->sc_flags |= RTWN_FLAG_BUSY; - - rtwn_stop(ifp); - - if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP) - rtwn_init(ifp); - - sc->sc_flags &= ~RTWN_FLAG_BUSY; - wakeup(&sc->sc_flags); - splx(s); -} - -void -rtwn_stop(struct ifnet *ifp) -{ - struct rtwn_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - int s, i; - u_int16_t reg; - - sc->sc_tx_timer = 0; - ifp->if_timer = 0; - ifp->if_flags &= ~IFF_RUNNING; - ifq_clr_oactive(&ifp->if_snd); - - s = splnet(); - ieee80211_new_state(ic, IEEE80211_S_INIT, -1); - - timeout_del(&sc->scan_to); - timeout_del(&sc->calib_to); - - task_del(systq, &sc->init_task); - - /* Disable interrupts. */ - rtwn_write_4(sc, R92C_HISR, 0x00000000); - rtwn_write_4(sc, R92C_HIMR, 0x00000000); - - /* Stop hardware. */ - rtwn_write_1(sc, R92C_TXPAUSE, 0xff); - rtwn_write_1(sc, R92C_RF_CTRL, 0x00); - reg = rtwn_read_1(sc, R92C_SYS_FUNC_EN); - reg |= R92C_SYS_FUNC_EN_BB_GLB_RST; - rtwn_write_1(sc, R92C_SYS_FUNC_EN, reg); - reg &= ~R92C_SYS_FUNC_EN_BB_GLB_RST; - rtwn_write_1(sc, R92C_SYS_FUNC_EN, reg); - reg = rtwn_read_2(sc, R92C_CR); - reg &= ~(R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | - R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | - R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN | - R92C_CR_ENSEC); - rtwn_write_2(sc, R92C_CR, reg); - if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) - rtwn_fw_reset(sc); - /* TODO: linux does additional btcoex stuff here */ - rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0x80); /* linux magic number */ - rtwn_write_1(sc, R92C_SPS0_CTRL, 0x23); /* ditto */ - rtwn_write_1(sc, R92C_AFE_XTAL_CTRL, 0x0e); /* different with btcoex */ - rtwn_write_1(sc, R92C_RSV_CTRL, 0x0e); - rtwn_write_1(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_PDN_EN); - for (i = 0; i < RTWN_NTXQUEUES; i++) rtwn_reset_tx_list(sc, i); rtwn_reset_rx_list(sc); - - splx(s); } int rtwn_intr(void *xsc) { - struct rtwn_softc *sc = xsc; + struct rtwn_pci_softc *sc = xsc; u_int32_t status; int i; - status = rtwn_read_4(sc, R92C_HISR); + status = rtwn_pci_read_4(sc, R92C_HISR); if (status == 0 || status == 0xffffffff) return (0); /* Disable interrupts. */ - rtwn_write_4(sc, R92C_HIMR, 0x00000000); + rtwn_pci_write_4(sc, R92C_HIMR, 0x00000000); /* Ack interrupts. */ - rtwn_write_4(sc, R92C_HISR, status); + rtwn_pci_write_4(sc, R92C_HISR, status); /* Vendor driver treats RX errors like ROK... */ if (status & (R92C_IMR_ROK | R92C_IMR_RXFOVW | R92C_IMR_RDU)) { @@ -3737,7 +1156,64 @@ rtwn_intr(void *xsc) rtwn_tx_done(sc, RTWN_VO_QUEUE); /* Enable interrupts. */ - rtwn_write_4(sc, R92C_HIMR, RTWN_INT_ENABLE); + rtwn_pci_write_4(sc, R92C_HIMR, RTWN_INT_ENABLE); return (1); } + +int +rtwn_is_oactive(void *cookie) +{ + struct rtwn_pci_softc *sc = cookie; + + return (sc->qfullmsk != 0); +} + +int +rtwn_configure_dma(void *cookie) +{ + struct rtwn_pci_softc *sc = cookie; + + /* Configure Tx DMA. */ + rtwn_pci_write_4(sc, R92C_BKQ_DESA, + sc->tx_ring[RTWN_BK_QUEUE].map->dm_segs[0].ds_addr); + rtwn_pci_write_4(sc, R92C_BEQ_DESA, + sc->tx_ring[RTWN_BE_QUEUE].map->dm_segs[0].ds_addr); + rtwn_pci_write_4(sc, R92C_VIQ_DESA, + sc->tx_ring[RTWN_VI_QUEUE].map->dm_segs[0].ds_addr); + rtwn_pci_write_4(sc, R92C_VOQ_DESA, + sc->tx_ring[RTWN_VO_QUEUE].map->dm_segs[0].ds_addr); + rtwn_pci_write_4(sc, R92C_BCNQ_DESA, + sc->tx_ring[RTWN_BEACON_QUEUE].map->dm_segs[0].ds_addr); + rtwn_pci_write_4(sc, R92C_MGQ_DESA, + sc->tx_ring[RTWN_MGNT_QUEUE].map->dm_segs[0].ds_addr); + rtwn_pci_write_4(sc, R92C_HQ_DESA, + sc->tx_ring[RTWN_HIGH_QUEUE].map->dm_segs[0].ds_addr); + + /* Configure Rx DMA. */ + rtwn_pci_write_4(sc, R92C_RX_DESA, sc->rx_ring.map->dm_segs[0].ds_addr); + + return (0); +} + +void +rtwn_enable_intr(void *cookie) +{ + struct rtwn_pci_softc *sc = cookie; + + /* CLear pending interrupts. */ + rtwn_pci_write_4(sc, R92C_HISR, 0xffffffff); + + /* Enable interrupts. */ + rtwn_pci_write_4(sc, R92C_HIMR, RTWN_INT_ENABLE); +} + +void +rtwn_disable_intr(void *cookie) +{ + struct rtwn_pci_softc *sc = cookie; + + /* Disable interrupts. */ + rtwn_pci_write_4(sc, R92C_HISR, 0x00000000); + rtwn_pci_write_4(sc, R92C_HIMR, 0x00000000); +} |