if_zyd.c revision 184610
1184610Salfred/* $OpenBSD: if_zyd.c,v 1.52 2007/02/11 00:08:04 jsg Exp $ */ 2184610Salfred/* $NetBSD: if_zyd.c,v 1.7 2007/06/21 04:04:29 kiyohara Exp $ */ 3184610Salfred/* $FreeBSD: head/sys/dev/usb2/wlan/if_zyd2.c 184610 2008-11-04 02:31:03Z alfred $ */ 4184610Salfred 5184610Salfred/*- 6184610Salfred * Copyright (c) 2006 by Damien Bergamini <damien.bergamini@free.fr> 7184610Salfred * Copyright (c) 2006 by Florian Stoehr <ich@florian-stoehr.de> 8184610Salfred * 9184610Salfred * Permission to use, copy, modify, and distribute this software for any 10184610Salfred * purpose with or without fee is hereby granted, provided that the above 11184610Salfred * copyright notice and this permission notice appear in all copies. 12184610Salfred * 13184610Salfred * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14184610Salfred * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15184610Salfred * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16184610Salfred * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17184610Salfred * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18184610Salfred * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19184610Salfred * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20184610Salfred */ 21184610Salfred 22184610Salfred#include <sys/cdefs.h> 23184610Salfred__FBSDID("$FreeBSD: head/sys/dev/usb2/wlan/if_zyd2.c 184610 2008-11-04 02:31:03Z alfred $"); 24184610Salfred 25184610Salfred/* 26184610Salfred * ZyDAS ZD1211/ZD1211B USB WLAN driver 27184610Salfred * 28184610Salfred * NOTE: all function names beginning like "zyd_cfg_" can only 29184610Salfred * be called from within the config thread function ! 30184610Salfred */ 31184610Salfred 32184610Salfred#include <dev/usb2/include/usb2_devid.h> 33184610Salfred#include <dev/usb2/include/usb2_standard.h> 34184610Salfred#include <dev/usb2/include/usb2_mfunc.h> 35184610Salfred#include <dev/usb2/include/usb2_error.h> 36184610Salfred 37184610Salfred#define usb2_config_td_cc zyd_config_copy 38184610Salfred#define usb2_config_td_softc zyd_softc 39184610Salfred 40184610Salfred#define USB_DEBUG_VAR zyd_debug 41184610Salfred 42184610Salfred#include <dev/usb2/core/usb2_core.h> 43184610Salfred#include <dev/usb2/core/usb2_lookup.h> 44184610Salfred#include <dev/usb2/core/usb2_process.h> 45184610Salfred#include <dev/usb2/core/usb2_config_td.h> 46184610Salfred#include <dev/usb2/core/usb2_debug.h> 47184610Salfred#include <dev/usb2/core/usb2_request.h> 48184610Salfred#include <dev/usb2/core/usb2_busdma.h> 49184610Salfred#include <dev/usb2/core/usb2_util.h> 50184610Salfred 51184610Salfred#include <dev/usb2/wlan/usb2_wlan.h> 52184610Salfred#include <dev/usb2/wlan/if_zyd2_reg.h> 53184610Salfred#include <dev/usb2/wlan/if_zyd2_fw.h> 54184610Salfred 55184610Salfred#if USB_DEBUG 56184610Salfredstatic int zyd_debug = 0; 57184610Salfred 58184610SalfredSYSCTL_NODE(_hw_usb2, OID_AUTO, zyd, CTLFLAG_RW, 0, "USB zyd"); 59184610SalfredSYSCTL_INT(_hw_usb2_zyd, OID_AUTO, debug, CTLFLAG_RW, &zyd_debug, 0, 60184610Salfred "zyd debug level"); 61184610Salfred#endif 62184610Salfred 63184610Salfred#undef INDEXES 64184610Salfred#define INDEXES(a) (sizeof(a) / sizeof((a)[0])) 65184610Salfred 66184610Salfredstatic device_probe_t zyd_probe; 67184610Salfredstatic device_attach_t zyd_attach; 68184610Salfredstatic device_detach_t zyd_detach; 69184610Salfred 70184610Salfredstatic usb2_callback_t zyd_intr_read_clear_stall_callback; 71184610Salfredstatic usb2_callback_t zyd_intr_read_callback; 72184610Salfredstatic usb2_callback_t zyd_intr_write_clear_stall_callback; 73184610Salfredstatic usb2_callback_t zyd_intr_write_callback; 74184610Salfredstatic usb2_callback_t zyd_bulk_read_clear_stall_callback; 75184610Salfredstatic usb2_callback_t zyd_bulk_read_callback; 76184610Salfredstatic usb2_callback_t zyd_bulk_write_clear_stall_callback; 77184610Salfredstatic usb2_callback_t zyd_bulk_write_callback; 78184610Salfred 79184610Salfredstatic usb2_config_td_command_t zyd_cfg_first_time_setup; 80184610Salfredstatic usb2_config_td_command_t zyd_cfg_update_promisc; 81184610Salfredstatic usb2_config_td_command_t zyd_cfg_set_chan; 82184610Salfredstatic usb2_config_td_command_t zyd_cfg_pre_init; 83184610Salfredstatic usb2_config_td_command_t zyd_cfg_init; 84184610Salfredstatic usb2_config_td_command_t zyd_cfg_pre_stop; 85184610Salfredstatic usb2_config_td_command_t zyd_cfg_stop; 86184610Salfredstatic usb2_config_td_command_t zyd_config_copy; 87184610Salfredstatic usb2_config_td_command_t zyd_cfg_scan_start; 88184610Salfredstatic usb2_config_td_command_t zyd_cfg_scan_end; 89184610Salfredstatic usb2_config_td_command_t zyd_cfg_set_rxfilter; 90184610Salfredstatic usb2_config_td_command_t zyd_cfg_amrr_timeout; 91184610Salfred 92184610Salfredstatic uint8_t zyd_plcp2ieee(uint8_t signal, uint8_t isofdm); 93184610Salfredstatic void zyd_cfg_usbrequest(struct zyd_softc *sc, struct usb2_device_request *req, uint8_t *data); 94184610Salfredstatic void zyd_cfg_usb2_intr_read(struct zyd_softc *sc, void *data, uint32_t size); 95184610Salfredstatic void zyd_cfg_usb2_intr_write(struct zyd_softc *sc, const void *data, uint16_t code, uint32_t size); 96184610Salfredstatic void zyd_cfg_read16(struct zyd_softc *sc, uint16_t addr, uint16_t *value); 97184610Salfredstatic void zyd_cfg_read32(struct zyd_softc *sc, uint16_t addr, uint32_t *value); 98184610Salfredstatic void zyd_cfg_write16(struct zyd_softc *sc, uint16_t addr, uint16_t value); 99184610Salfredstatic void zyd_cfg_write32(struct zyd_softc *sc, uint16_t addr, uint32_t value); 100184610Salfredstatic void zyd_cfg_rfwrite(struct zyd_softc *sc, uint32_t value); 101184610Salfredstatic uint8_t zyd_cfg_uploadfirmware(struct zyd_softc *sc, const uint8_t *fw_ptr, uint32_t fw_len); 102184610Salfredstatic void zyd_cfg_lock_phy(struct zyd_softc *sc); 103184610Salfredstatic void zyd_cfg_unlock_phy(struct zyd_softc *sc); 104184610Salfredstatic void zyd_cfg_set_beacon_interval(struct zyd_softc *sc, uint32_t interval); 105184610Salfredstatic const char *zyd_rf_name(uint8_t type); 106184610Salfredstatic void zyd_cfg_rf_rfmd_init(struct zyd_softc *sc, struct zyd_rf *rf); 107184610Salfredstatic void zyd_cfg_rf_rfmd_switch_radio(struct zyd_softc *sc, uint8_t onoff); 108184610Salfredstatic void zyd_cfg_rf_rfmd_set_channel(struct zyd_softc *sc, struct zyd_rf *rf, uint8_t channel); 109184610Salfredstatic void zyd_cfg_rf_al2230_switch_radio(struct zyd_softc *sc, uint8_t onoff); 110184610Salfredstatic void zyd_cfg_rf_al2230_init(struct zyd_softc *sc, struct zyd_rf *rf); 111184610Salfredstatic void zyd_cfg_rf_al2230_init_b(struct zyd_softc *sc, struct zyd_rf *rf); 112184610Salfredstatic void zyd_cfg_rf_al2230_set_channel(struct zyd_softc *sc, struct zyd_rf *rf, uint8_t channel); 113184610Salfredstatic uint8_t zyd_cfg_rf_init_hw(struct zyd_softc *sc, struct zyd_rf *rf); 114184610Salfredstatic uint8_t zyd_cfg_hw_init(struct zyd_softc *sc); 115184610Salfredstatic void zyd_cfg_set_mac_addr(struct zyd_softc *sc, const uint8_t *addr); 116184610Salfredstatic void zyd_cfg_switch_radio(struct zyd_softc *sc, uint8_t onoff); 117184610Salfredstatic void zyd_cfg_set_bssid(struct zyd_softc *sc, uint8_t *addr); 118184610Salfredstatic void zyd_start_cb(struct ifnet *ifp); 119184610Salfredstatic void zyd_init_cb(void *arg); 120184610Salfredstatic int zyd_ioctl_cb(struct ifnet *ifp, u_long command, caddr_t data); 121184610Salfredstatic void zyd_watchdog(void *arg); 122184610Salfredstatic void zyd_end_of_commands(struct zyd_softc *sc); 123184610Salfredstatic void zyd_newassoc_cb(struct ieee80211_node *ni, int isnew); 124184610Salfredstatic void zyd_scan_start_cb(struct ieee80211com *ic); 125184610Salfredstatic void zyd_scan_end_cb(struct ieee80211com *ic); 126184610Salfredstatic void zyd_set_channel_cb(struct ieee80211com *ic); 127184610Salfredstatic void zyd_cfg_set_led(struct zyd_softc *sc, uint32_t which, uint8_t on); 128184610Salfredstatic struct ieee80211vap *zyd_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, int opmode, int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]); 129184610Salfredstatic void zyd_vap_delete(struct ieee80211vap *); 130184610Salfredstatic struct ieee80211_node *zyd_node_alloc_cb(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]); 131184610Salfredstatic void zyd_cfg_set_run(struct zyd_softc *sc, struct usb2_config_td_cc *cc); 132184610Salfredstatic void zyd_fill_write_queue(struct zyd_softc *sc); 133184610Salfredstatic void zyd_tx_clean_queue(struct zyd_softc *sc); 134184610Salfredstatic void zyd_tx_freem(struct mbuf *m); 135184610Salfredstatic void zyd_tx_mgt(struct zyd_softc *sc, struct mbuf *m, struct ieee80211_node *ni); 136184610Salfredstatic struct ieee80211vap *zyd_get_vap(struct zyd_softc *sc); 137184610Salfredstatic void zyd_tx_data(struct zyd_softc *sc, struct mbuf *m, struct ieee80211_node *ni); 138184610Salfredstatic int zyd_raw_xmit_cb(struct ieee80211_node *ni, struct mbuf *m, const struct ieee80211_bpf_params *params); 139184610Salfredstatic void zyd_setup_desc_and_tx(struct zyd_softc *sc, struct mbuf *m, uint16_t rate); 140184610Salfredstatic int zyd_newstate_cb(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg); 141184610Salfredstatic void zyd_cfg_amrr_start(struct zyd_softc *sc); 142184610Salfredstatic void zyd_update_mcast_cb(struct ifnet *ifp); 143184610Salfredstatic void zyd_update_promisc_cb(struct ifnet *ifp); 144184610Salfred 145184610Salfredstatic const struct zyd_phy_pair zyd_def_phy[] = ZYD_DEF_PHY; 146184610Salfredstatic const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB; 147184610Salfred 148184610Salfred/* various supported device vendors/products */ 149184610Salfred#define ZYD_ZD1211 0 150184610Salfred#define ZYD_ZD1211B 1 151184610Salfred 152184610Salfredstatic const struct usb2_device_id zyd_devs[] = { 153184610Salfred /* ZYD_ZD1211 */ 154184610Salfred {USB_VPI(USB_VENDOR_3COM2, USB_PRODUCT_3COM2_3CRUSB10075, ZYD_ZD1211)}, 155184610Salfred {USB_VPI(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_WL54, ZYD_ZD1211)}, 156184610Salfred {USB_VPI(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_WL159G, ZYD_ZD1211)}, 157184610Salfred {USB_VPI(USB_VENDOR_CYBERTAN, USB_PRODUCT_CYBERTAN_TG54USB, ZYD_ZD1211)}, 158184610Salfred {USB_VPI(USB_VENDOR_DRAYTEK, USB_PRODUCT_DRAYTEK_VIGOR550, ZYD_ZD1211)}, 159184610Salfred {USB_VPI(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54GD, ZYD_ZD1211)}, 160184610Salfred {USB_VPI(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54GZL, ZYD_ZD1211)}, 161184610Salfred {USB_VPI(USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GWUS54GZ, ZYD_ZD1211)}, 162184610Salfred {USB_VPI(USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GWUS54MINI, ZYD_ZD1211)}, 163184610Salfred {USB_VPI(USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_XG760A, ZYD_ZD1211)}, 164184610Salfred {USB_VPI(USB_VENDOR_SENAO, USB_PRODUCT_SENAO_NUB8301, ZYD_ZD1211)}, 165184610Salfred {USB_VPI(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113, ZYD_ZD1211)}, 166184610Salfred {USB_VPI(USB_VENDOR_SWEEX, USB_PRODUCT_SWEEX_ZD1211, ZYD_ZD1211)}, 167184610Salfred {USB_VPI(USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_QUICKWLAN, ZYD_ZD1211)}, 168184610Salfred {USB_VPI(USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_ZD1211_1, ZYD_ZD1211)}, 169184610Salfred {USB_VPI(USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_ZD1211_2, ZYD_ZD1211)}, 170184610Salfred {USB_VPI(USB_VENDOR_TWINMOS, USB_PRODUCT_TWINMOS_G240, ZYD_ZD1211)}, 171184610Salfred {USB_VPI(USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_ALL0298V2, ZYD_ZD1211)}, 172184610Salfred {USB_VPI(USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UB_A, ZYD_ZD1211)}, 173184610Salfred {USB_VPI(USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UB, ZYD_ZD1211)}, 174184610Salfred {USB_VPI(USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_UR055G, ZYD_ZD1211)}, 175184610Salfred {USB_VPI(USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_ZD1211, ZYD_ZD1211)}, 176184610Salfred {USB_VPI(USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1211, ZYD_ZD1211)}, 177184610Salfred {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_AG225H, ZYD_ZD1211)}, 178184610Salfred {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_ZYAIRG220, ZYD_ZD1211)}, 179184610Salfred {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G200V2, ZYD_ZD1211)}, 180184610Salfred {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G202, ZYD_ZD1211)}, 181184610Salfred /* ZYD_ZD1211B */ 182184610Salfred {USB_VPI(USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_SMCWUSBG, ZYD_ZD1211B)}, 183184610Salfred {USB_VPI(USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_ZD1211B, ZYD_ZD1211B)}, 184184610Salfred {USB_VPI(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_A9T_WIFI, ZYD_ZD1211B)}, 185184610Salfred {USB_VPI(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050_V4000, ZYD_ZD1211B)}, 186184610Salfred {USB_VPI(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_ZD1211B, ZYD_ZD1211B)}, 187184610Salfred {USB_VPI(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSBF54G, ZYD_ZD1211B)}, 188184610Salfred {USB_VPI(USB_VENDOR_FIBERLINE, USB_PRODUCT_FIBERLINE_WL430U, ZYD_ZD1211B)}, 189184610Salfred {USB_VPI(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54L, ZYD_ZD1211B)}, 190184610Salfred {USB_VPI(USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_SNU5600, ZYD_ZD1211B)}, 191184610Salfred {USB_VPI(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GW_US54GXS, ZYD_ZD1211B)}, 192184610Salfred {USB_VPI(USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_XG76NA, ZYD_ZD1211B)}, 193184610Salfred {USB_VPI(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_ZD1211B, ZYD_ZD1211B)}, 194184610Salfred {USB_VPI(USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UBC1, ZYD_ZD1211B)}, 195184610Salfred {USB_VPI(USB_VENDOR_USR, USB_PRODUCT_USR_USR5423, ZYD_ZD1211B)}, 196184610Salfred {USB_VPI(USB_VENDOR_VTECH, USB_PRODUCT_VTECH_ZD1211B, ZYD_ZD1211B)}, 197184610Salfred {USB_VPI(USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_ZD1211B, ZYD_ZD1211B)}, 198184610Salfred {USB_VPI(USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1211B, ZYD_ZD1211B)}, 199184610Salfred {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_M202, ZYD_ZD1211B)}, 200184610Salfred {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G220V2, ZYD_ZD1211B)}, 201184610Salfred}; 202184610Salfred 203184610Salfredstatic const struct usb2_config zyd_config[ZYD_N_TRANSFER] = { 204184610Salfred [ZYD_TR_BULK_DT_WR] = { 205184610Salfred .type = UE_BULK, 206184610Salfred .endpoint = UE_ADDR_ANY, 207184610Salfred .direction = UE_DIR_OUT, 208184610Salfred .mh.bufsize = ZYD_MAX_TXBUFSZ, 209184610Salfred .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 210184610Salfred .mh.callback = &zyd_bulk_write_callback, 211184610Salfred .ep_index = 0, 212184610Salfred .mh.timeout = 10000, /* 10 seconds */ 213184610Salfred }, 214184610Salfred 215184610Salfred [ZYD_TR_BULK_DT_RD] = { 216184610Salfred .type = UE_BULK, 217184610Salfred .endpoint = UE_ADDR_ANY, 218184610Salfred .direction = UE_DIR_IN, 219184610Salfred .mh.bufsize = ZYX_MAX_RXBUFSZ, 220184610Salfred .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 221184610Salfred .mh.callback = &zyd_bulk_read_callback, 222184610Salfred .ep_index = 0, 223184610Salfred }, 224184610Salfred 225184610Salfred [ZYD_TR_BULK_CS_WR] = { 226184610Salfred .type = UE_CONTROL, 227184610Salfred .endpoint = 0x00, /* Control pipe */ 228184610Salfred .direction = UE_DIR_ANY, 229184610Salfred .mh.bufsize = sizeof(struct usb2_device_request), 230184610Salfred .mh.flags = {}, 231184610Salfred .mh.callback = &zyd_bulk_write_clear_stall_callback, 232184610Salfred .mh.timeout = 1000, /* 1 second */ 233184610Salfred .mh.interval = 50, /* 50ms */ 234184610Salfred }, 235184610Salfred 236184610Salfred [ZYD_TR_BULK_CS_RD] = { 237184610Salfred .type = UE_CONTROL, 238184610Salfred .endpoint = 0x00, /* Control pipe */ 239184610Salfred .direction = UE_DIR_ANY, 240184610Salfred .mh.bufsize = sizeof(struct usb2_device_request), 241184610Salfred .mh.flags = {}, 242184610Salfred .mh.callback = &zyd_bulk_read_clear_stall_callback, 243184610Salfred .mh.timeout = 1000, /* 1 second */ 244184610Salfred .mh.interval = 50, /* 50ms */ 245184610Salfred }, 246184610Salfred 247184610Salfred [ZYD_TR_INTR_DT_WR] = { 248184610Salfred .type = UE_BULK_INTR, 249184610Salfred .endpoint = UE_ADDR_ANY, 250184610Salfred .direction = UE_DIR_OUT, 251184610Salfred .mh.bufsize = sizeof(struct zyd_cmd), 252184610Salfred .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 253184610Salfred .mh.callback = &zyd_intr_write_callback, 254184610Salfred .mh.timeout = 1000, /* 1 second */ 255184610Salfred .ep_index = 1, 256184610Salfred }, 257184610Salfred 258184610Salfred [ZYD_TR_INTR_DT_RD] = { 259184610Salfred .type = UE_BULK_INTR, 260184610Salfred .endpoint = UE_ADDR_ANY, 261184610Salfred .direction = UE_DIR_IN, 262184610Salfred .mh.bufsize = sizeof(struct zyd_cmd), 263184610Salfred .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 264184610Salfred .mh.callback = &zyd_intr_read_callback, 265184610Salfred .ep_index = 1, 266184610Salfred }, 267184610Salfred 268184610Salfred [ZYD_TR_INTR_CS_WR] = { 269184610Salfred .type = UE_CONTROL, 270184610Salfred .endpoint = 0x00, /* Control pipe */ 271184610Salfred .direction = UE_DIR_ANY, 272184610Salfred .mh.bufsize = sizeof(struct usb2_device_request), 273184610Salfred .mh.flags = {}, 274184610Salfred .mh.callback = &zyd_intr_write_clear_stall_callback, 275184610Salfred .mh.timeout = 1000, /* 1 second */ 276184610Salfred .mh.interval = 50, /* 50ms */ 277184610Salfred }, 278184610Salfred 279184610Salfred [ZYD_TR_INTR_CS_RD] = { 280184610Salfred .type = UE_CONTROL, 281184610Salfred .endpoint = 0x00, /* Control pipe */ 282184610Salfred .direction = UE_DIR_ANY, 283184610Salfred .mh.bufsize = sizeof(struct usb2_device_request), 284184610Salfred .mh.flags = {}, 285184610Salfred .mh.callback = &zyd_intr_read_clear_stall_callback, 286184610Salfred .mh.timeout = 1000, /* 1 second */ 287184610Salfred .mh.interval = 50, /* 50ms */ 288184610Salfred }, 289184610Salfred}; 290184610Salfred 291184610Salfredstatic devclass_t zyd_devclass; 292184610Salfred 293184610Salfredstatic device_method_t zyd_methods[] = { 294184610Salfred DEVMETHOD(device_probe, zyd_probe), 295184610Salfred DEVMETHOD(device_attach, zyd_attach), 296184610Salfred DEVMETHOD(device_detach, zyd_detach), 297184610Salfred {0, 0} 298184610Salfred}; 299184610Salfred 300184610Salfredstatic driver_t zyd_driver = { 301184610Salfred .name = "zyd", 302184610Salfred .methods = zyd_methods, 303184610Salfred .size = sizeof(struct zyd_softc), 304184610Salfred}; 305184610Salfred 306184610SalfredDRIVER_MODULE(zyd, ushub, zyd_driver, zyd_devclass, NULL, 0); 307184610SalfredMODULE_DEPEND(zyd, usb2_wlan, 1, 1, 1); 308184610SalfredMODULE_DEPEND(zyd, usb2_core, 1, 1, 1); 309184610SalfredMODULE_DEPEND(zyd, wlan, 1, 1, 1); 310184610SalfredMODULE_DEPEND(zyd, wlan_amrr, 1, 1, 1); 311184610Salfred 312184610Salfredstatic uint8_t 313184610Salfredzyd_plcp2ieee(uint8_t signal, uint8_t isofdm) 314184610Salfred{ 315184610Salfred if (isofdm) { 316184610Salfred static const uint8_t ofdmrates[16] = 317184610Salfred {0, 0, 0, 0, 0, 0, 0, 96, 48, 24, 12, 108, 72, 36, 18}; 318184610Salfred 319184610Salfred return ofdmrates[signal & 0xf]; 320184610Salfred } else { 321184610Salfred static const uint8_t cckrates[16] = 322184610Salfred {0, 0, 0, 0, 4, 0, 0, 11, 0, 0, 2, 0, 0, 0, 22, 0}; 323184610Salfred 324184610Salfred return cckrates[signal & 0xf]; 325184610Salfred } 326184610Salfred} 327184610Salfred 328184610Salfred/* 329184610Salfred * USB request basic wrapper 330184610Salfred */ 331184610Salfredstatic void 332184610Salfredzyd_cfg_usbrequest(struct zyd_softc *sc, struct usb2_device_request *req, uint8_t *data) 333184610Salfred{ 334184610Salfred usb2_error_t err; 335184610Salfred uint16_t length; 336184610Salfred 337184610Salfred if (usb2_config_td_is_gone(&sc->sc_config_td)) { 338184610Salfred goto error; 339184610Salfred } 340184610Salfred err = usb2_do_request_flags 341184610Salfred (sc->sc_udev, &sc->sc_mtx, req, data, 0, NULL, 1000); 342184610Salfred 343184610Salfred if (err) { 344184610Salfred 345184610Salfred DPRINTFN(0, "%s: device request failed, err=%s " 346184610Salfred "(ignored)\n", sc->sc_name, usb2_errstr(err)); 347184610Salfred 348184610Salfrederror: 349184610Salfred length = UGETW(req->wLength); 350184610Salfred 351184610Salfred if ((req->bmRequestType & UT_READ) && length) { 352184610Salfred bzero(data, length); 353184610Salfred } 354184610Salfred } 355184610Salfred return; 356184610Salfred} 357184610Salfred 358184610Salfredstatic void 359184610Salfredzyd_intr_read_clear_stall_callback(struct usb2_xfer *xfer) 360184610Salfred{ 361184610Salfred struct zyd_softc *sc = xfer->priv_sc; 362184610Salfred struct usb2_xfer *xfer_other = sc->sc_xfer[ZYD_TR_INTR_DT_RD]; 363184610Salfred 364184610Salfred if (usb2_clear_stall_callback(xfer, xfer_other)) { 365184610Salfred DPRINTF("stall cleared\n"); 366184610Salfred sc->sc_flags &= ~ZYD_FLAG_INTR_READ_STALL; 367184610Salfred usb2_transfer_start(xfer_other); 368184610Salfred } 369184610Salfred return; 370184610Salfred} 371184610Salfred 372184610Salfred/* 373184610Salfred * Callback handler for interrupt transfer 374184610Salfred */ 375184610Salfredstatic void 376184610Salfredzyd_intr_read_callback(struct usb2_xfer *xfer) 377184610Salfred{ 378184610Salfred struct zyd_softc *sc = xfer->priv_sc; 379184610Salfred struct zyd_cmd *cmd = &sc->sc_intr_ibuf; 380184610Salfred uint32_t actlen; 381184610Salfred 382184610Salfred switch (USB_GET_STATE(xfer)) { 383184610Salfred case USB_ST_TRANSFERRED: 384184610Salfred 385184610Salfred actlen = xfer->actlen; 386184610Salfred 387184610Salfred DPRINTFN(3, "length=%d\n", actlen); 388184610Salfred 389184610Salfred if (actlen > sizeof(sc->sc_intr_ibuf)) { 390184610Salfred actlen = sizeof(sc->sc_intr_ibuf); 391184610Salfred } 392184610Salfred usb2_copy_out(xfer->frbuffers, 0, 393184610Salfred &sc->sc_intr_ibuf, actlen); 394184610Salfred 395184610Salfred switch (cmd->code) { 396184610Salfred case htole16(ZYD_NOTIF_RETRYSTATUS): 397184610Salfred goto handle_notif_retrystatus; 398184610Salfred case htole16(ZYD_NOTIF_IORD): 399184610Salfred goto handle_notif_iord; 400184610Salfred default: 401184610Salfred DPRINTFN(2, "unknown indication: 0x%04x\n", 402184610Salfred le16toh(cmd->code)); 403184610Salfred } 404184610Salfred 405184610Salfred /* fallthrough */ 406184610Salfred 407184610Salfred case USB_ST_SETUP: 408184610Salfredtr_setup: 409184610Salfred if (sc->sc_flags & ZYD_FLAG_INTR_READ_STALL) { 410184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_INTR_CS_RD]); 411184610Salfred break; 412184610Salfred } 413184610Salfred xfer->frlengths[0] = xfer->max_data_length; 414184610Salfred usb2_start_hardware(xfer); 415184610Salfred break; 416184610Salfred 417184610Salfred default: /* Error */ 418184610Salfred DPRINTFN(3, "error = %s\n", 419184610Salfred usb2_errstr(xfer->error)); 420184610Salfred 421184610Salfred if (xfer->error != USB_ERR_CANCELLED) { 422184610Salfred /* try to clear stall first */ 423184610Salfred sc->sc_flags |= ZYD_FLAG_INTR_READ_STALL; 424184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_INTR_CS_RD]); 425184610Salfred } 426184610Salfred break; 427184610Salfred } 428184610Salfred return; 429184610Salfred 430184610Salfredhandle_notif_retrystatus:{ 431184610Salfred 432184610Salfred struct zyd_notif_retry *retry = (void *)(cmd->data); 433184610Salfred struct ifnet *ifp = sc->sc_ifp; 434184610Salfred struct ieee80211vap *vap; 435184610Salfred struct ieee80211_node *ni; 436184610Salfred 437184610Salfred DPRINTF("retry intr: rate=0x%x " 438184610Salfred "addr=%02x:%02x:%02x:%02x:%02x:%02x count=%d (0x%x)\n", 439184610Salfred le16toh(retry->rate), retry->macaddr[0], retry->macaddr[1], 440184610Salfred retry->macaddr[2], retry->macaddr[3], retry->macaddr[4], 441184610Salfred retry->macaddr[5], le16toh(retry->count) & 0xff, 442184610Salfred le16toh(retry->count)); 443184610Salfred 444184610Salfred vap = zyd_get_vap(sc); 445184610Salfred if ((vap != NULL) && (sc->sc_amrr_timer)) { 446184610Salfred /* 447184610Salfred * Find the node to which the packet was sent 448184610Salfred * and update its retry statistics. In BSS 449184610Salfred * mode, this node is the AP we're associated 450184610Salfred * to so no lookup is actually needed. 451184610Salfred */ 452184610Salfred ni = ieee80211_find_txnode(vap, retry->macaddr); 453184610Salfred if (ni != NULL) { 454184610Salfred ieee80211_amrr_tx_complete(&ZYD_NODE(ni)->amn, 455184610Salfred IEEE80211_AMRR_FAILURE, 1); 456184610Salfred ieee80211_free_node(ni); 457184610Salfred } 458184610Salfred } 459184610Salfred if (retry->count & htole16(0x100)) { 460184610Salfred ifp->if_oerrors++; /* too many retries */ 461184610Salfred } 462184610Salfred goto tr_setup; 463184610Salfred } 464184610Salfred 465184610Salfredhandle_notif_iord: 466184610Salfred 467184610Salfred if (*(uint16_t *)cmd->data == htole16(ZYD_CR_INTERRUPT)) { 468184610Salfred goto tr_setup; /* HMAC interrupt */ 469184610Salfred } 470184610Salfred if (actlen < 4) { 471184610Salfred DPRINTFN(0, "too short, %u bytes\n", actlen); 472184610Salfred goto tr_setup; /* too short */ 473184610Salfred } 474184610Salfred actlen -= 4; 475184610Salfred 476184610Salfred sc->sc_intr_ilen = actlen; 477184610Salfred 478184610Salfred if (sc->sc_intr_iwakeup) { 479184610Salfred sc->sc_intr_iwakeup = 0; 480184610Salfred usb2_cv_signal(&sc->sc_intr_cv); 481184610Salfred } else { 482184610Salfred sc->sc_intr_iwakeup = 1; 483184610Salfred } 484184610Salfred /* 485184610Salfred * We pause reading data from the interrupt endpoint until the 486184610Salfred * data has been picked up! 487184610Salfred */ 488184610Salfred return; 489184610Salfred} 490184610Salfred 491184610Salfred/* 492184610Salfred * Interrupt call reply transfer, read 493184610Salfred */ 494184610Salfredstatic void 495184610Salfredzyd_cfg_usb2_intr_read(struct zyd_softc *sc, void *data, uint32_t size) 496184610Salfred{ 497184610Salfred uint16_t actlen; 498184610Salfred uint16_t x; 499184610Salfred 500184610Salfred if (size > sizeof(sc->sc_intr_ibuf.data)) { 501184610Salfred DPRINTFN(0, "truncating transfer size!\n"); 502184610Salfred size = sizeof(sc->sc_intr_ibuf.data); 503184610Salfred } 504184610Salfred if (usb2_config_td_is_gone(&sc->sc_config_td)) { 505184610Salfred bzero(data, size); 506184610Salfred goto done; 507184610Salfred } 508184610Salfred if (sc->sc_intr_iwakeup) { 509184610Salfred DPRINTF("got data already!\n"); 510184610Salfred sc->sc_intr_iwakeup = 0; 511184610Salfred goto skip0; 512184610Salfred } 513184610Salfredrepeat: 514184610Salfred sc->sc_intr_iwakeup = 1; 515184610Salfred 516184610Salfred while (sc->sc_intr_iwakeup) { 517184610Salfred 518184610Salfred /* wait for data */ 519184610Salfred 520184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_INTR_DT_RD]); 521184610Salfred 522184610Salfred if (usb2_cv_timedwait(&sc->sc_intr_cv, 523184610Salfred &sc->sc_mtx, hz / 2)) { 524184610Salfred /* should not happen */ 525184610Salfred } 526184610Salfred if (usb2_config_td_is_gone(&sc->sc_config_td)) { 527184610Salfred bzero(data, size); 528184610Salfred goto done; 529184610Salfred } 530184610Salfred } 531184610Salfredskip0: 532184610Salfred if (size != sc->sc_intr_ilen) { 533184610Salfred DPRINTFN(0, "unexpected length %u != %u\n", 534184610Salfred size, sc->sc_intr_ilen); 535184610Salfred goto repeat; 536184610Salfred } 537184610Salfred actlen = sc->sc_intr_ilen; 538184610Salfred actlen /= 4; 539184610Salfred 540184610Salfred /* verify register values */ 541184610Salfred for (x = 0; x != actlen; x++) { 542184610Salfred if (sc->sc_intr_obuf.data[(2 * x)] != 543184610Salfred sc->sc_intr_ibuf.data[(4 * x)]) { 544184610Salfred /* invalid register */ 545184610Salfred DPRINTFN(0, "Invalid register (1) at %u!\n", x); 546184610Salfred goto repeat; 547184610Salfred } 548184610Salfred if (sc->sc_intr_obuf.data[(2 * x) + 1] != 549184610Salfred sc->sc_intr_ibuf.data[(4 * x) + 1]) { 550184610Salfred /* invalid register */ 551184610Salfred DPRINTFN(0, "Invalid register (2) at %u!\n", x); 552184610Salfred goto repeat; 553184610Salfred } 554184610Salfred } 555184610Salfred 556184610Salfred bcopy(sc->sc_intr_ibuf.data, data, size); 557184610Salfred 558184610Salfred /* 559184610Salfred * We have fetched the data from the shared buffer and it is 560184610Salfred * safe to restart the interrupt transfer! 561184610Salfred */ 562184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_INTR_DT_RD]); 563184610Salfreddone: 564184610Salfred return; 565184610Salfred} 566184610Salfred 567184610Salfredstatic void 568184610Salfredzyd_intr_write_clear_stall_callback(struct usb2_xfer *xfer) 569184610Salfred{ 570184610Salfred struct zyd_softc *sc = xfer->priv_sc; 571184610Salfred struct usb2_xfer *xfer_other = sc->sc_xfer[ZYD_TR_INTR_DT_WR]; 572184610Salfred 573184610Salfred if (usb2_clear_stall_callback(xfer, xfer_other)) { 574184610Salfred DPRINTF("stall cleared\n"); 575184610Salfred sc->sc_flags &= ~ZYD_FLAG_INTR_WRITE_STALL; 576184610Salfred usb2_transfer_start(xfer_other); 577184610Salfred } 578184610Salfred return; 579184610Salfred} 580184610Salfred 581184610Salfredstatic void 582184610Salfredzyd_intr_write_callback(struct usb2_xfer *xfer) 583184610Salfred{ 584184610Salfred struct zyd_softc *sc = xfer->priv_sc; 585184610Salfred 586184610Salfred switch (USB_GET_STATE(xfer)) { 587184610Salfred case USB_ST_TRANSFERRED: 588184610Salfred DPRINTFN(3, "length=%d\n", xfer->actlen); 589184610Salfred goto wakeup; 590184610Salfred 591184610Salfred case USB_ST_SETUP: 592184610Salfred 593184610Salfred if (sc->sc_flags & ZYD_FLAG_INTR_WRITE_STALL) { 594184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_INTR_CS_WR]); 595184610Salfred goto wakeup; 596184610Salfred } 597184610Salfred if (sc->sc_intr_owakeup) { 598184610Salfred usb2_copy_in(xfer->frbuffers, 0, &sc->sc_intr_obuf, 599184610Salfred sc->sc_intr_olen); 600184610Salfred 601184610Salfred xfer->frlengths[0] = sc->sc_intr_olen; 602184610Salfred usb2_start_hardware(xfer); 603184610Salfred } 604184610Salfred break; 605184610Salfred 606184610Salfred default: /* Error */ 607184610Salfred DPRINTFN(3, "error = %s\n", 608184610Salfred usb2_errstr(xfer->error)); 609184610Salfred 610184610Salfred if (xfer->error != USB_ERR_CANCELLED) { 611184610Salfred /* try to clear stall first */ 612184610Salfred sc->sc_flags |= ZYD_FLAG_INTR_WRITE_STALL; 613184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_INTR_CS_WR]); 614184610Salfred } 615184610Salfred goto wakeup; 616184610Salfred } 617184610Salfred return; 618184610Salfred 619184610Salfredwakeup: 620184610Salfred if (sc->sc_intr_owakeup) { 621184610Salfred sc->sc_intr_owakeup = 0; 622184610Salfred usb2_cv_signal(&sc->sc_intr_cv); 623184610Salfred } 624184610Salfred return; 625184610Salfred} 626184610Salfred 627184610Salfred/* 628184610Salfred * Interrupt transfer, write. 629184610Salfred * 630184610Salfred * Not always an "interrupt transfer". If operating in 631184610Salfred * full speed mode, EP4 is bulk out, not interrupt out. 632184610Salfred */ 633184610Salfredstatic void 634184610Salfredzyd_cfg_usb2_intr_write(struct zyd_softc *sc, const void *data, 635184610Salfred uint16_t code, uint32_t size) 636184610Salfred{ 637184610Salfred if (size > sizeof(sc->sc_intr_obuf.data)) { 638184610Salfred DPRINTFN(0, "truncating transfer size!\n"); 639184610Salfred size = sizeof(sc->sc_intr_obuf.data); 640184610Salfred } 641184610Salfred if (usb2_config_td_is_gone(&sc->sc_config_td)) { 642184610Salfred goto done; 643184610Salfred } 644184610Salfred sc->sc_intr_olen = size + 2; 645184610Salfred sc->sc_intr_owakeup = 1; 646184610Salfred 647184610Salfred sc->sc_intr_obuf.code = htole16(code); 648184610Salfred bcopy(data, sc->sc_intr_obuf.data, size); 649184610Salfred 650184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_INTR_DT_WR]); 651184610Salfred 652184610Salfred while (sc->sc_intr_owakeup) { 653184610Salfred if (usb2_cv_timedwait(&sc->sc_intr_cv, 654184610Salfred &sc->sc_mtx, hz / 2)) { 655184610Salfred /* should not happen */ 656184610Salfred } 657184610Salfred if (usb2_config_td_is_gone(&sc->sc_config_td)) { 658184610Salfred sc->sc_intr_owakeup = 0; 659184610Salfred goto done; 660184610Salfred } 661184610Salfred } 662184610Salfreddone: 663184610Salfred return; 664184610Salfred} 665184610Salfred 666184610Salfredstatic void 667184610Salfredzyd_cfg_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, uint16_t ilen, 668184610Salfred void *odata, uint16_t olen, uint16_t flags) 669184610Salfred{ 670184610Salfred zyd_cfg_usb2_intr_write(sc, idata, code, ilen); 671184610Salfred 672184610Salfred if (flags & ZYD_CMD_FLAG_READ) { 673184610Salfred zyd_cfg_usb2_intr_read(sc, odata, olen); 674184610Salfred } 675184610Salfred return; 676184610Salfred} 677184610Salfred 678184610Salfredstatic void 679184610Salfredzyd_cfg_read16(struct zyd_softc *sc, uint16_t addr, uint16_t *value) 680184610Salfred{ 681184610Salfred struct zyd_pair tmp[1]; 682184610Salfred 683184610Salfred addr = htole16(addr); 684184610Salfred zyd_cfg_cmd(sc, ZYD_CMD_IORD, &addr, sizeof(addr), 685184610Salfred tmp, sizeof(tmp), ZYD_CMD_FLAG_READ); 686184610Salfred *value = le16toh(tmp[0].val); 687184610Salfred return; 688184610Salfred} 689184610Salfred 690184610Salfredstatic void 691184610Salfredzyd_cfg_read32(struct zyd_softc *sc, uint16_t addr, uint32_t *value) 692184610Salfred{ 693184610Salfred struct zyd_pair tmp[2]; 694184610Salfred uint16_t regs[2]; 695184610Salfred 696184610Salfred regs[0] = ZYD_REG32_HI(addr); 697184610Salfred regs[1] = ZYD_REG32_LO(addr); 698184610Salfred regs[0] = htole16(regs[0]); 699184610Salfred regs[1] = htole16(regs[1]); 700184610Salfred 701184610Salfred zyd_cfg_cmd(sc, ZYD_CMD_IORD, regs, sizeof(regs), 702184610Salfred tmp, sizeof(tmp), ZYD_CMD_FLAG_READ); 703184610Salfred *value = (le16toh(tmp[0].val) << 16) | le16toh(tmp[1].val); 704184610Salfred return; 705184610Salfred} 706184610Salfred 707184610Salfredstatic void 708184610Salfredzyd_cfg_write16(struct zyd_softc *sc, uint16_t reg, uint16_t val) 709184610Salfred{ 710184610Salfred struct zyd_pair pair[1]; 711184610Salfred 712184610Salfred pair[0].reg = htole16(reg); 713184610Salfred pair[0].val = htole16(val); 714184610Salfred 715184610Salfred zyd_cfg_cmd(sc, ZYD_CMD_IOWR, pair, sizeof(pair), NULL, 0, 0); 716184610Salfred return; 717184610Salfred} 718184610Salfred 719184610Salfredstatic void 720184610Salfredzyd_cfg_write32(struct zyd_softc *sc, uint16_t reg, uint32_t val) 721184610Salfred{ 722184610Salfred struct zyd_pair pair[2]; 723184610Salfred 724184610Salfred pair[0].reg = htole16(ZYD_REG32_HI(reg)); 725184610Salfred pair[0].val = htole16(val >> 16); 726184610Salfred pair[1].reg = htole16(ZYD_REG32_LO(reg)); 727184610Salfred pair[1].val = htole16(val & 0xffff); 728184610Salfred 729184610Salfred zyd_cfg_cmd(sc, ZYD_CMD_IOWR, pair, sizeof(pair), NULL, 0, 0); 730184610Salfred return; 731184610Salfred} 732184610Salfred 733184610Salfred/*------------------------------------------------------------------------* 734184610Salfred * zyd_cfg_rfwrite - write RF registers 735184610Salfred *------------------------------------------------------------------------*/ 736184610Salfredstatic void 737184610Salfredzyd_cfg_rfwrite(struct zyd_softc *sc, uint32_t value) 738184610Salfred{ 739184610Salfred struct zyd_rf *rf = &sc->sc_rf; 740184610Salfred struct zyd_rfwrite req; 741184610Salfred uint16_t cr203; 742184610Salfred uint16_t i; 743184610Salfred 744184610Salfred zyd_cfg_read16(sc, ZYD_CR203, &cr203); 745184610Salfred cr203 &= ~(ZYD_RF_IF_LE | ZYD_RF_CLK | ZYD_RF_DATA); 746184610Salfred 747184610Salfred req.code = htole16(2); 748184610Salfred req.width = htole16(rf->width); 749184610Salfred for (i = 0; i != rf->width; i++) { 750184610Salfred req.bit[i] = htole16(cr203); 751184610Salfred if (value & (1 << (rf->width - 1 - i))) 752184610Salfred req.bit[i] |= htole16(ZYD_RF_DATA); 753184610Salfred } 754184610Salfred zyd_cfg_cmd(sc, ZYD_CMD_RFCFG, &req, 4 + (2 * rf->width), NULL, 0, 0); 755184610Salfred return; 756184610Salfred} 757184610Salfred 758184610Salfredstatic void 759184610Salfredzyd_bulk_read_clear_stall_callback(struct usb2_xfer *xfer) 760184610Salfred{ 761184610Salfred struct zyd_softc *sc = xfer->priv_sc; 762184610Salfred struct usb2_xfer *xfer_other = sc->sc_xfer[ZYD_TR_BULK_DT_RD]; 763184610Salfred 764184610Salfred if (usb2_clear_stall_callback(xfer, xfer_other)) { 765184610Salfred DPRINTF("stall cleared\n"); 766184610Salfred sc->sc_flags &= ~ZYD_FLAG_BULK_READ_STALL; 767184610Salfred usb2_transfer_start(xfer_other); 768184610Salfred } 769184610Salfred return; 770184610Salfred} 771184610Salfred 772184610Salfredstatic void 773184610Salfredzyd_bulk_read_callback_sub(struct usb2_xfer *xfer, struct zyd_ifq *mq, 774184610Salfred uint32_t offset, uint16_t len) 775184610Salfred{ 776184610Salfred enum { 777184610Salfred ZYD_OVERHEAD = (ZYD_HW_PADDING + IEEE80211_CRC_LEN), 778184610Salfred }; 779184610Salfred struct zyd_softc *sc = xfer->priv_sc; 780184610Salfred struct ifnet *ifp = sc->sc_ifp; 781184610Salfred struct zyd_plcphdr plcp; 782184610Salfred struct zyd_rx_stat stat; 783184610Salfred struct mbuf *m; 784184610Salfred 785184610Salfred if (len < ZYD_OVERHEAD) { 786184610Salfred DPRINTF("frame too " 787184610Salfred "short (length=%d)\n", len); 788184610Salfred ifp->if_ierrors++; 789184610Salfred return; 790184610Salfred } 791184610Salfred usb2_copy_out(xfer->frbuffers, offset, &plcp, sizeof(plcp)); 792184610Salfred usb2_copy_out(xfer->frbuffers, offset + len - sizeof(stat), 793184610Salfred &stat, sizeof(stat)); 794184610Salfred 795184610Salfred if (stat.flags & ZYD_RX_ERROR) { 796184610Salfred DPRINTF("RX status indicated " 797184610Salfred "error (0x%02x)\n", stat.flags); 798184610Salfred ifp->if_ierrors++; 799184610Salfred return; 800184610Salfred } 801184610Salfred /* compute actual frame length */ 802184610Salfred len -= ZYD_OVERHEAD; 803184610Salfred 804184610Salfred /* allocate a mbuf to store the frame */ 805184610Salfred if (len > MCLBYTES) { 806184610Salfred DPRINTF("too large frame, " 807184610Salfred "%u bytes\n", len); 808184610Salfred return; 809184610Salfred } else if (len > MHLEN) 810184610Salfred m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 811184610Salfred else 812184610Salfred m = m_gethdr(M_DONTWAIT, MT_DATA); 813184610Salfred 814184610Salfred if (m == NULL) { 815184610Salfred DPRINTF("could not allocate rx mbuf\n"); 816184610Salfred ifp->if_ierrors++; 817184610Salfred return; 818184610Salfred } 819184610Salfred m->m_pkthdr.rcvif = ifp; 820184610Salfred m->m_pkthdr.len = len; 821184610Salfred m->m_len = len; 822184610Salfred 823184610Salfred usb2_copy_out(xfer->frbuffers, offset + 824184610Salfred sizeof(plcp), m->m_data, len); 825184610Salfred 826184610Salfred if (bpf_peers_present(ifp->if_bpf)) { 827184610Salfred struct zyd_rx_radiotap_header *tap = &sc->sc_rxtap; 828184610Salfred 829184610Salfred tap->wr_flags = 0; 830184610Salfred if (stat.flags & (ZYD_RX_BADCRC16 | ZYD_RX_BADCRC32)) 831184610Salfred tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; 832184610Salfred /* XXX toss, no way to express errors */ 833184610Salfred if (stat.flags & ZYD_RX_DECRYPTERR) 834184610Salfred tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; 835184610Salfred tap->wr_rate = 836184610Salfred zyd_plcp2ieee(plcp.signal, stat.flags & ZYD_RX_OFDM); 837184610Salfred tap->wr_antsignal = stat.rssi + -95; 838184610Salfred tap->wr_antnoise = -95; /* XXX */ 839184610Salfred 840184610Salfred bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m); 841184610Salfred } 842184610Salfred if (sizeof(m->m_hdr.pad) > 0) { 843184610Salfred m->m_hdr.pad[0] = stat.rssi; /* XXX hack */ 844184610Salfred } 845184610Salfred _IF_ENQUEUE(mq, m); 846184610Salfred 847184610Salfred return; 848184610Salfred} 849184610Salfred 850184610Salfredstatic void 851184610Salfredzyd_bulk_read_callback(struct usb2_xfer *xfer) 852184610Salfred{ 853184610Salfred struct zyd_softc *sc = xfer->priv_sc; 854184610Salfred struct ifnet *ifp = sc->sc_ifp; 855184610Salfred struct ieee80211com *ic = ifp->if_l2com; 856184610Salfred struct ieee80211_node *ni; 857184610Salfred struct zyd_rx_desc rx_desc; 858184610Salfred struct zyd_ifq mq = {NULL, NULL, 0}; 859184610Salfred struct mbuf *m; 860184610Salfred uint32_t offset; 861184610Salfred uint16_t len16; 862184610Salfred uint8_t x; 863184610Salfred uint8_t rssi; 864184610Salfred int8_t nf; 865184610Salfred 866184610Salfred switch (USB_GET_STATE(xfer)) { 867184610Salfred case USB_ST_TRANSFERRED: 868184610Salfred 869184610Salfred if (xfer->actlen < MAX(sizeof(rx_desc), ZYD_MIN_FRAGSZ)) { 870184610Salfred DPRINTFN(0, "xfer too short, %d bytes\n", xfer->actlen); 871184610Salfred ifp->if_ierrors++; 872184610Salfred goto tr_setup; 873184610Salfred } 874184610Salfred usb2_copy_out(xfer->frbuffers, xfer->actlen - sizeof(rx_desc), 875184610Salfred &rx_desc, sizeof(rx_desc)); 876184610Salfred 877184610Salfred if (UGETW(rx_desc.tag) == ZYD_TAG_MULTIFRAME) { 878184610Salfred 879184610Salfred offset = 0; 880184610Salfred 881184610Salfred DPRINTFN(4, "received multi-frame transfer, " 882184610Salfred "%u bytes\n", xfer->actlen); 883184610Salfred 884184610Salfred for (x = 0; x < ZYD_MAX_RXFRAMECNT; x++) { 885184610Salfred len16 = UGETW(rx_desc.len[x]); 886184610Salfred 887184610Salfred if ((len16 == 0) || (len16 > xfer->actlen)) { 888184610Salfred break; 889184610Salfred } 890184610Salfred zyd_bulk_read_callback_sub(xfer, &mq, offset, len16); 891184610Salfred 892184610Salfred /* 893184610Salfred * next frame is aligned on a 32-bit 894184610Salfred * boundary 895184610Salfred */ 896184610Salfred len16 = (len16 + 3) & ~3; 897184610Salfred offset += len16; 898184610Salfred if (len16 > xfer->actlen) { 899184610Salfred break; 900184610Salfred } 901184610Salfred xfer->actlen -= len16; 902184610Salfred } 903184610Salfred } else { 904184610Salfred DPRINTFN(4, "received single-frame transfer, " 905184610Salfred "%u bytes\n", xfer->actlen); 906184610Salfred zyd_bulk_read_callback_sub(xfer, &mq, 0, xfer->actlen); 907184610Salfred } 908184610Salfred 909184610Salfred case USB_ST_SETUP: 910184610Salfredtr_setup: 911184610Salfred DPRINTF("setup\n"); 912184610Salfred 913184610Salfred if (sc->sc_flags & ZYD_FLAG_BULK_READ_STALL) { 914184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_BULK_CS_RD]); 915184610Salfred } else { 916184610Salfred xfer->frlengths[0] = xfer->max_data_length; 917184610Salfred usb2_start_hardware(xfer); 918184610Salfred } 919184610Salfred 920184610Salfred /* 921184610Salfred * At the end of a USB callback it is always safe to unlock 922184610Salfred * the private mutex of a device! That is why we do the 923184610Salfred * "ieee80211_input" here, and not some lines up! 924184610Salfred */ 925184610Salfred if (mq.ifq_head) { 926184610Salfred 927184610Salfred mtx_unlock(&sc->sc_mtx); 928184610Salfred 929184610Salfred while (1) { 930184610Salfred 931184610Salfred _IF_DEQUEUE(&mq, m); 932184610Salfred 933184610Salfred if (m == NULL) 934184610Salfred break; 935184610Salfred 936184610Salfred rssi = m->m_hdr.pad[0]; /* XXX hack */ 937184610Salfred 938184610Salfred rssi = (rssi > 63) ? 127 : 2 * rssi; 939184610Salfred nf = -95; /* XXX */ 940184610Salfred 941184610Salfred ni = ieee80211_find_rxnode(ic, mtod(m, struct ieee80211_frame_min *)); 942184610Salfred if (ni != NULL) { 943184610Salfred if (ieee80211_input(ni, m, rssi, nf, 0)) { 944184610Salfred /* ignore */ 945184610Salfred } 946184610Salfred ieee80211_free_node(ni); 947184610Salfred } else { 948184610Salfred if (ieee80211_input_all(ic, m, rssi, nf, 0)) { 949184610Salfred /* ignore */ 950184610Salfred } 951184610Salfred } 952184610Salfred } 953184610Salfred 954184610Salfred mtx_lock(&sc->sc_mtx); 955184610Salfred } 956184610Salfred break; 957184610Salfred 958184610Salfred default: /* Error */ 959184610Salfred DPRINTF("frame error: %s\n", usb2_errstr(xfer->error)); 960184610Salfred 961184610Salfred if (xfer->error != USB_ERR_CANCELLED) { 962184610Salfred /* try to clear stall first */ 963184610Salfred sc->sc_flags |= ZYD_FLAG_BULK_READ_STALL; 964184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_BULK_CS_RD]); 965184610Salfred } 966184610Salfred break; 967184610Salfred } 968184610Salfred return; 969184610Salfred} 970184610Salfred 971184610Salfred/*------------------------------------------------------------------------* 972184610Salfred * zyd_cfg_uploadfirmware 973184610Salfred * Returns: 974184610Salfred * 0: Success 975184610Salfred * Else: Failure 976184610Salfred *------------------------------------------------------------------------*/ 977184610Salfredstatic uint8_t 978184610Salfredzyd_cfg_uploadfirmware(struct zyd_softc *sc, const uint8_t *fw_ptr, 979184610Salfred uint32_t fw_len) 980184610Salfred{ 981184610Salfred struct usb2_device_request req; 982184610Salfred uint16_t temp; 983184610Salfred uint16_t addr; 984184610Salfred uint8_t stat; 985184610Salfred 986184610Salfred DPRINTF("firmware %p size=%u\n", fw_ptr, fw_len); 987184610Salfred 988184610Salfred req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 989184610Salfred req.bRequest = ZYD_DOWNLOADREQ; 990184610Salfred USETW(req.wIndex, 0); 991184610Salfred 992184610Salfred temp = 64; 993184610Salfred 994184610Salfred addr = ZYD_FIRMWARE_START_ADDR; 995184610Salfred while (fw_len > 0) { 996184610Salfred 997184610Salfred if (fw_len < 64) { 998184610Salfred temp = fw_len; 999184610Salfred } 1000184610Salfred DPRINTF("firmware block: fw_len=%u\n", fw_len); 1001184610Salfred 1002184610Salfred USETW(req.wValue, addr); 1003184610Salfred USETW(req.wLength, temp); 1004184610Salfred 1005184610Salfred zyd_cfg_usbrequest(sc, &req, 1006184610Salfred USB_ADD_BYTES(fw_ptr, 0)); 1007184610Salfred 1008184610Salfred addr += (temp / 2); 1009184610Salfred fw_len -= temp; 1010184610Salfred fw_ptr += temp; 1011184610Salfred } 1012184610Salfred 1013184610Salfred /* check whether the upload succeeded */ 1014184610Salfred req.bmRequestType = UT_READ_VENDOR_DEVICE; 1015184610Salfred req.bRequest = ZYD_DOWNLOADSTS; 1016184610Salfred USETW(req.wValue, 0); 1017184610Salfred USETW(req.wIndex, 0); 1018184610Salfred USETW(req.wLength, sizeof(stat)); 1019184610Salfred 1020184610Salfred zyd_cfg_usbrequest(sc, &req, &stat); 1021184610Salfred 1022184610Salfred return ((stat & 0x80) ? 1 : 0); 1023184610Salfred} 1024184610Salfred 1025184610Salfred/* 1026184610Salfred * Driver OS interface 1027184610Salfred */ 1028184610Salfred 1029184610Salfred/* 1030184610Salfred * Probe for a ZD1211-containing product 1031184610Salfred */ 1032184610Salfredstatic int 1033184610Salfredzyd_probe(device_t dev) 1034184610Salfred{ 1035184610Salfred struct usb2_attach_arg *uaa = device_get_ivars(dev); 1036184610Salfred 1037184610Salfred if (uaa->usb2_mode != USB_MODE_HOST) { 1038184610Salfred return (ENXIO); 1039184610Salfred } 1040184610Salfred if (uaa->info.bConfigIndex != 0) { 1041184610Salfred return (ENXIO); 1042184610Salfred } 1043184610Salfred if (uaa->info.bIfaceIndex != ZYD_IFACE_INDEX) { 1044184610Salfred return (ENXIO); 1045184610Salfred } 1046184610Salfred return (usb2_lookup_id_by_uaa(zyd_devs, sizeof(zyd_devs), uaa)); 1047184610Salfred} 1048184610Salfred 1049184610Salfred/* 1050184610Salfred * Attach the interface. Allocate softc structures, do 1051184610Salfred * setup and ethernet/BPF attach. 1052184610Salfred */ 1053184610Salfredstatic int 1054184610Salfredzyd_attach(device_t dev) 1055184610Salfred{ 1056184610Salfred struct usb2_attach_arg *uaa = device_get_ivars(dev); 1057184610Salfred struct zyd_softc *sc = device_get_softc(dev); 1058184610Salfred int error; 1059184610Salfred uint8_t iface_index; 1060184610Salfred 1061184610Salfred if (sc == NULL) { 1062184610Salfred return (ENOMEM); 1063184610Salfred } 1064184610Salfred if (uaa->info.bcdDevice < 0x4330) { 1065184610Salfred device_printf(dev, "device version mismatch: 0x%X " 1066184610Salfred "(only >= 43.30 supported)\n", 1067184610Salfred uaa->info.bcdDevice); 1068184610Salfred return (EINVAL); 1069184610Salfred } 1070184610Salfred device_set_usb2_desc(dev); 1071184610Salfred 1072184610Salfred snprintf(sc->sc_name, sizeof(sc->sc_name), "%s", 1073184610Salfred device_get_nameunit(dev)); 1074184610Salfred 1075184610Salfred sc->sc_unit = device_get_unit(dev); 1076184610Salfred sc->sc_udev = uaa->device; 1077184610Salfred sc->sc_mac_rev = USB_GET_DRIVER_INFO(uaa); 1078184610Salfred 1079184610Salfred mtx_init(&sc->sc_mtx, "zyd lock", MTX_NETWORK_LOCK, 1080184610Salfred MTX_DEF | MTX_RECURSE); 1081184610Salfred 1082184610Salfred usb2_cv_init(&sc->sc_intr_cv, "IWAIT"); 1083184610Salfred 1084184610Salfred usb2_callout_init_mtx(&sc->sc_watchdog, 1085184610Salfred &sc->sc_mtx, CALLOUT_RETURNUNLOCKED); 1086184610Salfred 1087184610Salfred /* 1088184610Salfred * Endpoint 1 = Bulk out (512b @ high speed / 64b @ full speed) 1089184610Salfred * Endpoint 2 = Bulk in (512b @ high speed / 64b @ full speed) 1090184610Salfred * Endpoint 3 = Intr in (64b) 1091184610Salfred * Endpoint 4 = Intr out @ high speed / bulk out @ full speed (64b) 1092184610Salfred */ 1093184610Salfred iface_index = ZYD_IFACE_INDEX; 1094184610Salfred error = usb2_transfer_setup(uaa->device, &iface_index, 1095184610Salfred sc->sc_xfer, zyd_config, ZYD_N_TRANSFER, sc, &sc->sc_mtx); 1096184610Salfred if (error) { 1097184610Salfred device_printf(dev, "could not allocate USB " 1098184610Salfred "transfers: %s\n", usb2_errstr(error)); 1099184610Salfred goto detach; 1100184610Salfred } 1101184610Salfred error = usb2_config_td_setup(&sc->sc_config_td, sc, &sc->sc_mtx, 1102184610Salfred &zyd_end_of_commands, sizeof(struct usb2_config_td_cc), 16); 1103184610Salfred if (error) { 1104184610Salfred device_printf(dev, "could not setup config " 1105184610Salfred "thread!\n"); 1106184610Salfred goto detach; 1107184610Salfred } 1108184610Salfred mtx_lock(&sc->sc_mtx); 1109184610Salfred 1110184610Salfred /* start setup */ 1111184610Salfred 1112184610Salfred usb2_config_td_queue_command 1113184610Salfred (&sc->sc_config_td, NULL, &zyd_cfg_first_time_setup, 0, 0); 1114184610Salfred 1115184610Salfred /* start watchdog (will exit mutex) */ 1116184610Salfred 1117184610Salfred zyd_watchdog(sc); 1118184610Salfred 1119184610Salfred return (0); 1120184610Salfred 1121184610Salfreddetach: 1122184610Salfred zyd_detach(dev); 1123184610Salfred return (ENXIO); 1124184610Salfred} 1125184610Salfred 1126184610Salfred/* 1127184610Salfred * Lock PHY registers 1128184610Salfred */ 1129184610Salfredstatic void 1130184610Salfredzyd_cfg_lock_phy(struct zyd_softc *sc) 1131184610Salfred{ 1132184610Salfred uint32_t temp; 1133184610Salfred 1134184610Salfred zyd_cfg_read32(sc, ZYD_MAC_MISC, &temp); 1135184610Salfred temp &= ~ZYD_UNLOCK_PHY_REGS; 1136184610Salfred zyd_cfg_write32(sc, ZYD_MAC_MISC, temp); 1137184610Salfred} 1138184610Salfred 1139184610Salfred/* 1140184610Salfred * Unlock PHY registers 1141184610Salfred */ 1142184610Salfredstatic void 1143184610Salfredzyd_cfg_unlock_phy(struct zyd_softc *sc) 1144184610Salfred{ 1145184610Salfred uint32_t temp; 1146184610Salfred 1147184610Salfred zyd_cfg_read32(sc, ZYD_MAC_MISC, &temp); 1148184610Salfred temp |= ZYD_UNLOCK_PHY_REGS; 1149184610Salfred zyd_cfg_write32(sc, ZYD_MAC_MISC, temp); 1150184610Salfred} 1151184610Salfred 1152184610Salfredstatic void 1153184610Salfredzyd_cfg_set_beacon_interval(struct zyd_softc *sc, uint32_t bintval) 1154184610Salfred{ 1155184610Salfred /* XXX this is probably broken.. */ 1156184610Salfred zyd_cfg_write32(sc, ZYD_CR_ATIM_WND_PERIOD, bintval - 2); 1157184610Salfred zyd_cfg_write32(sc, ZYD_CR_PRE_TBTT, bintval - 1); 1158184610Salfred zyd_cfg_write32(sc, ZYD_CR_BCN_INTERVAL, bintval); 1159184610Salfred return; 1160184610Salfred} 1161184610Salfred 1162184610Salfred/* 1163184610Salfred * Get RF name 1164184610Salfred */ 1165184610Salfredstatic const char * 1166184610Salfredzyd_rf_name(uint8_t type) 1167184610Salfred{ 1168184610Salfred static const char *const zyd_rfs[] = { 1169184610Salfred "unknown", "unknown", "UW2451", "UCHIP", "AL2230", 1170184610Salfred "AL7230B", "THETA", "AL2210", "MAXIM_NEW", "GCT", 1171184610Salfred "PV2000", "RALINK", "INTERSIL", "RFMD", "MAXIM_NEW2", 1172184610Salfred "PHILIPS" 1173184610Salfred }; 1174184610Salfred 1175184610Salfred return (zyd_rfs[(type > 15) ? 0 : type]); 1176184610Salfred} 1177184610Salfred 1178184610Salfred/* 1179184610Salfred * RF driver: Init for RFMD chip 1180184610Salfred */ 1181184610Salfredstatic void 1182184610Salfredzyd_cfg_rf_rfmd_init(struct zyd_softc *sc, struct zyd_rf *rf) 1183184610Salfred{ 1184184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_RFMD_PHY; 1185184610Salfred static const uint32_t rfini[] = ZYD_RFMD_RF; 1186184610Salfred uint32_t i; 1187184610Salfred 1188184610Salfred /* init RF-dependent PHY registers */ 1189184610Salfred for (i = 0; i != INDEXES(phyini); i++) { 1190184610Salfred zyd_cfg_write16(sc, phyini[i].reg, phyini[i].val); 1191184610Salfred } 1192184610Salfred 1193184610Salfred /* init RFMD radio */ 1194184610Salfred for (i = 0; i != INDEXES(rfini); i++) { 1195184610Salfred zyd_cfg_rfwrite(sc, rfini[i]); 1196184610Salfred } 1197184610Salfred return; 1198184610Salfred} 1199184610Salfred 1200184610Salfred/* 1201184610Salfred * RF driver: Switch radio on/off for RFMD chip 1202184610Salfred */ 1203184610Salfredstatic void 1204184610Salfredzyd_cfg_rf_rfmd_switch_radio(struct zyd_softc *sc, uint8_t on) 1205184610Salfred{ 1206184610Salfred zyd_cfg_write16(sc, ZYD_CR10, on ? 0x89 : 0x15); 1207184610Salfred zyd_cfg_write16(sc, ZYD_CR11, on ? 0x00 : 0x81); 1208184610Salfred return; 1209184610Salfred} 1210184610Salfred 1211184610Salfred/* 1212184610Salfred * RF driver: Channel setting for RFMD chip 1213184610Salfred */ 1214184610Salfredstatic void 1215184610Salfredzyd_cfg_rf_rfmd_set_channel(struct zyd_softc *sc, struct zyd_rf *rf, 1216184610Salfred uint8_t channel) 1217184610Salfred{ 1218184610Salfred static const struct { 1219184610Salfred uint32_t r1, r2; 1220184610Salfred } rfprog[] = ZYD_RFMD_CHANTABLE; 1221184610Salfred 1222184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1].r1); 1223184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1].r2); 1224184610Salfred return; 1225184610Salfred} 1226184610Salfred 1227184610Salfred/* 1228184610Salfred * RF driver: Switch radio on/off for AL2230 chip 1229184610Salfred */ 1230184610Salfredstatic void 1231184610Salfredzyd_cfg_rf_al2230_switch_radio(struct zyd_softc *sc, uint8_t on) 1232184610Salfred{ 1233184610Salfred uint8_t on251 = (sc->sc_mac_rev == ZYD_ZD1211) ? 0x3f : 0x7f; 1234184610Salfred 1235184610Salfred zyd_cfg_write16(sc, ZYD_CR11, on ? 0x00 : 0x04); 1236184610Salfred zyd_cfg_write16(sc, ZYD_CR251, on ? on251 : 0x2f); 1237184610Salfred return; 1238184610Salfred} 1239184610Salfred 1240184610Salfred/* 1241184610Salfred * RF driver: Init for AL2230 chip 1242184610Salfred */ 1243184610Salfredstatic void 1244184610Salfredzyd_cfg_rf_al2230_init(struct zyd_softc *sc, struct zyd_rf *rf) 1245184610Salfred{ 1246184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY; 1247184610Salfred static const uint32_t rfini[] = ZYD_AL2230_RF; 1248184610Salfred uint32_t i; 1249184610Salfred 1250184610Salfred /* init RF-dependent PHY registers */ 1251184610Salfred for (i = 0; i != INDEXES(phyini); i++) { 1252184610Salfred zyd_cfg_write16(sc, phyini[i].reg, phyini[i].val); 1253184610Salfred } 1254184610Salfred 1255184610Salfred /* init AL2230 radio */ 1256184610Salfred for (i = 0; i != INDEXES(rfini); i++) { 1257184610Salfred zyd_cfg_rfwrite(sc, rfini[i]); 1258184610Salfred } 1259184610Salfred return; 1260184610Salfred} 1261184610Salfred 1262184610Salfredstatic void 1263184610Salfredzyd_cfg_rf_al2230_init_b(struct zyd_softc *sc, struct zyd_rf *rf) 1264184610Salfred{ 1265184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY_B; 1266184610Salfred static const uint32_t rfini[] = ZYD_AL2230_RF_B; 1267184610Salfred uint32_t i; 1268184610Salfred 1269184610Salfred /* init RF-dependent PHY registers */ 1270184610Salfred for (i = 0; i != INDEXES(phyini); i++) { 1271184610Salfred zyd_cfg_write16(sc, phyini[i].reg, phyini[i].val); 1272184610Salfred } 1273184610Salfred 1274184610Salfred /* init AL2230 radio */ 1275184610Salfred for (i = 0; i != INDEXES(rfini); i++) { 1276184610Salfred zyd_cfg_rfwrite(sc, rfini[i]); 1277184610Salfred } 1278184610Salfred return; 1279184610Salfred} 1280184610Salfred 1281184610Salfred/* 1282184610Salfred * RF driver: Channel setting for AL2230 chip 1283184610Salfred */ 1284184610Salfredstatic void 1285184610Salfredzyd_cfg_rf_al2230_set_channel(struct zyd_softc *sc, struct zyd_rf *rf, 1286184610Salfred uint8_t channel) 1287184610Salfred{ 1288184610Salfred static const struct { 1289184610Salfred uint32_t r1, r2, r3; 1290184610Salfred } rfprog[] = ZYD_AL2230_CHANTABLE; 1291184610Salfred 1292184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1].r1); 1293184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1].r2); 1294184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1].r3); 1295184610Salfred 1296184610Salfred zyd_cfg_write16(sc, ZYD_CR138, 0x28); 1297184610Salfred zyd_cfg_write16(sc, ZYD_CR203, 0x06); 1298184610Salfred return; 1299184610Salfred} 1300184610Salfred 1301184610Salfred/* 1302184610Salfred * AL7230B RF methods. 1303184610Salfred */ 1304184610Salfredstatic void 1305184610Salfredzyd_cfg_rf_al7230b_switch_radio(struct zyd_softc *sc, uint8_t on) 1306184610Salfred{ 1307184610Salfred zyd_cfg_write16(sc, ZYD_CR11, on ? 0x00 : 0x04); 1308184610Salfred zyd_cfg_write16(sc, ZYD_CR251, on ? 0x3f : 0x2f); 1309184610Salfred return; 1310184610Salfred} 1311184610Salfred 1312184610Salfredstatic void 1313184610Salfredzyd_cfg_rf_al7230b_init(struct zyd_softc *sc, struct zyd_rf *rf) 1314184610Salfred{ 1315184610Salfred static const struct zyd_phy_pair phyini_1[] = ZYD_AL7230B_PHY_1; 1316184610Salfred static const struct zyd_phy_pair phyini_2[] = ZYD_AL7230B_PHY_2; 1317184610Salfred static const struct zyd_phy_pair phyini_3[] = ZYD_AL7230B_PHY_3; 1318184610Salfred static const uint32_t rfini_1[] = ZYD_AL7230B_RF_1; 1319184610Salfred static const uint32_t rfini_2[] = ZYD_AL7230B_RF_2; 1320184610Salfred uint32_t i; 1321184610Salfred 1322184610Salfred /* for AL7230B, PHY and RF need to be initialized in "phases" */ 1323184610Salfred 1324184610Salfred /* init RF-dependent PHY registers, part one */ 1325184610Salfred for (i = 0; i != INDEXES(phyini_1); i++) { 1326184610Salfred zyd_cfg_write16(sc, phyini_1[i].reg, phyini_1[i].val); 1327184610Salfred } 1328184610Salfred /* init AL7230B radio, part one */ 1329184610Salfred for (i = 0; i != INDEXES(rfini_1); i++) { 1330184610Salfred zyd_cfg_rfwrite(sc, rfini_1[i]); 1331184610Salfred } 1332184610Salfred /* init RF-dependent PHY registers, part two */ 1333184610Salfred for (i = 0; i != INDEXES(phyini_2); i++) { 1334184610Salfred zyd_cfg_write16(sc, phyini_2[i].reg, phyini_2[i].val); 1335184610Salfred } 1336184610Salfred /* init AL7230B radio, part two */ 1337184610Salfred for (i = 0; i != INDEXES(rfini_2); i++) { 1338184610Salfred zyd_cfg_rfwrite(sc, rfini_2[i]); 1339184610Salfred } 1340184610Salfred /* init RF-dependent PHY registers, part three */ 1341184610Salfred for (i = 0; i != INDEXES(phyini_3); i++) { 1342184610Salfred zyd_cfg_write16(sc, phyini_3[i].reg, phyini_3[i].val); 1343184610Salfred } 1344184610Salfred return; 1345184610Salfred} 1346184610Salfred 1347184610Salfredstatic void 1348184610Salfredzyd_cfg_rf_al7230b_set_channel(struct zyd_softc *sc, struct zyd_rf *rf, 1349184610Salfred uint8_t channel) 1350184610Salfred{ 1351184610Salfred static const struct { 1352184610Salfred uint32_t r1, r2; 1353184610Salfred } rfprog[] = ZYD_AL7230B_CHANTABLE; 1354184610Salfred static const uint32_t rfsc[] = ZYD_AL7230B_RF_SETCHANNEL; 1355184610Salfred uint32_t i; 1356184610Salfred 1357184610Salfred zyd_cfg_write16(sc, ZYD_CR240, 0x57); 1358184610Salfred zyd_cfg_write16(sc, ZYD_CR251, 0x2f); 1359184610Salfred 1360184610Salfred for (i = 0; i != INDEXES(rfsc); i++) { 1361184610Salfred zyd_cfg_rfwrite(sc, rfsc[i]); 1362184610Salfred } 1363184610Salfred 1364184610Salfred zyd_cfg_write16(sc, ZYD_CR128, 0x14); 1365184610Salfred zyd_cfg_write16(sc, ZYD_CR129, 0x12); 1366184610Salfred zyd_cfg_write16(sc, ZYD_CR130, 0x10); 1367184610Salfred zyd_cfg_write16(sc, ZYD_CR38, 0x38); 1368184610Salfred zyd_cfg_write16(sc, ZYD_CR136, 0xdf); 1369184610Salfred 1370184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1].r1); 1371184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1].r2); 1372184610Salfred zyd_cfg_rfwrite(sc, 0x3c9000); 1373184610Salfred 1374184610Salfred zyd_cfg_write16(sc, ZYD_CR251, 0x3f); 1375184610Salfred zyd_cfg_write16(sc, ZYD_CR203, 0x06); 1376184610Salfred zyd_cfg_write16(sc, ZYD_CR240, 0x08); 1377184610Salfred 1378184610Salfred return; 1379184610Salfred} 1380184610Salfred 1381184610Salfred/* 1382184610Salfred * AL2210 RF methods. 1383184610Salfred */ 1384184610Salfredstatic void 1385184610Salfredzyd_cfg_rf_al2210_switch_radio(struct zyd_softc *sc, uint8_t on) 1386184610Salfred{ 1387184610Salfred 1388184610Salfred} 1389184610Salfred 1390184610Salfredstatic void 1391184610Salfredzyd_cfg_rf_al2210_init(struct zyd_softc *sc, struct zyd_rf *rf) 1392184610Salfred{ 1393184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_AL2210_PHY; 1394184610Salfred static const uint32_t rfini[] = ZYD_AL2210_RF; 1395184610Salfred uint32_t tmp; 1396184610Salfred uint32_t i; 1397184610Salfred 1398184610Salfred zyd_cfg_write32(sc, ZYD_CR18, 2); 1399184610Salfred 1400184610Salfred /* init RF-dependent PHY registers */ 1401184610Salfred for (i = 0; i != INDEXES(phyini); i++) { 1402184610Salfred zyd_cfg_write16(sc, phyini[i].reg, phyini[i].val); 1403184610Salfred } 1404184610Salfred /* init AL2210 radio */ 1405184610Salfred for (i = 0; i != INDEXES(rfini); i++) { 1406184610Salfred zyd_cfg_rfwrite(sc, rfini[i]); 1407184610Salfred } 1408184610Salfred zyd_cfg_write16(sc, ZYD_CR47, 0x1e); 1409184610Salfred zyd_cfg_read32(sc, ZYD_CR_RADIO_PD, &tmp); 1410184610Salfred zyd_cfg_write32(sc, ZYD_CR_RADIO_PD, tmp & ~1); 1411184610Salfred zyd_cfg_write32(sc, ZYD_CR_RADIO_PD, tmp | 1); 1412184610Salfred zyd_cfg_write32(sc, ZYD_CR_RFCFG, 0x05); 1413184610Salfred zyd_cfg_write32(sc, ZYD_CR_RFCFG, 0x00); 1414184610Salfred zyd_cfg_write16(sc, ZYD_CR47, 0x1e); 1415184610Salfred zyd_cfg_write32(sc, ZYD_CR18, 3); 1416184610Salfred 1417184610Salfred return; 1418184610Salfred} 1419184610Salfred 1420184610Salfredstatic void 1421184610Salfredzyd_cfg_rf_al2210_set_channel(struct zyd_softc *sc, struct zyd_rf *rf, 1422184610Salfred uint8_t channel) 1423184610Salfred{ 1424184610Salfred static const uint32_t rfprog[] = ZYD_AL2210_CHANTABLE; 1425184610Salfred uint32_t tmp; 1426184610Salfred 1427184610Salfred zyd_cfg_write32(sc, ZYD_CR18, 2); 1428184610Salfred zyd_cfg_write16(sc, ZYD_CR47, 0x1e); 1429184610Salfred zyd_cfg_read32(sc, ZYD_CR_RADIO_PD, &tmp); 1430184610Salfred zyd_cfg_write32(sc, ZYD_CR_RADIO_PD, tmp & ~1); 1431184610Salfred zyd_cfg_write32(sc, ZYD_CR_RADIO_PD, tmp | 1); 1432184610Salfred zyd_cfg_write32(sc, ZYD_CR_RFCFG, 0x05); 1433184610Salfred 1434184610Salfred zyd_cfg_write32(sc, ZYD_CR_RFCFG, 0x00); 1435184610Salfred zyd_cfg_write16(sc, ZYD_CR47, 0x1e); 1436184610Salfred 1437184610Salfred /* actually set the channel */ 1438184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1]); 1439184610Salfred 1440184610Salfred zyd_cfg_write32(sc, ZYD_CR18, 3); 1441184610Salfred return; 1442184610Salfred} 1443184610Salfred 1444184610Salfred/* 1445184610Salfred * GCT RF methods. 1446184610Salfred */ 1447184610Salfredstatic void 1448184610Salfredzyd_cfg_rf_gct_switch_radio(struct zyd_softc *sc, uint8_t on) 1449184610Salfred{ 1450184610Salfred /* vendor driver does nothing for this RF chip */ 1451184610Salfred 1452184610Salfred return; 1453184610Salfred} 1454184610Salfred 1455184610Salfredstatic void 1456184610Salfredzyd_cfg_rf_gct_init(struct zyd_softc *sc, struct zyd_rf *rf) 1457184610Salfred{ 1458184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_GCT_PHY; 1459184610Salfred static const uint32_t rfini[] = ZYD_GCT_RF; 1460184610Salfred uint32_t i; 1461184610Salfred 1462184610Salfred /* init RF-dependent PHY registers */ 1463184610Salfred for (i = 0; i != INDEXES(phyini); i++) { 1464184610Salfred zyd_cfg_write16(sc, phyini[i].reg, phyini[i].val); 1465184610Salfred } 1466184610Salfred /* init cgt radio */ 1467184610Salfred for (i = 0; i != INDEXES(rfini); i++) { 1468184610Salfred zyd_cfg_rfwrite(sc, rfini[i]); 1469184610Salfred } 1470184610Salfred return; 1471184610Salfred} 1472184610Salfred 1473184610Salfredstatic void 1474184610Salfredzyd_cfg_rf_gct_set_channel(struct zyd_softc *sc, struct zyd_rf *rf, 1475184610Salfred uint8_t channel) 1476184610Salfred{ 1477184610Salfred static const uint32_t rfprog[] = ZYD_GCT_CHANTABLE; 1478184610Salfred 1479184610Salfred zyd_cfg_rfwrite(sc, 0x1c0000); 1480184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1]); 1481184610Salfred zyd_cfg_rfwrite(sc, 0x1c0008); 1482184610Salfred 1483184610Salfred return; 1484184610Salfred} 1485184610Salfred 1486184610Salfred/* 1487184610Salfred * Maxim RF methods. 1488184610Salfred */ 1489184610Salfredstatic void 1490184610Salfredzyd_cfg_rf_maxim_switch_radio(struct zyd_softc *sc, uint8_t on) 1491184610Salfred{ 1492184610Salfred /* vendor driver does nothing for this RF chip */ 1493184610Salfred 1494184610Salfred return; 1495184610Salfred} 1496184610Salfred 1497184610Salfredstatic void 1498184610Salfredzyd_cfg_rf_maxim_init(struct zyd_softc *sc, struct zyd_rf *rf) 1499184610Salfred{ 1500184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY; 1501184610Salfred static const uint32_t rfini[] = ZYD_MAXIM_RF; 1502184610Salfred uint16_t tmp; 1503184610Salfred uint32_t i; 1504184610Salfred 1505184610Salfred /* init RF-dependent PHY registers */ 1506184610Salfred for (i = 0; i != INDEXES(phyini); i++) { 1507184610Salfred zyd_cfg_write16(sc, phyini[i].reg, phyini[i].val); 1508184610Salfred } 1509184610Salfred zyd_cfg_read16(sc, ZYD_CR203, &tmp); 1510184610Salfred zyd_cfg_write16(sc, ZYD_CR203, tmp & ~(1 << 4)); 1511184610Salfred 1512184610Salfred /* init maxim radio */ 1513184610Salfred for (i = 0; i != INDEXES(rfini); i++) { 1514184610Salfred zyd_cfg_rfwrite(sc, rfini[i]); 1515184610Salfred } 1516184610Salfred zyd_cfg_read16(sc, ZYD_CR203, &tmp); 1517184610Salfred zyd_cfg_write16(sc, ZYD_CR203, tmp | (1 << 4)); 1518184610Salfred 1519184610Salfred return; 1520184610Salfred} 1521184610Salfred 1522184610Salfredstatic void 1523184610Salfredzyd_cfg_rf_maxim_set_channel(struct zyd_softc *sc, struct zyd_rf *rf, 1524184610Salfred uint8_t channel) 1525184610Salfred{ 1526184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY; 1527184610Salfred static const uint32_t rfini[] = ZYD_MAXIM_RF; 1528184610Salfred static const struct { 1529184610Salfred uint32_t r1, r2; 1530184610Salfred } rfprog[] = ZYD_MAXIM_CHANTABLE; 1531184610Salfred uint16_t tmp; 1532184610Salfred uint32_t i; 1533184610Salfred 1534184610Salfred /* 1535184610Salfred * Do the same as we do when initializing it, except for the channel 1536184610Salfred * values coming from the two channel tables. 1537184610Salfred */ 1538184610Salfred 1539184610Salfred /* init RF-dependent PHY registers */ 1540184610Salfred for (i = 0; i != INDEXES(phyini); i++) { 1541184610Salfred zyd_cfg_write16(sc, phyini[i].reg, phyini[i].val); 1542184610Salfred } 1543184610Salfred zyd_cfg_read16(sc, ZYD_CR203, &tmp); 1544184610Salfred zyd_cfg_write16(sc, ZYD_CR203, tmp & ~(1 << 4)); 1545184610Salfred 1546184610Salfred /* first two values taken from the chantables */ 1547184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1].r1); 1548184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1].r2); 1549184610Salfred 1550184610Salfred /* init maxim radio - skipping the two first values */ 1551184610Salfred if (INDEXES(rfini) > 2) { 1552184610Salfred for (i = 2; i != INDEXES(rfini); i++) { 1553184610Salfred zyd_cfg_rfwrite(sc, rfini[i]); 1554184610Salfred } 1555184610Salfred } 1556184610Salfred zyd_cfg_read16(sc, ZYD_CR203, &tmp); 1557184610Salfred zyd_cfg_write16(sc, ZYD_CR203, tmp | (1 << 4)); 1558184610Salfred 1559184610Salfred return; 1560184610Salfred} 1561184610Salfred 1562184610Salfred/* 1563184610Salfred * Maxim2 RF methods. 1564184610Salfred */ 1565184610Salfredstatic void 1566184610Salfredzyd_cfg_rf_maxim2_switch_radio(struct zyd_softc *sc, uint8_t on) 1567184610Salfred{ 1568184610Salfred /* vendor driver does nothing for this RF chip */ 1569184610Salfred return; 1570184610Salfred} 1571184610Salfred 1572184610Salfredstatic void 1573184610Salfredzyd_cfg_rf_maxim2_init(struct zyd_softc *sc, struct zyd_rf *rf) 1574184610Salfred{ 1575184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY; 1576184610Salfred static const uint32_t rfini[] = ZYD_MAXIM2_RF; 1577184610Salfred uint16_t tmp; 1578184610Salfred uint32_t i; 1579184610Salfred 1580184610Salfred /* init RF-dependent PHY registers */ 1581184610Salfred for (i = 0; i != INDEXES(phyini); i++) { 1582184610Salfred zyd_cfg_write16(sc, phyini[i].reg, phyini[i].val); 1583184610Salfred } 1584184610Salfred zyd_cfg_read16(sc, ZYD_CR203, &tmp); 1585184610Salfred zyd_cfg_write16(sc, ZYD_CR203, tmp & ~(1 << 4)); 1586184610Salfred 1587184610Salfred /* init maxim2 radio */ 1588184610Salfred for (i = 0; i != INDEXES(rfini); i++) { 1589184610Salfred zyd_cfg_rfwrite(sc, rfini[i]); 1590184610Salfred } 1591184610Salfred zyd_cfg_read16(sc, ZYD_CR203, &tmp); 1592184610Salfred zyd_cfg_write16(sc, ZYD_CR203, tmp | (1 << 4)); 1593184610Salfred return; 1594184610Salfred} 1595184610Salfred 1596184610Salfredstatic void 1597184610Salfredzyd_cfg_rf_maxim2_set_channel(struct zyd_softc *sc, struct zyd_rf *rf, 1598184610Salfred uint8_t channel) 1599184610Salfred{ 1600184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY; 1601184610Salfred static const uint32_t rfini[] = ZYD_MAXIM2_RF; 1602184610Salfred static const struct { 1603184610Salfred uint32_t r1, r2; 1604184610Salfred } rfprog[] = ZYD_MAXIM2_CHANTABLE; 1605184610Salfred uint16_t tmp; 1606184610Salfred uint32_t i; 1607184610Salfred 1608184610Salfred /* 1609184610Salfred * Do the same as we do when initializing it, except for the channel 1610184610Salfred * values coming from the two channel tables. 1611184610Salfred */ 1612184610Salfred 1613184610Salfred /* init RF-dependent PHY registers */ 1614184610Salfred for (i = 0; i != INDEXES(phyini); i++) { 1615184610Salfred zyd_cfg_write16(sc, phyini[i].reg, phyini[i].val); 1616184610Salfred } 1617184610Salfred zyd_cfg_read16(sc, ZYD_CR203, &tmp); 1618184610Salfred zyd_cfg_write16(sc, ZYD_CR203, tmp & ~(1 << 4)); 1619184610Salfred 1620184610Salfred /* first two values taken from the chantables */ 1621184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1].r1); 1622184610Salfred zyd_cfg_rfwrite(sc, rfprog[channel - 1].r2); 1623184610Salfred 1624184610Salfred /* init maxim2 radio - skipping the two first values */ 1625184610Salfred if (INDEXES(rfini) > 2) { 1626184610Salfred for (i = 2; i != INDEXES(rfini); i++) { 1627184610Salfred zyd_cfg_rfwrite(sc, rfini[i]); 1628184610Salfred } 1629184610Salfred } 1630184610Salfred zyd_cfg_read16(sc, ZYD_CR203, &tmp); 1631184610Salfred zyd_cfg_write16(sc, ZYD_CR203, tmp | (1 << 4)); 1632184610Salfred return; 1633184610Salfred} 1634184610Salfred 1635184610Salfred/* 1636184610Salfred * Assign drivers and init the RF 1637184610Salfred */ 1638184610Salfredstatic uint8_t 1639184610Salfredzyd_cfg_rf_init_hw(struct zyd_softc *sc, struct zyd_rf *rf) 1640184610Salfred{ 1641184610Salfred ; /* fix for indent */ 1642184610Salfred 1643184610Salfred switch (sc->sc_rf_rev) { 1644184610Salfred case ZYD_RF_RFMD: 1645184610Salfred rf->cfg_init_hw = zyd_cfg_rf_rfmd_init; 1646184610Salfred rf->cfg_switch_radio = zyd_cfg_rf_rfmd_switch_radio; 1647184610Salfred rf->cfg_set_channel = zyd_cfg_rf_rfmd_set_channel; 1648184610Salfred rf->width = 24; /* 24-bit RF values */ 1649184610Salfred break; 1650184610Salfred case ZYD_RF_AL2230: 1651184610Salfred if (sc->sc_mac_rev == ZYD_ZD1211B) 1652184610Salfred rf->cfg_init_hw = zyd_cfg_rf_al2230_init_b; 1653184610Salfred else 1654184610Salfred rf->cfg_init_hw = zyd_cfg_rf_al2230_init; 1655184610Salfred rf->cfg_switch_radio = zyd_cfg_rf_al2230_switch_radio; 1656184610Salfred rf->cfg_set_channel = zyd_cfg_rf_al2230_set_channel; 1657184610Salfred rf->width = 24; /* 24-bit RF values */ 1658184610Salfred break; 1659184610Salfred case ZYD_RF_AL7230B: 1660184610Salfred rf->cfg_init_hw = zyd_cfg_rf_al7230b_init; 1661184610Salfred rf->cfg_switch_radio = zyd_cfg_rf_al7230b_switch_radio; 1662184610Salfred rf->cfg_set_channel = zyd_cfg_rf_al7230b_set_channel; 1663184610Salfred rf->width = 24; /* 24-bit RF values */ 1664184610Salfred break; 1665184610Salfred case ZYD_RF_AL2210: 1666184610Salfred rf->cfg_init_hw = zyd_cfg_rf_al2210_init; 1667184610Salfred rf->cfg_switch_radio = zyd_cfg_rf_al2210_switch_radio; 1668184610Salfred rf->cfg_set_channel = zyd_cfg_rf_al2210_set_channel; 1669184610Salfred rf->width = 24; /* 24-bit RF values */ 1670184610Salfred break; 1671184610Salfred case ZYD_RF_GCT: 1672184610Salfred rf->cfg_init_hw = zyd_cfg_rf_gct_init; 1673184610Salfred rf->cfg_switch_radio = zyd_cfg_rf_gct_switch_radio; 1674184610Salfred rf->cfg_set_channel = zyd_cfg_rf_gct_set_channel; 1675184610Salfred rf->width = 21; /* 21-bit RF values */ 1676184610Salfred break; 1677184610Salfred case ZYD_RF_MAXIM_NEW: 1678184610Salfred rf->cfg_init_hw = zyd_cfg_rf_maxim_init; 1679184610Salfred rf->cfg_switch_radio = zyd_cfg_rf_maxim_switch_radio; 1680184610Salfred rf->cfg_set_channel = zyd_cfg_rf_maxim_set_channel; 1681184610Salfred rf->width = 18; /* 18-bit RF values */ 1682184610Salfred break; 1683184610Salfred case ZYD_RF_MAXIM_NEW2: 1684184610Salfred rf->cfg_init_hw = zyd_cfg_rf_maxim2_init; 1685184610Salfred rf->cfg_switch_radio = zyd_cfg_rf_maxim2_switch_radio; 1686184610Salfred rf->cfg_set_channel = zyd_cfg_rf_maxim2_set_channel; 1687184610Salfred rf->width = 18; /* 18-bit RF values */ 1688184610Salfred break; 1689184610Salfred default: 1690184610Salfred DPRINTFN(0, "%s: Sorry, radio %s is not supported yet\n", 1691184610Salfred sc->sc_name, zyd_rf_name(sc->sc_rf_rev)); 1692184610Salfred return (1); 1693184610Salfred } 1694184610Salfred 1695184610Salfred zyd_cfg_lock_phy(sc); 1696184610Salfred (rf->cfg_init_hw) (sc, rf); 1697184610Salfred zyd_cfg_unlock_phy(sc); 1698184610Salfred 1699184610Salfred return (0); /* success */ 1700184610Salfred} 1701184610Salfred 1702184610Salfred/* 1703184610Salfred * Init the hardware 1704184610Salfred */ 1705184610Salfredstatic uint8_t 1706184610Salfredzyd_cfg_hw_init(struct zyd_softc *sc) 1707184610Salfred{ 1708184610Salfred const struct zyd_phy_pair *phyp; 1709184610Salfred uint32_t tmp; 1710184610Salfred 1711184610Salfred /* specify that the plug and play is finished */ 1712184610Salfred zyd_cfg_write32(sc, ZYD_MAC_AFTER_PNP, 1); 1713184610Salfred 1714184610Salfred zyd_cfg_read16(sc, ZYD_FIRMWARE_BASE_ADDR, &sc->sc_firmware_base); 1715184610Salfred DPRINTF("firmware base address=0x%04x\n", sc->sc_firmware_base); 1716184610Salfred 1717184610Salfred /* retrieve firmware revision number */ 1718184610Salfred zyd_cfg_read16(sc, sc->sc_firmware_base + ZYD_FW_FIRMWARE_REV, &sc->sc_fw_rev); 1719184610Salfred 1720184610Salfred zyd_cfg_write32(sc, ZYD_CR_GPI_EN, 0); 1721184610Salfred zyd_cfg_write32(sc, ZYD_MAC_CONT_WIN_LIMIT, 0x7f043f); 1722184610Salfred 1723184610Salfred /* disable interrupts */ 1724184610Salfred zyd_cfg_write32(sc, ZYD_CR_INTERRUPT, 0); 1725184610Salfred 1726184610Salfred /* PHY init */ 1727184610Salfred zyd_cfg_lock_phy(sc); 1728184610Salfred phyp = (sc->sc_mac_rev == ZYD_ZD1211B) ? zyd_def_phyB : zyd_def_phy; 1729184610Salfred for (; phyp->reg != 0; phyp++) { 1730184610Salfred zyd_cfg_write16(sc, phyp->reg, phyp->val); 1731184610Salfred } 1732184610Salfred if (sc->sc_fix_cr157) { 1733184610Salfred zyd_cfg_read32(sc, ZYD_EEPROM_PHY_REG, &tmp); 1734184610Salfred zyd_cfg_write32(sc, ZYD_CR157, tmp >> 8); 1735184610Salfred } 1736184610Salfred zyd_cfg_unlock_phy(sc); 1737184610Salfred 1738184610Salfred /* HMAC init */ 1739184610Salfred zyd_cfg_write32(sc, ZYD_MAC_ACK_EXT, 0x00000020); 1740184610Salfred zyd_cfg_write32(sc, ZYD_CR_ADDA_MBIAS_WT, 0x30000808); 1741184610Salfred 1742184610Salfred if (sc->sc_mac_rev == ZYD_ZD1211) { 1743184610Salfred zyd_cfg_write32(sc, ZYD_MAC_RETRY, 0x00000002); 1744184610Salfred } else { 1745184610Salfred zyd_cfg_write32(sc, ZYD_MACB_MAX_RETRY, 0x02020202); 1746184610Salfred zyd_cfg_write32(sc, ZYD_MACB_TXPWR_CTL4, 0x007f003f); 1747184610Salfred zyd_cfg_write32(sc, ZYD_MACB_TXPWR_CTL3, 0x007f003f); 1748184610Salfred zyd_cfg_write32(sc, ZYD_MACB_TXPWR_CTL2, 0x003f001f); 1749184610Salfred zyd_cfg_write32(sc, ZYD_MACB_TXPWR_CTL1, 0x001f000f); 1750184610Salfred zyd_cfg_write32(sc, ZYD_MACB_AIFS_CTL1, 0x00280028); 1751184610Salfred zyd_cfg_write32(sc, ZYD_MACB_AIFS_CTL2, 0x008C003C); 1752184610Salfred zyd_cfg_write32(sc, ZYD_MACB_TXOP, 0x01800824); 1753184610Salfred } 1754184610Salfred 1755184610Salfred zyd_cfg_write32(sc, ZYD_MAC_SNIFFER, 0x00000000); 1756184610Salfred zyd_cfg_write32(sc, ZYD_MAC_RXFILTER, 0x00000000); 1757184610Salfred zyd_cfg_write32(sc, ZYD_MAC_GHTBL, 0x00000000); 1758184610Salfred zyd_cfg_write32(sc, ZYD_MAC_GHTBH, 0x80000000); 1759184610Salfred zyd_cfg_write32(sc, ZYD_MAC_MISC, 0x000000a4); 1760184610Salfred zyd_cfg_write32(sc, ZYD_CR_ADDA_PWR_DWN, 0x0000007f); 1761184610Salfred zyd_cfg_write32(sc, ZYD_MAC_BCNCFG, 0x00f00401); 1762184610Salfred zyd_cfg_write32(sc, ZYD_MAC_PHY_DELAY2, 0x00000000); 1763184610Salfred zyd_cfg_write32(sc, ZYD_MAC_ACK_EXT, 0x00000080); 1764184610Salfred zyd_cfg_write32(sc, ZYD_CR_ADDA_PWR_DWN, 0x00000000); 1765184610Salfred zyd_cfg_write32(sc, ZYD_MAC_SIFS_ACK_TIME, 0x00000100); 1766184610Salfred zyd_cfg_write32(sc, ZYD_MAC_DIFS_EIFS_SIFS, 0x0547c032); 1767184610Salfred zyd_cfg_write32(sc, ZYD_CR_RX_PE_DELAY, 0x00000070); 1768184610Salfred zyd_cfg_write32(sc, ZYD_CR_PS_CTRL, 0x10000000); 1769184610Salfred zyd_cfg_write32(sc, ZYD_MAC_RTSCTSRATE, 0x02030203); 1770184610Salfred zyd_cfg_write32(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0640); 1771184610Salfred zyd_cfg_write32(sc, ZYD_MAC_BACKOFF_PROTECT, 0x00000114); 1772184610Salfred 1773184610Salfred /* init beacon interval to 100ms */ 1774184610Salfred zyd_cfg_set_beacon_interval(sc, 100); 1775184610Salfred 1776184610Salfred return (0); /* success */ 1777184610Salfred} 1778184610Salfred 1779184610Salfred/* 1780184610Salfred * Read information from EEPROM 1781184610Salfred */ 1782184610Salfredstatic void 1783184610Salfredzyd_cfg_read_eeprom(struct zyd_softc *sc) 1784184610Salfred{ 1785184610Salfred uint32_t tmp; 1786184610Salfred uint16_t i; 1787184610Salfred uint16_t val; 1788184610Salfred 1789184610Salfred /* read MAC address */ 1790184610Salfred zyd_cfg_read32(sc, ZYD_EEPROM_MAC_ADDR_P1, &tmp); 1791184610Salfred sc->sc_myaddr[0] = tmp & 0xff; 1792184610Salfred sc->sc_myaddr[1] = tmp >> 8; 1793184610Salfred sc->sc_myaddr[2] = tmp >> 16; 1794184610Salfred sc->sc_myaddr[3] = tmp >> 24; 1795184610Salfred zyd_cfg_read32(sc, ZYD_EEPROM_MAC_ADDR_P2, &tmp); 1796184610Salfred sc->sc_myaddr[4] = tmp & 0xff; 1797184610Salfred sc->sc_myaddr[5] = tmp >> 8; 1798184610Salfred 1799184610Salfred zyd_cfg_read32(sc, ZYD_EEPROM_POD, &tmp); 1800184610Salfred sc->sc_rf_rev = tmp & 0x0f; 1801184610Salfred sc->sc_fix_cr47 = (tmp >> 8) & 0x01; 1802184610Salfred sc->sc_fix_cr157 = (tmp >> 13) & 0x01; 1803184610Salfred sc->sc_pa_rev = (tmp >> 16) & 0x0f; 1804184610Salfred 1805184610Salfred /* read regulatory domain (currently unused) */ 1806184610Salfred zyd_cfg_read32(sc, ZYD_EEPROM_SUBID, &tmp); 1807184610Salfred sc->sc_regdomain = tmp >> 16; 1808184610Salfred DPRINTF("regulatory domain %x\n", sc->sc_regdomain); 1809184610Salfred 1810184610Salfred /* read Tx power calibration tables */ 1811184610Salfred for (i = 0; i < 7; i++) { 1812184610Salfred zyd_cfg_read16(sc, ZYD_EEPROM_PWR_CAL + i, &val); 1813184610Salfred sc->sc_pwr_cal[(i * 2)] = val >> 8; 1814184610Salfred sc->sc_pwr_cal[(i * 2) + 1] = val & 0xff; 1815184610Salfred 1816184610Salfred zyd_cfg_read16(sc, ZYD_EEPROM_PWR_INT + i, &val); 1817184610Salfred sc->sc_pwr_int[(i * 2)] = val >> 8; 1818184610Salfred sc->sc_pwr_int[(i * 2) + 1] = val & 0xff; 1819184610Salfred 1820184610Salfred zyd_cfg_read16(sc, ZYD_EEPROM_36M_CAL + i, &val); 1821184610Salfred sc->sc_ofdm36_cal[(i * 2)] = val >> 8; 1822184610Salfred sc->sc_ofdm36_cal[(i * 2) + 1] = val & 0xff; 1823184610Salfred 1824184610Salfred zyd_cfg_read16(sc, ZYD_EEPROM_48M_CAL + i, &val); 1825184610Salfred sc->sc_ofdm48_cal[(i * 2)] = val >> 8; 1826184610Salfred sc->sc_ofdm48_cal[(i * 2) + 1] = val & 0xff; 1827184610Salfred 1828184610Salfred zyd_cfg_read16(sc, ZYD_EEPROM_54M_CAL + i, &val); 1829184610Salfred sc->sc_ofdm54_cal[(i * 2)] = val >> 8; 1830184610Salfred sc->sc_ofdm54_cal[(i * 2) + 1] = val & 0xff; 1831184610Salfred } 1832184610Salfred return; 1833184610Salfred} 1834184610Salfred 1835184610Salfredstatic void 1836184610Salfredzyd_cfg_set_mac_addr(struct zyd_softc *sc, const uint8_t *addr) 1837184610Salfred{ 1838184610Salfred uint32_t tmp; 1839184610Salfred 1840184610Salfred tmp = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; 1841184610Salfred zyd_cfg_write32(sc, ZYD_MAC_MACADRL, tmp); 1842184610Salfred 1843184610Salfred tmp = (addr[5] << 8) | addr[4]; 1844184610Salfred zyd_cfg_write32(sc, ZYD_MAC_MACADRH, tmp); 1845184610Salfred return; 1846184610Salfred} 1847184610Salfred 1848184610Salfred/* 1849184610Salfred * Switch radio on/off 1850184610Salfred */ 1851184610Salfredstatic void 1852184610Salfredzyd_cfg_switch_radio(struct zyd_softc *sc, uint8_t onoff) 1853184610Salfred{ 1854184610Salfred zyd_cfg_lock_phy(sc); 1855184610Salfred (sc->sc_rf.cfg_switch_radio) (sc, onoff); 1856184610Salfred zyd_cfg_unlock_phy(sc); 1857184610Salfred 1858184610Salfred return; 1859184610Salfred} 1860184610Salfred 1861184610Salfred/* 1862184610Salfred * Set BSSID 1863184610Salfred */ 1864184610Salfredstatic void 1865184610Salfredzyd_cfg_set_bssid(struct zyd_softc *sc, uint8_t *addr) 1866184610Salfred{ 1867184610Salfred uint32_t tmp; 1868184610Salfred 1869184610Salfred tmp = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; 1870184610Salfred zyd_cfg_write32(sc, ZYD_MAC_BSSADRL, tmp); 1871184610Salfred 1872184610Salfred tmp = (addr[5] << 8) | addr[4]; 1873184610Salfred zyd_cfg_write32(sc, ZYD_MAC_BSSADRH, tmp); 1874184610Salfred return; 1875184610Salfred} 1876184610Salfred 1877184610Salfred/* 1878184610Salfred * Complete the attach process 1879184610Salfred */ 1880184610Salfredstatic void 1881184610Salfredzyd_cfg_first_time_setup(struct zyd_softc *sc, 1882184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 1883184610Salfred{ 1884184610Salfred struct usb2_config_descriptor *cd; 1885184610Salfred struct ieee80211com *ic; 1886184610Salfred struct ifnet *ifp; 1887184610Salfred const uint8_t *fw_ptr; 1888184610Salfred uint32_t fw_len; 1889184610Salfred uint8_t bands; 1890184610Salfred usb2_error_t err; 1891184610Salfred 1892184610Salfred /* setup RX tap header */ 1893184610Salfred sc->sc_rxtap_len = sizeof(sc->sc_rxtap); 1894184610Salfred sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); 1895184610Salfred sc->sc_rxtap.wr_ihdr.it_present = htole32(ZYD_RX_RADIOTAP_PRESENT); 1896184610Salfred 1897184610Salfred /* setup TX tap header */ 1898184610Salfred sc->sc_txtap_len = sizeof(sc->sc_txtap); 1899184610Salfred sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); 1900184610Salfred sc->sc_txtap.wt_ihdr.it_present = htole32(ZYD_TX_RADIOTAP_PRESENT); 1901184610Salfred 1902184610Salfred if (sc->sc_mac_rev == ZYD_ZD1211) { 1903184610Salfred fw_ptr = zd1211_firmware; 1904184610Salfred fw_len = sizeof(zd1211_firmware); 1905184610Salfred } else { 1906184610Salfred fw_ptr = zd1211b_firmware; 1907184610Salfred fw_len = sizeof(zd1211b_firmware); 1908184610Salfred } 1909184610Salfred 1910184610Salfred if (zyd_cfg_uploadfirmware(sc, fw_ptr, fw_len)) { 1911184610Salfred DPRINTFN(0, "%s: could not " 1912184610Salfred "upload firmware!\n", sc->sc_name); 1913184610Salfred return; 1914184610Salfred } 1915184610Salfred cd = usb2_get_config_descriptor(sc->sc_udev); 1916184610Salfred 1917184610Salfred /* reset device */ 1918184610Salfred err = usb2_req_set_config(sc->sc_udev, &sc->sc_mtx, 1919184610Salfred cd->bConfigurationValue); 1920184610Salfred if (err) { 1921184610Salfred DPRINTF("reset failed (ignored)\n"); 1922184610Salfred } 1923184610Salfred /* Read MAC and other stuff rom EEPROM */ 1924184610Salfred zyd_cfg_read_eeprom(sc); 1925184610Salfred 1926184610Salfred /* Init hardware */ 1927184610Salfred if (zyd_cfg_hw_init(sc)) { 1928184610Salfred DPRINTFN(0, "%s: HW init failed!\n", sc->sc_name); 1929184610Salfred return; 1930184610Salfred } 1931184610Salfred /* Now init the RF chip */ 1932184610Salfred if (zyd_cfg_rf_init_hw(sc, &sc->sc_rf)) { 1933184610Salfred DPRINTFN(0, "%s: RF init failed!\n", sc->sc_name); 1934184610Salfred return; 1935184610Salfred } 1936184610Salfred printf("%s: HMAC ZD1211%s, FW %02x.%02x, RF %s, PA %x, address %02x:%02x:%02x:%02x:%02x:%02x\n", 1937184610Salfred sc->sc_name, (sc->sc_mac_rev == ZYD_ZD1211) ? "" : "B", 1938184610Salfred sc->sc_fw_rev >> 8, sc->sc_fw_rev & 0xff, zyd_rf_name(sc->sc_rf_rev), 1939184610Salfred sc->sc_pa_rev, sc->sc_myaddr[0], 1940184610Salfred sc->sc_myaddr[1], sc->sc_myaddr[2], 1941184610Salfred sc->sc_myaddr[3], sc->sc_myaddr[4], 1942184610Salfred sc->sc_myaddr[5]); 1943184610Salfred 1944184610Salfred mtx_unlock(&sc->sc_mtx); 1945184610Salfred 1946184610Salfred ifp = if_alloc(IFT_IEEE80211); 1947184610Salfred 1948184610Salfred mtx_lock(&sc->sc_mtx); 1949184610Salfred 1950184610Salfred if (ifp == NULL) { 1951184610Salfred DPRINTFN(0, "%s: could not if_alloc()!\n", 1952184610Salfred sc->sc_name); 1953184610Salfred goto done; 1954184610Salfred } 1955184610Salfred sc->sc_evilhack = ifp; 1956184610Salfred sc->sc_ifp = ifp; 1957184610Salfred ic = ifp->if_l2com; 1958184610Salfred 1959184610Salfred ifp->if_softc = sc; 1960184610Salfred if_initname(ifp, "zyd", sc->sc_unit); 1961184610Salfred ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 1962184610Salfred ifp->if_init = &zyd_init_cb; 1963184610Salfred ifp->if_ioctl = &zyd_ioctl_cb; 1964184610Salfred ifp->if_start = &zyd_start_cb; 1965184610Salfred ifp->if_watchdog = NULL; 1966184610Salfred IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); 1967184610Salfred ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; 1968184610Salfred IFQ_SET_READY(&ifp->if_snd); 1969184610Salfred 1970184610Salfred bcopy(sc->sc_myaddr, ic->ic_myaddr, sizeof(ic->ic_myaddr)); 1971184610Salfred 1972184610Salfred ic->ic_ifp = ifp; 1973184610Salfred ic->ic_phytype = IEEE80211_T_OFDM; 1974184610Salfred ic->ic_opmode = IEEE80211_M_STA; 1975184610Salfred 1976184610Salfred /* Set device capabilities */ 1977184610Salfred ic->ic_caps = 1978184610Salfred IEEE80211_C_STA /* station mode supported */ 1979184610Salfred | IEEE80211_C_MONITOR /* monitor mode */ 1980184610Salfred | IEEE80211_C_SHPREAMBLE /* short preamble supported */ 1981184610Salfred | IEEE80211_C_SHSLOT /* short slot time supported */ 1982184610Salfred | IEEE80211_C_BGSCAN /* capable of bg scanning */ 1983184610Salfred | IEEE80211_C_WPA /* 802.11i */ 1984184610Salfred ; 1985184610Salfred 1986184610Salfred bands = 0; 1987184610Salfred setbit(&bands, IEEE80211_MODE_11B); 1988184610Salfred setbit(&bands, IEEE80211_MODE_11G); 1989184610Salfred ieee80211_init_channels(ic, NULL, &bands); 1990184610Salfred 1991184610Salfred mtx_unlock(&sc->sc_mtx); 1992184610Salfred 1993184610Salfred ieee80211_ifattach(ic); 1994184610Salfred 1995184610Salfred mtx_lock(&sc->sc_mtx); 1996184610Salfred 1997184610Salfred ic->ic_node_alloc = &zyd_node_alloc_cb; 1998184610Salfred ic->ic_raw_xmit = &zyd_raw_xmit_cb; 1999184610Salfred ic->ic_newassoc = &zyd_newassoc_cb; 2000184610Salfred 2001184610Salfred ic->ic_scan_start = &zyd_scan_start_cb; 2002184610Salfred ic->ic_scan_end = &zyd_scan_end_cb; 2003184610Salfred ic->ic_set_channel = &zyd_set_channel_cb; 2004184610Salfred ic->ic_vap_create = &zyd_vap_create; 2005184610Salfred ic->ic_vap_delete = &zyd_vap_delete; 2006184610Salfred ic->ic_update_mcast = &zyd_update_mcast_cb; 2007184610Salfred ic->ic_update_promisc = &zyd_update_promisc_cb; 2008184610Salfred 2009184610Salfred sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan); 2010184610Salfred 2011184610Salfred mtx_unlock(&sc->sc_mtx); 2012184610Salfred 2013184610Salfred bpfattach(ifp, DLT_IEEE802_11_RADIO, 2014184610Salfred sizeof(struct ieee80211_frame) + 2015184610Salfred sizeof(sc->sc_txtap)); 2016184610Salfred 2017184610Salfred mtx_lock(&sc->sc_mtx); 2018184610Salfred 2019184610Salfred if (bootverbose) { 2020184610Salfred ieee80211_announce(ic); 2021184610Salfred } 2022184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_INTR_DT_RD]); 2023184610Salfreddone: 2024184610Salfred return; 2025184610Salfred} 2026184610Salfred 2027184610Salfred/* 2028184610Salfred * Detach device 2029184610Salfred */ 2030184610Salfredstatic int 2031184610Salfredzyd_detach(device_t dev) 2032184610Salfred{ 2033184610Salfred struct zyd_softc *sc = device_get_softc(dev); 2034184610Salfred struct ieee80211com *ic; 2035184610Salfred struct ifnet *ifp; 2036184610Salfred 2037184610Salfred usb2_config_td_drain(&sc->sc_config_td); 2038184610Salfred 2039184610Salfred mtx_lock(&sc->sc_mtx); 2040184610Salfred 2041184610Salfred usb2_callout_stop(&sc->sc_watchdog); 2042184610Salfred 2043184610Salfred zyd_cfg_pre_stop(sc, NULL, 0); 2044184610Salfred 2045184610Salfred ifp = sc->sc_ifp; 2046184610Salfred ic = ifp->if_l2com; 2047184610Salfred 2048184610Salfred mtx_unlock(&sc->sc_mtx); 2049184610Salfred 2050184610Salfred /* stop all USB transfers first */ 2051184610Salfred usb2_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER); 2052184610Salfred 2053184610Salfred /* get rid of any late children */ 2054184610Salfred bus_generic_detach(dev); 2055184610Salfred 2056184610Salfred if (ifp) { 2057184610Salfred bpfdetach(ifp); 2058184610Salfred ieee80211_ifdetach(ic); 2059184610Salfred if_free(ifp); 2060184610Salfred } 2061184610Salfred usb2_config_td_unsetup(&sc->sc_config_td); 2062184610Salfred 2063184610Salfred usb2_callout_drain(&sc->sc_watchdog); 2064184610Salfred 2065184610Salfred usb2_cv_destroy(&sc->sc_intr_cv); 2066184610Salfred 2067184610Salfred mtx_destroy(&sc->sc_mtx); 2068184610Salfred 2069184610Salfred return (0); 2070184610Salfred} 2071184610Salfred 2072184610Salfredstatic void 2073184610Salfredzyd_cfg_newstate(struct zyd_softc *sc, 2074184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 2075184610Salfred{ 2076184610Salfred struct ifnet *ifp = sc->sc_ifp; 2077184610Salfred struct ieee80211com *ic = ifp->if_l2com; 2078184610Salfred struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 2079184610Salfred struct zyd_vap *uvp = ZYD_VAP(vap); 2080184610Salfred enum ieee80211_state ostate; 2081184610Salfred enum ieee80211_state nstate; 2082184610Salfred int arg; 2083184610Salfred 2084184610Salfred ostate = vap->iv_state; 2085184610Salfred nstate = sc->sc_ns_state; 2086184610Salfred arg = sc->sc_ns_arg; 2087184610Salfred 2088184610Salfred switch (nstate) { 2089184610Salfred case IEEE80211_S_INIT: 2090184610Salfred break; 2091184610Salfred 2092184610Salfred case IEEE80211_S_RUN: 2093184610Salfred zyd_cfg_set_run(sc, cc); 2094184610Salfred break; 2095184610Salfred 2096184610Salfred default: 2097184610Salfred break; 2098184610Salfred } 2099184610Salfred 2100184610Salfred mtx_unlock(&sc->sc_mtx); 2101184610Salfred IEEE80211_LOCK(ic); 2102184610Salfred uvp->newstate(vap, nstate, arg); 2103184610Salfred if (vap->iv_newstate_cb != NULL) 2104184610Salfred vap->iv_newstate_cb(vap, nstate, arg); 2105184610Salfred IEEE80211_UNLOCK(ic); 2106184610Salfred mtx_lock(&sc->sc_mtx); 2107184610Salfred return; 2108184610Salfred} 2109184610Salfred 2110184610Salfredstatic void 2111184610Salfredzyd_cfg_set_run(struct zyd_softc *sc, 2112184610Salfred struct usb2_config_td_cc *cc) 2113184610Salfred{ 2114184610Salfred zyd_cfg_set_chan(sc, cc, 0); 2115184610Salfred 2116184610Salfred if (cc->ic_opmode != IEEE80211_M_MONITOR) { 2117184610Salfred /* turn link LED on */ 2118184610Salfred zyd_cfg_set_led(sc, ZYD_LED1, 1); 2119184610Salfred 2120184610Salfred /* make data LED blink upon Tx */ 2121184610Salfred zyd_cfg_write32(sc, sc->sc_firmware_base + ZYD_FW_LINK_STATUS, 1); 2122184610Salfred 2123184610Salfred zyd_cfg_set_bssid(sc, cc->iv_bss.ni_bssid); 2124184610Salfred } 2125184610Salfred if (cc->iv_bss.fixed_rate_none) { 2126184610Salfred /* enable automatic rate adaptation */ 2127184610Salfred zyd_cfg_amrr_start(sc); 2128184610Salfred } 2129184610Salfred return; 2130184610Salfred} 2131184610Salfred 2132184610Salfredstatic int 2133184610Salfredzyd_newstate_cb(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 2134184610Salfred{ 2135184610Salfred struct zyd_vap *uvp = ZYD_VAP(vap); 2136184610Salfred struct ieee80211com *ic = vap->iv_ic; 2137184610Salfred struct zyd_softc *sc = ic->ic_ifp->if_softc; 2138184610Salfred 2139184610Salfred DPRINTF("setting new state: %d\n", nstate); 2140184610Salfred 2141184610Salfred mtx_lock(&sc->sc_mtx); 2142184610Salfred if (usb2_config_td_is_gone(&sc->sc_config_td)) { 2143184610Salfred mtx_unlock(&sc->sc_mtx); 2144184610Salfred /* Special case which happens at detach. */ 2145184610Salfred if (nstate == IEEE80211_S_INIT) { 2146184610Salfred (uvp->newstate) (vap, nstate, arg); 2147184610Salfred } 2148184610Salfred return (0); /* nothing to do */ 2149184610Salfred } 2150184610Salfred /* store next state */ 2151184610Salfred sc->sc_ns_state = nstate; 2152184610Salfred sc->sc_ns_arg = arg; 2153184610Salfred 2154184610Salfred /* stop timers */ 2155184610Salfred sc->sc_amrr_timer = 0; 2156184610Salfred 2157184610Salfred /* 2158184610Salfred * USB configuration can only be done from the USB configuration 2159184610Salfred * thread: 2160184610Salfred */ 2161184610Salfred usb2_config_td_queue_command 2162184610Salfred (&sc->sc_config_td, &zyd_config_copy, 2163184610Salfred &zyd_cfg_newstate, 0, 0); 2164184610Salfred 2165184610Salfred mtx_unlock(&sc->sc_mtx); 2166184610Salfred 2167184610Salfred return EINPROGRESS; 2168184610Salfred} 2169184610Salfred 2170184610Salfredstatic void 2171184610Salfredzyd_cfg_update_promisc(struct zyd_softc *sc, 2172184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 2173184610Salfred{ 2174184610Salfred uint32_t low; 2175184610Salfred uint32_t high; 2176184610Salfred 2177184610Salfred if ((cc->ic_opmode == IEEE80211_M_MONITOR) || 2178184610Salfred (cc->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) { 2179184610Salfred low = 0xffffffff; 2180184610Salfred high = 0xffffffff; 2181184610Salfred } else { 2182184610Salfred low = cc->zyd_multi_low; 2183184610Salfred high = cc->zyd_multi_high; 2184184610Salfred } 2185184610Salfred 2186184610Salfred /* reprogram multicast global hash table */ 2187184610Salfred zyd_cfg_write32(sc, ZYD_MAC_GHTBL, low); 2188184610Salfred zyd_cfg_write32(sc, ZYD_MAC_GHTBH, high); 2189184610Salfred return; 2190184610Salfred} 2191184610Salfred 2192184610Salfred/* 2193184610Salfred * Rate-to-bit-converter (Field "rate" in zyd_controlsetformat) 2194184610Salfred */ 2195184610Salfredstatic uint8_t 2196184610Salfredzyd_plcp_signal(uint8_t rate) 2197184610Salfred{ 2198184610Salfred ; /* fix for indent */ 2199184610Salfred 2200184610Salfred switch (rate) { 2201184610Salfred /* CCK rates (NB: not IEEE std, device-specific) */ 2202184610Salfred case 2: 2203184610Salfred return (0x0); 2204184610Salfred case 4: 2205184610Salfred return (0x1); 2206184610Salfred case 11: 2207184610Salfred return (0x2); 2208184610Salfred case 22: 2209184610Salfred return (0x3); 2210184610Salfred 2211184610Salfred /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ 2212184610Salfred case 12: 2213184610Salfred return (0xb); 2214184610Salfred case 18: 2215184610Salfred return (0xf); 2216184610Salfred case 24: 2217184610Salfred return (0xa); 2218184610Salfred case 36: 2219184610Salfred return (0xe); 2220184610Salfred case 48: 2221184610Salfred return (0x9); 2222184610Salfred case 72: 2223184610Salfred return (0xd); 2224184610Salfred case 96: 2225184610Salfred return (0x8); 2226184610Salfred case 108: 2227184610Salfred return (0xc); 2228184610Salfred 2229184610Salfred /* XXX unsupported/unknown rate */ 2230184610Salfred default: 2231184610Salfred return (0xff); 2232184610Salfred } 2233184610Salfred} 2234184610Salfred 2235184610Salfredstatic void 2236184610Salfredzyd_std_command(struct ieee80211com *ic, usb2_config_td_command_t *func) 2237184610Salfred{ 2238184610Salfred struct zyd_softc *sc = ic->ic_ifp->if_softc; 2239184610Salfred 2240184610Salfred mtx_lock(&sc->sc_mtx); 2241184610Salfred 2242184610Salfred sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan); 2243184610Salfred 2244184610Salfred usb2_config_td_queue_command 2245184610Salfred (&sc->sc_config_td, &zyd_config_copy, func, 0, 0); 2246184610Salfred 2247184610Salfred mtx_unlock(&sc->sc_mtx); 2248184610Salfred 2249184610Salfred return; 2250184610Salfred} 2251184610Salfred 2252184610Salfredstatic void 2253184610Salfredzyd_scan_start_cb(struct ieee80211com *ic) 2254184610Salfred{ 2255184610Salfred zyd_std_command(ic, &zyd_cfg_scan_start); 2256184610Salfred return; 2257184610Salfred} 2258184610Salfred 2259184610Salfredstatic void 2260184610Salfredzyd_scan_end_cb(struct ieee80211com *ic) 2261184610Salfred{ 2262184610Salfred zyd_std_command(ic, &zyd_cfg_scan_end); 2263184610Salfred return; 2264184610Salfred} 2265184610Salfred 2266184610Salfredstatic void 2267184610Salfredzyd_set_channel_cb(struct ieee80211com *ic) 2268184610Salfred{ 2269184610Salfred zyd_std_command(ic, &zyd_cfg_set_chan); 2270184610Salfred return; 2271184610Salfred} 2272184610Salfred 2273184610Salfred/*========================================================================* 2274184610Salfred * configure sub-routines, zyd_cfg_xxx 2275184610Salfred *========================================================================*/ 2276184610Salfred 2277184610Salfredstatic void 2278184610Salfredzyd_cfg_scan_start(struct zyd_softc *sc, 2279184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 2280184610Salfred{ 2281184610Salfred zyd_cfg_set_bssid(sc, cc->if_broadcastaddr); 2282184610Salfred return; 2283184610Salfred} 2284184610Salfred 2285184610Salfredstatic void 2286184610Salfredzyd_cfg_scan_end(struct zyd_softc *sc, 2287184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 2288184610Salfred{ 2289184610Salfred zyd_cfg_set_bssid(sc, cc->iv_bss.ni_bssid); 2290184610Salfred return; 2291184610Salfred} 2292184610Salfred 2293184610Salfredstatic void 2294184610Salfredzyd_cfg_set_chan(struct zyd_softc *sc, 2295184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 2296184610Salfred{ 2297184610Salfred uint32_t chan; 2298184610Salfred uint32_t tmp; 2299184610Salfred 2300184610Salfred chan = cc->ic_curchan.chan_to_ieee; 2301184610Salfred 2302184610Salfred DPRINTF("Will try %d\n", chan); 2303184610Salfred 2304184610Salfred if ((chan == 0) || (chan == IEEE80211_CHAN_ANY)) { 2305184610Salfred DPRINTF("0 or ANY, exiting\n"); 2306184610Salfred return; 2307184610Salfred } 2308184610Salfred zyd_cfg_lock_phy(sc); 2309184610Salfred 2310184610Salfred (sc->sc_rf.cfg_set_channel) (sc, &sc->sc_rf, chan); 2311184610Salfred 2312184610Salfred /* update Tx power */ 2313184610Salfred zyd_cfg_write16(sc, ZYD_CR31, sc->sc_pwr_int[chan - 1]); 2314184610Salfred 2315184610Salfred if (sc->sc_mac_rev == ZYD_ZD1211B) { 2316184610Salfred zyd_cfg_write16(sc, ZYD_CR67, sc->sc_ofdm36_cal[chan - 1]); 2317184610Salfred zyd_cfg_write16(sc, ZYD_CR66, sc->sc_ofdm48_cal[chan - 1]); 2318184610Salfred zyd_cfg_write16(sc, ZYD_CR65, sc->sc_ofdm54_cal[chan - 1]); 2319184610Salfred 2320184610Salfred zyd_cfg_write16(sc, ZYD_CR68, sc->sc_pwr_cal[chan - 1]); 2321184610Salfred 2322184610Salfred zyd_cfg_write16(sc, ZYD_CR69, 0x28); 2323184610Salfred zyd_cfg_write16(sc, ZYD_CR69, 0x2a); 2324184610Salfred } 2325184610Salfred if (sc->sc_fix_cr47) { 2326184610Salfred /* set CCK baseband gain from EEPROM */ 2327184610Salfred zyd_cfg_read32(sc, ZYD_EEPROM_PHY_REG, &tmp); 2328184610Salfred zyd_cfg_write16(sc, ZYD_CR47, tmp & 0xff); 2329184610Salfred } 2330184610Salfred zyd_cfg_write32(sc, ZYD_CR_CONFIG_PHILIPS, 0); 2331184610Salfred 2332184610Salfred zyd_cfg_unlock_phy(sc); 2333184610Salfred 2334184610Salfred sc->sc_rxtap.wr_chan_freq = 2335184610Salfred sc->sc_txtap.wt_chan_freq = 2336184610Salfred htole16(cc->ic_curchan.ic_freq); 2337184610Salfred 2338184610Salfred sc->sc_rxtap.wr_chan_flags = 2339184610Salfred sc->sc_txtap.wt_chan_flags = 2340184610Salfred htole16(cc->ic_flags); 2341184610Salfred 2342184610Salfred return; 2343184610Salfred} 2344184610Salfred 2345184610Salfred/* 2346184610Salfred * Interface: init 2347184610Salfred */ 2348184610Salfred 2349184610Salfred/* immediate configuration */ 2350184610Salfred 2351184610Salfredstatic void 2352184610Salfredzyd_cfg_pre_init(struct zyd_softc *sc, 2353184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 2354184610Salfred{ 2355184610Salfred struct ifnet *ifp = sc->sc_ifp; 2356184610Salfred struct ieee80211com *ic = ifp->if_l2com; 2357184610Salfred 2358184610Salfred zyd_cfg_pre_stop(sc, cc, 0); 2359184610Salfred 2360184610Salfred ifp->if_drv_flags |= IFF_DRV_RUNNING; 2361184610Salfred 2362184610Salfred sc->sc_flags |= ZYD_FLAG_HL_READY; 2363184610Salfred 2364184610Salfred IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp)); 2365184610Salfred 2366184610Salfred return; 2367184610Salfred} 2368184610Salfred 2369184610Salfred/* delayed configuration */ 2370184610Salfred 2371184610Salfredstatic void 2372184610Salfredzyd_cfg_init(struct zyd_softc *sc, 2373184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 2374184610Salfred{ 2375184610Salfred zyd_cfg_stop(sc, cc, 0); 2376184610Salfred 2377184610Salfred /* Do initial setup */ 2378184610Salfred 2379184610Salfred zyd_cfg_set_mac_addr(sc, cc->ic_myaddr); 2380184610Salfred 2381184610Salfred zyd_cfg_write32(sc, ZYD_MAC_ENCRYPTION_TYPE, ZYD_ENC_SNIFFER); 2382184610Salfred 2383184610Salfred /* promiscuous mode */ 2384184610Salfred zyd_cfg_write32(sc, ZYD_MAC_SNIFFER, 2385184610Salfred (cc->ic_opmode == IEEE80211_M_MONITOR) ? 1 : 0); 2386184610Salfred 2387184610Salfred /* multicast setup */ 2388184610Salfred zyd_cfg_update_promisc(sc, cc, refcount); 2389184610Salfred 2390184610Salfred zyd_cfg_set_rxfilter(sc, cc, refcount); 2391184610Salfred 2392184610Salfred /* switch radio transmitter ON */ 2393184610Salfred zyd_cfg_switch_radio(sc, 1); 2394184610Salfred 2395184610Salfred /* XXX wrong, can't set here */ 2396184610Salfred /* set basic rates */ 2397184610Salfred if (cc->ic_curmode == IEEE80211_MODE_11B) 2398184610Salfred zyd_cfg_write32(sc, ZYD_MAC_BAS_RATE, 0x0003); 2399184610Salfred else if (cc->ic_curmode == IEEE80211_MODE_11A) 2400184610Salfred zyd_cfg_write32(sc, ZYD_MAC_BAS_RATE, 0x1500); 2401184610Salfred else /* assumes 802.11b/g */ 2402184610Salfred zyd_cfg_write32(sc, ZYD_MAC_BAS_RATE, 0x000f); 2403184610Salfred 2404184610Salfred /* set mandatory rates */ 2405184610Salfred if (cc->ic_curmode == IEEE80211_MODE_11B) 2406184610Salfred zyd_cfg_write32(sc, ZYD_MAC_MAN_RATE, 0x000f); 2407184610Salfred else if (cc->ic_curmode == IEEE80211_MODE_11A) 2408184610Salfred zyd_cfg_write32(sc, ZYD_MAC_MAN_RATE, 0x1500); 2409184610Salfred else /* assumes 802.11b/g */ 2410184610Salfred zyd_cfg_write32(sc, ZYD_MAC_MAN_RATE, 0x150f); 2411184610Salfred 2412184610Salfred /* set default BSS channel */ 2413184610Salfred zyd_cfg_set_chan(sc, cc, 0); 2414184610Salfred 2415184610Salfred /* enable interrupts */ 2416184610Salfred zyd_cfg_write32(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK); 2417184610Salfred 2418184610Salfred /* make sure that the transfers get started */ 2419184610Salfred sc->sc_flags |= ( 2420184610Salfred ZYD_FLAG_BULK_READ_STALL | 2421184610Salfred ZYD_FLAG_BULK_WRITE_STALL | 2422184610Salfred ZYD_FLAG_LL_READY); 2423184610Salfred 2424184610Salfred if ((sc->sc_flags & ZYD_FLAG_LL_READY) && 2425184610Salfred (sc->sc_flags & ZYD_FLAG_HL_READY)) { 2426184610Salfred struct ifnet *ifp = sc->sc_ifp; 2427184610Salfred struct ieee80211com *ic = ifp->if_l2com; 2428184610Salfred 2429184610Salfred /* 2430184610Salfred * start the USB transfers, if not already started: 2431184610Salfred */ 2432184610Salfred usb2_transfer_start(sc->sc_xfer[1]); 2433184610Salfred usb2_transfer_start(sc->sc_xfer[0]); 2434184610Salfred 2435184610Salfred /* 2436184610Salfred * start IEEE802.11 layer 2437184610Salfred */ 2438184610Salfred mtx_unlock(&sc->sc_mtx); 2439184610Salfred ieee80211_start_all(ic); 2440184610Salfred mtx_lock(&sc->sc_mtx); 2441184610Salfred } 2442184610Salfred return; 2443184610Salfred} 2444184610Salfred 2445184610Salfred/* immediate configuration */ 2446184610Salfred 2447184610Salfredstatic void 2448184610Salfredzyd_cfg_pre_stop(struct zyd_softc *sc, 2449184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 2450184610Salfred{ 2451184610Salfred struct ifnet *ifp = sc->sc_ifp; 2452184610Salfred 2453184610Salfred if (cc) { 2454184610Salfred /* copy the needed configuration */ 2455184610Salfred zyd_config_copy(sc, cc, refcount); 2456184610Salfred } 2457184610Salfred if (ifp) { 2458184610Salfred /* clear flags */ 2459184610Salfred ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 2460184610Salfred } 2461184610Salfred sc->sc_flags &= ~(ZYD_FLAG_HL_READY | 2462184610Salfred ZYD_FLAG_LL_READY); 2463184610Salfred 2464184610Salfred /* 2465184610Salfred * stop all the transfers, if not already stopped: 2466184610Salfred */ 2467184610Salfred usb2_transfer_stop(sc->sc_xfer[ZYD_TR_BULK_DT_WR]); 2468184610Salfred usb2_transfer_stop(sc->sc_xfer[ZYD_TR_BULK_DT_RD]); 2469184610Salfred usb2_transfer_stop(sc->sc_xfer[ZYD_TR_BULK_CS_WR]); 2470184610Salfred usb2_transfer_stop(sc->sc_xfer[ZYD_TR_BULK_CS_RD]); 2471184610Salfred 2472184610Salfred /* clean up transmission */ 2473184610Salfred zyd_tx_clean_queue(sc); 2474184610Salfred return; 2475184610Salfred} 2476184610Salfred 2477184610Salfred/* delayed configuration */ 2478184610Salfred 2479184610Salfredstatic void 2480184610Salfredzyd_cfg_stop(struct zyd_softc *sc, 2481184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 2482184610Salfred{ 2483184610Salfred /* switch radio transmitter OFF */ 2484184610Salfred zyd_cfg_switch_radio(sc, 0); 2485184610Salfred 2486184610Salfred /* disable Rx */ 2487184610Salfred zyd_cfg_write32(sc, ZYD_MAC_RXFILTER, 0); 2488184610Salfred 2489184610Salfred /* disable interrupts */ 2490184610Salfred zyd_cfg_write32(sc, ZYD_CR_INTERRUPT, 0); 2491184610Salfred 2492184610Salfred return; 2493184610Salfred} 2494184610Salfred 2495184610Salfredstatic void 2496184610Salfredzyd_update_mcast_cb(struct ifnet *ifp) 2497184610Salfred{ 2498184610Salfred struct zyd_softc *sc = ifp->if_softc; 2499184610Salfred 2500184610Salfred mtx_lock(&sc->sc_mtx); 2501184610Salfred usb2_config_td_queue_command 2502184610Salfred (&sc->sc_config_td, &zyd_config_copy, 2503184610Salfred &zyd_cfg_update_promisc, 0, 0); 2504184610Salfred mtx_unlock(&sc->sc_mtx); 2505184610Salfred return; 2506184610Salfred} 2507184610Salfred 2508184610Salfredstatic void 2509184610Salfredzyd_update_promisc_cb(struct ifnet *ifp) 2510184610Salfred{ 2511184610Salfred struct zyd_softc *sc = ifp->if_softc; 2512184610Salfred 2513184610Salfred mtx_lock(&sc->sc_mtx); 2514184610Salfred usb2_config_td_queue_command 2515184610Salfred (&sc->sc_config_td, &zyd_config_copy, 2516184610Salfred &zyd_cfg_update_promisc, 0, 0); 2517184610Salfred mtx_unlock(&sc->sc_mtx); 2518184610Salfred return; 2519184610Salfred} 2520184610Salfred 2521184610Salfredstatic void 2522184610Salfredzyd_cfg_set_rxfilter(struct zyd_softc *sc, 2523184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 2524184610Salfred{ 2525184610Salfred uint32_t rxfilter; 2526184610Salfred 2527184610Salfred switch (cc->ic_opmode) { 2528184610Salfred case IEEE80211_M_STA: 2529184610Salfred rxfilter = ZYD_FILTER_BSS; 2530184610Salfred break; 2531184610Salfred case IEEE80211_M_IBSS: 2532184610Salfred case IEEE80211_M_HOSTAP: 2533184610Salfred rxfilter = ZYD_FILTER_HOSTAP; 2534184610Salfred break; 2535184610Salfred case IEEE80211_M_MONITOR: 2536184610Salfred rxfilter = ZYD_FILTER_MONITOR; 2537184610Salfred break; 2538184610Salfred default: 2539184610Salfred /* should not get there */ 2540184610Salfred return; 2541184610Salfred } 2542184610Salfred zyd_cfg_write32(sc, ZYD_MAC_RXFILTER, rxfilter); 2543184610Salfred return; 2544184610Salfred} 2545184610Salfred 2546184610Salfredstatic void 2547184610Salfredzyd_cfg_set_led(struct zyd_softc *sc, uint32_t which, uint8_t on) 2548184610Salfred{ 2549184610Salfred uint32_t tmp; 2550184610Salfred 2551184610Salfred zyd_cfg_read32(sc, ZYD_MAC_TX_PE_CONTROL, &tmp); 2552184610Salfred if (on) 2553184610Salfred tmp |= which; 2554184610Salfred else 2555184610Salfred tmp &= ~which; 2556184610Salfred 2557184610Salfred zyd_cfg_write32(sc, ZYD_MAC_TX_PE_CONTROL, tmp); 2558184610Salfred return; 2559184610Salfred} 2560184610Salfred 2561184610Salfredstatic void 2562184610Salfredzyd_start_cb(struct ifnet *ifp) 2563184610Salfred{ 2564184610Salfred struct zyd_softc *sc = ifp->if_softc; 2565184610Salfred 2566184610Salfred mtx_lock(&sc->sc_mtx); 2567184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_BULK_DT_WR]); 2568184610Salfred mtx_unlock(&sc->sc_mtx); 2569184610Salfred return; 2570184610Salfred} 2571184610Salfred 2572184610Salfredstatic void 2573184610Salfredzyd_bulk_write_clear_stall_callback(struct usb2_xfer *xfer) 2574184610Salfred{ 2575184610Salfred struct zyd_softc *sc = xfer->priv_sc; 2576184610Salfred struct usb2_xfer *xfer_other = sc->sc_xfer[ZYD_TR_BULK_DT_WR]; 2577184610Salfred 2578184610Salfred if (usb2_clear_stall_callback(xfer, xfer_other)) { 2579184610Salfred DPRINTF("stall cleared\n"); 2580184610Salfred sc->sc_flags &= ~ZYD_FLAG_BULK_WRITE_STALL; 2581184610Salfred usb2_transfer_start(xfer_other); 2582184610Salfred } 2583184610Salfred return; 2584184610Salfred} 2585184610Salfred 2586184610Salfred/* 2587184610Salfred * We assume that "m->m_pkthdr.rcvif" is pointing to the "ni" that 2588184610Salfred * should be freed, when "zyd_setup_desc_and_tx" is called. 2589184610Salfred */ 2590184610Salfredstatic void 2591184610Salfredzyd_setup_desc_and_tx(struct zyd_softc *sc, struct mbuf *m, 2592184610Salfred uint16_t rate) 2593184610Salfred{ 2594184610Salfred struct ifnet *ifp = sc->sc_ifp; 2595184610Salfred struct ieee80211com *ic = ifp->if_l2com; 2596184610Salfred struct mbuf *mm; 2597184610Salfred enum ieee80211_phytype phytype; 2598184610Salfred uint16_t len; 2599184610Salfred uint16_t totlen; 2600184610Salfred uint16_t pktlen; 2601184610Salfred uint8_t remainder; 2602184610Salfred 2603184610Salfred if (sc->sc_tx_queue.ifq_len >= IFQ_MAXLEN) { 2604184610Salfred /* free packet */ 2605184610Salfred zyd_tx_freem(m); 2606184610Salfred ifp->if_oerrors++; 2607184610Salfred return; 2608184610Salfred } 2609184610Salfred if (!((sc->sc_flags & ZYD_FLAG_LL_READY) && 2610184610Salfred (sc->sc_flags & ZYD_FLAG_HL_READY))) { 2611184610Salfred /* free packet */ 2612184610Salfred zyd_tx_freem(m); 2613184610Salfred ifp->if_oerrors++; 2614184610Salfred return; 2615184610Salfred } 2616184610Salfred if (rate < 2) { 2617184610Salfred DPRINTF("rate < 2!\n"); 2618184610Salfred 2619184610Salfred /* avoid division by zero */ 2620184610Salfred rate = 2; 2621184610Salfred } 2622184610Salfred ic->ic_lastdata = ticks; 2623184610Salfred 2624184610Salfred if (bpf_peers_present(ifp->if_bpf)) { 2625184610Salfred struct zyd_tx_radiotap_header *tap = &sc->sc_txtap; 2626184610Salfred 2627184610Salfred tap->wt_flags = 0; 2628184610Salfred tap->wt_rate = rate; 2629184610Salfred tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); 2630184610Salfred tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); 2631184610Salfred 2632184610Salfred bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m); 2633184610Salfred } 2634184610Salfred len = m->m_pkthdr.len; 2635184610Salfred totlen = m->m_pkthdr.len + IEEE80211_CRC_LEN; 2636184610Salfred phytype = ieee80211_rate2phytype(sc->sc_rates, rate); 2637184610Salfred 2638184610Salfred sc->sc_tx_desc.len = htole16(totlen); 2639184610Salfred sc->sc_tx_desc.phy = zyd_plcp_signal(rate); 2640184610Salfred if (phytype == IEEE80211_T_OFDM) { 2641184610Salfred sc->sc_tx_desc.phy |= ZYD_TX_PHY_OFDM; 2642184610Salfred if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) 2643184610Salfred sc->sc_tx_desc.phy |= ZYD_TX_PHY_5GHZ; 2644184610Salfred } else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 2645184610Salfred sc->sc_tx_desc.phy |= ZYD_TX_PHY_SHPREAMBLE; 2646184610Salfred 2647184610Salfred /* actual transmit length (XXX why +10?) */ 2648184610Salfred pktlen = sizeof(struct zyd_tx_desc) + 10; 2649184610Salfred if (sc->sc_mac_rev == ZYD_ZD1211) 2650184610Salfred pktlen += totlen; 2651184610Salfred sc->sc_tx_desc.pktlen = htole16(pktlen); 2652184610Salfred 2653184610Salfred sc->sc_tx_desc.plcp_length = ((16 * totlen) + rate - 1) / rate; 2654184610Salfred sc->sc_tx_desc.plcp_service = 0; 2655184610Salfred if (rate == 22) { 2656184610Salfred remainder = (16 * totlen) % 22; 2657184610Salfred if ((remainder != 0) && (remainder < 7)) 2658184610Salfred sc->sc_tx_desc.plcp_service |= ZYD_PLCP_LENGEXT; 2659184610Salfred } 2660184610Salfred if (sizeof(sc->sc_tx_desc) > MHLEN) { 2661184610Salfred DPRINTF("No room for header structure!\n"); 2662184610Salfred zyd_tx_freem(m); 2663184610Salfred return; 2664184610Salfred } 2665184610Salfred mm = m_gethdr(M_NOWAIT, MT_DATA); 2666184610Salfred if (mm == NULL) { 2667184610Salfred DPRINTF("Could not allocate header mbuf!\n"); 2668184610Salfred zyd_tx_freem(m); 2669184610Salfred return; 2670184610Salfred } 2671184610Salfred bcopy(&sc->sc_tx_desc, mm->m_data, sizeof(sc->sc_tx_desc)); 2672184610Salfred mm->m_len = sizeof(sc->sc_tx_desc); 2673184610Salfred 2674184610Salfred mm->m_next = m; 2675184610Salfred mm->m_pkthdr.len = mm->m_len + m->m_pkthdr.len; 2676184610Salfred mm->m_pkthdr.rcvif = NULL; 2677184610Salfred 2678184610Salfred /* start write transfer, if not started */ 2679184610Salfred _IF_ENQUEUE(&sc->sc_tx_queue, mm); 2680184610Salfred 2681184610Salfred usb2_transfer_start(sc->sc_xfer[0]); 2682184610Salfred return; 2683184610Salfred} 2684184610Salfred 2685184610Salfredstatic void 2686184610Salfredzyd_bulk_write_callback(struct usb2_xfer *xfer) 2687184610Salfred{ 2688184610Salfred struct zyd_softc *sc = xfer->priv_sc; 2689184610Salfred struct ifnet *ifp = sc->sc_ifp; 2690184610Salfred struct mbuf *m; 2691184610Salfred uint16_t temp_len; 2692184610Salfred 2693184610Salfred DPRINTF("\n"); 2694184610Salfred 2695184610Salfred switch (USB_GET_STATE(xfer)) { 2696184610Salfred case USB_ST_TRANSFERRED: 2697184610Salfred DPRINTFN(11, "transfer complete\n"); 2698184610Salfred 2699184610Salfred ifp->if_opackets++; 2700184610Salfred 2701184610Salfred case USB_ST_SETUP: 2702184610Salfred if (sc->sc_flags & ZYD_FLAG_BULK_WRITE_STALL) { 2703184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_BULK_CS_WR]); 2704184610Salfred DPRINTFN(11, "write stalled\n"); 2705184610Salfred break; 2706184610Salfred } 2707184610Salfred if (sc->sc_flags & ZYD_FLAG_WAIT_COMMAND) { 2708184610Salfred /* 2709184610Salfred * don't send anything while a command is pending ! 2710184610Salfred */ 2711184610Salfred DPRINTFN(11, "wait command\n"); 2712184610Salfred break; 2713184610Salfred } 2714184610Salfred zyd_fill_write_queue(sc); 2715184610Salfred 2716184610Salfred _IF_DEQUEUE(&sc->sc_tx_queue, m); 2717184610Salfred 2718184610Salfred if (m) { 2719184610Salfred if (m->m_pkthdr.len > ZYD_MAX_TXBUFSZ) { 2720184610Salfred DPRINTFN(0, "data overflow, %u bytes\n", 2721184610Salfred m->m_pkthdr.len); 2722184610Salfred m->m_pkthdr.len = ZYD_MAX_TXBUFSZ; 2723184610Salfred } 2724184610Salfred usb2_m_copy_in(xfer->frbuffers, 0, 2725184610Salfred m, 0, m->m_pkthdr.len); 2726184610Salfred 2727184610Salfred /* get transfer length */ 2728184610Salfred temp_len = m->m_pkthdr.len; 2729184610Salfred 2730184610Salfred DPRINTFN(11, "sending frame len=%u xferlen=%u\n", 2731184610Salfred m->m_pkthdr.len, temp_len); 2732184610Salfred 2733184610Salfred xfer->frlengths[0] = temp_len; 2734184610Salfred 2735184610Salfred usb2_start_hardware(xfer); 2736184610Salfred 2737184610Salfred /* free mbuf and node */ 2738184610Salfred zyd_tx_freem(m); 2739184610Salfred } 2740184610Salfred break; 2741184610Salfred 2742184610Salfred default: /* Error */ 2743184610Salfred DPRINTFN(11, "transfer error, %s\n", 2744184610Salfred usb2_errstr(xfer->error)); 2745184610Salfred 2746184610Salfred if (xfer->error != USB_ERR_CANCELLED) { 2747184610Salfred /* try to clear stall first */ 2748184610Salfred sc->sc_flags |= ZYD_FLAG_BULK_WRITE_STALL; 2749184610Salfred usb2_transfer_start(sc->sc_xfer[ZYD_TR_BULK_CS_WR]); 2750184610Salfred } 2751184610Salfred ifp->if_oerrors++; 2752184610Salfred break; 2753184610Salfred } 2754184610Salfred return; 2755184610Salfred} 2756184610Salfred 2757184610Salfredstatic void 2758184610Salfredzyd_init_cb(void *arg) 2759184610Salfred{ 2760184610Salfred struct zyd_softc *sc = arg; 2761184610Salfred 2762184610Salfred mtx_lock(&sc->sc_mtx); 2763184610Salfred usb2_config_td_queue_command 2764184610Salfred (&sc->sc_config_td, &zyd_cfg_pre_init, 2765184610Salfred &zyd_cfg_init, 0, 0); 2766184610Salfred mtx_unlock(&sc->sc_mtx); 2767184610Salfred 2768184610Salfred return; 2769184610Salfred} 2770184610Salfred 2771184610Salfredstatic int 2772184610Salfredzyd_ioctl_cb(struct ifnet *ifp, u_long cmd, caddr_t data) 2773184610Salfred{ 2774184610Salfred struct zyd_softc *sc = ifp->if_softc; 2775184610Salfred struct ieee80211com *ic = ifp->if_l2com; 2776184610Salfred int error; 2777184610Salfred 2778184610Salfred switch (cmd) { 2779184610Salfred case SIOCSIFFLAGS: 2780184610Salfred mtx_lock(&sc->sc_mtx); 2781184610Salfred if (ifp->if_flags & IFF_UP) { 2782184610Salfred if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 2783184610Salfred usb2_config_td_queue_command 2784184610Salfred (&sc->sc_config_td, &zyd_cfg_pre_init, 2785184610Salfred &zyd_cfg_init, 0, 0); 2786184610Salfred } 2787184610Salfred } else { 2788184610Salfred if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 2789184610Salfred usb2_config_td_queue_command 2790184610Salfred (&sc->sc_config_td, &zyd_cfg_pre_stop, 2791184610Salfred &zyd_cfg_stop, 0, 0); 2792184610Salfred } 2793184610Salfred } 2794184610Salfred mtx_unlock(&sc->sc_mtx); 2795184610Salfred error = 0; 2796184610Salfred break; 2797184610Salfred 2798184610Salfred case SIOCGIFMEDIA: 2799184610Salfred case SIOCADDMULTI: 2800184610Salfred case SIOCDELMULTI: 2801184610Salfred error = ifmedia_ioctl(ifp, (void *)data, &ic->ic_media, cmd); 2802184610Salfred break; 2803184610Salfred 2804184610Salfred default: 2805184610Salfred error = ether_ioctl(ifp, cmd, data); 2806184610Salfred break; 2807184610Salfred } 2808184610Salfred return (error); 2809184610Salfred} 2810184610Salfred 2811184610Salfredstatic void 2812184610Salfredzyd_watchdog(void *arg) 2813184610Salfred{ 2814184610Salfred struct zyd_softc *sc = arg; 2815184610Salfred 2816184610Salfred mtx_assert(&sc->sc_mtx, MA_OWNED); 2817184610Salfred 2818184610Salfred if (sc->sc_amrr_timer) { 2819184610Salfred usb2_config_td_queue_command 2820184610Salfred (&sc->sc_config_td, NULL, 2821184610Salfred &zyd_cfg_amrr_timeout, 0, 0); 2822184610Salfred } 2823184610Salfred usb2_callout_reset(&sc->sc_watchdog, 2824184610Salfred hz, &zyd_watchdog, sc); 2825184610Salfred 2826184610Salfred mtx_unlock(&sc->sc_mtx); 2827184610Salfred 2828184610Salfred return; 2829184610Salfred} 2830184610Salfred 2831184610Salfredstatic void 2832184610Salfredzyd_config_copy_chan(struct zyd_config_copy_chan *cc, 2833184610Salfred struct ieee80211com *ic, struct ieee80211_channel *c) 2834184610Salfred{ 2835184610Salfred if (!c) 2836184610Salfred return; 2837184610Salfred cc->chan_to_ieee = 2838184610Salfred ieee80211_chan2ieee(ic, c); 2839184610Salfred if (c != IEEE80211_CHAN_ANYC) { 2840184610Salfred cc->chan_to_mode = 2841184610Salfred ieee80211_chan2mode(c); 2842184610Salfred cc->ic_freq = c->ic_freq; 2843184610Salfred if (IEEE80211_IS_CHAN_B(c)) 2844184610Salfred cc->chan_is_b = 1; 2845184610Salfred if (IEEE80211_IS_CHAN_A(c)) 2846184610Salfred cc->chan_is_a = 1; 2847184610Salfred if (IEEE80211_IS_CHAN_2GHZ(c)) 2848184610Salfred cc->chan_is_2ghz = 1; 2849184610Salfred if (IEEE80211_IS_CHAN_5GHZ(c)) 2850184610Salfred cc->chan_is_5ghz = 1; 2851184610Salfred if (IEEE80211_IS_CHAN_ANYG(c)) 2852184610Salfred cc->chan_is_g = 1; 2853184610Salfred } 2854184610Salfred return; 2855184610Salfred} 2856184610Salfred 2857184610Salfredstatic void 2858184610Salfredzyd_config_copy(struct zyd_softc *sc, 2859184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 2860184610Salfred{ 2861184610Salfred const struct ieee80211_txparam *tp; 2862184610Salfred struct ieee80211vap *vap; 2863184610Salfred struct ifmultiaddr *ifma; 2864184610Salfred struct ieee80211_node *ni; 2865184610Salfred struct ieee80211com *ic; 2866184610Salfred struct ifnet *ifp; 2867184610Salfred 2868184610Salfred bzero(cc, sizeof(*cc)); 2869184610Salfred 2870184610Salfred ifp = sc->sc_ifp; 2871184610Salfred if (ifp) { 2872184610Salfred cc->if_flags = ifp->if_flags; 2873184610Salfred bcopy(ifp->if_broadcastaddr, cc->if_broadcastaddr, 2874184610Salfred sizeof(cc->if_broadcastaddr)); 2875184610Salfred 2876184610Salfred cc->zyd_multi_low = 0x00000000; 2877184610Salfred cc->zyd_multi_high = 0x80000000; 2878184610Salfred 2879184610Salfred IF_ADDR_LOCK(ifp); 2880184610Salfred TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 2881184610Salfred uint8_t v; 2882184610Salfred 2883184610Salfred if (ifma->ifma_addr->sa_family != AF_LINK) 2884184610Salfred continue; 2885184610Salfred v = ((uint8_t *)LLADDR((struct sockaddr_dl *) 2886184610Salfred ifma->ifma_addr))[5] >> 2; 2887184610Salfred if (v < 32) 2888184610Salfred cc->zyd_multi_low |= 1 << v; 2889184610Salfred else 2890184610Salfred cc->zyd_multi_high |= 1 << (v - 32); 2891184610Salfred } 2892184610Salfred IF_ADDR_UNLOCK(ifp); 2893184610Salfred 2894184610Salfred ic = ifp->if_l2com; 2895184610Salfred if (ic) { 2896184610Salfred zyd_config_copy_chan(&cc->ic_curchan, ic, ic->ic_curchan); 2897184610Salfred zyd_config_copy_chan(&cc->ic_bsschan, ic, ic->ic_bsschan); 2898184610Salfred vap = TAILQ_FIRST(&ic->ic_vaps); 2899184610Salfred if (vap) { 2900184610Salfred ni = vap->iv_bss; 2901184610Salfred if (ni) { 2902184610Salfred cc->iv_bss.ni_intval = ni->ni_intval; 2903184610Salfred bcopy(ni->ni_bssid, cc->iv_bss.ni_bssid, 2904184610Salfred sizeof(cc->iv_bss.ni_bssid)); 2905184610Salfred } 2906184610Salfred tp = vap->iv_txparms + cc->ic_bsschan.chan_to_mode; 2907184610Salfred if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) { 2908184610Salfred cc->iv_bss.fixed_rate_none = 1; 2909184610Salfred } 2910184610Salfred } 2911184610Salfred cc->ic_opmode = ic->ic_opmode; 2912184610Salfred cc->ic_flags = ic->ic_flags; 2913184610Salfred cc->ic_txpowlimit = ic->ic_txpowlimit; 2914184610Salfred cc->ic_curmode = ic->ic_curmode; 2915184610Salfred 2916184610Salfred bcopy(ic->ic_myaddr, cc->ic_myaddr, 2917184610Salfred sizeof(cc->ic_myaddr)); 2918184610Salfred } 2919184610Salfred } 2920184610Salfred sc->sc_flags |= ZYD_FLAG_WAIT_COMMAND; 2921184610Salfred return; 2922184610Salfred} 2923184610Salfred 2924184610Salfredstatic void 2925184610Salfredzyd_end_of_commands(struct zyd_softc *sc) 2926184610Salfred{ 2927184610Salfred sc->sc_flags &= ~ZYD_FLAG_WAIT_COMMAND; 2928184610Salfred 2929184610Salfred /* start write transfer, if not started */ 2930184610Salfred usb2_transfer_start(sc->sc_xfer[0]); 2931184610Salfred return; 2932184610Salfred} 2933184610Salfred 2934184610Salfredstatic void 2935184610Salfredzyd_newassoc_cb(struct ieee80211_node *ni, int isnew) 2936184610Salfred{ 2937184610Salfred struct ieee80211vap *vap = ni->ni_vap; 2938184610Salfred 2939184610Salfred ieee80211_amrr_node_init(&ZYD_VAP(vap)->amrr, &ZYD_NODE(ni)->amn, ni); 2940184610Salfred return; 2941184610Salfred} 2942184610Salfred 2943184610Salfredstatic void 2944184610Salfredzyd_cfg_amrr_timeout(struct zyd_softc *sc, 2945184610Salfred struct usb2_config_td_cc *cc, uint16_t refcount) 2946184610Salfred{ 2947184610Salfred struct ieee80211vap *vap; 2948184610Salfred struct ieee80211_node *ni; 2949184610Salfred 2950184610Salfred vap = zyd_get_vap(sc); 2951184610Salfred if (vap == NULL) { 2952184610Salfred return; 2953184610Salfred } 2954184610Salfred ni = vap->iv_bss; 2955184610Salfred if (ni == NULL) { 2956184610Salfred return; 2957184610Salfred } 2958184610Salfred if ((sc->sc_flags & ZYD_FLAG_LL_READY) && 2959184610Salfred (sc->sc_flags & ZYD_FLAG_HL_READY)) { 2960184610Salfred 2961184610Salfred if (sc->sc_amrr_timer) { 2962184610Salfred 2963184610Salfred if (ieee80211_amrr_choose(ni, &ZYD_NODE(ni)->amn)) { 2964184610Salfred /* ignore */ 2965184610Salfred } 2966184610Salfred } 2967184610Salfred } 2968184610Salfred return; 2969184610Salfred} 2970184610Salfred 2971184610Salfredstatic void 2972184610Salfredzyd_cfg_amrr_start(struct zyd_softc *sc) 2973184610Salfred{ 2974184610Salfred struct ieee80211vap *vap; 2975184610Salfred struct ieee80211_node *ni; 2976184610Salfred 2977184610Salfred vap = zyd_get_vap(sc); 2978184610Salfred 2979184610Salfred if (vap == NULL) { 2980184610Salfred return; 2981184610Salfred } 2982184610Salfred ni = vap->iv_bss; 2983184610Salfred if (ni == NULL) { 2984184610Salfred return; 2985184610Salfred } 2986184610Salfred /* init AMRR */ 2987184610Salfred 2988184610Salfred ieee80211_amrr_node_init(&ZYD_VAP(vap)->amrr, &ZYD_NODE(ni)->amn, ni); 2989184610Salfred 2990184610Salfred /* enable AMRR timer */ 2991184610Salfred 2992184610Salfred sc->sc_amrr_timer = 1; 2993184610Salfred return; 2994184610Salfred} 2995184610Salfred 2996184610Salfredstatic struct ieee80211vap * 2997184610Salfredzyd_vap_create(struct ieee80211com *ic, 2998184610Salfred const char name[IFNAMSIZ], int unit, int opmode, int flags, 2999184610Salfred const uint8_t bssid[IEEE80211_ADDR_LEN], 3000184610Salfred const uint8_t mac[IEEE80211_ADDR_LEN]) 3001184610Salfred{ 3002184610Salfred struct zyd_vap *zvp; 3003184610Salfred struct ieee80211vap *vap; 3004184610Salfred struct zyd_softc *sc = ic->ic_ifp->if_softc; 3005184610Salfred 3006184610Salfred /* Need to sync with config thread: */ 3007184610Salfred mtx_lock(&sc->sc_mtx); 3008184610Salfred if (usb2_config_td_sync(&sc->sc_config_td)) { 3009184610Salfred mtx_unlock(&sc->sc_mtx); 3010184610Salfred /* config thread is gone */ 3011184610Salfred return (NULL); 3012184610Salfred } 3013184610Salfred mtx_unlock(&sc->sc_mtx); 3014184610Salfred 3015184610Salfred if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ 3016184610Salfred return NULL; 3017184610Salfred zvp = (struct zyd_vap *)malloc(sizeof(struct zyd_vap), 3018184610Salfred M_80211_VAP, M_NOWAIT | M_ZERO); 3019184610Salfred if (zvp == NULL) 3020184610Salfred return NULL; 3021184610Salfred vap = &zvp->vap; 3022184610Salfred /* enable s/w bmiss handling for sta mode */ 3023184610Salfred ieee80211_vap_setup(ic, vap, name, unit, opmode, 3024184610Salfred flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); 3025184610Salfred 3026184610Salfred /* override state transition machine */ 3027184610Salfred zvp->newstate = vap->iv_newstate; 3028184610Salfred vap->iv_newstate = &zyd_newstate_cb; 3029184610Salfred 3030184610Salfred ieee80211_amrr_init(&zvp->amrr, vap, 3031184610Salfred IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, 3032184610Salfred IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, 3033184610Salfred 1000 /* 1 sec */ ); 3034184610Salfred 3035184610Salfred /* complete setup */ 3036184610Salfred ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); 3037184610Salfred ic->ic_opmode = opmode; 3038184610Salfred 3039184610Salfred return (vap); 3040184610Salfred} 3041184610Salfred 3042184610Salfredstatic void 3043184610Salfredzyd_vap_delete(struct ieee80211vap *vap) 3044184610Salfred{ 3045184610Salfred struct zyd_vap *zvp = ZYD_VAP(vap); 3046184610Salfred struct zyd_softc *sc = vap->iv_ic->ic_ifp->if_softc; 3047184610Salfred 3048184610Salfred /* Need to sync with config thread: */ 3049184610Salfred mtx_lock(&sc->sc_mtx); 3050184610Salfred if (usb2_config_td_sync(&sc->sc_config_td)) { 3051184610Salfred /* ignore */ 3052184610Salfred } 3053184610Salfred mtx_unlock(&sc->sc_mtx); 3054184610Salfred 3055184610Salfred ieee80211_amrr_cleanup(&zvp->amrr); 3056184610Salfred ieee80211_vap_detach(vap); 3057184610Salfred free(zvp, M_80211_VAP); 3058184610Salfred return; 3059184610Salfred} 3060184610Salfred 3061184610Salfred/* ARGUSED */ 3062184610Salfredstatic struct ieee80211_node * 3063184610Salfredzyd_node_alloc_cb(struct ieee80211vap *vap __unused, 3064184610Salfred const uint8_t mac[IEEE80211_ADDR_LEN] __unused) 3065184610Salfred{ 3066184610Salfred struct zyd_node *zn; 3067184610Salfred 3068184610Salfred zn = malloc(sizeof(struct zyd_node), M_80211_NODE, M_NOWAIT | M_ZERO); 3069184610Salfred return ((zn != NULL) ? &zn->ni : NULL); 3070184610Salfred} 3071184610Salfred 3072184610Salfredstatic void 3073184610Salfredzyd_fill_write_queue(struct zyd_softc *sc) 3074184610Salfred{ 3075184610Salfred struct ifnet *ifp = sc->sc_ifp; 3076184610Salfred struct ieee80211_node *ni; 3077184610Salfred struct mbuf *m; 3078184610Salfred 3079184610Salfred /* 3080184610Salfred * We only fill up half of the queue with data frames. The rest is 3081184610Salfred * reserved for other kinds of frames. 3082184610Salfred */ 3083184610Salfred 3084184610Salfred while (sc->sc_tx_queue.ifq_len < (IFQ_MAXLEN / 2)) { 3085184610Salfred 3086184610Salfred IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 3087184610Salfred if (m == NULL) 3088184610Salfred break; 3089184610Salfred 3090184610Salfred ni = (void *)(m->m_pkthdr.rcvif); 3091184610Salfred m = ieee80211_encap(ni, m); 3092184610Salfred if (m == NULL) { 3093184610Salfred ieee80211_free_node(ni); 3094184610Salfred continue; 3095184610Salfred } 3096184610Salfred zyd_tx_data(sc, m, ni); 3097184610Salfred } 3098184610Salfred return; 3099184610Salfred} 3100184610Salfred 3101184610Salfredstatic void 3102184610Salfredzyd_tx_clean_queue(struct zyd_softc *sc) 3103184610Salfred{ 3104184610Salfred struct mbuf *m; 3105184610Salfred 3106184610Salfred for (;;) { 3107184610Salfred _IF_DEQUEUE(&sc->sc_tx_queue, m); 3108184610Salfred 3109184610Salfred if (!m) { 3110184610Salfred break; 3111184610Salfred } 3112184610Salfred zyd_tx_freem(m); 3113184610Salfred } 3114184610Salfred 3115184610Salfred return; 3116184610Salfred} 3117184610Salfred 3118184610Salfredstatic void 3119184610Salfredzyd_tx_freem(struct mbuf *m) 3120184610Salfred{ 3121184610Salfred struct ieee80211_node *ni; 3122184610Salfred 3123184610Salfred while (m) { 3124184610Salfred ni = (void *)(m->m_pkthdr.rcvif); 3125184610Salfred if (!ni) { 3126184610Salfred m = m_free(m); 3127184610Salfred continue; 3128184610Salfred } 3129184610Salfred if (m->m_flags & M_TXCB) { 3130184610Salfred ieee80211_process_callback(ni, m, 0); 3131184610Salfred } 3132184610Salfred m_freem(m); 3133184610Salfred ieee80211_free_node(ni); 3134184610Salfred 3135184610Salfred break; 3136184610Salfred } 3137184610Salfred return; 3138184610Salfred} 3139184610Salfred 3140184610Salfredstatic void 3141184610Salfredzyd_tx_mgt(struct zyd_softc *sc, struct mbuf *m, struct ieee80211_node *ni) 3142184610Salfred{ 3143184610Salfred struct ieee80211vap *vap = ni->ni_vap; 3144184610Salfred struct ieee80211com *ic = ni->ni_ic; 3145184610Salfred const struct ieee80211_txparam *tp; 3146184610Salfred struct ieee80211_frame *wh; 3147184610Salfred struct ieee80211_key *k; 3148184610Salfred uint16_t totlen; 3149184610Salfred uint16_t rate; 3150184610Salfred 3151184610Salfred tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; 3152184610Salfred rate = tp->mgmtrate; 3153184610Salfred 3154184610Salfred wh = mtod(m, struct ieee80211_frame *); 3155184610Salfred if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 3156184610Salfred k = ieee80211_crypto_encap(ni, m); 3157184610Salfred if (k == NULL) { 3158184610Salfred m_freem(m); 3159184610Salfred ieee80211_free_node(ni); 3160184610Salfred return; 3161184610Salfred } 3162184610Salfred wh = mtod(m, struct ieee80211_frame *); 3163184610Salfred } 3164184610Salfred /* fill Tx descriptor */ 3165184610Salfred 3166184610Salfred sc->sc_tx_desc.flags = ZYD_TX_FLAG_BACKOFF; 3167184610Salfred if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 3168184610Salfred /* get total length */ 3169184610Salfred totlen = m->m_pkthdr.len + IEEE80211_CRC_LEN; 3170184610Salfred /* multicast frames are not sent at OFDM rates in 802.11b/g */ 3171184610Salfred if (totlen > vap->iv_rtsthreshold) { 3172184610Salfred sc->sc_tx_desc.flags |= ZYD_TX_FLAG_RTS; 3173184610Salfred } else if (ZYD_RATE_IS_OFDM(rate) && 3174184610Salfred (ic->ic_flags & IEEE80211_F_USEPROT)) { 3175184610Salfred if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) 3176184610Salfred sc->sc_tx_desc.flags |= ZYD_TX_FLAG_CTS_TO_SELF; 3177184610Salfred else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) 3178184610Salfred sc->sc_tx_desc.flags |= ZYD_TX_FLAG_RTS; 3179184610Salfred } 3180184610Salfred } else 3181184610Salfred sc->sc_tx_desc.flags |= ZYD_TX_FLAG_MULTICAST; 3182184610Salfred 3183184610Salfred if ((wh->i_fc[0] & 3184184610Salfred (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == 3185184610Salfred (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL)) 3186184610Salfred sc->sc_tx_desc.flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL); 3187184610Salfred 3188184610Salfred m->m_pkthdr.rcvif = (void *)ni; 3189184610Salfred zyd_setup_desc_and_tx(sc, m, rate); 3190184610Salfred return; 3191184610Salfred} 3192184610Salfred 3193184610Salfredstatic void 3194184610Salfredzyd_tx_data(struct zyd_softc *sc, struct mbuf *m, struct ieee80211_node *ni) 3195184610Salfred{ 3196184610Salfred struct ieee80211vap *vap = ni->ni_vap; 3197184610Salfred struct ieee80211com *ic = ni->ni_ic; 3198184610Salfred const struct ieee80211_txparam *tp; 3199184610Salfred struct ieee80211_frame *wh; 3200184610Salfred struct ieee80211_key *k; 3201184610Salfred uint16_t rate; 3202184610Salfred 3203184610Salfred wh = mtod(m, struct ieee80211_frame *); 3204184610Salfred 3205184610Salfred sc->sc_tx_desc.flags = ZYD_TX_FLAG_BACKOFF; 3206184610Salfred tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; 3207184610Salfred if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { 3208184610Salfred rate = tp->mcastrate; 3209184610Salfred sc->sc_tx_desc.flags |= ZYD_TX_FLAG_MULTICAST; 3210184610Salfred } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { 3211184610Salfred rate = tp->ucastrate; 3212184610Salfred } else 3213184610Salfred rate = ni->ni_txrate; 3214184610Salfred 3215184610Salfred if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 3216184610Salfred k = ieee80211_crypto_encap(ni, m); 3217184610Salfred if (k == NULL) { 3218184610Salfred m_freem(m); 3219184610Salfred ieee80211_free_node(ni); 3220184610Salfred return; 3221184610Salfred } 3222184610Salfred /* packet header may have moved, reset our local pointer */ 3223184610Salfred wh = mtod(m, struct ieee80211_frame *); 3224184610Salfred } 3225184610Salfred /* fill Tx descriptor */ 3226184610Salfred 3227184610Salfred if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 3228184610Salfred uint16_t totlen; 3229184610Salfred 3230184610Salfred totlen = m->m_pkthdr.len + IEEE80211_CRC_LEN; 3231184610Salfred 3232184610Salfred /* multicast frames are not sent at OFDM rates in 802.11b/g */ 3233184610Salfred if (totlen > vap->iv_rtsthreshold) { 3234184610Salfred sc->sc_tx_desc.flags |= ZYD_TX_FLAG_RTS; 3235184610Salfred } else if (ZYD_RATE_IS_OFDM(rate) && 3236184610Salfred (ic->ic_flags & IEEE80211_F_USEPROT)) { 3237184610Salfred if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) 3238184610Salfred sc->sc_tx_desc.flags |= ZYD_TX_FLAG_CTS_TO_SELF; 3239184610Salfred else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) 3240184610Salfred sc->sc_tx_desc.flags |= ZYD_TX_FLAG_RTS; 3241184610Salfred } 3242184610Salfred } 3243184610Salfred if ((wh->i_fc[0] & 3244184610Salfred (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == 3245184610Salfred (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL)) 3246184610Salfred sc->sc_tx_desc.flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL); 3247184610Salfred 3248184610Salfred m->m_pkthdr.rcvif = (void *)ni; 3249184610Salfred zyd_setup_desc_and_tx(sc, m, rate); 3250184610Salfred return; 3251184610Salfred} 3252184610Salfred 3253184610Salfredstatic int 3254184610Salfredzyd_raw_xmit_cb(struct ieee80211_node *ni, struct mbuf *m, 3255184610Salfred const struct ieee80211_bpf_params *params) 3256184610Salfred{ 3257184610Salfred struct ieee80211com *ic = ni->ni_ic; 3258184610Salfred struct ifnet *ifp = ic->ic_ifp; 3259184610Salfred struct zyd_softc *sc = ifp->if_softc; 3260184610Salfred 3261184610Salfred mtx_lock(&sc->sc_mtx); 3262184610Salfred if (params == NULL) { 3263184610Salfred /* 3264184610Salfred * Legacy path; interpret frame contents to decide 3265184610Salfred * precisely how to send the frame. 3266184610Salfred */ 3267184610Salfred zyd_tx_mgt(sc, m, ni); 3268184610Salfred } else { 3269184610Salfred /* 3270184610Salfred * Caller supplied explicit parameters to use in 3271184610Salfred * sending the frame. 3272184610Salfred */ 3273184610Salfred zyd_tx_mgt(sc, m, ni); /* XXX zyd_tx_raw() */ 3274184610Salfred } 3275184610Salfred mtx_unlock(&sc->sc_mtx); 3276184610Salfred return (0); 3277184610Salfred} 3278184610Salfred 3279184610Salfredstatic struct ieee80211vap * 3280184610Salfredzyd_get_vap(struct zyd_softc *sc) 3281184610Salfred{ 3282184610Salfred struct ifnet *ifp; 3283184610Salfred struct ieee80211com *ic; 3284184610Salfred 3285184610Salfred if (sc == NULL) { 3286184610Salfred return NULL; 3287184610Salfred } 3288184610Salfred ifp = sc->sc_ifp; 3289184610Salfred if (ifp == NULL) { 3290184610Salfred return NULL; 3291184610Salfred } 3292184610Salfred ic = ifp->if_l2com; 3293184610Salfred if (ic == NULL) { 3294184610Salfred return NULL; 3295184610Salfred } 3296184610Salfred return TAILQ_FIRST(&ic->ic_vaps); 3297184610Salfred} 3298