if_ural.c revision 189123
1184610Salfred/* $FreeBSD: head/sys/dev/usb/wlan/if_ural.c 189123 2009-02-27 21:14:29Z thompsa $ */ 2184610Salfred 3184610Salfred/*- 4184610Salfred * Copyright (c) 2005, 2006 5184610Salfred * Damien Bergamini <damien.bergamini@free.fr> 6184610Salfred * 7184610Salfred * Copyright (c) 2006, 2008 8189002Sed * Hans Petter Selasky <hselasky@FreeBSD.org> 9184610Salfred * 10184610Salfred * Permission to use, copy, modify, and distribute this software for any 11184610Salfred * purpose with or without fee is hereby granted, provided that the above 12184610Salfred * copyright notice and this permission notice appear in all copies. 13184610Salfred * 14184610Salfred * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 15184610Salfred * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 16184610Salfred * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 17184610Salfred * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18184610Salfred * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 19184610Salfred * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 20184610Salfred * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21184610Salfred */ 22184610Salfred 23184610Salfred#include <sys/cdefs.h> 24184610Salfred__FBSDID("$FreeBSD: head/sys/dev/usb/wlan/if_ural.c 189123 2009-02-27 21:14:29Z thompsa $"); 25184610Salfred 26184610Salfred/*- 27184610Salfred * Ralink Technology RT2500USB chipset driver 28184610Salfred * http://www.ralinktech.com/ 29184610Salfred */ 30184610Salfred 31188746Sthompsa#include "usbdevs.h" 32188942Sthompsa#include <dev/usb/usb.h> 33188942Sthompsa#include <dev/usb/usb_mfunc.h> 34188942Sthompsa#include <dev/usb/usb_error.h> 35184610Salfred 36184610Salfred#define USB_DEBUG_VAR ural_debug 37184610Salfred 38188942Sthompsa#include <dev/usb/usb_core.h> 39188942Sthompsa#include <dev/usb/usb_lookup.h> 40188942Sthompsa#include <dev/usb/usb_process.h> 41188942Sthompsa#include <dev/usb/usb_debug.h> 42188942Sthompsa#include <dev/usb/usb_request.h> 43188942Sthompsa#include <dev/usb/usb_busdma.h> 44188942Sthompsa#include <dev/usb/usb_util.h> 45184610Salfred 46188942Sthompsa#include <dev/usb/wlan/usb_wlan.h> 47188942Sthompsa#include <dev/usb/wlan/if_uralreg.h> 48188942Sthompsa#include <dev/usb/wlan/if_uralvar.h> 49184610Salfred 50184610Salfred#if USB_DEBUG 51184610Salfredstatic int ural_debug = 0; 52184610Salfred 53184610SalfredSYSCTL_NODE(_hw_usb2, OID_AUTO, ural, CTLFLAG_RW, 0, "USB ural"); 54184610SalfredSYSCTL_INT(_hw_usb2_ural, OID_AUTO, debug, CTLFLAG_RW, &ural_debug, 0, 55184610Salfred "Debug level"); 56184610Salfred#endif 57184610Salfred 58188417Sthompsa#define URAL_RSSI(rssi) \ 59188417Sthompsa ((rssi) > (RAL_NOISE_FLOOR + RAL_RSSI_CORR) ? \ 60188417Sthompsa ((rssi) - (RAL_NOISE_FLOOR + RAL_RSSI_CORR)) : 0) 61184610Salfred 62188417Sthompsa/* various supported device vendors/products */ 63188417Sthompsastatic const struct usb2_device_id ural_devs[] = { 64188417Sthompsa { USB_VP(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_WL167G) }, 65188417Sthompsa { USB_VP(USB_VENDOR_ASUS, USB_PRODUCT_RALINK_RT2570) }, 66188417Sthompsa { USB_VP(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050) }, 67188417Sthompsa { USB_VP(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7051) }, 68188417Sthompsa { USB_VP(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_HU200TS) }, 69188417Sthompsa { USB_VP(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54G) }, 70188417Sthompsa { USB_VP(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GP) }, 71188417Sthompsa { USB_VP(USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_C54RU) }, 72188417Sthompsa { USB_VP(USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLG122) }, 73188417Sthompsa { USB_VP(USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GN54G) }, 74188417Sthompsa { USB_VP(USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWBKG) }, 75188417Sthompsa { USB_VP(USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254) }, 76188417Sthompsa { USB_VP(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54) }, 77188417Sthompsa { USB_VP(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54AI) }, 78188417Sthompsa { USB_VP(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54YB) }, 79188417Sthompsa { USB_VP(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_NINWIFI) }, 80188417Sthompsa { USB_VP(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570) }, 81188417Sthompsa { USB_VP(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570_2) }, 82188417Sthompsa { USB_VP(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570_3) }, 83188417Sthompsa { USB_VP(USB_VENDOR_NOVATECH, USB_PRODUCT_NOVATECH_NV902) }, 84188417Sthompsa { USB_VP(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570) }, 85188417Sthompsa { USB_VP(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570_2) }, 86188417Sthompsa { USB_VP(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570_3) }, 87188417Sthompsa { USB_VP(USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_WL54G) }, 88188417Sthompsa { USB_VP(USB_VENDOR_SMC, USB_PRODUCT_SMC_2862WG) }, 89188417Sthompsa { USB_VP(USB_VENDOR_SPHAIRON, USB_PRODUCT_SPHAIRON_UB801R) }, 90188417Sthompsa { USB_VP(USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_RT2570) }, 91188417Sthompsa { USB_VP(USB_VENDOR_VTECH, USB_PRODUCT_VTECH_RT2570) }, 92188417Sthompsa { USB_VP(USB_VENDOR_ZINWELL, USB_PRODUCT_ZINWELL_RT2570) }, 93188417Sthompsa}; 94184610Salfred 95184610Salfredstatic usb2_callback_t ural_bulk_read_callback; 96184610Salfredstatic usb2_callback_t ural_bulk_write_callback; 97184610Salfred 98189123Sthompsastatic usb2_proc_callback_t ural_command_wrapper; 99188419Sthompsastatic usb2_proc_callback_t ural_attach_post; 100188417Sthompsastatic usb2_proc_callback_t ural_task; 101188417Sthompsastatic usb2_proc_callback_t ural_scantask; 102188417Sthompsastatic usb2_proc_callback_t ural_promisctask; 103188417Sthompsastatic usb2_proc_callback_t ural_amrr_task; 104188419Sthompsastatic usb2_proc_callback_t ural_init_task; 105188419Sthompsastatic usb2_proc_callback_t ural_stop_task; 106189123Sthompsastatic usb2_proc_callback_t ural_flush_task; 107184610Salfred 108189123Sthompsastatic usb2_error_t ural_do_request(struct ural_softc *sc, 109189123Sthompsa struct usb2_device_request *req, void *data); 110185948Sthompsastatic struct ieee80211vap *ural_vap_create(struct ieee80211com *, 111188417Sthompsa const char name[IFNAMSIZ], int unit, int opmode, 112188417Sthompsa int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], 113188417Sthompsa const uint8_t mac[IEEE80211_ADDR_LEN]); 114188417Sthompsastatic void ural_vap_delete(struct ieee80211vap *); 115188417Sthompsastatic void ural_tx_free(struct ural_tx_data *, int); 116188419Sthompsastatic void ural_setup_tx_list(struct ural_softc *); 117188419Sthompsastatic void ural_unsetup_tx_list(struct ural_softc *); 118188417Sthompsastatic int ural_newstate(struct ieee80211vap *, 119188417Sthompsa enum ieee80211_state, int); 120188417Sthompsastatic void ural_setup_tx_desc(struct ural_softc *, 121188417Sthompsa struct ural_tx_desc *, uint32_t, int, int); 122188417Sthompsastatic int ural_tx_bcn(struct ural_softc *, struct mbuf *, 123188417Sthompsa struct ieee80211_node *); 124188417Sthompsastatic int ural_tx_mgt(struct ural_softc *, struct mbuf *, 125188417Sthompsa struct ieee80211_node *); 126188417Sthompsastatic int ural_tx_data(struct ural_softc *, struct mbuf *, 127188417Sthompsa struct ieee80211_node *); 128188417Sthompsastatic void ural_start(struct ifnet *); 129188417Sthompsastatic int ural_ioctl(struct ifnet *, u_long, caddr_t); 130188417Sthompsastatic void ural_set_testmode(struct ural_softc *); 131188417Sthompsastatic void ural_eeprom_read(struct ural_softc *, uint16_t, void *, 132188417Sthompsa int); 133188417Sthompsastatic uint16_t ural_read(struct ural_softc *, uint16_t); 134188417Sthompsastatic void ural_read_multi(struct ural_softc *, uint16_t, void *, 135188417Sthompsa int); 136188417Sthompsastatic void ural_write(struct ural_softc *, uint16_t, uint16_t); 137188417Sthompsastatic void ural_write_multi(struct ural_softc *, uint16_t, void *, 138188417Sthompsa int) __unused; 139188417Sthompsastatic void ural_bbp_write(struct ural_softc *, uint8_t, uint8_t); 140188417Sthompsastatic uint8_t ural_bbp_read(struct ural_softc *, uint8_t); 141188417Sthompsastatic void ural_rf_write(struct ural_softc *, uint8_t, uint32_t); 142185948Sthompsastatic struct ieee80211_node *ural_node_alloc(struct ieee80211vap *, 143188417Sthompsa const uint8_t mac[IEEE80211_ADDR_LEN]); 144188417Sthompsastatic void ural_newassoc(struct ieee80211_node *, int); 145188417Sthompsastatic void ural_scan_start(struct ieee80211com *); 146188417Sthompsastatic void ural_scan_end(struct ieee80211com *); 147188417Sthompsastatic void ural_set_channel(struct ieee80211com *); 148188417Sthompsastatic void ural_set_chan(struct ural_softc *, 149188417Sthompsa struct ieee80211_channel *); 150188417Sthompsastatic void ural_disable_rf_tune(struct ural_softc *); 151188417Sthompsastatic void ural_enable_tsf_sync(struct ural_softc *); 152188417Sthompsastatic void ural_update_slot(struct ifnet *); 153188417Sthompsastatic void ural_set_txpreamble(struct ural_softc *); 154188417Sthompsastatic void ural_set_basicrates(struct ural_softc *, 155188417Sthompsa const struct ieee80211_channel *); 156188417Sthompsastatic void ural_set_bssid(struct ural_softc *, const uint8_t *); 157188417Sthompsastatic void ural_set_macaddr(struct ural_softc *, uint8_t *); 158189123Sthompsastatic void ural_update_mcast(struct ifnet *); 159189123Sthompsastatic void ural_update_promisc(struct ifnet *); 160188417Sthompsastatic const char *ural_get_rf(int); 161188417Sthompsastatic void ural_read_eeprom(struct ural_softc *); 162188417Sthompsastatic int ural_bbp_init(struct ural_softc *); 163188417Sthompsastatic void ural_set_txantenna(struct ural_softc *, int); 164188417Sthompsastatic void ural_set_rxantenna(struct ural_softc *, int); 165188417Sthompsastatic void ural_init(void *); 166188417Sthompsastatic int ural_raw_xmit(struct ieee80211_node *, struct mbuf *, 167188417Sthompsa const struct ieee80211_bpf_params *); 168188417Sthompsastatic void ural_amrr_start(struct ural_softc *, 169188417Sthompsa struct ieee80211_node *); 170188417Sthompsastatic void ural_amrr_timeout(void *); 171188619Sthompsastatic int ural_pause(struct ural_softc *sc, int timeout); 172188417Sthompsastatic void ural_queue_command(struct ural_softc *, 173188417Sthompsa usb2_proc_callback_t *, struct usb2_proc_msg *, 174188417Sthompsa struct usb2_proc_msg *); 175184610Salfred 176184610Salfred/* 177188417Sthompsa * Default values for MAC registers; values taken from the reference driver. 178184610Salfred */ 179188417Sthompsastatic const struct { 180188417Sthompsa uint16_t reg; 181188417Sthompsa uint16_t val; 182188417Sthompsa} ural_def_mac[] = { 183188417Sthompsa { RAL_TXRX_CSR5, 0x8c8d }, 184188417Sthompsa { RAL_TXRX_CSR6, 0x8b8a }, 185188417Sthompsa { RAL_TXRX_CSR7, 0x8687 }, 186188417Sthompsa { RAL_TXRX_CSR8, 0x0085 }, 187188417Sthompsa { RAL_MAC_CSR13, 0x1111 }, 188188417Sthompsa { RAL_MAC_CSR14, 0x1e11 }, 189188417Sthompsa { RAL_TXRX_CSR21, 0xe78f }, 190188417Sthompsa { RAL_MAC_CSR9, 0xff1d }, 191188417Sthompsa { RAL_MAC_CSR11, 0x0002 }, 192188417Sthompsa { RAL_MAC_CSR22, 0x0053 }, 193188417Sthompsa { RAL_MAC_CSR15, 0x0000 }, 194188417Sthompsa { RAL_MAC_CSR8, RAL_FRAME_SIZE }, 195188417Sthompsa { RAL_TXRX_CSR19, 0x0000 }, 196188417Sthompsa { RAL_TXRX_CSR18, 0x005a }, 197188417Sthompsa { RAL_PHY_CSR2, 0x0000 }, 198188417Sthompsa { RAL_TXRX_CSR0, 0x1ec0 }, 199188417Sthompsa { RAL_PHY_CSR4, 0x000f } 200184610Salfred}; 201184610Salfred 202184610Salfred/* 203184610Salfred * Default values for BBP registers; values taken from the reference driver. 204184610Salfred */ 205188417Sthompsastatic const struct { 206184610Salfred uint8_t reg; 207184610Salfred uint8_t val; 208188417Sthompsa} ural_def_bbp[] = { 209188417Sthompsa { 3, 0x02 }, 210188417Sthompsa { 4, 0x19 }, 211188417Sthompsa { 14, 0x1c }, 212188417Sthompsa { 15, 0x30 }, 213188417Sthompsa { 16, 0xac }, 214188417Sthompsa { 17, 0x48 }, 215188417Sthompsa { 18, 0x18 }, 216188417Sthompsa { 19, 0xff }, 217188417Sthompsa { 20, 0x1e }, 218188417Sthompsa { 21, 0x08 }, 219188417Sthompsa { 22, 0x08 }, 220188417Sthompsa { 23, 0x08 }, 221188417Sthompsa { 24, 0x80 }, 222188417Sthompsa { 25, 0x50 }, 223188417Sthompsa { 26, 0x08 }, 224188417Sthompsa { 27, 0x23 }, 225188417Sthompsa { 30, 0x10 }, 226188417Sthompsa { 31, 0x2b }, 227188417Sthompsa { 32, 0xb9 }, 228188417Sthompsa { 34, 0x12 }, 229188417Sthompsa { 35, 0x50 }, 230188417Sthompsa { 39, 0xc4 }, 231188417Sthompsa { 40, 0x02 }, 232188417Sthompsa { 41, 0x60 }, 233188417Sthompsa { 53, 0x10 }, 234188417Sthompsa { 54, 0x18 }, 235188417Sthompsa { 56, 0x08 }, 236188417Sthompsa { 57, 0x10 }, 237188417Sthompsa { 58, 0x08 }, 238188417Sthompsa { 61, 0x60 }, 239188417Sthompsa { 62, 0x10 }, 240188417Sthompsa { 75, 0xff } 241184610Salfred}; 242184610Salfred 243184610Salfred/* 244184610Salfred * Default values for RF register R2 indexed by channel numbers. 245184610Salfred */ 246184610Salfredstatic const uint32_t ural_rf2522_r2[] = { 247184610Salfred 0x307f6, 0x307fb, 0x30800, 0x30805, 0x3080a, 0x3080f, 0x30814, 248184610Salfred 0x30819, 0x3081e, 0x30823, 0x30828, 0x3082d, 0x30832, 0x3083e 249184610Salfred}; 250184610Salfred 251184610Salfredstatic const uint32_t ural_rf2523_r2[] = { 252184610Salfred 0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d, 253184610Salfred 0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346 254184610Salfred}; 255184610Salfred 256184610Salfredstatic const uint32_t ural_rf2524_r2[] = { 257184610Salfred 0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d, 258184610Salfred 0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346 259184610Salfred}; 260184610Salfred 261184610Salfredstatic const uint32_t ural_rf2525_r2[] = { 262184610Salfred 0x20327, 0x20328, 0x20329, 0x2032a, 0x2032b, 0x2032c, 0x2032d, 263184610Salfred 0x2032e, 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20346 264184610Salfred}; 265184610Salfred 266184610Salfredstatic const uint32_t ural_rf2525_hi_r2[] = { 267184610Salfred 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20344, 0x20345, 268184610Salfred 0x20346, 0x20347, 0x20348, 0x20349, 0x2034a, 0x2034b, 0x2034e 269184610Salfred}; 270184610Salfred 271184610Salfredstatic const uint32_t ural_rf2525e_r2[] = { 272184610Salfred 0x2044d, 0x2044e, 0x2044f, 0x20460, 0x20461, 0x20462, 0x20463, 273184610Salfred 0x20464, 0x20465, 0x20466, 0x20467, 0x20468, 0x20469, 0x2046b 274184610Salfred}; 275184610Salfred 276184610Salfredstatic const uint32_t ural_rf2526_hi_r2[] = { 277184610Salfred 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d, 0x0022d, 278184610Salfred 0x0022e, 0x0022e, 0x0022f, 0x0022d, 0x00240, 0x00240, 0x00241 279184610Salfred}; 280184610Salfred 281184610Salfredstatic const uint32_t ural_rf2526_r2[] = { 282184610Salfred 0x00226, 0x00227, 0x00227, 0x00228, 0x00228, 0x00229, 0x00229, 283184610Salfred 0x0022a, 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d 284184610Salfred}; 285184610Salfred 286184610Salfred/* 287184610Salfred * For dual-band RF, RF registers R1 and R4 also depend on channel number; 288184610Salfred * values taken from the reference driver. 289184610Salfred */ 290188417Sthompsastatic const struct { 291188417Sthompsa uint8_t chan; 292188417Sthompsa uint32_t r1; 293188417Sthompsa uint32_t r2; 294188417Sthompsa uint32_t r4; 295188417Sthompsa} ural_rf5222[] = { 296188417Sthompsa { 1, 0x08808, 0x0044d, 0x00282 }, 297188417Sthompsa { 2, 0x08808, 0x0044e, 0x00282 }, 298188417Sthompsa { 3, 0x08808, 0x0044f, 0x00282 }, 299188417Sthompsa { 4, 0x08808, 0x00460, 0x00282 }, 300188417Sthompsa { 5, 0x08808, 0x00461, 0x00282 }, 301188417Sthompsa { 6, 0x08808, 0x00462, 0x00282 }, 302188417Sthompsa { 7, 0x08808, 0x00463, 0x00282 }, 303188417Sthompsa { 8, 0x08808, 0x00464, 0x00282 }, 304188417Sthompsa { 9, 0x08808, 0x00465, 0x00282 }, 305188417Sthompsa { 10, 0x08808, 0x00466, 0x00282 }, 306188417Sthompsa { 11, 0x08808, 0x00467, 0x00282 }, 307188417Sthompsa { 12, 0x08808, 0x00468, 0x00282 }, 308188417Sthompsa { 13, 0x08808, 0x00469, 0x00282 }, 309188417Sthompsa { 14, 0x08808, 0x0046b, 0x00286 }, 310184610Salfred 311188417Sthompsa { 36, 0x08804, 0x06225, 0x00287 }, 312188417Sthompsa { 40, 0x08804, 0x06226, 0x00287 }, 313188417Sthompsa { 44, 0x08804, 0x06227, 0x00287 }, 314188417Sthompsa { 48, 0x08804, 0x06228, 0x00287 }, 315188417Sthompsa { 52, 0x08804, 0x06229, 0x00287 }, 316188417Sthompsa { 56, 0x08804, 0x0622a, 0x00287 }, 317188417Sthompsa { 60, 0x08804, 0x0622b, 0x00287 }, 318188417Sthompsa { 64, 0x08804, 0x0622c, 0x00287 }, 319184610Salfred 320188417Sthompsa { 100, 0x08804, 0x02200, 0x00283 }, 321188417Sthompsa { 104, 0x08804, 0x02201, 0x00283 }, 322188417Sthompsa { 108, 0x08804, 0x02202, 0x00283 }, 323188417Sthompsa { 112, 0x08804, 0x02203, 0x00283 }, 324188417Sthompsa { 116, 0x08804, 0x02204, 0x00283 }, 325188417Sthompsa { 120, 0x08804, 0x02205, 0x00283 }, 326188417Sthompsa { 124, 0x08804, 0x02206, 0x00283 }, 327188417Sthompsa { 128, 0x08804, 0x02207, 0x00283 }, 328188417Sthompsa { 132, 0x08804, 0x02208, 0x00283 }, 329188417Sthompsa { 136, 0x08804, 0x02209, 0x00283 }, 330188417Sthompsa { 140, 0x08804, 0x0220a, 0x00283 }, 331184610Salfred 332188417Sthompsa { 149, 0x08808, 0x02429, 0x00281 }, 333188417Sthompsa { 153, 0x08808, 0x0242b, 0x00281 }, 334188417Sthompsa { 157, 0x08808, 0x0242d, 0x00281 }, 335188417Sthompsa { 161, 0x08808, 0x0242f, 0x00281 } 336184610Salfred}; 337184610Salfred 338184610Salfredstatic const struct usb2_config ural_config[URAL_N_TRANSFER] = { 339188417Sthompsa [URAL_BULK_WR] = { 340184610Salfred .type = UE_BULK, 341184610Salfred .endpoint = UE_ADDR_ANY, 342184610Salfred .direction = UE_DIR_OUT, 343184610Salfred .mh.bufsize = (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE + 4), 344184610Salfred .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 345188417Sthompsa .mh.callback = ural_bulk_write_callback, 346184610Salfred .mh.timeout = 5000, /* ms */ 347184610Salfred }, 348188417Sthompsa [URAL_BULK_RD] = { 349184610Salfred .type = UE_BULK, 350184610Salfred .endpoint = UE_ADDR_ANY, 351184610Salfred .direction = UE_DIR_IN, 352184610Salfred .mh.bufsize = (RAL_FRAME_SIZE + RAL_RX_DESC_SIZE), 353184610Salfred .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 354188417Sthompsa .mh.callback = ural_bulk_read_callback, 355184610Salfred }, 356184610Salfred}; 357184610Salfred 358188417Sthompsastatic device_probe_t ural_match; 359188417Sthompsastatic device_attach_t ural_attach; 360188417Sthompsastatic device_detach_t ural_detach; 361184610Salfred 362184610Salfredstatic device_method_t ural_methods[] = { 363188417Sthompsa /* Device interface */ 364188417Sthompsa DEVMETHOD(device_probe, ural_match), 365188417Sthompsa DEVMETHOD(device_attach, ural_attach), 366188417Sthompsa DEVMETHOD(device_detach, ural_detach), 367188417Sthompsa 368188417Sthompsa { 0, 0 } 369184610Salfred}; 370184610Salfred 371184610Salfredstatic driver_t ural_driver = { 372184610Salfred .name = "ural", 373184610Salfred .methods = ural_methods, 374184610Salfred .size = sizeof(struct ural_softc), 375184610Salfred}; 376184610Salfred 377188417Sthompsastatic devclass_t ural_devclass; 378188417Sthompsa 379184610SalfredDRIVER_MODULE(ural, ushub, ural_driver, ural_devclass, NULL, 0); 380188942SthompsaMODULE_DEPEND(ural, usb, 1, 1, 1); 381184610SalfredMODULE_DEPEND(ural, wlan, 1, 1, 1); 382184610SalfredMODULE_DEPEND(ural, wlan_amrr, 1, 1, 1); 383184610Salfred 384184610Salfredstatic int 385188417Sthompsaural_match(device_t self) 386184610Salfred{ 387188417Sthompsa struct usb2_attach_arg *uaa = device_get_ivars(self); 388184610Salfred 389188417Sthompsa if (uaa->usb2_mode != USB_MODE_HOST) 390184610Salfred return (ENXIO); 391188417Sthompsa if (uaa->info.bConfigIndex != 0) 392184610Salfred return (ENXIO); 393188417Sthompsa if (uaa->info.bIfaceIndex != RAL_IFACE_INDEX) 394184610Salfred return (ENXIO); 395188417Sthompsa 396184610Salfred return (usb2_lookup_id_by_uaa(ural_devs, sizeof(ural_devs), uaa)); 397184610Salfred} 398184610Salfred 399184610Salfredstatic int 400188417Sthompsaural_attach(device_t self) 401184610Salfred{ 402188417Sthompsa struct usb2_attach_arg *uaa = device_get_ivars(self); 403188417Sthompsa struct ural_softc *sc = device_get_softc(self); 404184610Salfred int error; 405188419Sthompsa uint8_t iface_index; 406184610Salfred 407188417Sthompsa device_set_usb2_desc(self); 408184610Salfred sc->sc_udev = uaa->device; 409188417Sthompsa sc->sc_dev = self; 410184610Salfred 411188417Sthompsa mtx_init(&sc->sc_mtx, device_get_nameunit(self), 412188417Sthompsa MTX_NETWORK_LOCK, MTX_DEF); 413184610Salfred 414189123Sthompsa cv_init(&sc->sc_cmd_cv, "wtxdone"); 415189123Sthompsa 416184610Salfred iface_index = RAL_IFACE_INDEX; 417184610Salfred error = usb2_transfer_setup(uaa->device, 418184610Salfred &iface_index, sc->sc_xfer, ural_config, 419184610Salfred URAL_N_TRANSFER, sc, &sc->sc_mtx); 420184610Salfred if (error) { 421188417Sthompsa device_printf(self, "could not allocate USB transfers, " 422184610Salfred "err=%s\n", usb2_errstr(error)); 423184610Salfred goto detach; 424184610Salfred } 425188417Sthompsa error = usb2_proc_create(&sc->sc_tq, &sc->sc_mtx, 426188417Sthompsa device_get_nameunit(self), USB_PRI_MED); 427184610Salfred if (error) { 428188417Sthompsa device_printf(self, "could not setup config thread!\n"); 429184610Salfred goto detach; 430184610Salfred } 431184610Salfred 432188419Sthompsa /* fork rest of the attach code */ 433188419Sthompsa RAL_LOCK(sc); 434188419Sthompsa ural_queue_command(sc, ural_attach_post, 435188419Sthompsa &sc->sc_synctask[0].hdr, 436188419Sthompsa &sc->sc_synctask[1].hdr); 437188419Sthompsa RAL_UNLOCK(sc); 438188419Sthompsa return (0); 439188418Sthompsa 440188419Sthompsadetach: 441188419Sthompsa ural_detach(self); 442188419Sthompsa return (ENXIO); /* failure */ 443188419Sthompsa} 444188419Sthompsa 445188419Sthompsastatic void 446188419Sthompsaural_attach_post(struct usb2_proc_msg *pm) 447188419Sthompsa{ 448188419Sthompsa struct ural_task *task = (struct ural_task *)pm; 449188419Sthompsa struct ural_softc *sc = task->sc; 450188419Sthompsa struct ifnet *ifp; 451188419Sthompsa struct ieee80211com *ic; 452188419Sthompsa uint8_t bands; 453188419Sthompsa 454188417Sthompsa /* retrieve RT2570 rev. no */ 455188417Sthompsa sc->asic_rev = ural_read(sc, RAL_MAC_CSR0); 456184610Salfred 457188417Sthompsa /* retrieve MAC address and various other things from EEPROM */ 458188417Sthompsa ural_read_eeprom(sc); 459189123Sthompsa 460189123Sthompsa /* XXX Async attach race */ 461189123Sthompsa if (usb2_proc_is_gone(&sc->sc_tq)) 462189123Sthompsa return; 463189123Sthompsa 464188417Sthompsa RAL_UNLOCK(sc); 465184610Salfred 466188417Sthompsa device_printf(sc->sc_dev, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n", 467188417Sthompsa sc->asic_rev, ural_get_rf(sc->rf_rev)); 468184610Salfred 469188419Sthompsa ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); 470188419Sthompsa if (ifp == NULL) { 471188419Sthompsa device_printf(sc->sc_dev, "can not if_alloc()\n"); 472188419Sthompsa RAL_LOCK(sc); 473188419Sthompsa return; 474188419Sthompsa } 475188419Sthompsa ic = ifp->if_l2com; 476188419Sthompsa 477188417Sthompsa ifp->if_softc = sc; 478188417Sthompsa if_initname(ifp, "ural", device_get_unit(sc->sc_dev)); 479188417Sthompsa ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 480188417Sthompsa ifp->if_init = ural_init; 481188417Sthompsa ifp->if_ioctl = ural_ioctl; 482188417Sthompsa ifp->if_start = ural_start; 483188417Sthompsa IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); 484188417Sthompsa ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; 485188417Sthompsa IFQ_SET_READY(&ifp->if_snd); 486184610Salfred 487188417Sthompsa ic->ic_ifp = ifp; 488188417Sthompsa ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 489188419Sthompsa IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_bssid); 490184610Salfred 491188417Sthompsa /* set device capabilities */ 492188417Sthompsa ic->ic_caps = 493188417Sthompsa IEEE80211_C_STA /* station mode supported */ 494188417Sthompsa | IEEE80211_C_IBSS /* IBSS mode supported */ 495188417Sthompsa | IEEE80211_C_MONITOR /* monitor mode supported */ 496188417Sthompsa | IEEE80211_C_HOSTAP /* HostAp mode supported */ 497188417Sthompsa | IEEE80211_C_TXPMGT /* tx power management */ 498188417Sthompsa | IEEE80211_C_SHPREAMBLE /* short preamble supported */ 499188417Sthompsa | IEEE80211_C_SHSLOT /* short slot time supported */ 500188417Sthompsa | IEEE80211_C_BGSCAN /* bg scanning supported */ 501188417Sthompsa | IEEE80211_C_WPA /* 802.11i */ 502188417Sthompsa ; 503184610Salfred 504188417Sthompsa bands = 0; 505188417Sthompsa setbit(&bands, IEEE80211_MODE_11B); 506188417Sthompsa setbit(&bands, IEEE80211_MODE_11G); 507188417Sthompsa if (sc->rf_rev == RAL_RF_5222) 508188417Sthompsa setbit(&bands, IEEE80211_MODE_11A); 509188417Sthompsa ieee80211_init_channels(ic, NULL, &bands); 510184610Salfred 511188417Sthompsa ieee80211_ifattach(ic); 512189123Sthompsa ic->ic_update_mcast = ural_update_mcast; 513189123Sthompsa ic->ic_update_promisc = ural_update_promisc; 514188417Sthompsa ic->ic_newassoc = ural_newassoc; 515188417Sthompsa ic->ic_raw_xmit = ural_raw_xmit; 516188417Sthompsa ic->ic_node_alloc = ural_node_alloc; 517188417Sthompsa ic->ic_scan_start = ural_scan_start; 518188417Sthompsa ic->ic_scan_end = ural_scan_end; 519188417Sthompsa ic->ic_set_channel = ural_set_channel; 520184610Salfred 521188417Sthompsa ic->ic_vap_create = ural_vap_create; 522188417Sthompsa ic->ic_vap_delete = ural_vap_delete; 523184610Salfred 524188417Sthompsa sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan); 525184610Salfred 526188417Sthompsa bpfattach(ifp, DLT_IEEE802_11_RADIO, 527188417Sthompsa sizeof (struct ieee80211_frame) + sizeof(sc->sc_txtap)); 528184610Salfred 529188417Sthompsa sc->sc_rxtap_len = sizeof sc->sc_rxtap; 530188417Sthompsa sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); 531188417Sthompsa sc->sc_rxtap.wr_ihdr.it_present = htole32(RAL_RX_RADIOTAP_PRESENT); 532184610Salfred 533188417Sthompsa sc->sc_txtap_len = sizeof sc->sc_txtap; 534188417Sthompsa sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); 535188417Sthompsa sc->sc_txtap.wt_ihdr.it_present = htole32(RAL_TX_RADIOTAP_PRESENT); 536184610Salfred 537188417Sthompsa if (bootverbose) 538188417Sthompsa ieee80211_announce(ic); 539184610Salfred 540188419Sthompsa RAL_LOCK(sc); 541188417Sthompsa} 542184610Salfred 543188417Sthompsastatic int 544188417Sthompsaural_detach(device_t self) 545188417Sthompsa{ 546188417Sthompsa struct ural_softc *sc = device_get_softc(self); 547188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 548188619Sthompsa struct ieee80211com *ic; 549184610Salfred 550188419Sthompsa /* wait for any post attach or other command to complete */ 551188419Sthompsa usb2_proc_drain(&sc->sc_tq); 552184610Salfred 553188419Sthompsa /* stop all USB transfers */ 554188417Sthompsa usb2_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER); 555188417Sthompsa usb2_proc_free(&sc->sc_tq); 556184610Salfred 557188419Sthompsa /* free TX list, if any */ 558188419Sthompsa RAL_LOCK(sc); 559188419Sthompsa ural_unsetup_tx_list(sc); 560188419Sthompsa RAL_UNLOCK(sc); 561188419Sthompsa 562188417Sthompsa if (ifp) { 563188619Sthompsa ic = ifp->if_l2com; 564188417Sthompsa bpfdetach(ifp); 565188417Sthompsa ieee80211_ifdetach(ic); 566188417Sthompsa if_free(ifp); 567184610Salfred } 568189123Sthompsa cv_destroy(&sc->sc_cmd_cv); 569188417Sthompsa mtx_destroy(&sc->sc_mtx); 570184610Salfred 571188417Sthompsa return (0); 572184610Salfred} 573184610Salfred 574189123Sthompsastatic usb2_error_t 575189123Sthompsaural_do_request(struct ural_softc *sc, 576189123Sthompsa struct usb2_device_request *req, void *data) 577189123Sthompsa{ 578189123Sthompsa usb2_error_t err; 579189123Sthompsa int ntries = 10; 580189123Sthompsa 581189123Sthompsa while (ntries--) { 582189123Sthompsa err = usb2_do_request_proc(sc->sc_udev, &sc->sc_tq, 583189123Sthompsa req, data, 0, NULL, 250 /* ms */); 584189123Sthompsa if (err == 0) 585189123Sthompsa break; 586189123Sthompsa 587189123Sthompsa DPRINTFN(1, "Control request failed, %s (retrying)\n", 588189123Sthompsa usb2_errstr(err)); 589189123Sthompsa if (ural_pause(sc, hz / 100)) 590189123Sthompsa break; 591189123Sthompsa } 592189123Sthompsa return (err); 593189123Sthompsa} 594189123Sthompsa 595188417Sthompsastatic struct ieee80211vap * 596188417Sthompsaural_vap_create(struct ieee80211com *ic, 597188417Sthompsa const char name[IFNAMSIZ], int unit, int opmode, int flags, 598188417Sthompsa const uint8_t bssid[IEEE80211_ADDR_LEN], 599188417Sthompsa const uint8_t mac[IEEE80211_ADDR_LEN]) 600184610Salfred{ 601188417Sthompsa struct ural_softc *sc = ic->ic_ifp->if_softc; 602188417Sthompsa struct ural_vap *uvp; 603188417Sthompsa struct ieee80211vap *vap; 604184610Salfred 605188417Sthompsa if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ 606188417Sthompsa return NULL; 607188417Sthompsa uvp = (struct ural_vap *) malloc(sizeof(struct ural_vap), 608188417Sthompsa M_80211_VAP, M_NOWAIT | M_ZERO); 609188417Sthompsa if (uvp == NULL) 610188417Sthompsa return NULL; 611188417Sthompsa vap = &uvp->vap; 612188417Sthompsa /* enable s/w bmiss handling for sta mode */ 613188417Sthompsa ieee80211_vap_setup(ic, vap, name, unit, opmode, 614188417Sthompsa flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); 615184610Salfred 616188417Sthompsa /* override state transition machine */ 617188417Sthompsa uvp->newstate = vap->iv_newstate; 618188417Sthompsa vap->iv_newstate = ural_newstate; 619184610Salfred 620188417Sthompsa uvp->sc = sc; 621188417Sthompsa usb2_callout_init_mtx(&uvp->amrr_ch, &sc->sc_mtx, 0); 622188417Sthompsa ieee80211_amrr_init(&uvp->amrr, vap, 623188417Sthompsa IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, 624188417Sthompsa IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, 625188417Sthompsa 1000 /* 1 sec */); 626184610Salfred 627188417Sthompsa /* complete setup */ 628188417Sthompsa ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); 629188417Sthompsa ic->ic_opmode = opmode; 630188417Sthompsa return vap; 631184610Salfred} 632184610Salfred 633184610Salfredstatic void 634189123Sthompsaural_flush_task(struct usb2_proc_msg *pm) 635189123Sthompsa{ 636189123Sthompsa /* nothing to do */ 637189123Sthompsa} 638189123Sthompsa 639189123Sthompsastatic void 640188417Sthompsaural_vap_delete(struct ieee80211vap *vap) 641184610Salfred{ 642188417Sthompsa struct ural_vap *uvp = URAL_VAP(vap); 643189123Sthompsa struct ural_softc *sc = uvp->sc; 644184610Salfred 645189123Sthompsa RAL_LOCK(sc); 646189123Sthompsa /* wait for any pending tasks to complete */ 647189123Sthompsa ural_queue_command(sc, ural_flush_task, 648189123Sthompsa &sc->sc_synctask[0].hdr, 649189123Sthompsa &sc->sc_synctask[1].hdr); 650189123Sthompsa RAL_UNLOCK(sc); 651189123Sthompsa 652188419Sthompsa usb2_callout_drain(&uvp->amrr_ch); 653188417Sthompsa ieee80211_amrr_cleanup(&uvp->amrr); 654188417Sthompsa ieee80211_vap_detach(vap); 655188417Sthompsa free(uvp, M_80211_VAP); 656184610Salfred} 657184610Salfred 658184610Salfredstatic void 659188417Sthompsaural_tx_free(struct ural_tx_data *data, int txerr) 660184610Salfred{ 661188417Sthompsa struct ural_softc *sc = data->sc; 662184610Salfred 663188417Sthompsa if (data->m != NULL) { 664188417Sthompsa if (data->m->m_flags & M_TXCB) 665188417Sthompsa ieee80211_process_callback(data->ni, data->m, 666188417Sthompsa txerr ? ETIMEDOUT : 0); 667188417Sthompsa m_freem(data->m); 668188417Sthompsa data->m = NULL; 669184610Salfred 670188417Sthompsa ieee80211_free_node(data->ni); 671188417Sthompsa data->ni = NULL; 672188417Sthompsa } 673188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_free, data, next); 674188417Sthompsa sc->tx_nfree++; 675184610Salfred} 676184610Salfred 677188419Sthompsastatic void 678188419Sthompsaural_setup_tx_list(struct ural_softc *sc) 679184610Salfred{ 680188417Sthompsa struct ural_tx_data *data; 681188417Sthompsa int i; 682184610Salfred 683188417Sthompsa sc->tx_nfree = 0; 684188417Sthompsa STAILQ_INIT(&sc->tx_q); 685188417Sthompsa STAILQ_INIT(&sc->tx_free); 686184610Salfred 687188417Sthompsa for (i = 0; i < RAL_TX_LIST_COUNT; i++) { 688188417Sthompsa data = &sc->tx_data[i]; 689184610Salfred 690188417Sthompsa data->sc = sc; 691188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_free, data, next); 692188417Sthompsa sc->tx_nfree++; 693184610Salfred } 694184610Salfred} 695184610Salfred 696184610Salfredstatic void 697188419Sthompsaural_unsetup_tx_list(struct ural_softc *sc) 698184610Salfred{ 699188417Sthompsa struct ural_tx_data *data; 700188417Sthompsa int i; 701184610Salfred 702188419Sthompsa /* make sure any subsequent use of the queues will fail */ 703188419Sthompsa sc->tx_nfree = 0; 704188419Sthompsa STAILQ_INIT(&sc->tx_q); 705188419Sthompsa STAILQ_INIT(&sc->tx_free); 706184610Salfred 707188419Sthompsa /* free up all node references and mbufs */ 708188417Sthompsa for (i = 0; i < RAL_TX_LIST_COUNT; i++) { 709188417Sthompsa data = &sc->tx_data[i]; 710184610Salfred 711188417Sthompsa if (data->m != NULL) { 712188417Sthompsa m_freem(data->m); 713188417Sthompsa data->m = NULL; 714188417Sthompsa } 715188417Sthompsa if (data->ni != NULL) { 716188417Sthompsa ieee80211_free_node(data->ni); 717188417Sthompsa data->ni = NULL; 718188417Sthompsa } 719184610Salfred } 720184610Salfred} 721184610Salfred 722184610Salfredstatic void 723188417Sthompsaural_task(struct usb2_proc_msg *pm) 724184610Salfred{ 725188417Sthompsa struct ural_task *task = (struct ural_task *)pm; 726188417Sthompsa struct ural_softc *sc = task->sc; 727188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 728188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 729188417Sthompsa struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 730188417Sthompsa struct ural_vap *uvp = URAL_VAP(vap); 731188417Sthompsa const struct ieee80211_txparam *tp; 732188417Sthompsa enum ieee80211_state ostate; 733188417Sthompsa struct ieee80211_node *ni; 734188417Sthompsa struct mbuf *m; 735184610Salfred 736188417Sthompsa ostate = vap->iv_state; 737184610Salfred 738188417Sthompsa switch (sc->sc_state) { 739188417Sthompsa case IEEE80211_S_INIT: 740188417Sthompsa if (ostate == IEEE80211_S_RUN) { 741188417Sthompsa /* abort TSF synchronization */ 742188417Sthompsa ural_write(sc, RAL_TXRX_CSR19, 0); 743184610Salfred 744188417Sthompsa /* force tx led to stop blinking */ 745188417Sthompsa ural_write(sc, RAL_MAC_CSR20, 0); 746188417Sthompsa } 747188417Sthompsa break; 748184610Salfred 749188417Sthompsa case IEEE80211_S_RUN: 750188417Sthompsa ni = vap->iv_bss; 751188417Sthompsa 752188417Sthompsa if (vap->iv_opmode != IEEE80211_M_MONITOR) { 753188417Sthompsa ural_update_slot(ic->ic_ifp); 754188417Sthompsa ural_set_txpreamble(sc); 755188417Sthompsa ural_set_basicrates(sc, ic->ic_bsschan); 756188419Sthompsa IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); 757188419Sthompsa ural_set_bssid(sc, sc->sc_bssid); 758188417Sthompsa } 759188417Sthompsa 760188417Sthompsa if (vap->iv_opmode == IEEE80211_M_HOSTAP || 761188417Sthompsa vap->iv_opmode == IEEE80211_M_IBSS) { 762188417Sthompsa m = ieee80211_beacon_alloc(ni, &uvp->bo); 763188417Sthompsa if (m == NULL) { 764188417Sthompsa device_printf(sc->sc_dev, 765188417Sthompsa "could not allocate beacon\n"); 766188417Sthompsa return; 767184610Salfred } 768188417Sthompsa 769188417Sthompsa if (ural_tx_bcn(sc, m, ni) != 0) { 770188417Sthompsa device_printf(sc->sc_dev, 771188417Sthompsa "could not send beacon\n"); 772184610Salfred return; 773184610Salfred } 774184610Salfred } 775184610Salfred 776188417Sthompsa /* make tx led blink on tx (controlled by ASIC) */ 777188417Sthompsa ural_write(sc, RAL_MAC_CSR20, 1); 778184610Salfred 779188417Sthompsa if (vap->iv_opmode != IEEE80211_M_MONITOR) 780188417Sthompsa ural_enable_tsf_sync(sc); 781184610Salfred 782188417Sthompsa /* enable automatic rate adaptation */ 783188417Sthompsa tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)]; 784188417Sthompsa if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) 785188417Sthompsa ural_amrr_start(sc, ni); 786184610Salfred 787188417Sthompsa break; 788184610Salfred 789188417Sthompsa default: 790188417Sthompsa break; 791188417Sthompsa } 792184610Salfred 793188417Sthompsa RAL_UNLOCK(sc); 794188417Sthompsa IEEE80211_LOCK(ic); 795188417Sthompsa uvp->newstate(vap, sc->sc_state, sc->sc_arg); 796188417Sthompsa if (vap->iv_newstate_cb != NULL) 797188417Sthompsa vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg); 798188417Sthompsa IEEE80211_UNLOCK(ic); 799188417Sthompsa RAL_LOCK(sc); 800188417Sthompsa} 801184610Salfred 802188417Sthompsastatic void 803188417Sthompsaural_scantask(struct usb2_proc_msg *pm) 804188417Sthompsa{ 805188417Sthompsa struct ural_task *task = (struct ural_task *)pm; 806188417Sthompsa struct ural_softc *sc = task->sc; 807188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 808188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 809184610Salfred 810188417Sthompsa RAL_LOCK_ASSERT(sc, MA_OWNED); 811184610Salfred 812188419Sthompsa switch (sc->sc_scan_action) { 813188419Sthompsa case URAL_SCAN_START: 814188417Sthompsa /* abort TSF synchronization */ 815188417Sthompsa DPRINTF("starting scan\n"); 816188417Sthompsa ural_write(sc, RAL_TXRX_CSR19, 0); 817188417Sthompsa ural_set_bssid(sc, ifp->if_broadcastaddr); 818188419Sthompsa break; 819188419Sthompsa 820188419Sthompsa case URAL_SET_CHANNEL: 821188417Sthompsa ural_set_chan(sc, ic->ic_curchan); 822188419Sthompsa break; 823188419Sthompsa 824188419Sthompsa default: /* URAL_SCAN_END */ 825188417Sthompsa DPRINTF("stopping scan\n"); 826188417Sthompsa ural_enable_tsf_sync(sc); 827188419Sthompsa ural_set_bssid(sc, sc->sc_bssid); 828188419Sthompsa break; 829188419Sthompsa } 830188417Sthompsa} 831184610Salfred 832188417Sthompsastatic int 833188417Sthompsaural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 834188417Sthompsa{ 835188417Sthompsa struct ural_vap *uvp = URAL_VAP(vap); 836188417Sthompsa struct ieee80211com *ic = vap->iv_ic; 837188417Sthompsa struct ural_softc *sc = ic->ic_ifp->if_softc; 838184610Salfred 839188417Sthompsa DPRINTF("%s -> %s\n", 840188417Sthompsa ieee80211_state_name[vap->iv_state], 841188417Sthompsa ieee80211_state_name[nstate]); 842184610Salfred 843188417Sthompsa RAL_LOCK(sc); 844188417Sthompsa usb2_callout_stop(&uvp->amrr_ch); 845184610Salfred 846188417Sthompsa /* do it in a process context */ 847188417Sthompsa sc->sc_state = nstate; 848188417Sthompsa sc->sc_arg = arg; 849188417Sthompsa RAL_UNLOCK(sc); 850184610Salfred 851188417Sthompsa if (nstate == IEEE80211_S_INIT) { 852188417Sthompsa uvp->newstate(vap, nstate, arg); 853188417Sthompsa return 0; 854188417Sthompsa } else { 855188417Sthompsa RAL_LOCK(sc); 856188417Sthompsa ural_queue_command(sc, ural_task, &sc->sc_task[0].hdr, 857188417Sthompsa &sc->sc_task[1].hdr); 858188417Sthompsa RAL_UNLOCK(sc); 859188417Sthompsa return EINPROGRESS; 860184610Salfred } 861188417Sthompsa} 862184610Salfred 863184610Salfred 864188417Sthompsastatic void 865188417Sthompsaural_bulk_write_callback(struct usb2_xfer *xfer) 866188417Sthompsa{ 867188417Sthompsa struct ural_softc *sc = xfer->priv_sc; 868188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 869188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 870188417Sthompsa struct ieee80211_channel *c = ic->ic_curchan; 871188417Sthompsa struct ural_tx_data *data; 872188417Sthompsa struct mbuf *m; 873188419Sthompsa unsigned int len; 874184610Salfred 875189123Sthompsa /* wakeup waiting command, if any */ 876189123Sthompsa if (sc->sc_last_task != NULL) 877189123Sthompsa cv_signal(&sc->sc_cmd_cv); 878189123Sthompsa 879188417Sthompsa switch (USB_GET_STATE(xfer)) { 880188417Sthompsa case USB_ST_TRANSFERRED: 881188417Sthompsa DPRINTFN(11, "transfer complete, %d bytes\n", xfer->actlen); 882184610Salfred 883188417Sthompsa /* free resources */ 884188417Sthompsa data = xfer->priv_fifo; 885188417Sthompsa ural_tx_free(data, 0); 886188417Sthompsa xfer->priv_fifo = NULL; 887184610Salfred 888188417Sthompsa ifp->if_opackets++; 889188417Sthompsa ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 890184610Salfred 891188417Sthompsa /* FALLTHROUGH */ 892188417Sthompsa case USB_ST_SETUP: 893188417Sthompsatr_setup: 894189123Sthompsa /* wait for command to complete, if any */ 895189123Sthompsa if (sc->sc_last_task != NULL) 896189123Sthompsa break; 897189123Sthompsa 898188417Sthompsa data = STAILQ_FIRST(&sc->tx_q); 899188417Sthompsa if (data) { 900188417Sthompsa STAILQ_REMOVE_HEAD(&sc->tx_q, next); 901188417Sthompsa m = data->m; 902184610Salfred 903188417Sthompsa if (m->m_pkthdr.len > (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE)) { 904188417Sthompsa DPRINTFN(0, "data overflow, %u bytes\n", 905188417Sthompsa m->m_pkthdr.len); 906188417Sthompsa m->m_pkthdr.len = (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE); 907188417Sthompsa } 908188417Sthompsa usb2_copy_in(xfer->frbuffers, 0, &data->desc, 909188417Sthompsa RAL_TX_DESC_SIZE); 910188417Sthompsa usb2_m_copy_in(xfer->frbuffers, RAL_TX_DESC_SIZE, m, 0, 911188417Sthompsa m->m_pkthdr.len); 912184610Salfred 913188417Sthompsa if (bpf_peers_present(ifp->if_bpf)) { 914188417Sthompsa struct ural_tx_radiotap_header *tap = &sc->sc_txtap; 915184610Salfred 916188417Sthompsa tap->wt_flags = 0; 917188417Sthompsa tap->wt_rate = data->rate; 918188417Sthompsa tap->wt_chan_freq = htole16(c->ic_freq); 919188417Sthompsa tap->wt_chan_flags = htole16(c->ic_flags); 920188417Sthompsa tap->wt_antenna = sc->tx_ant; 921184610Salfred 922188417Sthompsa bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m); 923188417Sthompsa } 924184610Salfred 925188417Sthompsa /* xfer length needs to be a multiple of two! */ 926188417Sthompsa len = (RAL_TX_DESC_SIZE + m->m_pkthdr.len + 1) & ~1; 927188417Sthompsa if ((len % 64) == 0) 928188417Sthompsa len += 2; 929184610Salfred 930188417Sthompsa DPRINTFN(11, "sending frame len=%u xferlen=%u\n", 931188417Sthompsa m->m_pkthdr.len, len); 932184610Salfred 933188417Sthompsa xfer->frlengths[0] = len; 934188417Sthompsa xfer->priv_fifo = data; 935184610Salfred 936188417Sthompsa usb2_start_hardware(xfer); 937188417Sthompsa } 938188417Sthompsa break; 939184610Salfred 940188417Sthompsa default: /* Error */ 941188417Sthompsa DPRINTFN(11, "transfer error, %s\n", 942188417Sthompsa usb2_errstr(xfer->error)); 943184610Salfred 944188419Sthompsa ifp->if_oerrors++; 945188419Sthompsa data = xfer->priv_fifo; 946188419Sthompsa if (data != NULL) { 947188419Sthompsa ural_tx_free(data, xfer->error); 948188419Sthompsa xfer->priv_fifo = NULL; 949188419Sthompsa } 950188419Sthompsa 951188417Sthompsa if (xfer->error == USB_ERR_STALLED) { 952188417Sthompsa /* try to clear stall first */ 953188417Sthompsa xfer->flags.stall_pipe = 1; 954188417Sthompsa goto tr_setup; 955188417Sthompsa } 956188417Sthompsa if (xfer->error == USB_ERR_TIMEOUT) 957188417Sthompsa device_printf(sc->sc_dev, "device timeout\n"); 958188417Sthompsa break; 959184610Salfred } 960184610Salfred} 961184610Salfred 962184610Salfredstatic void 963184610Salfredural_bulk_read_callback(struct usb2_xfer *xfer) 964184610Salfred{ 965184610Salfred struct ural_softc *sc = xfer->priv_sc; 966184610Salfred struct ifnet *ifp = sc->sc_ifp; 967184610Salfred struct ieee80211com *ic = ifp->if_l2com; 968184610Salfred struct ieee80211_node *ni; 969184610Salfred struct mbuf *m = NULL; 970184610Salfred uint32_t flags; 971184610Salfred uint8_t rssi = 0; 972188419Sthompsa unsigned int len; 973184610Salfred 974184610Salfred switch (USB_GET_STATE(xfer)) { 975184610Salfred case USB_ST_TRANSFERRED: 976184610Salfred 977184610Salfred DPRINTFN(15, "rx done, actlen=%d\n", xfer->actlen); 978184610Salfred 979188417Sthompsa len = xfer->actlen; 980188417Sthompsa if (len < RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN) { 981188417Sthompsa DPRINTF("%s: xfer too short %d\n", 982188417Sthompsa device_get_nameunit(sc->sc_dev), len); 983184610Salfred ifp->if_ierrors++; 984184610Salfred goto tr_setup; 985184610Salfred } 986184610Salfred 987188417Sthompsa len -= RAL_RX_DESC_SIZE; 988188417Sthompsa /* rx descriptor is located at the end */ 989188417Sthompsa usb2_copy_out(xfer->frbuffers, len, &sc->sc_rx_desc, 990188417Sthompsa RAL_RX_DESC_SIZE); 991184610Salfred 992188417Sthompsa rssi = URAL_RSSI(sc->sc_rx_desc.rssi); 993184610Salfred flags = le32toh(sc->sc_rx_desc.flags); 994184610Salfred if (flags & (RAL_RX_PHY_ERROR | RAL_RX_CRC_ERROR)) { 995184610Salfred /* 996184610Salfred * This should not happen since we did not 997184610Salfred * request to receive those frames when we 998184610Salfred * filled RAL_TXRX_CSR2: 999184610Salfred */ 1000188417Sthompsa DPRINTFN(5, "PHY or CRC error\n"); 1001184610Salfred ifp->if_ierrors++; 1002184610Salfred goto tr_setup; 1003184610Salfred } 1004184610Salfred 1005184610Salfred m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 1006184610Salfred if (m == NULL) { 1007184610Salfred DPRINTF("could not allocate mbuf\n"); 1008184610Salfred ifp->if_ierrors++; 1009184610Salfred goto tr_setup; 1010184610Salfred } 1011188417Sthompsa usb2_copy_out(xfer->frbuffers, 0, mtod(m, uint8_t *), len); 1012184610Salfred 1013184610Salfred /* finalize mbuf */ 1014184610Salfred m->m_pkthdr.rcvif = ifp; 1015188417Sthompsa m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff; 1016184610Salfred 1017184610Salfred if (bpf_peers_present(ifp->if_bpf)) { 1018184610Salfred struct ural_rx_radiotap_header *tap = &sc->sc_rxtap; 1019184610Salfred 1020184610Salfred tap->wr_flags = IEEE80211_RADIOTAP_F_FCS; 1021184610Salfred tap->wr_rate = ieee80211_plcp2rate(sc->sc_rx_desc.rate, 1022188417Sthompsa (flags & RAL_RX_OFDM) ? 1023184610Salfred IEEE80211_T_OFDM : IEEE80211_T_CCK); 1024184610Salfred tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); 1025184610Salfred tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); 1026188417Sthompsa tap->wr_antenna = sc->rx_ant; 1027184610Salfred tap->wr_antsignal = rssi; 1028184610Salfred 1029184610Salfred bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m); 1030184610Salfred } 1031184610Salfred /* Strip trailing 802.11 MAC FCS. */ 1032184610Salfred m_adj(m, -IEEE80211_CRC_LEN); 1033184610Salfred 1034188417Sthompsa /* FALLTHROUGH */ 1035184610Salfred case USB_ST_SETUP: 1036184610Salfredtr_setup: 1037188417Sthompsa xfer->frlengths[0] = xfer->max_data_length; 1038188417Sthompsa usb2_start_hardware(xfer); 1039184610Salfred 1040184610Salfred /* 1041184610Salfred * At the end of a USB callback it is always safe to unlock 1042184610Salfred * the private mutex of a device! That is why we do the 1043184610Salfred * "ieee80211_input" here, and not some lines up! 1044184610Salfred */ 1045184610Salfred if (m) { 1046188417Sthompsa RAL_UNLOCK(sc); 1047188417Sthompsa ni = ieee80211_find_rxnode(ic, 1048188417Sthompsa mtod(m, struct ieee80211_frame_min *)); 1049188417Sthompsa if (ni != NULL) { 1050188417Sthompsa (void) ieee80211_input(ni, m, rssi, 1051188417Sthompsa RAL_NOISE_FLOOR, 0); 1052184610Salfred ieee80211_free_node(ni); 1053188417Sthompsa } else 1054188417Sthompsa (void) ieee80211_input_all(ic, m, rssi, 1055188417Sthompsa RAL_NOISE_FLOOR, 0); 1056188417Sthompsa RAL_LOCK(sc); 1057184610Salfred } 1058184610Salfred return; 1059184610Salfred 1060184610Salfred default: /* Error */ 1061184610Salfred if (xfer->error != USB_ERR_CANCELLED) { 1062184610Salfred /* try to clear stall first */ 1063188417Sthompsa xfer->flags.stall_pipe = 1; 1064188417Sthompsa goto tr_setup; 1065184610Salfred } 1066184610Salfred return; 1067184610Salfred } 1068184610Salfred} 1069184610Salfred 1070184610Salfredstatic uint8_t 1071188417Sthompsaural_plcp_signal(int rate) 1072184610Salfred{ 1073184610Salfred switch (rate) { 1074188417Sthompsa /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ 1075188417Sthompsa case 12: return 0xb; 1076188417Sthompsa case 18: return 0xf; 1077188417Sthompsa case 24: return 0xa; 1078188417Sthompsa case 36: return 0xe; 1079188417Sthompsa case 48: return 0x9; 1080188417Sthompsa case 72: return 0xd; 1081188417Sthompsa case 96: return 0x8; 1082188417Sthompsa case 108: return 0xc; 1083184610Salfred 1084188417Sthompsa /* CCK rates (NB: not IEEE std, device-specific) */ 1085188417Sthompsa case 2: return 0x0; 1086188417Sthompsa case 4: return 0x1; 1087188417Sthompsa case 11: return 0x2; 1088188417Sthompsa case 22: return 0x3; 1089184610Salfred } 1090188417Sthompsa return 0xff; /* XXX unsupported/unknown rate */ 1091184610Salfred} 1092184610Salfred 1093184610Salfredstatic void 1094188417Sthompsaural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc, 1095188417Sthompsa uint32_t flags, int len, int rate) 1096184610Salfred{ 1097184610Salfred struct ifnet *ifp = sc->sc_ifp; 1098184610Salfred struct ieee80211com *ic = ifp->if_l2com; 1099184610Salfred uint16_t plcp_length; 1100188417Sthompsa int remainder; 1101184610Salfred 1102188417Sthompsa desc->flags = htole32(flags); 1103188417Sthompsa desc->flags |= htole32(RAL_TX_NEWSEQ); 1104188417Sthompsa desc->flags |= htole32(len << 16); 1105184610Salfred 1106188417Sthompsa desc->wme = htole16(RAL_AIFSN(2) | RAL_LOGCWMIN(3) | RAL_LOGCWMAX(5)); 1107188417Sthompsa desc->wme |= htole16(RAL_IVOFFSET(sizeof (struct ieee80211_frame))); 1108184610Salfred 1109188417Sthompsa /* setup PLCP fields */ 1110188417Sthompsa desc->plcp_signal = ural_plcp_signal(rate); 1111188417Sthompsa desc->plcp_service = 4; 1112188417Sthompsa 1113188417Sthompsa len += IEEE80211_CRC_LEN; 1114188417Sthompsa if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) { 1115188417Sthompsa desc->flags |= htole32(RAL_TX_OFDM); 1116188417Sthompsa 1117188417Sthompsa plcp_length = len & 0xfff; 1118188417Sthompsa desc->plcp_length_hi = plcp_length >> 6; 1119188417Sthompsa desc->plcp_length_lo = plcp_length & 0x3f; 1120188417Sthompsa } else { 1121188417Sthompsa plcp_length = (16 * len + rate - 1) / rate; 1122188417Sthompsa if (rate == 22) { 1123188417Sthompsa remainder = (16 * len) % 22; 1124188417Sthompsa if (remainder != 0 && remainder < 7) 1125188417Sthompsa desc->plcp_service |= RAL_PLCP_LENGEXT; 1126188417Sthompsa } 1127188417Sthompsa desc->plcp_length_hi = plcp_length >> 8; 1128188417Sthompsa desc->plcp_length_lo = plcp_length & 0xff; 1129188417Sthompsa 1130188417Sthompsa if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 1131188417Sthompsa desc->plcp_signal |= 0x08; 1132184610Salfred } 1133184610Salfred 1134188417Sthompsa desc->iv = 0; 1135188417Sthompsa desc->eiv = 0; 1136188417Sthompsa} 1137184610Salfred 1138188417Sthompsa#define RAL_TX_TIMEOUT 5000 1139184610Salfred 1140188417Sthompsastatic int 1141188417Sthompsaural_tx_bcn(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) 1142188417Sthompsa{ 1143188417Sthompsa struct ieee80211vap *vap = ni->ni_vap; 1144188417Sthompsa struct ieee80211com *ic = ni->ni_ic; 1145188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 1146188417Sthompsa const struct ieee80211_txparam *tp; 1147188417Sthompsa struct ural_tx_data *data; 1148188417Sthompsa 1149188417Sthompsa if (sc->tx_nfree == 0) { 1150188417Sthompsa ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1151188417Sthompsa m_freem(m0); 1152188417Sthompsa ieee80211_free_node(ni); 1153188417Sthompsa return EIO; 1154184610Salfred } 1155188417Sthompsa data = STAILQ_FIRST(&sc->tx_free); 1156188417Sthompsa STAILQ_REMOVE_HEAD(&sc->tx_free, next); 1157188417Sthompsa sc->tx_nfree--; 1158188417Sthompsa tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)]; 1159184610Salfred 1160188417Sthompsa data->m = m0; 1161188417Sthompsa data->ni = ni; 1162188417Sthompsa data->rate = tp->mgmtrate; 1163184610Salfred 1164188417Sthompsa ural_setup_tx_desc(sc, &data->desc, 1165188417Sthompsa RAL_TX_IFS_NEWBACKOFF | RAL_TX_TIMESTAMP, m0->m_pkthdr.len, 1166188417Sthompsa tp->mgmtrate); 1167184610Salfred 1168188417Sthompsa DPRINTFN(10, "sending beacon frame len=%u rate=%u\n", 1169188417Sthompsa m0->m_pkthdr.len, tp->mgmtrate); 1170184610Salfred 1171188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_q, data, next); 1172188417Sthompsa usb2_transfer_start(sc->sc_xfer[URAL_BULK_WR]); 1173184610Salfred 1174188417Sthompsa return (0); 1175188417Sthompsa} 1176184610Salfred 1177188417Sthompsastatic int 1178188417Sthompsaural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) 1179188417Sthompsa{ 1180188417Sthompsa struct ieee80211vap *vap = ni->ni_vap; 1181188417Sthompsa struct ieee80211com *ic = ni->ni_ic; 1182188417Sthompsa const struct ieee80211_txparam *tp; 1183188417Sthompsa struct ural_tx_data *data; 1184188417Sthompsa struct ieee80211_frame *wh; 1185188417Sthompsa struct ieee80211_key *k; 1186188417Sthompsa uint32_t flags; 1187188417Sthompsa uint16_t dur; 1188184610Salfred 1189188417Sthompsa RAL_LOCK_ASSERT(sc, MA_OWNED); 1190184610Salfred 1191188417Sthompsa data = STAILQ_FIRST(&sc->tx_free); 1192188417Sthompsa STAILQ_REMOVE_HEAD(&sc->tx_free, next); 1193188417Sthompsa sc->tx_nfree--; 1194184610Salfred 1195188417Sthompsa tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; 1196188417Sthompsa 1197188417Sthompsa wh = mtod(m0, struct ieee80211_frame *); 1198188417Sthompsa if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 1199188417Sthompsa k = ieee80211_crypto_encap(ni, m0); 1200188417Sthompsa if (k == NULL) { 1201188417Sthompsa m_freem(m0); 1202188417Sthompsa return ENOBUFS; 1203184610Salfred } 1204188417Sthompsa wh = mtod(m0, struct ieee80211_frame *); 1205184610Salfred } 1206184610Salfred 1207188417Sthompsa data->m = m0; 1208188417Sthompsa data->ni = ni; 1209188417Sthompsa data->rate = tp->mgmtrate; 1210184610Salfred 1211188417Sthompsa flags = 0; 1212188417Sthompsa if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 1213188417Sthompsa flags |= RAL_TX_ACK; 1214188417Sthompsa 1215188417Sthompsa dur = ieee80211_ack_duration(sc->sc_rates, tp->mgmtrate, 1216188417Sthompsa ic->ic_flags & IEEE80211_F_SHPREAMBLE); 1217188417Sthompsa *(uint16_t *)wh->i_dur = htole16(dur); 1218188417Sthompsa 1219188417Sthompsa /* tell hardware to add timestamp for probe responses */ 1220188417Sthompsa if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 1221188417Sthompsa IEEE80211_FC0_TYPE_MGT && 1222188417Sthompsa (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 1223188417Sthompsa IEEE80211_FC0_SUBTYPE_PROBE_RESP) 1224188417Sthompsa flags |= RAL_TX_TIMESTAMP; 1225184610Salfred } 1226184610Salfred 1227188417Sthompsa ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, tp->mgmtrate); 1228184610Salfred 1229188417Sthompsa DPRINTFN(10, "sending mgt frame len=%u rate=%u\n", 1230188417Sthompsa m0->m_pkthdr.len, tp->mgmtrate); 1231184610Salfred 1232188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_q, data, next); 1233188417Sthompsa usb2_transfer_start(sc->sc_xfer[URAL_BULK_WR]); 1234184610Salfred 1235188417Sthompsa return 0; 1236184610Salfred} 1237184610Salfred 1238188417Sthompsastatic int 1239188417Sthompsaural_sendprot(struct ural_softc *sc, 1240188417Sthompsa const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate) 1241184610Salfred{ 1242188417Sthompsa struct ieee80211com *ic = ni->ni_ic; 1243188417Sthompsa const struct ieee80211_frame *wh; 1244188417Sthompsa struct ural_tx_data *data; 1245188417Sthompsa struct mbuf *mprot; 1246188417Sthompsa int protrate, ackrate, pktlen, flags, isshort; 1247188417Sthompsa uint16_t dur; 1248184610Salfred 1249188417Sthompsa KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY, 1250188417Sthompsa ("protection %d", prot)); 1251184610Salfred 1252188417Sthompsa wh = mtod(m, const struct ieee80211_frame *); 1253188417Sthompsa pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN; 1254184610Salfred 1255188417Sthompsa protrate = ieee80211_ctl_rate(sc->sc_rates, rate); 1256188417Sthompsa ackrate = ieee80211_ack_rate(sc->sc_rates, rate); 1257188417Sthompsa 1258188417Sthompsa isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; 1259188417Sthompsa dur = ieee80211_compute_duration(sc->sc_rates, pktlen, rate, isshort); 1260188417Sthompsa + ieee80211_ack_duration(sc->sc_rates, rate, isshort); 1261188417Sthompsa flags = RAL_TX_RETRY(7); 1262188417Sthompsa if (prot == IEEE80211_PROT_RTSCTS) { 1263188417Sthompsa /* NB: CTS is the same size as an ACK */ 1264188417Sthompsa dur += ieee80211_ack_duration(sc->sc_rates, rate, isshort); 1265188417Sthompsa flags |= RAL_TX_ACK; 1266188417Sthompsa mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur); 1267188417Sthompsa } else { 1268188417Sthompsa mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur); 1269188417Sthompsa } 1270188417Sthompsa if (mprot == NULL) { 1271188417Sthompsa /* XXX stat + msg */ 1272188417Sthompsa return ENOBUFS; 1273188417Sthompsa } 1274188417Sthompsa data = STAILQ_FIRST(&sc->tx_free); 1275188417Sthompsa STAILQ_REMOVE_HEAD(&sc->tx_free, next); 1276188417Sthompsa sc->tx_nfree--; 1277188417Sthompsa 1278188417Sthompsa data->m = mprot; 1279188417Sthompsa data->ni = ieee80211_ref_node(ni); 1280188417Sthompsa data->rate = protrate; 1281188417Sthompsa ural_setup_tx_desc(sc, &data->desc, flags, mprot->m_pkthdr.len, protrate); 1282188417Sthompsa 1283188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_q, data, next); 1284188417Sthompsa usb2_transfer_start(sc->sc_xfer[URAL_BULK_WR]); 1285188417Sthompsa 1286188417Sthompsa return 0; 1287188417Sthompsa} 1288188417Sthompsa 1289188417Sthompsastatic int 1290188417Sthompsaural_tx_raw(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, 1291188417Sthompsa const struct ieee80211_bpf_params *params) 1292188417Sthompsa{ 1293188417Sthompsa struct ural_tx_data *data; 1294188417Sthompsa uint32_t flags; 1295188417Sthompsa int error; 1296188417Sthompsa int rate; 1297188417Sthompsa 1298188417Sthompsa RAL_LOCK_ASSERT(sc, MA_OWNED); 1299188417Sthompsa KASSERT(params != NULL, ("no raw xmit params")); 1300188417Sthompsa 1301188417Sthompsa rate = params->ibp_rate0 & IEEE80211_RATE_VAL; 1302188417Sthompsa /* XXX validate */ 1303188417Sthompsa if (rate == 0) { 1304188417Sthompsa m_freem(m0); 1305188417Sthompsa return EINVAL; 1306188417Sthompsa } 1307188417Sthompsa flags = 0; 1308188417Sthompsa if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) 1309188417Sthompsa flags |= RAL_TX_ACK; 1310188417Sthompsa if (params->ibp_flags & (IEEE80211_BPF_RTS|IEEE80211_BPF_CTS)) { 1311188417Sthompsa error = ural_sendprot(sc, m0, ni, 1312188417Sthompsa params->ibp_flags & IEEE80211_BPF_RTS ? 1313188417Sthompsa IEEE80211_PROT_RTSCTS : IEEE80211_PROT_CTSONLY, 1314188417Sthompsa rate); 1315188969Sthompsa if (error || sc->tx_nfree == 0) { 1316188417Sthompsa m_freem(m0); 1317188969Sthompsa return ENOBUFS; 1318184610Salfred } 1319188417Sthompsa flags |= RAL_TX_IFS_SIFS; 1320188417Sthompsa } 1321184610Salfred 1322188969Sthompsa data = STAILQ_FIRST(&sc->tx_free); 1323188969Sthompsa STAILQ_REMOVE_HEAD(&sc->tx_free, next); 1324188969Sthompsa sc->tx_nfree--; 1325188969Sthompsa 1326188417Sthompsa data->m = m0; 1327188417Sthompsa data->ni = ni; 1328188417Sthompsa data->rate = rate; 1329184610Salfred 1330188417Sthompsa /* XXX need to setup descriptor ourself */ 1331188417Sthompsa ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate); 1332184610Salfred 1333188417Sthompsa DPRINTFN(10, "sending raw frame len=%u rate=%u\n", 1334188417Sthompsa m0->m_pkthdr.len, rate); 1335184610Salfred 1336188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_q, data, next); 1337188417Sthompsa usb2_transfer_start(sc->sc_xfer[URAL_BULK_WR]); 1338184610Salfred 1339188417Sthompsa return 0; 1340188417Sthompsa} 1341184610Salfred 1342188417Sthompsastatic int 1343188417Sthompsaural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) 1344188417Sthompsa{ 1345188417Sthompsa struct ieee80211vap *vap = ni->ni_vap; 1346188417Sthompsa struct ieee80211com *ic = ni->ni_ic; 1347188417Sthompsa struct ural_tx_data *data; 1348188417Sthompsa struct ieee80211_frame *wh; 1349188417Sthompsa const struct ieee80211_txparam *tp; 1350188417Sthompsa struct ieee80211_key *k; 1351188417Sthompsa uint32_t flags = 0; 1352188417Sthompsa uint16_t dur; 1353188417Sthompsa int error, rate; 1354184610Salfred 1355188417Sthompsa RAL_LOCK_ASSERT(sc, MA_OWNED); 1356184610Salfred 1357188417Sthompsa wh = mtod(m0, struct ieee80211_frame *); 1358184610Salfred 1359188417Sthompsa tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; 1360188417Sthompsa if (IEEE80211_IS_MULTICAST(wh->i_addr1)) 1361188417Sthompsa rate = tp->mcastrate; 1362188417Sthompsa else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) 1363188417Sthompsa rate = tp->ucastrate; 1364188417Sthompsa else 1365188417Sthompsa rate = ni->ni_txrate; 1366188417Sthompsa 1367188417Sthompsa if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 1368188417Sthompsa k = ieee80211_crypto_encap(ni, m0); 1369188417Sthompsa if (k == NULL) { 1370188417Sthompsa m_freem(m0); 1371188417Sthompsa return ENOBUFS; 1372184610Salfred } 1373188417Sthompsa /* packet header may have moved, reset our local pointer */ 1374188417Sthompsa wh = mtod(m0, struct ieee80211_frame *); 1375188417Sthompsa } 1376184610Salfred 1377188417Sthompsa if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 1378188417Sthompsa int prot = IEEE80211_PROT_NONE; 1379188417Sthompsa if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) 1380188417Sthompsa prot = IEEE80211_PROT_RTSCTS; 1381188417Sthompsa else if ((ic->ic_flags & IEEE80211_F_USEPROT) && 1382188417Sthompsa ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) 1383188417Sthompsa prot = ic->ic_protmode; 1384188417Sthompsa if (prot != IEEE80211_PROT_NONE) { 1385188417Sthompsa error = ural_sendprot(sc, m0, ni, prot, rate); 1386188969Sthompsa if (error || sc->tx_nfree == 0) { 1387188417Sthompsa m_freem(m0); 1388188969Sthompsa return ENOBUFS; 1389188417Sthompsa } 1390188417Sthompsa flags |= RAL_TX_IFS_SIFS; 1391184610Salfred } 1392184610Salfred } 1393184610Salfred 1394188417Sthompsa data = STAILQ_FIRST(&sc->tx_free); 1395188417Sthompsa STAILQ_REMOVE_HEAD(&sc->tx_free, next); 1396188417Sthompsa sc->tx_nfree--; 1397184610Salfred 1398188417Sthompsa data->m = m0; 1399188417Sthompsa data->ni = ni; 1400188417Sthompsa data->rate = rate; 1401188417Sthompsa 1402188417Sthompsa if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 1403188417Sthompsa flags |= RAL_TX_ACK; 1404188417Sthompsa flags |= RAL_TX_RETRY(7); 1405188417Sthompsa 1406188417Sthompsa dur = ieee80211_ack_duration(sc->sc_rates, rate, 1407188417Sthompsa ic->ic_flags & IEEE80211_F_SHPREAMBLE); 1408188417Sthompsa *(uint16_t *)wh->i_dur = htole16(dur); 1409184610Salfred } 1410184610Salfred 1411188417Sthompsa ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate); 1412184610Salfred 1413188417Sthompsa DPRINTFN(10, "sending data frame len=%u rate=%u\n", 1414188417Sthompsa m0->m_pkthdr.len, rate); 1415184610Salfred 1416188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_q, data, next); 1417188417Sthompsa usb2_transfer_start(sc->sc_xfer[URAL_BULK_WR]); 1418188417Sthompsa 1419188417Sthompsa return 0; 1420184610Salfred} 1421184610Salfred 1422184610Salfredstatic void 1423188417Sthompsaural_start(struct ifnet *ifp) 1424184610Salfred{ 1425188417Sthompsa struct ural_softc *sc = ifp->if_softc; 1426188417Sthompsa struct ieee80211_node *ni; 1427188417Sthompsa struct mbuf *m; 1428184610Salfred 1429188417Sthompsa RAL_LOCK(sc); 1430188417Sthompsa if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1431188417Sthompsa RAL_UNLOCK(sc); 1432188417Sthompsa return; 1433188417Sthompsa } 1434188417Sthompsa for (;;) { 1435188417Sthompsa IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 1436188417Sthompsa if (m == NULL) 1437188417Sthompsa break; 1438188969Sthompsa if (sc->tx_nfree < RAL_TX_MINFREE) { 1439188417Sthompsa IFQ_DRV_PREPEND(&ifp->if_snd, m); 1440188417Sthompsa ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1441188417Sthompsa break; 1442188417Sthompsa } 1443188417Sthompsa ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; 1444188417Sthompsa m = ieee80211_encap(ni, m); 1445188417Sthompsa if (m == NULL) { 1446188417Sthompsa ieee80211_free_node(ni); 1447189123Sthompsa ifp->if_oerrors++; 1448188417Sthompsa continue; 1449188417Sthompsa } 1450188417Sthompsa if (ural_tx_data(sc, m, ni) != 0) { 1451188417Sthompsa ieee80211_free_node(ni); 1452188417Sthompsa ifp->if_oerrors++; 1453188417Sthompsa break; 1454188417Sthompsa } 1455188417Sthompsa } 1456188417Sthompsa RAL_UNLOCK(sc); 1457184610Salfred} 1458184610Salfred 1459184610Salfredstatic int 1460188417Sthompsaural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1461184610Salfred{ 1462184610Salfred struct ural_softc *sc = ifp->if_softc; 1463184610Salfred struct ieee80211com *ic = ifp->if_l2com; 1464188417Sthompsa struct ifreq *ifr = (struct ifreq *) data; 1465188417Sthompsa int error = 0, startall = 0; 1466184610Salfred 1467184610Salfred switch (cmd) { 1468184610Salfred case SIOCSIFFLAGS: 1469188417Sthompsa RAL_LOCK(sc); 1470184610Salfred if (ifp->if_flags & IFF_UP) { 1471188417Sthompsa if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1472188419Sthompsa ural_queue_command(sc, ural_init_task, 1473188419Sthompsa &sc->sc_synctask[0].hdr, 1474188419Sthompsa &sc->sc_synctask[1].hdr); 1475188417Sthompsa startall = 1; 1476188417Sthompsa } else 1477188417Sthompsa ural_queue_command(sc, ural_promisctask, 1478188417Sthompsa &sc->sc_promisctask[0].hdr, 1479188417Sthompsa &sc->sc_promisctask[1].hdr); 1480184610Salfred } else { 1481188419Sthompsa if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1482188419Sthompsa ural_queue_command(sc, ural_stop_task, 1483188419Sthompsa &sc->sc_synctask[0].hdr, 1484188419Sthompsa &sc->sc_synctask[1].hdr); 1485188419Sthompsa } 1486184610Salfred } 1487188417Sthompsa RAL_UNLOCK(sc); 1488188417Sthompsa if (startall) 1489188417Sthompsa ieee80211_start_all(ic); 1490184610Salfred break; 1491184610Salfred case SIOCGIFMEDIA: 1492184610Salfred case SIOCSIFMEDIA: 1493188417Sthompsa error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); 1494184610Salfred break; 1495184610Salfred default: 1496184610Salfred error = ether_ioctl(ifp, cmd, data); 1497188417Sthompsa break; 1498184610Salfred } 1499188417Sthompsa return error; 1500184610Salfred} 1501184610Salfred 1502184610Salfredstatic void 1503188417Sthompsaural_set_testmode(struct ural_softc *sc) 1504184610Salfred{ 1505188417Sthompsa struct usb2_device_request req; 1506188417Sthompsa usb2_error_t error; 1507184610Salfred 1508188417Sthompsa req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1509188417Sthompsa req.bRequest = RAL_VENDOR_REQUEST; 1510188417Sthompsa USETW(req.wValue, 4); 1511188417Sthompsa USETW(req.wIndex, 1); 1512188417Sthompsa USETW(req.wLength, 0); 1513188417Sthompsa 1514188419Sthompsa error = ural_do_request(sc, &req, NULL); 1515188417Sthompsa if (error != 0) { 1516188417Sthompsa device_printf(sc->sc_dev, "could not set test mode: %s\n", 1517188417Sthompsa usb2_errstr(error)); 1518188417Sthompsa } 1519184610Salfred} 1520184610Salfred 1521184610Salfredstatic void 1522188417Sthompsaural_eeprom_read(struct ural_softc *sc, uint16_t addr, void *buf, int len) 1523184610Salfred{ 1524188417Sthompsa struct usb2_device_request req; 1525188417Sthompsa usb2_error_t error; 1526184610Salfred 1527188417Sthompsa req.bmRequestType = UT_READ_VENDOR_DEVICE; 1528188417Sthompsa req.bRequest = RAL_READ_EEPROM; 1529188417Sthompsa USETW(req.wValue, 0); 1530188417Sthompsa USETW(req.wIndex, addr); 1531188417Sthompsa USETW(req.wLength, len); 1532184610Salfred 1533188419Sthompsa error = ural_do_request(sc, &req, buf); 1534188417Sthompsa if (error != 0) { 1535188417Sthompsa device_printf(sc->sc_dev, "could not read EEPROM: %s\n", 1536188417Sthompsa usb2_errstr(error)); 1537184610Salfred } 1538188417Sthompsa} 1539184610Salfred 1540188417Sthompsastatic uint16_t 1541188417Sthompsaural_read(struct ural_softc *sc, uint16_t reg) 1542188417Sthompsa{ 1543188417Sthompsa struct usb2_device_request req; 1544188417Sthompsa usb2_error_t error; 1545188417Sthompsa uint16_t val; 1546184610Salfred 1547188417Sthompsa req.bmRequestType = UT_READ_VENDOR_DEVICE; 1548188417Sthompsa req.bRequest = RAL_READ_MAC; 1549188417Sthompsa USETW(req.wValue, 0); 1550188417Sthompsa USETW(req.wIndex, reg); 1551188417Sthompsa USETW(req.wLength, sizeof (uint16_t)); 1552188417Sthompsa 1553188419Sthompsa error = ural_do_request(sc, &req, &val); 1554188417Sthompsa if (error != 0) { 1555188417Sthompsa device_printf(sc->sc_dev, "could not read MAC register: %s\n", 1556188417Sthompsa usb2_errstr(error)); 1557188417Sthompsa return 0; 1558184610Salfred } 1559184610Salfred 1560188417Sthompsa return le16toh(val); 1561184610Salfred} 1562184610Salfred 1563188417Sthompsastatic void 1564188417Sthompsaural_read_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len) 1565184610Salfred{ 1566188417Sthompsa struct usb2_device_request req; 1567188417Sthompsa usb2_error_t error; 1568184610Salfred 1569188417Sthompsa req.bmRequestType = UT_READ_VENDOR_DEVICE; 1570188417Sthompsa req.bRequest = RAL_READ_MULTI_MAC; 1571188417Sthompsa USETW(req.wValue, 0); 1572188417Sthompsa USETW(req.wIndex, reg); 1573188417Sthompsa USETW(req.wLength, len); 1574184610Salfred 1575188419Sthompsa error = ural_do_request(sc, &req, buf); 1576188417Sthompsa if (error != 0) { 1577188417Sthompsa device_printf(sc->sc_dev, "could not read MAC register: %s\n", 1578188417Sthompsa usb2_errstr(error)); 1579184610Salfred } 1580188417Sthompsa} 1581188417Sthompsa 1582188417Sthompsastatic void 1583188417Sthompsaural_write(struct ural_softc *sc, uint16_t reg, uint16_t val) 1584188417Sthompsa{ 1585188417Sthompsa struct usb2_device_request req; 1586188417Sthompsa usb2_error_t error; 1587188417Sthompsa 1588188417Sthompsa req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1589188417Sthompsa req.bRequest = RAL_WRITE_MAC; 1590188417Sthompsa USETW(req.wValue, val); 1591188417Sthompsa USETW(req.wIndex, reg); 1592188417Sthompsa USETW(req.wLength, 0); 1593188417Sthompsa 1594188419Sthompsa error = ural_do_request(sc, &req, NULL); 1595188417Sthompsa if (error != 0) { 1596188417Sthompsa device_printf(sc->sc_dev, "could not write MAC register: %s\n", 1597188417Sthompsa usb2_errstr(error)); 1598184610Salfred } 1599188417Sthompsa} 1600184610Salfred 1601188417Sthompsastatic void 1602188417Sthompsaural_write_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len) 1603188417Sthompsa{ 1604188417Sthompsa struct usb2_device_request req; 1605188417Sthompsa usb2_error_t error; 1606184610Salfred 1607188417Sthompsa req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 1608188417Sthompsa req.bRequest = RAL_WRITE_MULTI_MAC; 1609188417Sthompsa USETW(req.wValue, 0); 1610188417Sthompsa USETW(req.wIndex, reg); 1611188417Sthompsa USETW(req.wLength, len); 1612184610Salfred 1613188419Sthompsa error = ural_do_request(sc, &req, buf); 1614188417Sthompsa if (error != 0) { 1615188417Sthompsa device_printf(sc->sc_dev, "could not write MAC register: %s\n", 1616188417Sthompsa usb2_errstr(error)); 1617188417Sthompsa } 1618184610Salfred} 1619184610Salfred 1620184610Salfredstatic void 1621188417Sthompsaural_bbp_write(struct ural_softc *sc, uint8_t reg, uint8_t val) 1622184610Salfred{ 1623188417Sthompsa uint16_t tmp; 1624188417Sthompsa int ntries; 1625184610Salfred 1626188619Sthompsa for (ntries = 0; ntries < 100; ntries++) { 1627188417Sthompsa if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY)) 1628188417Sthompsa break; 1629188619Sthompsa if (ural_pause(sc, hz / 100)) 1630188619Sthompsa break; 1631188417Sthompsa } 1632188619Sthompsa if (ntries == 100) { 1633188417Sthompsa device_printf(sc->sc_dev, "could not write to BBP\n"); 1634188417Sthompsa return; 1635188417Sthompsa } 1636184610Salfred 1637188417Sthompsa tmp = reg << 8 | val; 1638188417Sthompsa ural_write(sc, RAL_PHY_CSR7, tmp); 1639188417Sthompsa} 1640184610Salfred 1641188417Sthompsastatic uint8_t 1642188417Sthompsaural_bbp_read(struct ural_softc *sc, uint8_t reg) 1643188417Sthompsa{ 1644188417Sthompsa uint16_t val; 1645188417Sthompsa int ntries; 1646184610Salfred 1647188417Sthompsa val = RAL_BBP_WRITE | reg << 8; 1648188417Sthompsa ural_write(sc, RAL_PHY_CSR7, val); 1649188417Sthompsa 1650188619Sthompsa for (ntries = 0; ntries < 100; ntries++) { 1651188417Sthompsa if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY)) 1652188417Sthompsa break; 1653188619Sthompsa if (ural_pause(sc, hz / 100)) 1654188619Sthompsa break; 1655188417Sthompsa } 1656188619Sthompsa if (ntries == 100) { 1657188417Sthompsa device_printf(sc->sc_dev, "could not read BBP\n"); 1658188417Sthompsa return 0; 1659188417Sthompsa } 1660188417Sthompsa 1661188417Sthompsa return ural_read(sc, RAL_PHY_CSR7) & 0xff; 1662184610Salfred} 1663184610Salfred 1664184610Salfredstatic void 1665188417Sthompsaural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val) 1666184610Salfred{ 1667188417Sthompsa uint32_t tmp; 1668188417Sthompsa int ntries; 1669188417Sthompsa 1670188619Sthompsa for (ntries = 0; ntries < 100; ntries++) { 1671188417Sthompsa if (!(ural_read(sc, RAL_PHY_CSR10) & RAL_RF_LOBUSY)) 1672188417Sthompsa break; 1673188619Sthompsa if (ural_pause(sc, hz / 100)) 1674188619Sthompsa break; 1675188417Sthompsa } 1676188619Sthompsa if (ntries == 100) { 1677188417Sthompsa device_printf(sc->sc_dev, "could not write to RF\n"); 1678188417Sthompsa return; 1679188417Sthompsa } 1680188417Sthompsa 1681188417Sthompsa tmp = RAL_RF_BUSY | RAL_RF_20BIT | (val & 0xfffff) << 2 | (reg & 0x3); 1682188417Sthompsa ural_write(sc, RAL_PHY_CSR9, tmp & 0xffff); 1683188417Sthompsa ural_write(sc, RAL_PHY_CSR10, tmp >> 16); 1684188417Sthompsa 1685188417Sthompsa /* remember last written value in sc */ 1686188417Sthompsa sc->rf_regs[reg] = val; 1687188417Sthompsa 1688188417Sthompsa DPRINTFN(15, "RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff); 1689184610Salfred} 1690184610Salfred 1691188417Sthompsa/* ARGUSED */ 1692188417Sthompsastatic struct ieee80211_node * 1693188417Sthompsaural_node_alloc(struct ieee80211vap *vap __unused, 1694188417Sthompsa const uint8_t mac[IEEE80211_ADDR_LEN] __unused) 1695188417Sthompsa{ 1696188417Sthompsa struct ural_node *un; 1697188417Sthompsa 1698188417Sthompsa un = malloc(sizeof(struct ural_node), M_80211_NODE, M_NOWAIT | M_ZERO); 1699188417Sthompsa return un != NULL ? &un->ni : NULL; 1700188417Sthompsa} 1701188417Sthompsa 1702184610Salfredstatic void 1703188417Sthompsaural_newassoc(struct ieee80211_node *ni, int isnew) 1704184610Salfred{ 1705188417Sthompsa struct ieee80211vap *vap = ni->ni_vap; 1706188417Sthompsa 1707188417Sthompsa ieee80211_amrr_node_init(&URAL_VAP(vap)->amrr, &URAL_NODE(ni)->amn, ni); 1708184610Salfred} 1709184610Salfred 1710184610Salfredstatic void 1711188417Sthompsaural_scan_start(struct ieee80211com *ic) 1712184610Salfred{ 1713188417Sthompsa struct ural_softc *sc = ic->ic_ifp->if_softc; 1714188417Sthompsa 1715188417Sthompsa RAL_LOCK(sc); 1716188417Sthompsa /* do it in a process context */ 1717188417Sthompsa sc->sc_scan_action = URAL_SCAN_START; 1718188417Sthompsa ural_queue_command(sc, ural_scantask, 1719188417Sthompsa &sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr); 1720188417Sthompsa RAL_UNLOCK(sc); 1721188417Sthompsa 1722184610Salfred} 1723184610Salfred 1724184610Salfredstatic void 1725188417Sthompsaural_scan_end(struct ieee80211com *ic) 1726184610Salfred{ 1727188417Sthompsa struct ural_softc *sc = ic->ic_ifp->if_softc; 1728188417Sthompsa 1729188417Sthompsa RAL_LOCK(sc); 1730188417Sthompsa /* do it in a process context */ 1731188417Sthompsa sc->sc_scan_action = URAL_SCAN_END; 1732188417Sthompsa ural_queue_command(sc, ural_scantask, 1733188417Sthompsa &sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr); 1734188417Sthompsa RAL_UNLOCK(sc); 1735188417Sthompsa 1736184610Salfred} 1737184610Salfred 1738184610Salfredstatic void 1739188417Sthompsaural_set_channel(struct ieee80211com *ic) 1740184610Salfred{ 1741188417Sthompsa struct ural_softc *sc = ic->ic_ifp->if_softc; 1742188417Sthompsa 1743188417Sthompsa RAL_LOCK(sc); 1744188417Sthompsa /* do it in a process context */ 1745188417Sthompsa sc->sc_scan_action = URAL_SET_CHANNEL; 1746188417Sthompsa ural_queue_command(sc, ural_scantask, 1747188417Sthompsa &sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr); 1748188417Sthompsa 1749188417Sthompsa sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan); 1750188417Sthompsa RAL_UNLOCK(sc); 1751184610Salfred} 1752184610Salfred 1753184610Salfredstatic void 1754188417Sthompsaural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c) 1755184610Salfred{ 1756188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 1757188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 1758188417Sthompsa uint8_t power, tmp; 1759188619Sthompsa int i, chan; 1760184610Salfred 1761188417Sthompsa chan = ieee80211_chan2ieee(ic, c); 1762188417Sthompsa if (chan == 0 || chan == IEEE80211_CHAN_ANY) 1763188417Sthompsa return; 1764184610Salfred 1765188417Sthompsa if (IEEE80211_IS_CHAN_2GHZ(c)) 1766188417Sthompsa power = min(sc->txpow[chan - 1], 31); 1767184610Salfred else 1768184610Salfred power = 31; 1769184610Salfred 1770184610Salfred /* adjust txpower using ifconfig settings */ 1771188417Sthompsa power -= (100 - ic->ic_txpowlimit) / 8; 1772184610Salfred 1773188417Sthompsa DPRINTFN(2, "setting channel to %u, txpower to %u\n", chan, power); 1774184610Salfred 1775188417Sthompsa switch (sc->rf_rev) { 1776184610Salfred case RAL_RF_2522: 1777188417Sthompsa ural_rf_write(sc, RAL_RF1, 0x00814); 1778188417Sthompsa ural_rf_write(sc, RAL_RF2, ural_rf2522_r2[chan - 1]); 1779188417Sthompsa ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040); 1780184610Salfred break; 1781184610Salfred 1782184610Salfred case RAL_RF_2523: 1783188417Sthompsa ural_rf_write(sc, RAL_RF1, 0x08804); 1784188417Sthompsa ural_rf_write(sc, RAL_RF2, ural_rf2523_r2[chan - 1]); 1785188417Sthompsa ural_rf_write(sc, RAL_RF3, power << 7 | 0x38044); 1786188417Sthompsa ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 1787184610Salfred break; 1788184610Salfred 1789184610Salfred case RAL_RF_2524: 1790188417Sthompsa ural_rf_write(sc, RAL_RF1, 0x0c808); 1791188417Sthompsa ural_rf_write(sc, RAL_RF2, ural_rf2524_r2[chan - 1]); 1792188417Sthompsa ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040); 1793188417Sthompsa ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 1794184610Salfred break; 1795184610Salfred 1796184610Salfred case RAL_RF_2525: 1797188417Sthompsa ural_rf_write(sc, RAL_RF1, 0x08808); 1798188417Sthompsa ural_rf_write(sc, RAL_RF2, ural_rf2525_hi_r2[chan - 1]); 1799188417Sthompsa ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 1800188417Sthompsa ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 1801184610Salfred 1802188417Sthompsa ural_rf_write(sc, RAL_RF1, 0x08808); 1803188417Sthompsa ural_rf_write(sc, RAL_RF2, ural_rf2525_r2[chan - 1]); 1804188417Sthompsa ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 1805188417Sthompsa ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 1806184610Salfred break; 1807184610Salfred 1808184610Salfred case RAL_RF_2525E: 1809188417Sthompsa ural_rf_write(sc, RAL_RF1, 0x08808); 1810188417Sthompsa ural_rf_write(sc, RAL_RF2, ural_rf2525e_r2[chan - 1]); 1811188417Sthompsa ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 1812188417Sthompsa ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00286 : 0x00282); 1813184610Salfred break; 1814184610Salfred 1815184610Salfred case RAL_RF_2526: 1816188417Sthompsa ural_rf_write(sc, RAL_RF2, ural_rf2526_hi_r2[chan - 1]); 1817188417Sthompsa ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381); 1818188417Sthompsa ural_rf_write(sc, RAL_RF1, 0x08804); 1819184610Salfred 1820188417Sthompsa ural_rf_write(sc, RAL_RF2, ural_rf2526_r2[chan - 1]); 1821188417Sthompsa ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 1822188417Sthompsa ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381); 1823184610Salfred break; 1824184610Salfred 1825188417Sthompsa /* dual-band RF */ 1826184610Salfred case RAL_RF_5222: 1827188417Sthompsa for (i = 0; ural_rf5222[i].chan != chan; i++); 1828188417Sthompsa 1829188417Sthompsa ural_rf_write(sc, RAL_RF1, ural_rf5222[i].r1); 1830188417Sthompsa ural_rf_write(sc, RAL_RF2, ural_rf5222[i].r2); 1831188417Sthompsa ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040); 1832188417Sthompsa ural_rf_write(sc, RAL_RF4, ural_rf5222[i].r4); 1833184610Salfred break; 1834184610Salfred } 1835184610Salfred 1836188417Sthompsa if (ic->ic_opmode != IEEE80211_M_MONITOR && 1837188417Sthompsa (ic->ic_flags & IEEE80211_F_SCAN) == 0) { 1838184610Salfred /* set Japan filter bit for channel 14 */ 1839188417Sthompsa tmp = ural_bbp_read(sc, 70); 1840184610Salfred 1841188417Sthompsa tmp &= ~RAL_JAPAN_FILTER; 1842188417Sthompsa if (chan == 14) 1843184610Salfred tmp |= RAL_JAPAN_FILTER; 1844184610Salfred 1845188417Sthompsa ural_bbp_write(sc, 70, tmp); 1846184610Salfred 1847184610Salfred /* clear CRC errors */ 1848188417Sthompsa ural_read(sc, RAL_STA_CSR0); 1849184610Salfred 1850188619Sthompsa ural_pause(sc, hz / 100); 1851188417Sthompsa ural_disable_rf_tune(sc); 1852184610Salfred } 1853188417Sthompsa 1854188417Sthompsa /* XXX doesn't belong here */ 1855184610Salfred /* update basic rate set */ 1856188417Sthompsa ural_set_basicrates(sc, c); 1857189123Sthompsa 1858189123Sthompsa /* give the hardware some time to do the switchover */ 1859189123Sthompsa ural_pause(sc, hz / 100); 1860184610Salfred} 1861184610Salfred 1862188417Sthompsa/* 1863188417Sthompsa * Disable RF auto-tuning. 1864188417Sthompsa */ 1865184610Salfredstatic void 1866188417Sthompsaural_disable_rf_tune(struct ural_softc *sc) 1867184610Salfred{ 1868188417Sthompsa uint32_t tmp; 1869184610Salfred 1870188417Sthompsa if (sc->rf_rev != RAL_RF_2523) { 1871188417Sthompsa tmp = sc->rf_regs[RAL_RF1] & ~RAL_RF1_AUTOTUNE; 1872188417Sthompsa ural_rf_write(sc, RAL_RF1, tmp); 1873184610Salfred } 1874184610Salfred 1875188417Sthompsa tmp = sc->rf_regs[RAL_RF3] & ~RAL_RF3_AUTOTUNE; 1876188417Sthompsa ural_rf_write(sc, RAL_RF3, tmp); 1877184610Salfred 1878188417Sthompsa DPRINTFN(2, "disabling RF autotune\n"); 1879184610Salfred} 1880184610Salfred 1881188417Sthompsa/* 1882188417Sthompsa * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF 1883188417Sthompsa * synchronization. 1884188417Sthompsa */ 1885184610Salfredstatic void 1886188417Sthompsaural_enable_tsf_sync(struct ural_softc *sc) 1887184610Salfred{ 1888188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 1889188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 1890188417Sthompsa struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 1891188417Sthompsa uint16_t logcwmin, preload, tmp; 1892184610Salfred 1893184610Salfred /* first, disable TSF synchronization */ 1894188417Sthompsa ural_write(sc, RAL_TXRX_CSR19, 0); 1895184610Salfred 1896188417Sthompsa tmp = (16 * vap->iv_bss->ni_intval) << 4; 1897188417Sthompsa ural_write(sc, RAL_TXRX_CSR18, tmp); 1898184610Salfred 1899188417Sthompsa logcwmin = (ic->ic_opmode == IEEE80211_M_IBSS) ? 2 : 0; 1900188417Sthompsa preload = (ic->ic_opmode == IEEE80211_M_IBSS) ? 320 : 6; 1901188417Sthompsa tmp = logcwmin << 12 | preload; 1902188417Sthompsa ural_write(sc, RAL_TXRX_CSR20, tmp); 1903184610Salfred 1904184610Salfred /* finally, enable TSF synchronization */ 1905184610Salfred tmp = RAL_ENABLE_TSF | RAL_ENABLE_TBCN; 1906188417Sthompsa if (ic->ic_opmode == IEEE80211_M_STA) 1907184610Salfred tmp |= RAL_ENABLE_TSF_SYNC(1); 1908184610Salfred else 1909184610Salfred tmp |= RAL_ENABLE_TSF_SYNC(2) | RAL_ENABLE_BEACON_GENERATOR; 1910188417Sthompsa ural_write(sc, RAL_TXRX_CSR19, tmp); 1911184610Salfred 1912184610Salfred DPRINTF("enabling TSF synchronization\n"); 1913184610Salfred} 1914184610Salfred 1915188417Sthompsa#define RAL_RXTX_TURNAROUND 5 /* us */ 1916184610Salfredstatic void 1917188417Sthompsaural_update_slot(struct ifnet *ifp) 1918184610Salfred{ 1919188417Sthompsa struct ural_softc *sc = ifp->if_softc; 1920188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 1921188417Sthompsa uint16_t slottime, sifs, eifs; 1922184610Salfred 1923188417Sthompsa slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; 1924184610Salfred 1925184610Salfred /* 1926184610Salfred * These settings may sound a bit inconsistent but this is what the 1927184610Salfred * reference driver does. 1928184610Salfred */ 1929188417Sthompsa if (ic->ic_curmode == IEEE80211_MODE_11B) { 1930184610Salfred sifs = 16 - RAL_RXTX_TURNAROUND; 1931184610Salfred eifs = 364; 1932184610Salfred } else { 1933184610Salfred sifs = 10 - RAL_RXTX_TURNAROUND; 1934184610Salfred eifs = 64; 1935184610Salfred } 1936184610Salfred 1937188417Sthompsa ural_write(sc, RAL_MAC_CSR10, slottime); 1938188417Sthompsa ural_write(sc, RAL_MAC_CSR11, sifs); 1939188417Sthompsa ural_write(sc, RAL_MAC_CSR12, eifs); 1940184610Salfred} 1941184610Salfred 1942184610Salfredstatic void 1943188417Sthompsaural_set_txpreamble(struct ural_softc *sc) 1944184610Salfred{ 1945188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 1946188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 1947184610Salfred uint16_t tmp; 1948184610Salfred 1949188417Sthompsa tmp = ural_read(sc, RAL_TXRX_CSR10); 1950184610Salfred 1951188417Sthompsa tmp &= ~RAL_SHORT_PREAMBLE; 1952188417Sthompsa if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) 1953184610Salfred tmp |= RAL_SHORT_PREAMBLE; 1954184610Salfred 1955188417Sthompsa ural_write(sc, RAL_TXRX_CSR10, tmp); 1956184610Salfred} 1957184610Salfred 1958184610Salfredstatic void 1959188417Sthompsaural_set_basicrates(struct ural_softc *sc, const struct ieee80211_channel *c) 1960184610Salfred{ 1961188417Sthompsa /* XXX wrong, take from rate set */ 1962188417Sthompsa /* update basic rate set */ 1963188417Sthompsa if (IEEE80211_IS_CHAN_5GHZ(c)) { 1964188417Sthompsa /* 11a basic rates: 6, 12, 24Mbps */ 1965188417Sthompsa ural_write(sc, RAL_TXRX_CSR11, 0x150); 1966188417Sthompsa } else if (IEEE80211_IS_CHAN_ANYG(c)) { 1967188417Sthompsa /* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */ 1968188417Sthompsa ural_write(sc, RAL_TXRX_CSR11, 0x15f); 1969188417Sthompsa } else { 1970188417Sthompsa /* 11b basic rates: 1, 2Mbps */ 1971188417Sthompsa ural_write(sc, RAL_TXRX_CSR11, 0x3); 1972188417Sthompsa } 1973184610Salfred} 1974184610Salfred 1975184610Salfredstatic void 1976188417Sthompsaural_set_bssid(struct ural_softc *sc, const uint8_t *bssid) 1977184610Salfred{ 1978188417Sthompsa uint16_t tmp; 1979184610Salfred 1980188417Sthompsa tmp = bssid[0] | bssid[1] << 8; 1981188417Sthompsa ural_write(sc, RAL_MAC_CSR5, tmp); 1982188417Sthompsa 1983188417Sthompsa tmp = bssid[2] | bssid[3] << 8; 1984188417Sthompsa ural_write(sc, RAL_MAC_CSR6, tmp); 1985188417Sthompsa 1986188417Sthompsa tmp = bssid[4] | bssid[5] << 8; 1987188417Sthompsa ural_write(sc, RAL_MAC_CSR7, tmp); 1988188417Sthompsa 1989188417Sthompsa DPRINTF("setting BSSID to %6D\n", bssid, ":"); 1990184610Salfred} 1991184610Salfred 1992184610Salfredstatic void 1993188417Sthompsaural_set_macaddr(struct ural_softc *sc, uint8_t *addr) 1994184610Salfred{ 1995184610Salfred uint16_t tmp; 1996184610Salfred 1997188417Sthompsa tmp = addr[0] | addr[1] << 8; 1998188417Sthompsa ural_write(sc, RAL_MAC_CSR2, tmp); 1999184610Salfred 2000188417Sthompsa tmp = addr[2] | addr[3] << 8; 2001188417Sthompsa ural_write(sc, RAL_MAC_CSR3, tmp); 2002184610Salfred 2003188417Sthompsa tmp = addr[4] | addr[5] << 8; 2004188417Sthompsa ural_write(sc, RAL_MAC_CSR4, tmp); 2005184610Salfred 2006188417Sthompsa DPRINTF("setting MAC address to %6D\n", addr, ":"); 2007184610Salfred} 2008184610Salfred 2009184610Salfredstatic void 2010188417Sthompsaural_promisctask(struct usb2_proc_msg *pm) 2011184610Salfred{ 2012188417Sthompsa struct ural_task *task = (struct ural_task *)pm; 2013188417Sthompsa struct ural_softc *sc = task->sc; 2014188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2015188417Sthompsa uint32_t tmp; 2016184610Salfred 2017188417Sthompsa tmp = ural_read(sc, RAL_TXRX_CSR2); 2018184610Salfred 2019188417Sthompsa tmp &= ~RAL_DROP_NOT_TO_ME; 2020188417Sthompsa if (!(ifp->if_flags & IFF_PROMISC)) 2021188417Sthompsa tmp |= RAL_DROP_NOT_TO_ME; 2022184610Salfred 2023188417Sthompsa ural_write(sc, RAL_TXRX_CSR2, tmp); 2024184610Salfred 2025188417Sthompsa DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ? 2026188417Sthompsa "entering" : "leaving"); 2027184610Salfred} 2028184610Salfred 2029189123Sthompsastatic void 2030189123Sthompsaural_update_mcast(struct ifnet *ifp) 2031189123Sthompsa{ 2032189123Sthompsa /* not supported */ 2033189123Sthompsa} 2034189123Sthompsa 2035189123Sthompsastatic void 2036189123Sthompsaural_update_promisc(struct ifnet *ifp) 2037189123Sthompsa{ 2038189123Sthompsa struct ural_softc *sc = ifp->if_softc; 2039189123Sthompsa 2040189123Sthompsa if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 2041189123Sthompsa return; 2042189123Sthompsa 2043189123Sthompsa RAL_LOCK(sc); 2044189123Sthompsa ural_queue_command(sc, ural_promisctask, 2045189123Sthompsa &sc->sc_promisctask[0].hdr, 2046189123Sthompsa &sc->sc_promisctask[1].hdr); 2047189123Sthompsa RAL_UNLOCK(sc); 2048189123Sthompsa} 2049189123Sthompsa 2050188417Sthompsastatic const char * 2051188417Sthompsaural_get_rf(int rev) 2052184610Salfred{ 2053188417Sthompsa switch (rev) { 2054188417Sthompsa case RAL_RF_2522: return "RT2522"; 2055188417Sthompsa case RAL_RF_2523: return "RT2523"; 2056188417Sthompsa case RAL_RF_2524: return "RT2524"; 2057188417Sthompsa case RAL_RF_2525: return "RT2525"; 2058188417Sthompsa case RAL_RF_2525E: return "RT2525e"; 2059188417Sthompsa case RAL_RF_2526: return "RT2526"; 2060188417Sthompsa case RAL_RF_5222: return "RT5222"; 2061188417Sthompsa default: return "unknown"; 2062184610Salfred } 2063184610Salfred} 2064184610Salfred 2065184610Salfredstatic void 2066188417Sthompsaural_read_eeprom(struct ural_softc *sc) 2067184610Salfred{ 2068184610Salfred uint16_t val; 2069184610Salfred 2070188417Sthompsa ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2); 2071184610Salfred val = le16toh(val); 2072188417Sthompsa sc->rf_rev = (val >> 11) & 0x7; 2073188417Sthompsa sc->hw_radio = (val >> 10) & 0x1; 2074188417Sthompsa sc->led_mode = (val >> 6) & 0x7; 2075188417Sthompsa sc->rx_ant = (val >> 4) & 0x3; 2076188417Sthompsa sc->tx_ant = (val >> 2) & 0x3; 2077188417Sthompsa sc->nb_ant = val & 0x3; 2078184610Salfred 2079184610Salfred /* read MAC address */ 2080188419Sthompsa ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, sc->sc_bssid, 6); 2081184610Salfred 2082184610Salfred /* read default values for BBP registers */ 2083188417Sthompsa ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16); 2084184610Salfred 2085184610Salfred /* read Tx power for all b/g channels */ 2086188417Sthompsa ural_eeprom_read(sc, RAL_EEPROM_TXPOWER, sc->txpow, 14); 2087184610Salfred} 2088184610Salfred 2089188417Sthompsastatic int 2090188417Sthompsaural_bbp_init(struct ural_softc *sc) 2091184610Salfred{ 2092188417Sthompsa#define N(a) (sizeof (a) / sizeof ((a)[0])) 2093188417Sthompsa int i, ntries; 2094184610Salfred 2095188417Sthompsa /* wait for BBP to be ready */ 2096188417Sthompsa for (ntries = 0; ntries < 100; ntries++) { 2097188417Sthompsa if (ural_bbp_read(sc, RAL_BBP_VERSION) != 0) 2098188417Sthompsa break; 2099188619Sthompsa if (ural_pause(sc, hz / 100)) 2100188619Sthompsa break; 2101184610Salfred } 2102188417Sthompsa if (ntries == 100) { 2103188417Sthompsa device_printf(sc->sc_dev, "timeout waiting for BBP\n"); 2104188417Sthompsa return EIO; 2105188417Sthompsa } 2106184610Salfred 2107184610Salfred /* initialize BBP registers to default values */ 2108188417Sthompsa for (i = 0; i < N(ural_def_bbp); i++) 2109188417Sthompsa ural_bbp_write(sc, ural_def_bbp[i].reg, ural_def_bbp[i].val); 2110184610Salfred 2111184610Salfred#if 0 2112184610Salfred /* initialize BBP registers to values stored in EEPROM */ 2113184610Salfred for (i = 0; i < 16; i++) { 2114188417Sthompsa if (sc->bbp_prom[i].reg == 0xff) 2115184610Salfred continue; 2116188417Sthompsa ural_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val); 2117184610Salfred } 2118184610Salfred#endif 2119188417Sthompsa 2120188417Sthompsa return 0; 2121188417Sthompsa#undef N 2122184610Salfred} 2123184610Salfred 2124184610Salfredstatic void 2125188417Sthompsaural_set_txantenna(struct ural_softc *sc, int antenna) 2126184610Salfred{ 2127188417Sthompsa uint16_t tmp; 2128188417Sthompsa uint8_t tx; 2129184610Salfred 2130188417Sthompsa tx = ural_bbp_read(sc, RAL_BBP_TX) & ~RAL_BBP_ANTMASK; 2131188417Sthompsa if (antenna == 1) 2132188417Sthompsa tx |= RAL_BBP_ANTA; 2133188417Sthompsa else if (antenna == 2) 2134188417Sthompsa tx |= RAL_BBP_ANTB; 2135188417Sthompsa else 2136188417Sthompsa tx |= RAL_BBP_DIVERSITY; 2137184610Salfred 2138188417Sthompsa /* need to force I/Q flip for RF 2525e, 2526 and 5222 */ 2139188417Sthompsa if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526 || 2140188417Sthompsa sc->rf_rev == RAL_RF_5222) 2141188417Sthompsa tx |= RAL_BBP_FLIPIQ; 2142184610Salfred 2143188417Sthompsa ural_bbp_write(sc, RAL_BBP_TX, tx); 2144184610Salfred 2145188417Sthompsa /* update values in PHY_CSR5 and PHY_CSR6 */ 2146188417Sthompsa tmp = ural_read(sc, RAL_PHY_CSR5) & ~0x7; 2147188417Sthompsa ural_write(sc, RAL_PHY_CSR5, tmp | (tx & 0x7)); 2148184610Salfred 2149188417Sthompsa tmp = ural_read(sc, RAL_PHY_CSR6) & ~0x7; 2150188417Sthompsa ural_write(sc, RAL_PHY_CSR6, tmp | (tx & 0x7)); 2151184610Salfred} 2152184610Salfred 2153184610Salfredstatic void 2154188417Sthompsaural_set_rxantenna(struct ural_softc *sc, int antenna) 2155184610Salfred{ 2156188417Sthompsa uint8_t rx; 2157188417Sthompsa 2158188417Sthompsa rx = ural_bbp_read(sc, RAL_BBP_RX) & ~RAL_BBP_ANTMASK; 2159188417Sthompsa if (antenna == 1) 2160188417Sthompsa rx |= RAL_BBP_ANTA; 2161188417Sthompsa else if (antenna == 2) 2162188417Sthompsa rx |= RAL_BBP_ANTB; 2163188417Sthompsa else 2164188417Sthompsa rx |= RAL_BBP_DIVERSITY; 2165188417Sthompsa 2166188417Sthompsa /* need to force no I/Q flip for RF 2525e and 2526 */ 2167188417Sthompsa if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526) 2168188417Sthompsa rx &= ~RAL_BBP_FLIPIQ; 2169188417Sthompsa 2170188417Sthompsa ural_bbp_write(sc, RAL_BBP_RX, rx); 2171188417Sthompsa} 2172188417Sthompsa 2173188417Sthompsastatic void 2174188419Sthompsaural_init_task(struct usb2_proc_msg *pm) 2175188417Sthompsa{ 2176188417Sthompsa#define N(a) (sizeof (a) / sizeof ((a)[0])) 2177188419Sthompsa struct ural_task *task = (struct ural_task *)pm; 2178188419Sthompsa struct ural_softc *sc = task->sc; 2179188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2180188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 2181184610Salfred uint16_t tmp; 2182188417Sthompsa int i, ntries; 2183184610Salfred 2184188417Sthompsa RAL_LOCK_ASSERT(sc, MA_OWNED); 2185184610Salfred 2186188417Sthompsa ural_set_testmode(sc); 2187188417Sthompsa ural_write(sc, 0x308, 0x00f0); /* XXX magic */ 2188184610Salfred 2189188419Sthompsa ural_stop_task(pm); 2190184610Salfred 2191184610Salfred /* initialize MAC registers to default values */ 2192188417Sthompsa for (i = 0; i < N(ural_def_mac); i++) 2193188417Sthompsa ural_write(sc, ural_def_mac[i].reg, ural_def_mac[i].val); 2194184610Salfred 2195184610Salfred /* wait for BBP and RF to wake up (this can take a long time!) */ 2196188417Sthompsa for (ntries = 0; ntries < 100; ntries++) { 2197188417Sthompsa tmp = ural_read(sc, RAL_MAC_CSR17); 2198188417Sthompsa if ((tmp & (RAL_BBP_AWAKE | RAL_RF_AWAKE)) == 2199188417Sthompsa (RAL_BBP_AWAKE | RAL_RF_AWAKE)) 2200188417Sthompsa break; 2201188619Sthompsa if (ural_pause(sc, hz / 100)) 2202188619Sthompsa break; 2203184610Salfred } 2204188417Sthompsa if (ntries == 100) { 2205188417Sthompsa device_printf(sc->sc_dev, 2206188417Sthompsa "timeout waiting for BBP/RF to wakeup\n"); 2207188417Sthompsa goto fail; 2208188417Sthompsa } 2209184610Salfred 2210184610Salfred /* we're ready! */ 2211188417Sthompsa ural_write(sc, RAL_MAC_CSR1, RAL_HOST_READY); 2212184610Salfred 2213184610Salfred /* set basic rate set (will be updated later) */ 2214188417Sthompsa ural_write(sc, RAL_TXRX_CSR11, 0x15f); 2215184610Salfred 2216188417Sthompsa if (ural_bbp_init(sc) != 0) 2217184610Salfred goto fail; 2218184610Salfred 2219188417Sthompsa ural_set_chan(sc, ic->ic_curchan); 2220188417Sthompsa 2221184610Salfred /* clear statistic registers (STA_CSR0 to STA_CSR10) */ 2222188417Sthompsa ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta); 2223184610Salfred 2224188417Sthompsa ural_set_txantenna(sc, sc->tx_ant); 2225188417Sthompsa ural_set_rxantenna(sc, sc->rx_ant); 2226184610Salfred 2227188417Sthompsa IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp)); 2228188417Sthompsa ural_set_macaddr(sc, ic->ic_myaddr); 2229184610Salfred 2230184610Salfred /* 2231188417Sthompsa * Allocate Tx and Rx xfer queues. 2232184610Salfred */ 2233188419Sthompsa ural_setup_tx_list(sc); 2234184610Salfred 2235188417Sthompsa /* kick Rx */ 2236184610Salfred tmp = RAL_DROP_PHY | RAL_DROP_CRC; 2237188417Sthompsa if (ic->ic_opmode != IEEE80211_M_MONITOR) { 2238188417Sthompsa tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION; 2239188417Sthompsa if (ic->ic_opmode != IEEE80211_M_HOSTAP) 2240184610Salfred tmp |= RAL_DROP_TODS; 2241188417Sthompsa if (!(ifp->if_flags & IFF_PROMISC)) 2242184610Salfred tmp |= RAL_DROP_NOT_TO_ME; 2243184610Salfred } 2244188417Sthompsa ural_write(sc, RAL_TXRX_CSR2, tmp); 2245184610Salfred 2246188417Sthompsa ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2247188417Sthompsa ifp->if_drv_flags |= IFF_DRV_RUNNING; 2248189123Sthompsa usb2_transfer_set_stall(sc->sc_xfer[URAL_BULK_WR]); 2249188417Sthompsa usb2_transfer_start(sc->sc_xfer[URAL_BULK_RD]); 2250184610Salfred return; 2251184610Salfred 2252188419Sthompsafail: ural_stop_task(pm); 2253188417Sthompsa#undef N 2254184610Salfred} 2255184610Salfred 2256184610Salfredstatic void 2257188417Sthompsaural_init(void *priv) 2258184610Salfred{ 2259188417Sthompsa struct ural_softc *sc = priv; 2260184610Salfred struct ifnet *ifp = sc->sc_ifp; 2261188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 2262184610Salfred 2263188417Sthompsa RAL_LOCK(sc); 2264188419Sthompsa ural_queue_command(sc, ural_init_task, 2265188419Sthompsa &sc->sc_synctask[0].hdr, 2266188419Sthompsa &sc->sc_synctask[1].hdr); 2267188417Sthompsa RAL_UNLOCK(sc); 2268184610Salfred 2269188417Sthompsa if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2270188417Sthompsa ieee80211_start_all(ic); /* start all vap's */ 2271184610Salfred} 2272184610Salfred 2273184610Salfredstatic void 2274188419Sthompsaural_stop_task(struct usb2_proc_msg *pm) 2275184610Salfred{ 2276188419Sthompsa struct ural_task *task = (struct ural_task *)pm; 2277188419Sthompsa struct ural_softc *sc = task->sc; 2278184610Salfred struct ifnet *ifp = sc->sc_ifp; 2279184610Salfred 2280188417Sthompsa RAL_LOCK_ASSERT(sc, MA_OWNED); 2281184610Salfred 2282188417Sthompsa ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 2283184610Salfred 2284184610Salfred /* 2285188419Sthompsa * Drain all the transfers, if not already drained: 2286184610Salfred */ 2287188419Sthompsa RAL_UNLOCK(sc); 2288188419Sthompsa usb2_transfer_drain(sc->sc_xfer[URAL_BULK_WR]); 2289188419Sthompsa usb2_transfer_drain(sc->sc_xfer[URAL_BULK_RD]); 2290188419Sthompsa RAL_LOCK(sc); 2291184610Salfred 2292188419Sthompsa ural_unsetup_tx_list(sc); 2293184610Salfred 2294188417Sthompsa /* disable Rx */ 2295188417Sthompsa ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX); 2296188417Sthompsa /* reset ASIC and BBP (but won't reset MAC registers!) */ 2297188417Sthompsa ural_write(sc, RAL_MAC_CSR1, RAL_RESET_ASIC | RAL_RESET_BBP); 2298188619Sthompsa /* wait a little */ 2299188619Sthompsa ural_pause(sc, hz / 10); 2300188417Sthompsa ural_write(sc, RAL_MAC_CSR1, 0); 2301189123Sthompsa /* wait a little */ 2302189123Sthompsa ural_pause(sc, hz / 10); 2303184610Salfred} 2304184610Salfred 2305188417Sthompsastatic int 2306188417Sthompsaural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 2307188417Sthompsa const struct ieee80211_bpf_params *params) 2308184610Salfred{ 2309188417Sthompsa struct ieee80211com *ic = ni->ni_ic; 2310188417Sthompsa struct ifnet *ifp = ic->ic_ifp; 2311188417Sthompsa struct ural_softc *sc = ifp->if_softc; 2312184610Salfred 2313188417Sthompsa RAL_LOCK(sc); 2314188417Sthompsa /* prevent management frames from being sent if we're not ready */ 2315188417Sthompsa if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 2316188417Sthompsa RAL_UNLOCK(sc); 2317188417Sthompsa m_freem(m); 2318188417Sthompsa ieee80211_free_node(ni); 2319188417Sthompsa return ENETDOWN; 2320184610Salfred } 2321188969Sthompsa if (sc->tx_nfree < RAL_TX_MINFREE) { 2322188417Sthompsa ifp->if_drv_flags |= IFF_DRV_OACTIVE; 2323188417Sthompsa RAL_UNLOCK(sc); 2324184610Salfred m_freem(m); 2325184610Salfred ieee80211_free_node(ni); 2326188417Sthompsa return EIO; 2327184610Salfred } 2328184610Salfred 2329188417Sthompsa ifp->if_opackets++; 2330184610Salfred 2331188417Sthompsa if (params == NULL) { 2332188417Sthompsa /* 2333188417Sthompsa * Legacy path; interpret frame contents to decide 2334188417Sthompsa * precisely how to send the frame. 2335188417Sthompsa */ 2336188417Sthompsa if (ural_tx_mgt(sc, m, ni) != 0) 2337188417Sthompsa goto bad; 2338188417Sthompsa } else { 2339188417Sthompsa /* 2340188417Sthompsa * Caller supplied explicit parameters to use in 2341188417Sthompsa * sending the frame. 2342188417Sthompsa */ 2343188417Sthompsa if (ural_tx_raw(sc, m, ni, params) != 0) 2344188417Sthompsa goto bad; 2345184610Salfred } 2346188417Sthompsa RAL_UNLOCK(sc); 2347188417Sthompsa return 0; 2348188417Sthompsabad: 2349188417Sthompsa ifp->if_oerrors++; 2350188417Sthompsa RAL_UNLOCK(sc); 2351188417Sthompsa ieee80211_free_node(ni); 2352188417Sthompsa return EIO; /* XXX */ 2353184610Salfred} 2354184610Salfred 2355184610Salfredstatic void 2356188417Sthompsaural_amrr_start(struct ural_softc *sc, struct ieee80211_node *ni) 2357184610Salfred{ 2358188417Sthompsa struct ieee80211vap *vap = ni->ni_vap; 2359188417Sthompsa struct ural_vap *uvp = URAL_VAP(vap); 2360184610Salfred 2361188417Sthompsa /* clear statistic registers (STA_CSR0 to STA_CSR10) */ 2362188417Sthompsa ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta); 2363184610Salfred 2364188417Sthompsa ieee80211_amrr_node_init(&uvp->amrr, &URAL_NODE(ni)->amn, ni); 2365184610Salfred 2366188417Sthompsa usb2_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp); 2367184610Salfred} 2368184610Salfred 2369184610Salfredstatic void 2370188417Sthompsaural_amrr_timeout(void *arg) 2371184610Salfred{ 2372188417Sthompsa struct ural_vap *uvp = arg; 2373188417Sthompsa struct ural_softc *sc = uvp->sc; 2374184610Salfred 2375188417Sthompsa ural_queue_command(sc, ural_amrr_task, 2376188417Sthompsa &uvp->amrr_task[0].hdr, &uvp->amrr_task[1].hdr); 2377184610Salfred} 2378184610Salfred 2379184610Salfredstatic void 2380188417Sthompsaural_amrr_task(struct usb2_proc_msg *pm) 2381184610Salfred{ 2382188417Sthompsa struct ural_task *task = (struct ural_task *)pm; 2383188417Sthompsa struct ural_softc *sc = task->sc; 2384188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2385188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 2386188417Sthompsa struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 2387188417Sthompsa struct ural_vap *uvp = URAL_VAP(vap); 2388188417Sthompsa struct ieee80211_node *ni = vap->iv_bss; 2389188417Sthompsa int ok, fail; 2390184610Salfred 2391188417Sthompsa /* read and clear statistic registers (STA_CSR0 to STA_CSR10) */ 2392188417Sthompsa ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof(sc->sta)); 2393184610Salfred 2394188417Sthompsa ok = sc->sta[7] + /* TX ok w/o retry */ 2395188417Sthompsa sc->sta[8]; /* TX ok w/ retry */ 2396188417Sthompsa fail = sc->sta[9]; /* TX retry-fail count */ 2397184610Salfred 2398188417Sthompsa ieee80211_amrr_tx_update(&URAL_NODE(ni)->amn, 2399188417Sthompsa ok+fail, ok, sc->sta[8] + fail); 2400188417Sthompsa (void) ieee80211_amrr_choose(ni, &URAL_NODE(ni)->amn); 2401184610Salfred 2402188417Sthompsa ifp->if_oerrors += fail; /* count TX retry-fail as Tx errors */ 2403184610Salfred 2404188417Sthompsa usb2_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp); 2405184610Salfred} 2406184610Salfred 2407188619Sthompsastatic int 2408188619Sthompsaural_pause(struct ural_softc *sc, int timeout) 2409188619Sthompsa{ 2410188619Sthompsa if (usb2_proc_is_gone(&sc->sc_tq)) 2411188619Sthompsa return (1); 2412188619Sthompsa 2413188619Sthompsa usb2_pause_mtx(&sc->sc_mtx, timeout); 2414188619Sthompsa return (0); 2415188619Sthompsa} 2416188619Sthompsa 2417184610Salfredstatic void 2418189123Sthompsaural_command_wrapper(struct usb2_proc_msg *pm) 2419189123Sthompsa{ 2420189123Sthompsa struct ural_task *task = (struct ural_task *)pm; 2421189123Sthompsa struct ural_softc *sc = task->sc; 2422189123Sthompsa struct ifnet *ifp; 2423189123Sthompsa 2424189123Sthompsa /* wait for pending transfer, if any */ 2425189123Sthompsa while (usb2_transfer_pending(sc->sc_xfer[URAL_BULK_WR])) 2426189123Sthompsa cv_wait(&sc->sc_cmd_cv, &sc->sc_mtx); 2427189123Sthompsa 2428189123Sthompsa /* make sure any hardware FIFOs are emptied */ 2429189123Sthompsa ural_pause(sc, hz / 1000); 2430189123Sthompsa 2431189123Sthompsa /* execute task */ 2432189123Sthompsa task->func(pm); 2433189123Sthompsa 2434189123Sthompsa /* check if this is the last task executed */ 2435189123Sthompsa if (sc->sc_last_task == task) { 2436189123Sthompsa sc->sc_last_task = NULL; 2437189123Sthompsa ifp = sc->sc_ifp; 2438189123Sthompsa /* re-start TX, if any */ 2439189123Sthompsa if ((ifp != NULL) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) 2440189123Sthompsa usb2_transfer_start(sc->sc_xfer[URAL_BULK_WR]); 2441189123Sthompsa } 2442189123Sthompsa} 2443189123Sthompsa 2444189123Sthompsastatic void 2445188417Sthompsaural_queue_command(struct ural_softc *sc, usb2_proc_callback_t *fn, 2446188417Sthompsa struct usb2_proc_msg *t0, struct usb2_proc_msg *t1) 2447184610Salfred{ 2448188417Sthompsa struct ural_task *task; 2449184610Salfred 2450188417Sthompsa RAL_LOCK_ASSERT(sc, MA_OWNED); 2451184610Salfred 2452188417Sthompsa /* 2453188417Sthompsa * NOTE: The task cannot get executed before we drop the 2454188417Sthompsa * "sc_mtx" mutex. It is safe to update fields in the message 2455188417Sthompsa * structure after that the message got queued. 2456188417Sthompsa */ 2457188417Sthompsa task = (struct ural_task *) 2458188417Sthompsa usb2_proc_msignal(&sc->sc_tq, t0, t1); 2459184610Salfred 2460188417Sthompsa /* Setup callback and softc pointers */ 2461189123Sthompsa task->hdr.pm_callback = ural_command_wrapper; 2462189123Sthompsa task->func = fn; 2463188417Sthompsa task->sc = sc; 2464184610Salfred 2465189123Sthompsa /* Make sure that any TX operation will stop */ 2466189123Sthompsa sc->sc_last_task = task; 2467189123Sthompsa 2468188419Sthompsa /* 2469189123Sthompsa * Init, stop and flush must be synchronous! 2470188419Sthompsa */ 2471189123Sthompsa if ((fn == ural_init_task) || (fn == ural_stop_task) || 2472189123Sthompsa (fn == ural_stop_task)) 2473188419Sthompsa usb2_proc_mwait(&sc->sc_tq, t0, t1); 2474184610Salfred} 2475