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