if_zyd.c revision 191746
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/usb/wlan/if_zyd.c 191746 2009-05-02 15:14:18Z thompsa $ */ 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/usb/wlan/if_zyd.c 191746 2009-05-02 15:14:18Z thompsa $"); 24184610Salfred 25184610Salfred/* 26188417Sthompsa * ZyDAS ZD1211/ZD1211B USB WLAN driver. 27184610Salfred */ 28184610Salfred 29191746Sthompsa#include <sys/param.h> 30191746Sthompsa#include <sys/sockio.h> 31191746Sthompsa#include <sys/sysctl.h> 32191746Sthompsa#include <sys/lock.h> 33191746Sthompsa#include <sys/mutex.h> 34191746Sthompsa#include <sys/mbuf.h> 35191746Sthompsa#include <sys/kernel.h> 36191746Sthompsa#include <sys/socket.h> 37191746Sthompsa#include <sys/systm.h> 38191746Sthompsa#include <sys/malloc.h> 39191746Sthompsa#include <sys/module.h> 40191746Sthompsa#include <sys/bus.h> 41191746Sthompsa#include <sys/endian.h> 42191746Sthompsa#include <sys/kdb.h> 43191746Sthompsa 44191746Sthompsa#include <machine/bus.h> 45191746Sthompsa#include <machine/resource.h> 46191746Sthompsa#include <sys/rman.h> 47191746Sthompsa 48191746Sthompsa#include <net/bpf.h> 49191746Sthompsa#include <net/if.h> 50191746Sthompsa#include <net/if_arp.h> 51191746Sthompsa#include <net/ethernet.h> 52191746Sthompsa#include <net/if_dl.h> 53191746Sthompsa#include <net/if_media.h> 54191746Sthompsa#include <net/if_types.h> 55191746Sthompsa 56191746Sthompsa#ifdef INET 57191746Sthompsa#include <netinet/in.h> 58191746Sthompsa#include <netinet/in_systm.h> 59191746Sthompsa#include <netinet/in_var.h> 60191746Sthompsa#include <netinet/if_ether.h> 61191746Sthompsa#include <netinet/ip.h> 62191746Sthompsa#endif 63191746Sthompsa 64191746Sthompsa#include <net80211/ieee80211_var.h> 65191746Sthompsa#include <net80211/ieee80211_regdomain.h> 66191746Sthompsa#include <net80211/ieee80211_radiotap.h> 67191746Sthompsa#include <net80211/ieee80211_amrr.h> 68191746Sthompsa 69188942Sthompsa#include <dev/usb/usb.h> 70188942Sthompsa#include <dev/usb/usb_error.h> 71188942Sthompsa#include <dev/usb/usb_core.h> 72188942Sthompsa#include <dev/usb/usb_lookup.h> 73188942Sthompsa#include <dev/usb/usb_debug.h> 74188942Sthompsa#include <dev/usb/usb_request.h> 75188942Sthompsa#include <dev/usb/usb_busdma.h> 76188942Sthompsa#include <dev/usb/usb_util.h> 77191746Sthompsa#include "usbdevs.h" 78184610Salfred 79188942Sthompsa#include <dev/usb/wlan/if_zydreg.h> 80188942Sthompsa#include <dev/usb/wlan/if_zydfw.h> 81184610Salfred 82184610Salfred#if USB_DEBUG 83184610Salfredstatic int zyd_debug = 0; 84184610Salfred 85184610SalfredSYSCTL_NODE(_hw_usb2, OID_AUTO, zyd, CTLFLAG_RW, 0, "USB zyd"); 86184610SalfredSYSCTL_INT(_hw_usb2_zyd, OID_AUTO, debug, CTLFLAG_RW, &zyd_debug, 0, 87184610Salfred "zyd debug level"); 88188417Sthompsa 89188417Sthompsaenum { 90188417Sthompsa ZYD_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ 91188417Sthompsa ZYD_DEBUG_RECV = 0x00000002, /* basic recv operation */ 92188417Sthompsa ZYD_DEBUG_RESET = 0x00000004, /* reset processing */ 93188417Sthompsa ZYD_DEBUG_INIT = 0x00000008, /* device init */ 94188417Sthompsa ZYD_DEBUG_TX_PROC = 0x00000010, /* tx ISR proc */ 95188417Sthompsa ZYD_DEBUG_RX_PROC = 0x00000020, /* rx ISR proc */ 96188417Sthompsa ZYD_DEBUG_STATE = 0x00000040, /* 802.11 state transitions */ 97188417Sthompsa ZYD_DEBUG_STAT = 0x00000080, /* statistic */ 98188417Sthompsa ZYD_DEBUG_FW = 0x00000100, /* firmware */ 99188417Sthompsa ZYD_DEBUG_CMD = 0x00000200, /* fw commands */ 100188417Sthompsa ZYD_DEBUG_ANY = 0xffffffff 101188417Sthompsa}; 102188417Sthompsa#define DPRINTF(sc, m, fmt, ...) do { \ 103188419Sthompsa if (zyd_debug & (m)) \ 104188417Sthompsa printf("%s: " fmt, __func__, ## __VA_ARGS__); \ 105188417Sthompsa} while (0) 106188417Sthompsa#else 107188417Sthompsa#define DPRINTF(sc, m, fmt, ...) do { \ 108188417Sthompsa (void) sc; \ 109188417Sthompsa} while (0) 110184610Salfred#endif 111184610Salfred 112188419Sthompsa#define zyd_do_request(sc,req,data) \ 113191746Sthompsa usb2_do_request_flags((sc)->sc_udev, &(sc)->sc_mtx, req, data, 0, NULL, 5000) 114188419Sthompsa 115188417Sthompsastatic device_probe_t zyd_match; 116184610Salfredstatic device_attach_t zyd_attach; 117184610Salfredstatic device_detach_t zyd_detach; 118184610Salfred 119184610Salfredstatic usb2_callback_t zyd_intr_read_callback; 120184610Salfredstatic usb2_callback_t zyd_intr_write_callback; 121184610Salfredstatic usb2_callback_t zyd_bulk_read_callback; 122184610Salfredstatic usb2_callback_t zyd_bulk_write_callback; 123184610Salfred 124185948Sthompsastatic struct ieee80211vap *zyd_vap_create(struct ieee80211com *, 125188417Sthompsa const char name[IFNAMSIZ], int unit, int opmode, 126188417Sthompsa int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], 127188417Sthompsa const uint8_t mac[IEEE80211_ADDR_LEN]); 128185948Sthompsastatic void zyd_vap_delete(struct ieee80211vap *); 129188417Sthompsastatic void zyd_tx_free(struct zyd_tx_data *, int); 130188419Sthompsastatic void zyd_setup_tx_list(struct zyd_softc *); 131188419Sthompsastatic void zyd_unsetup_tx_list(struct zyd_softc *); 132188417Sthompsastatic struct ieee80211_node *zyd_node_alloc(struct ieee80211vap *, 133188417Sthompsa const uint8_t mac[IEEE80211_ADDR_LEN]); 134188417Sthompsastatic int zyd_newstate(struct ieee80211vap *, enum ieee80211_state, int); 135188417Sthompsastatic int zyd_cmd(struct zyd_softc *, uint16_t, const void *, int, 136188601Sthompsa void *, int, int); 137188417Sthompsastatic int zyd_read16(struct zyd_softc *, uint16_t, uint16_t *); 138188417Sthompsastatic int zyd_read32(struct zyd_softc *, uint16_t, uint32_t *); 139188417Sthompsastatic int zyd_write16(struct zyd_softc *, uint16_t, uint16_t); 140188417Sthompsastatic int zyd_write32(struct zyd_softc *, uint16_t, uint32_t); 141188417Sthompsastatic int zyd_rfwrite(struct zyd_softc *, uint32_t); 142188417Sthompsastatic int zyd_lock_phy(struct zyd_softc *); 143188417Sthompsastatic int zyd_unlock_phy(struct zyd_softc *); 144188417Sthompsastatic int zyd_rf_attach(struct zyd_softc *, uint8_t); 145188417Sthompsastatic const char *zyd_rf_name(uint8_t); 146188417Sthompsastatic int zyd_hw_init(struct zyd_softc *); 147188417Sthompsastatic int zyd_read_pod(struct zyd_softc *); 148188417Sthompsastatic int zyd_read_eeprom(struct zyd_softc *); 149188417Sthompsastatic int zyd_get_macaddr(struct zyd_softc *); 150188417Sthompsastatic int zyd_set_macaddr(struct zyd_softc *, const uint8_t *); 151188417Sthompsastatic int zyd_set_bssid(struct zyd_softc *, const uint8_t *); 152188417Sthompsastatic int zyd_switch_radio(struct zyd_softc *, int); 153188417Sthompsastatic int zyd_set_led(struct zyd_softc *, int, int); 154188417Sthompsastatic void zyd_set_multi(struct zyd_softc *); 155188417Sthompsastatic void zyd_update_mcast(struct ifnet *); 156188417Sthompsastatic int zyd_set_rxfilter(struct zyd_softc *); 157188417Sthompsastatic void zyd_set_chan(struct zyd_softc *, struct ieee80211_channel *); 158188417Sthompsastatic int zyd_set_beacon_interval(struct zyd_softc *, int); 159188417Sthompsastatic void zyd_rx_data(struct usb2_xfer *, int, uint16_t); 160188417Sthompsastatic int zyd_tx_mgt(struct zyd_softc *, struct mbuf *, 161185948Sthompsa struct ieee80211_node *); 162188417Sthompsastatic int zyd_tx_data(struct zyd_softc *, struct mbuf *, 163185948Sthompsa struct ieee80211_node *); 164188417Sthompsastatic void zyd_start(struct ifnet *); 165188417Sthompsastatic int zyd_raw_xmit(struct ieee80211_node *, struct mbuf *, 166185948Sthompsa const struct ieee80211_bpf_params *); 167188417Sthompsastatic int zyd_ioctl(struct ifnet *, u_long, caddr_t); 168191746Sthompsastatic void zyd_init_locked(struct zyd_softc *); 169188417Sthompsastatic void zyd_init(void *); 170191746Sthompsastatic void zyd_stop(struct zyd_softc *); 171188417Sthompsastatic int zyd_loadfirmware(struct zyd_softc *); 172188417Sthompsastatic void zyd_newassoc(struct ieee80211_node *, int); 173188417Sthompsastatic void zyd_scan_start(struct ieee80211com *); 174188417Sthompsastatic void zyd_scan_end(struct ieee80211com *); 175188417Sthompsastatic void zyd_set_channel(struct ieee80211com *); 176188417Sthompsastatic int zyd_rfmd_init(struct zyd_rf *); 177188417Sthompsastatic int zyd_rfmd_switch_radio(struct zyd_rf *, int); 178188417Sthompsastatic int zyd_rfmd_set_channel(struct zyd_rf *, uint8_t); 179188417Sthompsastatic int zyd_al2230_init(struct zyd_rf *); 180188417Sthompsastatic int zyd_al2230_switch_radio(struct zyd_rf *, int); 181188417Sthompsastatic int zyd_al2230_set_channel(struct zyd_rf *, uint8_t); 182188417Sthompsastatic int zyd_al2230_set_channel_b(struct zyd_rf *, uint8_t); 183188417Sthompsastatic int zyd_al2230_init_b(struct zyd_rf *); 184188417Sthompsastatic int zyd_al7230B_init(struct zyd_rf *); 185188417Sthompsastatic int zyd_al7230B_switch_radio(struct zyd_rf *, int); 186188417Sthompsastatic int zyd_al7230B_set_channel(struct zyd_rf *, uint8_t); 187188417Sthompsastatic int zyd_al2210_init(struct zyd_rf *); 188188417Sthompsastatic int zyd_al2210_switch_radio(struct zyd_rf *, int); 189188417Sthompsastatic int zyd_al2210_set_channel(struct zyd_rf *, uint8_t); 190188417Sthompsastatic int zyd_gct_init(struct zyd_rf *); 191188417Sthompsastatic int zyd_gct_switch_radio(struct zyd_rf *, int); 192188417Sthompsastatic int zyd_gct_set_channel(struct zyd_rf *, uint8_t); 193188417Sthompsastatic int zyd_maxim_init(struct zyd_rf *); 194188417Sthompsastatic int zyd_maxim_switch_radio(struct zyd_rf *, int); 195188417Sthompsastatic int zyd_maxim_set_channel(struct zyd_rf *, uint8_t); 196188417Sthompsastatic int zyd_maxim2_init(struct zyd_rf *); 197188417Sthompsastatic int zyd_maxim2_switch_radio(struct zyd_rf *, int); 198188417Sthompsastatic int zyd_maxim2_set_channel(struct zyd_rf *, uint8_t); 199184610Salfred 200184610Salfredstatic const struct zyd_phy_pair zyd_def_phy[] = ZYD_DEF_PHY; 201184610Salfredstatic const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB; 202184610Salfred 203184610Salfred/* various supported device vendors/products */ 204188417Sthompsa#define ZYD_ZD1211 0 205188417Sthompsa#define ZYD_ZD1211B 1 206184610Salfred 207184610Salfredstatic const struct usb2_device_id zyd_devs[] = { 208188417Sthompsa /* ZYD_ZD1211 */ 209188417Sthompsa {USB_VPI(USB_VENDOR_3COM2, USB_PRODUCT_3COM2_3CRUSB10075, ZYD_ZD1211)}, 210188417Sthompsa {USB_VPI(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_WL54, ZYD_ZD1211)}, 211188417Sthompsa {USB_VPI(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_WL159G, ZYD_ZD1211)}, 212188417Sthompsa {USB_VPI(USB_VENDOR_CYBERTAN, USB_PRODUCT_CYBERTAN_TG54USB, ZYD_ZD1211)}, 213188417Sthompsa {USB_VPI(USB_VENDOR_DRAYTEK, USB_PRODUCT_DRAYTEK_VIGOR550, ZYD_ZD1211)}, 214188417Sthompsa {USB_VPI(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54GD, ZYD_ZD1211)}, 215188417Sthompsa {USB_VPI(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54GZL, ZYD_ZD1211)}, 216188417Sthompsa {USB_VPI(USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GWUS54GZ, ZYD_ZD1211)}, 217188417Sthompsa {USB_VPI(USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GWUS54MINI, ZYD_ZD1211)}, 218188417Sthompsa {USB_VPI(USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_XG760A, ZYD_ZD1211)}, 219188417Sthompsa {USB_VPI(USB_VENDOR_SENAO, USB_PRODUCT_SENAO_NUB8301, ZYD_ZD1211)}, 220188417Sthompsa {USB_VPI(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113, ZYD_ZD1211)}, 221188417Sthompsa {USB_VPI(USB_VENDOR_SWEEX, USB_PRODUCT_SWEEX_ZD1211, ZYD_ZD1211)}, 222188417Sthompsa {USB_VPI(USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_QUICKWLAN, ZYD_ZD1211)}, 223188417Sthompsa {USB_VPI(USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_ZD1211_1, ZYD_ZD1211)}, 224188417Sthompsa {USB_VPI(USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_ZD1211_2, ZYD_ZD1211)}, 225188417Sthompsa {USB_VPI(USB_VENDOR_TWINMOS, USB_PRODUCT_TWINMOS_G240, ZYD_ZD1211)}, 226188417Sthompsa {USB_VPI(USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_ALL0298V2, ZYD_ZD1211)}, 227188417Sthompsa {USB_VPI(USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UB_A, ZYD_ZD1211)}, 228188417Sthompsa {USB_VPI(USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UB, ZYD_ZD1211)}, 229188417Sthompsa {USB_VPI(USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_UR055G, ZYD_ZD1211)}, 230188417Sthompsa {USB_VPI(USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_ZD1211, ZYD_ZD1211)}, 231188417Sthompsa {USB_VPI(USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1211, ZYD_ZD1211)}, 232188417Sthompsa {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_AG225H, ZYD_ZD1211)}, 233188417Sthompsa {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_ZYAIRG220, ZYD_ZD1211)}, 234188417Sthompsa {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G200V2, ZYD_ZD1211)}, 235188417Sthompsa {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G202, ZYD_ZD1211)}, 236188417Sthompsa /* ZYD_ZD1211B */ 237188417Sthompsa {USB_VPI(USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_SMCWUSBG, ZYD_ZD1211B)}, 238188417Sthompsa {USB_VPI(USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_ZD1211B, ZYD_ZD1211B)}, 239188417Sthompsa {USB_VPI(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_A9T_WIFI, ZYD_ZD1211B)}, 240188417Sthompsa {USB_VPI(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050_V4000, ZYD_ZD1211B)}, 241188417Sthompsa {USB_VPI(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_ZD1211B, ZYD_ZD1211B)}, 242188417Sthompsa {USB_VPI(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSBF54G, ZYD_ZD1211B)}, 243188417Sthompsa {USB_VPI(USB_VENDOR_FIBERLINE, USB_PRODUCT_FIBERLINE_WL430U, ZYD_ZD1211B)}, 244188417Sthompsa {USB_VPI(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54L, ZYD_ZD1211B)}, 245188417Sthompsa {USB_VPI(USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_SNU5600, ZYD_ZD1211B)}, 246188417Sthompsa {USB_VPI(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GW_US54GXS, ZYD_ZD1211B)}, 247188417Sthompsa {USB_VPI(USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_XG76NA, ZYD_ZD1211B)}, 248188417Sthompsa {USB_VPI(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_ZD1211B, ZYD_ZD1211B)}, 249188417Sthompsa {USB_VPI(USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UBC1, ZYD_ZD1211B)}, 250188417Sthompsa {USB_VPI(USB_VENDOR_USR, USB_PRODUCT_USR_USR5423, ZYD_ZD1211B)}, 251188417Sthompsa {USB_VPI(USB_VENDOR_VTECH, USB_PRODUCT_VTECH_ZD1211B, ZYD_ZD1211B)}, 252188417Sthompsa {USB_VPI(USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_ZD1211B, ZYD_ZD1211B)}, 253188417Sthompsa {USB_VPI(USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1211B, ZYD_ZD1211B)}, 254188417Sthompsa {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_M202, ZYD_ZD1211B)}, 255188417Sthompsa {USB_VPI(USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G220V2, ZYD_ZD1211B)}, 256184610Salfred}; 257184610Salfred 258184610Salfredstatic const struct usb2_config zyd_config[ZYD_N_TRANSFER] = { 259188417Sthompsa [ZYD_BULK_WR] = { 260184610Salfred .type = UE_BULK, 261184610Salfred .endpoint = UE_ADDR_ANY, 262184610Salfred .direction = UE_DIR_OUT, 263190734Sthompsa .bufsize = ZYD_MAX_TXBUFSZ, 264190734Sthompsa .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 265190734Sthompsa .callback = zyd_bulk_write_callback, 266184610Salfred .ep_index = 0, 267190734Sthompsa .timeout = 10000, /* 10 seconds */ 268184610Salfred }, 269188417Sthompsa [ZYD_BULK_RD] = { 270184610Salfred .type = UE_BULK, 271184610Salfred .endpoint = UE_ADDR_ANY, 272184610Salfred .direction = UE_DIR_IN, 273190734Sthompsa .bufsize = ZYX_MAX_RXBUFSZ, 274190734Sthompsa .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 275190734Sthompsa .callback = zyd_bulk_read_callback, 276184610Salfred .ep_index = 0, 277184610Salfred }, 278188417Sthompsa [ZYD_INTR_WR] = { 279184610Salfred .type = UE_BULK_INTR, 280184610Salfred .endpoint = UE_ADDR_ANY, 281184610Salfred .direction = UE_DIR_OUT, 282190734Sthompsa .bufsize = sizeof(struct zyd_cmd), 283190734Sthompsa .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 284190734Sthompsa .callback = zyd_intr_write_callback, 285190734Sthompsa .timeout = 1000, /* 1 second */ 286184610Salfred .ep_index = 1, 287184610Salfred }, 288188417Sthompsa [ZYD_INTR_RD] = { 289188417Sthompsa .type = UE_INTERRUPT, 290184610Salfred .endpoint = UE_ADDR_ANY, 291184610Salfred .direction = UE_DIR_IN, 292190734Sthompsa .bufsize = sizeof(struct zyd_cmd), 293190734Sthompsa .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 294190734Sthompsa .callback = zyd_intr_read_callback, 295184610Salfred }, 296184610Salfred}; 297188417Sthompsa#define zyd_read16_m(sc, val, data) do { \ 298188417Sthompsa error = zyd_read16(sc, val, data); \ 299188417Sthompsa if (error != 0) \ 300188417Sthompsa goto fail; \ 301188417Sthompsa} while (0) 302188417Sthompsa#define zyd_write16_m(sc, val, data) do { \ 303188417Sthompsa error = zyd_write16(sc, val, data); \ 304188417Sthompsa if (error != 0) \ 305188417Sthompsa goto fail; \ 306188417Sthompsa} while (0) 307188417Sthompsa#define zyd_read32_m(sc, val, data) do { \ 308188417Sthompsa error = zyd_read32(sc, val, data); \ 309188417Sthompsa if (error != 0) \ 310188417Sthompsa goto fail; \ 311188417Sthompsa} while (0) 312188417Sthompsa#define zyd_write32_m(sc, val, data) do { \ 313188417Sthompsa error = zyd_write32(sc, val, data); \ 314188417Sthompsa if (error != 0) \ 315188417Sthompsa goto fail; \ 316188417Sthompsa} while (0) 317184610Salfred 318188417Sthompsastatic int 319188417Sthompsazyd_match(device_t dev) 320184610Salfred{ 321188417Sthompsa struct usb2_attach_arg *uaa = device_get_ivars(dev); 322184610Salfred 323188417Sthompsa if (uaa->usb2_mode != USB_MODE_HOST) 324188417Sthompsa return (ENXIO); 325188419Sthompsa if (uaa->info.bConfigIndex != ZYD_CONFIG_INDEX) 326188417Sthompsa return (ENXIO); 327188417Sthompsa if (uaa->info.bIfaceIndex != ZYD_IFACE_INDEX) 328188417Sthompsa return (ENXIO); 329184610Salfred 330188417Sthompsa return (usb2_lookup_id_by_uaa(zyd_devs, sizeof(zyd_devs), uaa)); 331184610Salfred} 332184610Salfred 333188417Sthompsastatic int 334188417Sthompsazyd_attach(device_t dev) 335184610Salfred{ 336188417Sthompsa struct usb2_attach_arg *uaa = device_get_ivars(dev); 337188417Sthompsa struct zyd_softc *sc = device_get_softc(dev); 338191746Sthompsa struct ifnet *ifp; 339191746Sthompsa struct ieee80211com *ic; 340191746Sthompsa uint8_t iface_index, bands; 341188419Sthompsa int error; 342184610Salfred 343188417Sthompsa if (uaa->info.bcdDevice < 0x4330) { 344188417Sthompsa device_printf(dev, "device version mismatch: 0x%X " 345188417Sthompsa "(only >= 43.30 supported)\n", 346188417Sthompsa uaa->info.bcdDevice); 347188417Sthompsa return (EINVAL); 348184610Salfred } 349184610Salfred 350188417Sthompsa device_set_usb2_desc(dev); 351188417Sthompsa sc->sc_dev = dev; 352188417Sthompsa sc->sc_udev = uaa->device; 353188417Sthompsa sc->sc_macrev = USB_GET_DRIVER_INFO(uaa); 354188419Sthompsa 355188417Sthompsa mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), 356188417Sthompsa MTX_NETWORK_LOCK, MTX_DEF); 357188417Sthompsa STAILQ_INIT(&sc->sc_rqh); 358184610Salfred 359188417Sthompsa iface_index = ZYD_IFACE_INDEX; 360188417Sthompsa error = usb2_transfer_setup(uaa->device, 361188417Sthompsa &iface_index, sc->sc_xfer, zyd_config, 362188417Sthompsa ZYD_N_TRANSFER, sc, &sc->sc_mtx); 363188417Sthompsa if (error) { 364188417Sthompsa device_printf(dev, "could not allocate USB transfers, " 365188417Sthompsa "err=%s\n", usb2_errstr(error)); 366188419Sthompsa goto detach; 367184610Salfred } 368184610Salfred 369188419Sthompsa ZYD_LOCK(sc); 370188417Sthompsa if ((error = zyd_get_macaddr(sc)) != 0) { 371188417Sthompsa device_printf(sc->sc_dev, "could not read EEPROM\n"); 372191746Sthompsa ZYD_UNLOCK(sc); 373191746Sthompsa goto detach; 374188417Sthompsa } 375188419Sthompsa ZYD_UNLOCK(sc); 376188419Sthompsa 377188417Sthompsa ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); 378188417Sthompsa if (ifp == NULL) { 379188419Sthompsa device_printf(sc->sc_dev, "can not if_alloc()\n"); 380191746Sthompsa goto detach; 381184610Salfred } 382188417Sthompsa ifp->if_softc = sc; 383188417Sthompsa if_initname(ifp, "zyd", device_get_unit(sc->sc_dev)); 384188417Sthompsa ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 385188417Sthompsa ifp->if_init = zyd_init; 386188417Sthompsa ifp->if_ioctl = zyd_ioctl; 387188417Sthompsa ifp->if_start = zyd_start; 388188417Sthompsa IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); 389188417Sthompsa IFQ_SET_READY(&ifp->if_snd); 390184610Salfred 391188417Sthompsa ic = ifp->if_l2com; 392188417Sthompsa ic->ic_ifp = ifp; 393188417Sthompsa ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 394188417Sthompsa ic->ic_opmode = IEEE80211_M_STA; 395184610Salfred 396188417Sthompsa /* set device capabilities */ 397188417Sthompsa ic->ic_caps = 398188417Sthompsa IEEE80211_C_STA /* station mode */ 399188417Sthompsa | IEEE80211_C_MONITOR /* monitor mode */ 400188417Sthompsa | IEEE80211_C_SHPREAMBLE /* short preamble supported */ 401188417Sthompsa | IEEE80211_C_SHSLOT /* short slot time supported */ 402188417Sthompsa | IEEE80211_C_BGSCAN /* capable of bg scanning */ 403188417Sthompsa | IEEE80211_C_WPA /* 802.11i */ 404188417Sthompsa ; 405184610Salfred 406188417Sthompsa bands = 0; 407188417Sthompsa setbit(&bands, IEEE80211_MODE_11B); 408188417Sthompsa setbit(&bands, IEEE80211_MODE_11G); 409188417Sthompsa ieee80211_init_channels(ic, NULL, &bands); 410184610Salfred 411190526Ssam ieee80211_ifattach(ic, sc->sc_bssid); 412188417Sthompsa ic->ic_newassoc = zyd_newassoc; 413188417Sthompsa ic->ic_raw_xmit = zyd_raw_xmit; 414188417Sthompsa ic->ic_node_alloc = zyd_node_alloc; 415188417Sthompsa ic->ic_scan_start = zyd_scan_start; 416188417Sthompsa ic->ic_scan_end = zyd_scan_end; 417188417Sthompsa ic->ic_set_channel = zyd_set_channel; 418184610Salfred 419188417Sthompsa ic->ic_vap_create = zyd_vap_create; 420188417Sthompsa ic->ic_vap_delete = zyd_vap_delete; 421188417Sthompsa ic->ic_update_mcast = zyd_update_mcast; 422188601Sthompsa ic->ic_update_promisc = zyd_update_mcast; 423184610Salfred 424188417Sthompsa bpfattach(ifp, DLT_IEEE802_11_RADIO, 425188417Sthompsa sizeof(struct ieee80211_frame) + sizeof(sc->sc_txtap)); 426188417Sthompsa sc->sc_rxtap_len = sizeof(sc->sc_rxtap); 427188417Sthompsa sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); 428188417Sthompsa sc->sc_rxtap.wr_ihdr.it_present = htole32(ZYD_RX_RADIOTAP_PRESENT); 429188417Sthompsa sc->sc_txtap_len = sizeof(sc->sc_txtap); 430188417Sthompsa sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); 431188417Sthompsa sc->sc_txtap.wt_ihdr.it_present = htole32(ZYD_TX_RADIOTAP_PRESENT); 432184610Salfred 433188417Sthompsa if (bootverbose) 434188417Sthompsa ieee80211_announce(ic); 435184610Salfred 436191746Sthompsa return (0); 437191746Sthompsa 438191746Sthompsadetach: 439191746Sthompsa zyd_detach(dev); 440191746Sthompsa return (ENXIO); /* failure */ 441184610Salfred} 442184610Salfred 443188417Sthompsastatic int 444188417Sthompsazyd_detach(device_t dev) 445184610Salfred{ 446188417Sthompsa struct zyd_softc *sc = device_get_softc(dev); 447188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 448188601Sthompsa struct ieee80211com *ic; 449184610Salfred 450188419Sthompsa /* stop all USB transfers */ 451188417Sthompsa usb2_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER); 452184610Salfred 453188419Sthompsa /* free TX list, if any */ 454188419Sthompsa zyd_unsetup_tx_list(sc); 455188419Sthompsa 456188417Sthompsa if (ifp) { 457188601Sthompsa ic = ifp->if_l2com; 458188417Sthompsa bpfdetach(ifp); 459188417Sthompsa ieee80211_ifdetach(ic); 460188417Sthompsa if_free(ifp); 461184610Salfred } 462188417Sthompsa mtx_destroy(&sc->sc_mtx); 463184610Salfred 464188417Sthompsa return (0); 465184610Salfred} 466184610Salfred 467188417Sthompsastatic struct ieee80211vap * 468188417Sthompsazyd_vap_create(struct ieee80211com *ic, 469188417Sthompsa const char name[IFNAMSIZ], int unit, int opmode, int flags, 470188417Sthompsa const uint8_t bssid[IEEE80211_ADDR_LEN], 471188417Sthompsa const uint8_t mac[IEEE80211_ADDR_LEN]) 472184610Salfred{ 473188417Sthompsa struct zyd_vap *zvp; 474188417Sthompsa struct ieee80211vap *vap; 475184610Salfred 476188417Sthompsa if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ 477188417Sthompsa return (NULL); 478188417Sthompsa zvp = (struct zyd_vap *) malloc(sizeof(struct zyd_vap), 479188417Sthompsa M_80211_VAP, M_NOWAIT | M_ZERO); 480188417Sthompsa if (zvp == NULL) 481188417Sthompsa return (NULL); 482188417Sthompsa vap = &zvp->vap; 483188417Sthompsa /* enable s/w bmiss handling for sta mode */ 484188417Sthompsa ieee80211_vap_setup(ic, vap, name, unit, opmode, 485188417Sthompsa flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); 486184610Salfred 487188417Sthompsa /* override state transition machine */ 488188417Sthompsa zvp->newstate = vap->iv_newstate; 489188417Sthompsa vap->iv_newstate = zyd_newstate; 490184610Salfred 491188417Sthompsa ieee80211_amrr_init(&zvp->amrr, vap, 492188417Sthompsa IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, 493188417Sthompsa IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, 494188417Sthompsa 1000 /* 1 sec */); 495184610Salfred 496188417Sthompsa /* complete setup */ 497188417Sthompsa ieee80211_vap_attach(vap, ieee80211_media_change, 498188417Sthompsa ieee80211_media_status); 499188417Sthompsa ic->ic_opmode = opmode; 500188417Sthompsa return (vap); 501184610Salfred} 502184610Salfred 503184610Salfredstatic void 504188417Sthompsazyd_vap_delete(struct ieee80211vap *vap) 505184610Salfred{ 506188417Sthompsa struct zyd_vap *zvp = ZYD_VAP(vap); 507184610Salfred 508188417Sthompsa ieee80211_amrr_cleanup(&zvp->amrr); 509188417Sthompsa ieee80211_vap_detach(vap); 510188417Sthompsa free(zvp, M_80211_VAP); 511184610Salfred} 512184610Salfred 513184610Salfredstatic void 514188417Sthompsazyd_tx_free(struct zyd_tx_data *data, int txerr) 515184610Salfred{ 516188417Sthompsa struct zyd_softc *sc = data->sc; 517184610Salfred 518188417Sthompsa if (data->m != NULL) { 519188417Sthompsa if (data->m->m_flags & M_TXCB) 520188417Sthompsa ieee80211_process_callback(data->ni, data->m, 521188417Sthompsa txerr ? ETIMEDOUT : 0); 522188417Sthompsa m_freem(data->m); 523188417Sthompsa data->m = NULL; 524188417Sthompsa 525188417Sthompsa ieee80211_free_node(data->ni); 526188417Sthompsa data->ni = NULL; 527184610Salfred } 528188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_free, data, next); 529188417Sthompsa sc->tx_nfree++; 530184610Salfred} 531184610Salfred 532188419Sthompsastatic void 533188419Sthompsazyd_setup_tx_list(struct zyd_softc *sc) 534184610Salfred{ 535188417Sthompsa struct zyd_tx_data *data; 536188417Sthompsa int i; 537184610Salfred 538188417Sthompsa sc->tx_nfree = 0; 539188417Sthompsa STAILQ_INIT(&sc->tx_q); 540188417Sthompsa STAILQ_INIT(&sc->tx_free); 541184610Salfred 542188417Sthompsa for (i = 0; i < ZYD_TX_LIST_CNT; i++) { 543188417Sthompsa data = &sc->tx_data[i]; 544184610Salfred 545188417Sthompsa data->sc = sc; 546188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_free, data, next); 547188417Sthompsa sc->tx_nfree++; 548188417Sthompsa } 549184610Salfred} 550184610Salfred 551184610Salfredstatic void 552188419Sthompsazyd_unsetup_tx_list(struct zyd_softc *sc) 553184610Salfred{ 554188417Sthompsa struct zyd_tx_data *data; 555188417Sthompsa int i; 556184610Salfred 557188419Sthompsa /* make sure any subsequent use of the queues will fail */ 558188419Sthompsa sc->tx_nfree = 0; 559188419Sthompsa STAILQ_INIT(&sc->tx_q); 560188419Sthompsa STAILQ_INIT(&sc->tx_free); 561184610Salfred 562188419Sthompsa /* free up all node references and mbufs */ 563188417Sthompsa for (i = 0; i < ZYD_TX_LIST_CNT; i++) { 564188417Sthompsa data = &sc->tx_data[i]; 565184610Salfred 566188417Sthompsa if (data->m != NULL) { 567188417Sthompsa m_freem(data->m); 568188417Sthompsa data->m = NULL; 569188417Sthompsa } 570188417Sthompsa if (data->ni != NULL) { 571188417Sthompsa ieee80211_free_node(data->ni); 572188417Sthompsa data->ni = NULL; 573188417Sthompsa } 574188417Sthompsa } 575184610Salfred} 576184610Salfred 577188417Sthompsa/* ARGUSED */ 578188417Sthompsastatic struct ieee80211_node * 579188417Sthompsazyd_node_alloc(struct ieee80211vap *vap __unused, 580188417Sthompsa const uint8_t mac[IEEE80211_ADDR_LEN] __unused) 581184610Salfred{ 582188417Sthompsa struct zyd_node *zn; 583184610Salfred 584188417Sthompsa zn = malloc(sizeof(struct zyd_node), M_80211_NODE, M_NOWAIT | M_ZERO); 585188417Sthompsa return (zn != NULL) ? (&zn->ni) : (NULL); 586184610Salfred} 587184610Salfred 588191746Sthompsastatic int 589191746Sthompsazyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 590186730Salfred{ 591188417Sthompsa struct zyd_vap *zvp = ZYD_VAP(vap); 592191746Sthompsa struct ieee80211com *ic = vap->iv_ic; 593191746Sthompsa struct zyd_softc *sc = ic->ic_ifp->if_softc; 594191746Sthompsa struct ieee80211_node *ni; 595188417Sthompsa int error; 596186730Salfred 597191746Sthompsa DPRINTF(sc, ZYD_DEBUG_STATE, "%s: %s -> %s\n", __func__, 598191746Sthompsa ieee80211_state_name[vap->iv_state], 599191746Sthompsa ieee80211_state_name[nstate]); 600191746Sthompsa 601191746Sthompsa IEEE80211_UNLOCK(ic); 602191746Sthompsa ZYD_LOCK(sc); 603191746Sthompsa switch (nstate) { 604188417Sthompsa case IEEE80211_S_AUTH: 605188417Sthompsa zyd_set_chan(sc, ic->ic_curchan); 606188417Sthompsa break; 607188417Sthompsa case IEEE80211_S_RUN: 608191746Sthompsa ni = vap->iv_bss; 609188417Sthompsa if (vap->iv_opmode == IEEE80211_M_MONITOR) 610188417Sthompsa break; 611184610Salfred 612188417Sthompsa /* turn link LED on */ 613188417Sthompsa error = zyd_set_led(sc, ZYD_LED1, 1); 614188417Sthompsa if (error != 0) 615191746Sthompsa break; 616191746Sthompsa 617188417Sthompsa /* make data LED blink upon Tx */ 618188417Sthompsa zyd_write32_m(sc, sc->sc_fwbase + ZYD_FW_LINK_STATUS, 1); 619191746Sthompsa 620188417Sthompsa IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); 621188417Sthompsa zyd_set_bssid(sc, sc->sc_bssid); 622188417Sthompsa break; 623188417Sthompsa default: 624188417Sthompsa break; 625184610Salfred } 626188417Sthompsafail: 627188417Sthompsa ZYD_UNLOCK(sc); 628188417Sthompsa IEEE80211_LOCK(ic); 629191746Sthompsa return (zvp->newstate(vap, nstate, arg)); 630184610Salfred} 631184610Salfred 632188417Sthompsa/* 633188417Sthompsa * Callback handler for interrupt transfer 634188417Sthompsa */ 635184610Salfredstatic void 636188417Sthompsazyd_intr_read_callback(struct usb2_xfer *xfer) 637184610Salfred{ 638184610Salfred struct zyd_softc *sc = xfer->priv_sc; 639184610Salfred struct ifnet *ifp = sc->sc_ifp; 640184610Salfred struct ieee80211com *ic = ifp->if_l2com; 641188417Sthompsa struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 642184610Salfred struct ieee80211_node *ni; 643188417Sthompsa struct zyd_cmd *cmd = &sc->sc_ibuf; 644188417Sthompsa int datalen; 645184610Salfred 646184610Salfred switch (USB_GET_STATE(xfer)) { 647184610Salfred case USB_ST_TRANSFERRED: 648188417Sthompsa usb2_copy_out(xfer->frbuffers, 0, cmd, sizeof(*cmd)); 649184610Salfred 650188417Sthompsa switch (le16toh(cmd->code)) { 651188417Sthompsa case ZYD_NOTIF_RETRYSTATUS: 652188417Sthompsa { 653188417Sthompsa struct zyd_notif_retry *retry = 654188417Sthompsa (struct zyd_notif_retry *)cmd->data; 655184610Salfred 656188417Sthompsa DPRINTF(sc, ZYD_DEBUG_TX_PROC, 657188417Sthompsa "retry intr: rate=0x%x addr=%s count=%d (0x%x)\n", 658188417Sthompsa le16toh(retry->rate), ether_sprintf(retry->macaddr), 659188417Sthompsa le16toh(retry->count)&0xff, le16toh(retry->count)); 660184610Salfred 661188417Sthompsa /* 662188417Sthompsa * Find the node to which the packet was sent and 663188417Sthompsa * update its retry statistics. In BSS mode, this node 664188417Sthompsa * is the AP we're associated to so no lookup is 665188417Sthompsa * actually needed. 666188417Sthompsa */ 667188417Sthompsa ni = ieee80211_find_txnode(vap, retry->macaddr); 668188417Sthompsa if (ni != NULL) { 669188417Sthompsa ieee80211_amrr_tx_complete(&ZYD_NODE(ni)->amn, 670188417Sthompsa IEEE80211_AMRR_FAILURE, 1); 671188417Sthompsa ieee80211_free_node(ni); 672188417Sthompsa } 673188417Sthompsa if (le16toh(retry->count) & 0x100) 674188417Sthompsa ifp->if_oerrors++; /* too many retries */ 675188417Sthompsa break; 676188417Sthompsa } 677188417Sthompsa case ZYD_NOTIF_IORD: 678188417Sthompsa { 679188417Sthompsa struct zyd_rq *rqp; 680184610Salfred 681188417Sthompsa if (le16toh(*(uint16_t *)cmd->data) == ZYD_CR_INTERRUPT) 682188417Sthompsa break; /* HMAC interrupt */ 683184610Salfred 684188417Sthompsa datalen = xfer->actlen - sizeof(cmd->code); 685188417Sthompsa datalen -= 2; /* XXX: padding? */ 686184610Salfred 687188417Sthompsa STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) { 688188417Sthompsa int i, cnt; 689184610Salfred 690188417Sthompsa if (rqp->olen != datalen) 691188417Sthompsa continue; 692188417Sthompsa cnt = rqp->olen / sizeof(struct zyd_pair); 693188417Sthompsa for (i = 0; i < cnt; i++) { 694188417Sthompsa if (*(((const uint16_t *)rqp->idata) + i) != 695188417Sthompsa (((struct zyd_pair *)cmd->data) + i)->reg) 696188417Sthompsa break; 697184610Salfred } 698188417Sthompsa if (i != cnt) 699188417Sthompsa continue; 700188417Sthompsa /* copy answer into caller-supplied buffer */ 701188417Sthompsa bcopy(cmd->data, rqp->odata, rqp->olen); 702188417Sthompsa DPRINTF(sc, ZYD_DEBUG_CMD, 703188417Sthompsa "command %p complete, data = %*D \n", 704188417Sthompsa rqp, rqp->olen, rqp->odata, ":"); 705188417Sthompsa wakeup(rqp); /* wakeup caller */ 706188417Sthompsa break; 707184610Salfred } 708188417Sthompsa if (rqp == NULL) { 709188417Sthompsa device_printf(sc->sc_dev, 710188417Sthompsa "unexpected IORD notification %*D\n", 711188417Sthompsa datalen, cmd->data, ":"); 712188417Sthompsa } 713188417Sthompsa break; 714184610Salfred } 715188417Sthompsa default: 716188417Sthompsa device_printf(sc->sc_dev, "unknown notification %x\n", 717188417Sthompsa le16toh(cmd->code)); 718188417Sthompsa } 719184610Salfred 720188417Sthompsa /* FALLTHROUGH */ 721184610Salfred case USB_ST_SETUP: 722184610Salfredtr_setup: 723188417Sthompsa xfer->frlengths[0] = xfer->max_data_length; 724188417Sthompsa usb2_start_hardware(xfer); 725188417Sthompsa break; 726184610Salfred 727188417Sthompsa default: /* Error */ 728188417Sthompsa DPRINTF(sc, ZYD_DEBUG_CMD, "error = %s\n", 729188417Sthompsa usb2_errstr(xfer->error)); 730188417Sthompsa 731188417Sthompsa if (xfer->error != USB_ERR_CANCELLED) { 732188417Sthompsa /* try to clear stall first */ 733188417Sthompsa xfer->flags.stall_pipe = 1; 734188417Sthompsa goto tr_setup; 735184610Salfred } 736188417Sthompsa break; 737188417Sthompsa } 738188417Sthompsa} 739184610Salfred 740188417Sthompsastatic void 741188417Sthompsazyd_intr_write_callback(struct usb2_xfer *xfer) 742188417Sthompsa{ 743188417Sthompsa struct zyd_softc *sc = xfer->priv_sc; 744188417Sthompsa struct zyd_rq *rqp; 745184610Salfred 746188417Sthompsa switch (USB_GET_STATE(xfer)) { 747188417Sthompsa case USB_ST_TRANSFERRED: 748189452Sthompsa DPRINTF(sc, ZYD_DEBUG_CMD, "command %p transferred\n", 749189452Sthompsa xfer->priv_fifo); 750189452Sthompsa STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) { 751189452Sthompsa /* Ensure the cached rq pointer is still valid */ 752189452Sthompsa if (rqp == xfer->priv_fifo && 753189452Sthompsa (rqp->flags & ZYD_CMD_FLAG_READ) == 0) 754189452Sthompsa wakeup(rqp); /* wakeup caller */ 755189452Sthompsa } 756184610Salfred 757188417Sthompsa /* FALLTHROUGH */ 758188417Sthompsa case USB_ST_SETUP: 759188417Sthompsatr_setup: 760188417Sthompsa STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) { 761188417Sthompsa if (rqp->flags & ZYD_CMD_FLAG_SENT) 762188417Sthompsa continue; 763184610Salfred 764188417Sthompsa usb2_copy_in(xfer->frbuffers, 0, rqp->cmd, rqp->ilen); 765184610Salfred 766188417Sthompsa xfer->frlengths[0] = rqp->ilen; 767188417Sthompsa xfer->priv_fifo = rqp; 768188417Sthompsa rqp->flags |= ZYD_CMD_FLAG_SENT; 769188417Sthompsa usb2_start_hardware(xfer); 770188417Sthompsa break; 771184610Salfred } 772184610Salfred break; 773184610Salfred 774184610Salfred default: /* Error */ 775188417Sthompsa DPRINTF(sc, ZYD_DEBUG_ANY, "error = %s\n", 776188417Sthompsa usb2_errstr(xfer->error)); 777184610Salfred 778184610Salfred if (xfer->error != USB_ERR_CANCELLED) { 779184610Salfred /* try to clear stall first */ 780188417Sthompsa xfer->flags.stall_pipe = 1; 781188417Sthompsa goto tr_setup; 782184610Salfred } 783184610Salfred break; 784184610Salfred } 785184610Salfred} 786184610Salfred 787188417Sthompsastatic int 788188417Sthompsazyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen, 789188601Sthompsa void *odata, int olen, int flags) 790184610Salfred{ 791188417Sthompsa struct zyd_cmd cmd; 792188417Sthompsa struct zyd_rq rq; 793188417Sthompsa int error; 794184610Salfred 795188417Sthompsa if (ilen > sizeof(cmd.data)) 796188417Sthompsa return (EINVAL); 797188419Sthompsa 798188417Sthompsa cmd.code = htole16(code); 799188417Sthompsa bcopy(idata, cmd.data, ilen); 800188417Sthompsa DPRINTF(sc, ZYD_DEBUG_CMD, "sending cmd %p = %*D\n", 801188417Sthompsa &rq, ilen, idata, ":"); 802184610Salfred 803188417Sthompsa rq.cmd = &cmd; 804188417Sthompsa rq.idata = idata; 805188417Sthompsa rq.odata = odata; 806188417Sthompsa rq.ilen = sizeof(uint16_t) + ilen; 807188417Sthompsa rq.olen = olen; 808188417Sthompsa rq.flags = flags; 809188417Sthompsa STAILQ_INSERT_TAIL(&sc->sc_rqh, &rq, rq); 810188417Sthompsa usb2_transfer_start(sc->sc_xfer[ZYD_INTR_RD]); 811188417Sthompsa usb2_transfer_start(sc->sc_xfer[ZYD_INTR_WR]); 812184610Salfred 813188417Sthompsa /* wait at most one second for command reply */ 814188417Sthompsa error = mtx_sleep(&rq, &sc->sc_mtx, 0 , "zydcmd", hz); 815188417Sthompsa if (error) 816188417Sthompsa device_printf(sc->sc_dev, "command timeout\n"); 817188417Sthompsa STAILQ_REMOVE(&sc->sc_rqh, &rq, zyd_rq, rq); 818188417Sthompsa DPRINTF(sc, ZYD_DEBUG_CMD, "finsihed cmd %p, error = %d \n", 819188417Sthompsa &rq, error); 820184610Salfred 821188417Sthompsa return (error); 822184610Salfred} 823184610Salfred 824184610Salfredstatic int 825188417Sthompsazyd_read16(struct zyd_softc *sc, uint16_t reg, uint16_t *val) 826184610Salfred{ 827188417Sthompsa struct zyd_pair tmp; 828188417Sthompsa int error; 829184610Salfred 830188417Sthompsa reg = htole16(reg); 831188417Sthompsa error = zyd_cmd(sc, ZYD_CMD_IORD, ®, sizeof(reg), &tmp, sizeof(tmp), 832188417Sthompsa ZYD_CMD_FLAG_READ); 833188417Sthompsa if (error == 0) 834188417Sthompsa *val = le16toh(tmp.val); 835188417Sthompsa return (error); 836184610Salfred} 837184610Salfred 838184610Salfredstatic int 839188417Sthompsazyd_read32(struct zyd_softc *sc, uint16_t reg, uint32_t *val) 840184610Salfred{ 841188417Sthompsa struct zyd_pair tmp[2]; 842188417Sthompsa uint16_t regs[2]; 843184610Salfred int error; 844184610Salfred 845188417Sthompsa regs[0] = htole16(ZYD_REG32_HI(reg)); 846188417Sthompsa regs[1] = htole16(ZYD_REG32_LO(reg)); 847188417Sthompsa error = zyd_cmd(sc, ZYD_CMD_IORD, regs, sizeof(regs), tmp, sizeof(tmp), 848188417Sthompsa ZYD_CMD_FLAG_READ); 849188417Sthompsa if (error == 0) 850188417Sthompsa *val = le16toh(tmp[0].val) << 16 | le16toh(tmp[1].val); 851188417Sthompsa return (error); 852188417Sthompsa} 853184610Salfred 854188417Sthompsastatic int 855188417Sthompsazyd_write16(struct zyd_softc *sc, uint16_t reg, uint16_t val) 856188417Sthompsa{ 857188417Sthompsa struct zyd_pair pair; 858184610Salfred 859188417Sthompsa pair.reg = htole16(reg); 860188417Sthompsa pair.val = htole16(val); 861184610Salfred 862188417Sthompsa return zyd_cmd(sc, ZYD_CMD_IOWR, &pair, sizeof(pair), NULL, 0, 0); 863188417Sthompsa} 864184610Salfred 865188417Sthompsastatic int 866188417Sthompsazyd_write32(struct zyd_softc *sc, uint16_t reg, uint32_t val) 867188417Sthompsa{ 868188417Sthompsa struct zyd_pair pair[2]; 869184610Salfred 870188417Sthompsa pair[0].reg = htole16(ZYD_REG32_HI(reg)); 871188417Sthompsa pair[0].val = htole16(val >> 16); 872188417Sthompsa pair[1].reg = htole16(ZYD_REG32_LO(reg)); 873188417Sthompsa pair[1].val = htole16(val & 0xffff); 874184610Salfred 875188417Sthompsa return zyd_cmd(sc, ZYD_CMD_IOWR, pair, sizeof(pair), NULL, 0, 0); 876184610Salfred} 877184610Salfred 878188417Sthompsastatic int 879188417Sthompsazyd_rfwrite(struct zyd_softc *sc, uint32_t val) 880184610Salfred{ 881188417Sthompsa struct zyd_rf *rf = &sc->sc_rf; 882188417Sthompsa struct zyd_rfwrite_cmd req; 883188417Sthompsa uint16_t cr203; 884188417Sthompsa int error, i; 885184610Salfred 886188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &cr203); 887188417Sthompsa cr203 &= ~(ZYD_RF_IF_LE | ZYD_RF_CLK | ZYD_RF_DATA); 888188417Sthompsa 889188417Sthompsa req.code = htole16(2); 890188417Sthompsa req.width = htole16(rf->width); 891188417Sthompsa for (i = 0; i < rf->width; i++) { 892188417Sthompsa req.bit[i] = htole16(cr203); 893188417Sthompsa if (val & (1 << (rf->width - 1 - i))) 894188417Sthompsa req.bit[i] |= htole16(ZYD_RF_DATA); 895188417Sthompsa } 896188417Sthompsa error = zyd_cmd(sc, ZYD_CMD_RFCFG, &req, 4 + 2 * rf->width, NULL, 0, 0); 897188417Sthompsafail: 898188417Sthompsa return (error); 899184610Salfred} 900184610Salfred 901188417Sthompsastatic int 902188417Sthompsazyd_rfwrite_cr(struct zyd_softc *sc, uint32_t val) 903184610Salfred{ 904188417Sthompsa int error; 905184610Salfred 906188417Sthompsa zyd_write16_m(sc, ZYD_CR244, (val >> 16) & 0xff); 907188417Sthompsa zyd_write16_m(sc, ZYD_CR243, (val >> 8) & 0xff); 908188417Sthompsa zyd_write16_m(sc, ZYD_CR242, (val >> 0) & 0xff); 909188417Sthompsafail: 910188417Sthompsa return (error); 911184610Salfred} 912184610Salfred 913188417Sthompsastatic int 914188417Sthompsazyd_lock_phy(struct zyd_softc *sc) 915184610Salfred{ 916188417Sthompsa int error; 917188417Sthompsa uint32_t tmp; 918186730Salfred 919188417Sthompsa zyd_read32_m(sc, ZYD_MAC_MISC, &tmp); 920188417Sthompsa tmp &= ~ZYD_UNLOCK_PHY_REGS; 921188417Sthompsa zyd_write32_m(sc, ZYD_MAC_MISC, tmp); 922188417Sthompsafail: 923188417Sthompsa return (error); 924184610Salfred} 925184610Salfred 926188417Sthompsastatic int 927188417Sthompsazyd_unlock_phy(struct zyd_softc *sc) 928184610Salfred{ 929188417Sthompsa int error; 930188417Sthompsa uint32_t tmp; 931184610Salfred 932188417Sthompsa zyd_read32_m(sc, ZYD_MAC_MISC, &tmp); 933188417Sthompsa tmp |= ZYD_UNLOCK_PHY_REGS; 934188417Sthompsa zyd_write32_m(sc, ZYD_MAC_MISC, tmp); 935188417Sthompsafail: 936188417Sthompsa return (error); 937184610Salfred} 938184610Salfred 939184610Salfred/* 940188417Sthompsa * RFMD RF methods. 941184610Salfred */ 942188417Sthompsastatic int 943188417Sthompsazyd_rfmd_init(struct zyd_rf *rf) 944184610Salfred{ 945188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 946188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 947184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_RFMD_PHY; 948184610Salfred static const uint32_t rfini[] = ZYD_RFMD_RF; 949188417Sthompsa int i, error; 950184610Salfred 951184610Salfred /* init RF-dependent PHY registers */ 952188417Sthompsa for (i = 0; i < N(phyini); i++) { 953188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 954184610Salfred } 955184610Salfred 956184610Salfred /* init RFMD radio */ 957188417Sthompsa for (i = 0; i < N(rfini); i++) { 958188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 959188417Sthompsa return (error); 960184610Salfred } 961188417Sthompsafail: 962188417Sthompsa return (error); 963188417Sthompsa#undef N 964184610Salfred} 965184610Salfred 966188417Sthompsastatic int 967188417Sthompsazyd_rfmd_switch_radio(struct zyd_rf *rf, int on) 968184610Salfred{ 969188417Sthompsa int error; 970188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 971188417Sthompsa 972188417Sthompsa zyd_write16_m(sc, ZYD_CR10, on ? 0x89 : 0x15); 973188417Sthompsa zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x81); 974188417Sthompsafail: 975188417Sthompsa return (error); 976184610Salfred} 977184610Salfred 978188417Sthompsastatic int 979188417Sthompsazyd_rfmd_set_channel(struct zyd_rf *rf, uint8_t chan) 980184610Salfred{ 981188417Sthompsa int error; 982188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 983184610Salfred static const struct { 984188417Sthompsa uint32_t r1, r2; 985188417Sthompsa } rfprog[] = ZYD_RFMD_CHANTABLE; 986184610Salfred 987188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r1); 988188417Sthompsa if (error != 0) 989188417Sthompsa goto fail; 990188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r2); 991188417Sthompsa if (error != 0) 992188417Sthompsa goto fail; 993184610Salfred 994188417Sthompsafail: 995188417Sthompsa return (error); 996184610Salfred} 997184610Salfred 998184610Salfred/* 999188417Sthompsa * AL2230 RF methods. 1000184610Salfred */ 1001188417Sthompsastatic int 1002188417Sthompsazyd_al2230_init(struct zyd_rf *rf) 1003184610Salfred{ 1004188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1005188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1006184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY; 1007186730Salfred static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT; 1008186730Salfred static const struct zyd_phy_pair phypll[] = { 1009188417Sthompsa { ZYD_CR251, 0x2f }, { ZYD_CR251, 0x3f }, 1010188417Sthompsa { ZYD_CR138, 0x28 }, { ZYD_CR203, 0x06 } 1011186730Salfred }; 1012186730Salfred static const uint32_t rfini1[] = ZYD_AL2230_RF_PART1; 1013186730Salfred static const uint32_t rfini2[] = ZYD_AL2230_RF_PART2; 1014186730Salfred static const uint32_t rfini3[] = ZYD_AL2230_RF_PART3; 1015188417Sthompsa int i, error; 1016184610Salfred 1017184610Salfred /* init RF-dependent PHY registers */ 1018188417Sthompsa for (i = 0; i < N(phyini); i++) 1019188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1020186730Salfred 1021188417Sthompsa if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) { 1022188417Sthompsa for (i = 0; i < N(phy2230s); i++) 1023188417Sthompsa zyd_write16_m(sc, phy2230s[i].reg, phy2230s[i].val); 1024184610Salfred } 1025188417Sthompsa 1026186730Salfred /* init AL2230 radio */ 1027188417Sthompsa for (i = 0; i < N(rfini1); i++) { 1028188417Sthompsa error = zyd_rfwrite(sc, rfini1[i]); 1029188417Sthompsa if (error != 0) 1030188417Sthompsa goto fail; 1031188417Sthompsa } 1032184610Salfred 1033188417Sthompsa if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) 1034188417Sthompsa error = zyd_rfwrite(sc, 0x000824); 1035186730Salfred else 1036188417Sthompsa error = zyd_rfwrite(sc, 0x0005a4); 1037188417Sthompsa if (error != 0) 1038188417Sthompsa goto fail; 1039186730Salfred 1040188417Sthompsa for (i = 0; i < N(rfini2); i++) { 1041188417Sthompsa error = zyd_rfwrite(sc, rfini2[i]); 1042188417Sthompsa if (error != 0) 1043188417Sthompsa goto fail; 1044188417Sthompsa } 1045186730Salfred 1046188417Sthompsa for (i = 0; i < N(phypll); i++) 1047188417Sthompsa zyd_write16_m(sc, phypll[i].reg, phypll[i].val); 1048186730Salfred 1049188417Sthompsa for (i = 0; i < N(rfini3); i++) { 1050188417Sthompsa error = zyd_rfwrite(sc, rfini3[i]); 1051188417Sthompsa if (error != 0) 1052188417Sthompsa goto fail; 1053188417Sthompsa } 1054188417Sthompsafail: 1055188417Sthompsa return (error); 1056188417Sthompsa#undef N 1057184610Salfred} 1058184610Salfred 1059188417Sthompsastatic int 1060188417Sthompsazyd_al2230_fini(struct zyd_rf *rf) 1061186730Salfred{ 1062188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1063188417Sthompsa int error, i; 1064188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1065186730Salfred static const struct zyd_phy_pair phy[] = ZYD_AL2230_PHY_FINI_PART1; 1066186730Salfred 1067188417Sthompsa for (i = 0; i < N(phy); i++) 1068188417Sthompsa zyd_write16_m(sc, phy[i].reg, phy[i].val); 1069186730Salfred 1070186730Salfred if (sc->sc_newphy != 0) 1071188417Sthompsa zyd_write16_m(sc, ZYD_CR9, 0xe1); 1072188417Sthompsa 1073188417Sthompsa zyd_write16_m(sc, ZYD_CR203, 0x6); 1074188417Sthompsafail: 1075188417Sthompsa return (error); 1076188417Sthompsa#undef N 1077186730Salfred} 1078186730Salfred 1079188417Sthompsastatic int 1080188417Sthompsazyd_al2230_init_b(struct zyd_rf *rf) 1081184610Salfred{ 1082188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1083188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1084186730Salfred static const struct zyd_phy_pair phy1[] = ZYD_AL2230_PHY_PART1; 1085186730Salfred static const struct zyd_phy_pair phy2[] = ZYD_AL2230_PHY_PART2; 1086186730Salfred static const struct zyd_phy_pair phy3[] = ZYD_AL2230_PHY_PART3; 1087186730Salfred static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT; 1088188417Sthompsa static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY_B; 1089186730Salfred static const uint32_t rfini_part1[] = ZYD_AL2230_RF_B_PART1; 1090186730Salfred static const uint32_t rfini_part2[] = ZYD_AL2230_RF_B_PART2; 1091186730Salfred static const uint32_t rfini_part3[] = ZYD_AL2230_RF_B_PART3; 1092186730Salfred static const uint32_t zyd_al2230_chtable[][3] = ZYD_AL2230_CHANTABLE; 1093188417Sthompsa int i, error; 1094184610Salfred 1095188417Sthompsa for (i = 0; i < N(phy1); i++) 1096188417Sthompsa zyd_write16_m(sc, phy1[i].reg, phy1[i].val); 1097186730Salfred 1098184610Salfred /* init RF-dependent PHY registers */ 1099188417Sthompsa for (i = 0; i < N(phyini); i++) 1100188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1101184610Salfred 1102188417Sthompsa if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) { 1103188417Sthompsa for (i = 0; i < N(phy2230s); i++) 1104188417Sthompsa zyd_write16_m(sc, phy2230s[i].reg, phy2230s[i].val); 1105188417Sthompsa } 1106186730Salfred 1107188417Sthompsa for (i = 0; i < 3; i++) { 1108188417Sthompsa error = zyd_rfwrite_cr(sc, zyd_al2230_chtable[0][i]); 1109188417Sthompsa if (error != 0) 1110188417Sthompsa return (error); 1111188417Sthompsa } 1112186730Salfred 1113188417Sthompsa for (i = 0; i < N(rfini_part1); i++) { 1114188417Sthompsa error = zyd_rfwrite_cr(sc, rfini_part1[i]); 1115188417Sthompsa if (error != 0) 1116188417Sthompsa return (error); 1117188417Sthompsa } 1118186730Salfred 1119188417Sthompsa if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) 1120188417Sthompsa error = zyd_rfwrite(sc, 0x241000); 1121186730Salfred else 1122188417Sthompsa error = zyd_rfwrite(sc, 0x25a000); 1123188417Sthompsa if (error != 0) 1124188417Sthompsa goto fail; 1125186730Salfred 1126188417Sthompsa for (i = 0; i < N(rfini_part2); i++) { 1127188417Sthompsa error = zyd_rfwrite_cr(sc, rfini_part2[i]); 1128188417Sthompsa if (error != 0) 1129188417Sthompsa return (error); 1130188417Sthompsa } 1131186730Salfred 1132188417Sthompsa for (i = 0; i < N(phy2); i++) 1133188417Sthompsa zyd_write16_m(sc, phy2[i].reg, phy2[i].val); 1134186730Salfred 1135188417Sthompsa for (i = 0; i < N(rfini_part3); i++) { 1136188417Sthompsa error = zyd_rfwrite_cr(sc, rfini_part3[i]); 1137188417Sthompsa if (error != 0) 1138188417Sthompsa return (error); 1139188417Sthompsa } 1140186730Salfred 1141188417Sthompsa for (i = 0; i < N(phy3); i++) 1142188417Sthompsa zyd_write16_m(sc, phy3[i].reg, phy3[i].val); 1143186730Salfred 1144188417Sthompsa error = zyd_al2230_fini(rf); 1145188417Sthompsafail: 1146188417Sthompsa return (error); 1147188417Sthompsa#undef N 1148184610Salfred} 1149184610Salfred 1150188417Sthompsastatic int 1151188417Sthompsazyd_al2230_switch_radio(struct zyd_rf *rf, int on) 1152184610Salfred{ 1153188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1154188417Sthompsa int error, on251 = (sc->sc_macrev == ZYD_ZD1211) ? 0x3f : 0x7f; 1155188417Sthompsa 1156188417Sthompsa zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x04); 1157188417Sthompsa zyd_write16_m(sc, ZYD_CR251, on ? on251 : 0x2f); 1158188417Sthompsafail: 1159188417Sthompsa return (error); 1160188417Sthompsa} 1161188417Sthompsa 1162188417Sthompsastatic int 1163188417Sthompsazyd_al2230_set_channel(struct zyd_rf *rf, uint8_t chan) 1164188417Sthompsa{ 1165188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1166188417Sthompsa int error, i; 1167188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1168186730Salfred static const struct zyd_phy_pair phy1[] = { 1169188417Sthompsa { ZYD_CR138, 0x28 }, { ZYD_CR203, 0x06 }, 1170186730Salfred }; 1171184610Salfred static const struct { 1172188417Sthompsa uint32_t r1, r2, r3; 1173188417Sthompsa } rfprog[] = ZYD_AL2230_CHANTABLE; 1174184610Salfred 1175188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r1); 1176188417Sthompsa if (error != 0) 1177188417Sthompsa goto fail; 1178188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r2); 1179188417Sthompsa if (error != 0) 1180188417Sthompsa goto fail; 1181188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r3); 1182188417Sthompsa if (error != 0) 1183188417Sthompsa goto fail; 1184184610Salfred 1185188417Sthompsa for (i = 0; i < N(phy1); i++) 1186188417Sthompsa zyd_write16_m(sc, phy1[i].reg, phy1[i].val); 1187188417Sthompsafail: 1188188417Sthompsa return (error); 1189188417Sthompsa#undef N 1190184610Salfred} 1191184610Salfred 1192188417Sthompsastatic int 1193188417Sthompsazyd_al2230_set_channel_b(struct zyd_rf *rf, uint8_t chan) 1194186730Salfred{ 1195188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1196188417Sthompsa int error, i; 1197188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1198186730Salfred static const struct zyd_phy_pair phy1[] = ZYD_AL2230_PHY_PART1; 1199186730Salfred static const struct { 1200188417Sthompsa uint32_t r1, r2, r3; 1201188417Sthompsa } rfprog[] = ZYD_AL2230_CHANTABLE_B; 1202186730Salfred 1203188417Sthompsa for (i = 0; i < N(phy1); i++) 1204188417Sthompsa zyd_write16_m(sc, phy1[i].reg, phy1[i].val); 1205186730Salfred 1206188417Sthompsa error = zyd_rfwrite_cr(sc, rfprog[chan - 1].r1); 1207188417Sthompsa if (error != 0) 1208188417Sthompsa goto fail; 1209188417Sthompsa error = zyd_rfwrite_cr(sc, rfprog[chan - 1].r2); 1210188417Sthompsa if (error != 0) 1211188417Sthompsa goto fail; 1212188417Sthompsa error = zyd_rfwrite_cr(sc, rfprog[chan - 1].r3); 1213188417Sthompsa if (error != 0) 1214188417Sthompsa goto fail; 1215188417Sthompsa error = zyd_al2230_fini(rf); 1216188417Sthompsafail: 1217188417Sthompsa return (error); 1218188417Sthompsa#undef N 1219186730Salfred} 1220186730Salfred 1221186730Salfred#define ZYD_AL2230_PHY_BANDEDGE6 \ 1222186730Salfred{ \ 1223188417Sthompsa { ZYD_CR128, 0x14 }, { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, \ 1224186730Salfred { ZYD_CR47, 0x1e } \ 1225186730Salfred} 1226186730Salfred 1227188417Sthompsastatic int 1228188417Sthompsazyd_al2230_bandedge6(struct zyd_rf *rf, struct ieee80211_channel *c) 1229186730Salfred{ 1230188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1231188417Sthompsa int error = 0, i; 1232188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1233188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 1234188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 1235186730Salfred struct zyd_phy_pair r[] = ZYD_AL2230_PHY_BANDEDGE6; 1236188601Sthompsa int chan = ieee80211_chan2ieee(ic, c); 1237186730Salfred 1238188417Sthompsa if (chan == 1 || chan == 11) 1239186730Salfred r[0].val = 0x12; 1240188417Sthompsa 1241188417Sthompsa for (i = 0; i < N(r); i++) 1242188417Sthompsa zyd_write16_m(sc, r[i].reg, r[i].val); 1243188417Sthompsafail: 1244188417Sthompsa return (error); 1245188417Sthompsa#undef N 1246186730Salfred} 1247186730Salfred 1248184610Salfred/* 1249184610Salfred * AL7230B RF methods. 1250184610Salfred */ 1251188417Sthompsastatic int 1252188417Sthompsazyd_al7230B_init(struct zyd_rf *rf) 1253184610Salfred{ 1254188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1255188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1256184610Salfred static const struct zyd_phy_pair phyini_1[] = ZYD_AL7230B_PHY_1; 1257184610Salfred static const struct zyd_phy_pair phyini_2[] = ZYD_AL7230B_PHY_2; 1258184610Salfred static const struct zyd_phy_pair phyini_3[] = ZYD_AL7230B_PHY_3; 1259184610Salfred static const uint32_t rfini_1[] = ZYD_AL7230B_RF_1; 1260184610Salfred static const uint32_t rfini_2[] = ZYD_AL7230B_RF_2; 1261188417Sthompsa int i, error; 1262184610Salfred 1263184610Salfred /* for AL7230B, PHY and RF need to be initialized in "phases" */ 1264184610Salfred 1265184610Salfred /* init RF-dependent PHY registers, part one */ 1266188417Sthompsa for (i = 0; i < N(phyini_1); i++) 1267188417Sthompsa zyd_write16_m(sc, phyini_1[i].reg, phyini_1[i].val); 1268188417Sthompsa 1269184610Salfred /* init AL7230B radio, part one */ 1270188417Sthompsa for (i = 0; i < N(rfini_1); i++) { 1271188417Sthompsa if ((error = zyd_rfwrite(sc, rfini_1[i])) != 0) 1272188417Sthompsa return (error); 1273184610Salfred } 1274184610Salfred /* init RF-dependent PHY registers, part two */ 1275188417Sthompsa for (i = 0; i < N(phyini_2); i++) 1276188417Sthompsa zyd_write16_m(sc, phyini_2[i].reg, phyini_2[i].val); 1277188417Sthompsa 1278184610Salfred /* init AL7230B radio, part two */ 1279188417Sthompsa for (i = 0; i < N(rfini_2); i++) { 1280188417Sthompsa if ((error = zyd_rfwrite(sc, rfini_2[i])) != 0) 1281188417Sthompsa return (error); 1282184610Salfred } 1283184610Salfred /* init RF-dependent PHY registers, part three */ 1284188417Sthompsa for (i = 0; i < N(phyini_3); i++) 1285188417Sthompsa zyd_write16_m(sc, phyini_3[i].reg, phyini_3[i].val); 1286188417Sthompsafail: 1287188417Sthompsa return (error); 1288188417Sthompsa#undef N 1289184610Salfred} 1290184610Salfred 1291188417Sthompsastatic int 1292188417Sthompsazyd_al7230B_switch_radio(struct zyd_rf *rf, int on) 1293184610Salfred{ 1294188417Sthompsa int error; 1295188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1296188417Sthompsa 1297188417Sthompsa zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x04); 1298188417Sthompsa zyd_write16_m(sc, ZYD_CR251, on ? 0x3f : 0x2f); 1299188417Sthompsafail: 1300188417Sthompsa return (error); 1301188417Sthompsa} 1302188417Sthompsa 1303188417Sthompsastatic int 1304188417Sthompsazyd_al7230B_set_channel(struct zyd_rf *rf, uint8_t chan) 1305188417Sthompsa{ 1306188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1307188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1308184610Salfred static const struct { 1309188417Sthompsa uint32_t r1, r2; 1310188417Sthompsa } rfprog[] = ZYD_AL7230B_CHANTABLE; 1311184610Salfred static const uint32_t rfsc[] = ZYD_AL7230B_RF_SETCHANNEL; 1312188417Sthompsa int i, error; 1313184610Salfred 1314188417Sthompsa zyd_write16_m(sc, ZYD_CR240, 0x57); 1315188417Sthompsa zyd_write16_m(sc, ZYD_CR251, 0x2f); 1316184610Salfred 1317188417Sthompsa for (i = 0; i < N(rfsc); i++) { 1318188417Sthompsa if ((error = zyd_rfwrite(sc, rfsc[i])) != 0) 1319188417Sthompsa return (error); 1320184610Salfred } 1321184610Salfred 1322188417Sthompsa zyd_write16_m(sc, ZYD_CR128, 0x14); 1323188417Sthompsa zyd_write16_m(sc, ZYD_CR129, 0x12); 1324188417Sthompsa zyd_write16_m(sc, ZYD_CR130, 0x10); 1325188417Sthompsa zyd_write16_m(sc, ZYD_CR38, 0x38); 1326188417Sthompsa zyd_write16_m(sc, ZYD_CR136, 0xdf); 1327184610Salfred 1328188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r1); 1329188417Sthompsa if (error != 0) 1330188417Sthompsa goto fail; 1331188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r2); 1332188417Sthompsa if (error != 0) 1333188417Sthompsa goto fail; 1334188417Sthompsa error = zyd_rfwrite(sc, 0x3c9000); 1335188417Sthompsa if (error != 0) 1336188417Sthompsa goto fail; 1337184610Salfred 1338188417Sthompsa zyd_write16_m(sc, ZYD_CR251, 0x3f); 1339188417Sthompsa zyd_write16_m(sc, ZYD_CR203, 0x06); 1340188417Sthompsa zyd_write16_m(sc, ZYD_CR240, 0x08); 1341188417Sthompsafail: 1342188417Sthompsa return (error); 1343188417Sthompsa#undef N 1344184610Salfred} 1345184610Salfred 1346184610Salfred/* 1347184610Salfred * AL2210 RF methods. 1348184610Salfred */ 1349188417Sthompsastatic int 1350188417Sthompsazyd_al2210_init(struct zyd_rf *rf) 1351184610Salfred{ 1352188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1353188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1354184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_AL2210_PHY; 1355184610Salfred static const uint32_t rfini[] = ZYD_AL2210_RF; 1356184610Salfred uint32_t tmp; 1357188417Sthompsa int i, error; 1358184610Salfred 1359188417Sthompsa zyd_write32_m(sc, ZYD_CR18, 2); 1360184610Salfred 1361184610Salfred /* init RF-dependent PHY registers */ 1362188417Sthompsa for (i = 0; i < N(phyini); i++) 1363188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1364188417Sthompsa 1365184610Salfred /* init AL2210 radio */ 1366188417Sthompsa for (i = 0; i < N(rfini); i++) { 1367188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 1368188417Sthompsa return (error); 1369184610Salfred } 1370188417Sthompsa zyd_write16_m(sc, ZYD_CR47, 0x1e); 1371188417Sthompsa zyd_read32_m(sc, ZYD_CR_RADIO_PD, &tmp); 1372188417Sthompsa zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp & ~1); 1373188417Sthompsa zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp | 1); 1374188417Sthompsa zyd_write32_m(sc, ZYD_CR_RFCFG, 0x05); 1375188417Sthompsa zyd_write32_m(sc, ZYD_CR_RFCFG, 0x00); 1376188417Sthompsa zyd_write16_m(sc, ZYD_CR47, 0x1e); 1377188417Sthompsa zyd_write32_m(sc, ZYD_CR18, 3); 1378188417Sthompsafail: 1379188417Sthompsa return (error); 1380188417Sthompsa#undef N 1381184610Salfred} 1382184610Salfred 1383188417Sthompsastatic int 1384188417Sthompsazyd_al2210_switch_radio(struct zyd_rf *rf, int on) 1385184610Salfred{ 1386188417Sthompsa /* vendor driver does nothing for this RF chip */ 1387188417Sthompsa 1388188417Sthompsa return (0); 1389188417Sthompsa} 1390188417Sthompsa 1391188417Sthompsastatic int 1392188417Sthompsazyd_al2210_set_channel(struct zyd_rf *rf, uint8_t chan) 1393188417Sthompsa{ 1394188417Sthompsa int error; 1395188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1396184610Salfred static const uint32_t rfprog[] = ZYD_AL2210_CHANTABLE; 1397184610Salfred uint32_t tmp; 1398184610Salfred 1399188417Sthompsa zyd_write32_m(sc, ZYD_CR18, 2); 1400188417Sthompsa zyd_write16_m(sc, ZYD_CR47, 0x1e); 1401188417Sthompsa zyd_read32_m(sc, ZYD_CR_RADIO_PD, &tmp); 1402188417Sthompsa zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp & ~1); 1403188417Sthompsa zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp | 1); 1404188417Sthompsa zyd_write32_m(sc, ZYD_CR_RFCFG, 0x05); 1405188417Sthompsa zyd_write32_m(sc, ZYD_CR_RFCFG, 0x00); 1406188417Sthompsa zyd_write16_m(sc, ZYD_CR47, 0x1e); 1407184610Salfred 1408184610Salfred /* actually set the channel */ 1409188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1]); 1410188417Sthompsa if (error != 0) 1411188417Sthompsa goto fail; 1412184610Salfred 1413188417Sthompsa zyd_write32_m(sc, ZYD_CR18, 3); 1414188417Sthompsafail: 1415188417Sthompsa return (error); 1416184610Salfred} 1417184610Salfred 1418184610Salfred/* 1419184610Salfred * GCT RF methods. 1420184610Salfred */ 1421188417Sthompsastatic int 1422188417Sthompsazyd_gct_init(struct zyd_rf *rf) 1423184610Salfred{ 1424188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1425188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1426184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_GCT_PHY; 1427184610Salfred static const uint32_t rfini[] = ZYD_GCT_RF; 1428188417Sthompsa int i, error; 1429184610Salfred 1430184610Salfred /* init RF-dependent PHY registers */ 1431188417Sthompsa for (i = 0; i < N(phyini); i++) 1432188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1433188417Sthompsa 1434184610Salfred /* init cgt radio */ 1435188417Sthompsa for (i = 0; i < N(rfini); i++) { 1436188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 1437188417Sthompsa return (error); 1438184610Salfred } 1439188417Sthompsafail: 1440188417Sthompsa return (error); 1441188417Sthompsa#undef N 1442184610Salfred} 1443184610Salfred 1444188417Sthompsastatic int 1445188417Sthompsazyd_gct_switch_radio(struct zyd_rf *rf, int on) 1446184610Salfred{ 1447188417Sthompsa /* vendor driver does nothing for this RF chip */ 1448188417Sthompsa 1449188417Sthompsa return (0); 1450188417Sthompsa} 1451188417Sthompsa 1452188417Sthompsastatic int 1453188417Sthompsazyd_gct_set_channel(struct zyd_rf *rf, uint8_t chan) 1454188417Sthompsa{ 1455188417Sthompsa int error; 1456188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1457184610Salfred static const uint32_t rfprog[] = ZYD_GCT_CHANTABLE; 1458184610Salfred 1459188417Sthompsa error = zyd_rfwrite(sc, 0x1c0000); 1460188417Sthompsa if (error != 0) 1461188417Sthompsa goto fail; 1462188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1]); 1463188417Sthompsa if (error != 0) 1464188417Sthompsa goto fail; 1465188417Sthompsa error = zyd_rfwrite(sc, 0x1c0008); 1466188417Sthompsafail: 1467188417Sthompsa return (error); 1468184610Salfred} 1469184610Salfred 1470184610Salfred/* 1471184610Salfred * Maxim RF methods. 1472184610Salfred */ 1473188417Sthompsastatic int 1474188417Sthompsazyd_maxim_init(struct zyd_rf *rf) 1475184610Salfred{ 1476188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1477188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1478184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY; 1479184610Salfred static const uint32_t rfini[] = ZYD_MAXIM_RF; 1480184610Salfred uint16_t tmp; 1481188417Sthompsa int i, error; 1482184610Salfred 1483184610Salfred /* init RF-dependent PHY registers */ 1484188417Sthompsa for (i = 0; i < N(phyini); i++) 1485188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1486184610Salfred 1487188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1488188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); 1489188417Sthompsa 1490184610Salfred /* init maxim radio */ 1491188417Sthompsa for (i = 0; i < N(rfini); i++) { 1492188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 1493188417Sthompsa return (error); 1494184610Salfred } 1495188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1496188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); 1497188417Sthompsafail: 1498188417Sthompsa return (error); 1499188417Sthompsa#undef N 1500184610Salfred} 1501184610Salfred 1502188417Sthompsastatic int 1503188417Sthompsazyd_maxim_switch_radio(struct zyd_rf *rf, int on) 1504184610Salfred{ 1505188417Sthompsa 1506188417Sthompsa /* vendor driver does nothing for this RF chip */ 1507188417Sthompsa return (0); 1508188417Sthompsa} 1509188417Sthompsa 1510188417Sthompsastatic int 1511188417Sthompsazyd_maxim_set_channel(struct zyd_rf *rf, uint8_t chan) 1512188417Sthompsa{ 1513188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1514188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1515184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY; 1516184610Salfred static const uint32_t rfini[] = ZYD_MAXIM_RF; 1517184610Salfred static const struct { 1518188417Sthompsa uint32_t r1, r2; 1519188417Sthompsa } rfprog[] = ZYD_MAXIM_CHANTABLE; 1520184610Salfred uint16_t tmp; 1521188417Sthompsa int i, error; 1522184610Salfred 1523184610Salfred /* 1524184610Salfred * Do the same as we do when initializing it, except for the channel 1525184610Salfred * values coming from the two channel tables. 1526184610Salfred */ 1527184610Salfred 1528184610Salfred /* init RF-dependent PHY registers */ 1529188417Sthompsa for (i = 0; i < N(phyini); i++) 1530188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1531184610Salfred 1532188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1533188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); 1534188417Sthompsa 1535184610Salfred /* first two values taken from the chantables */ 1536188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r1); 1537188417Sthompsa if (error != 0) 1538188417Sthompsa goto fail; 1539188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r2); 1540188417Sthompsa if (error != 0) 1541188417Sthompsa goto fail; 1542184610Salfred 1543184610Salfred /* init maxim radio - skipping the two first values */ 1544188417Sthompsa for (i = 2; i < N(rfini); i++) { 1545188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 1546188417Sthompsa return (error); 1547184610Salfred } 1548188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1549188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); 1550188417Sthompsafail: 1551188417Sthompsa return (error); 1552188417Sthompsa#undef N 1553184610Salfred} 1554184610Salfred 1555184610Salfred/* 1556184610Salfred * Maxim2 RF methods. 1557184610Salfred */ 1558188417Sthompsastatic int 1559188417Sthompsazyd_maxim2_init(struct zyd_rf *rf) 1560184610Salfred{ 1561188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1562188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1563184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY; 1564184610Salfred static const uint32_t rfini[] = ZYD_MAXIM2_RF; 1565184610Salfred uint16_t tmp; 1566188417Sthompsa int i, error; 1567184610Salfred 1568184610Salfred /* init RF-dependent PHY registers */ 1569188417Sthompsa for (i = 0; i < N(phyini); i++) 1570188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1571184610Salfred 1572188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1573188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); 1574188417Sthompsa 1575184610Salfred /* init maxim2 radio */ 1576188417Sthompsa for (i = 0; i < N(rfini); i++) { 1577188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 1578188417Sthompsa return (error); 1579184610Salfred } 1580188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1581188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); 1582188417Sthompsafail: 1583188417Sthompsa return (error); 1584188417Sthompsa#undef N 1585184610Salfred} 1586184610Salfred 1587188417Sthompsastatic int 1588188417Sthompsazyd_maxim2_switch_radio(struct zyd_rf *rf, int on) 1589184610Salfred{ 1590188417Sthompsa 1591188417Sthompsa /* vendor driver does nothing for this RF chip */ 1592188417Sthompsa return (0); 1593188417Sthompsa} 1594188417Sthompsa 1595188417Sthompsastatic int 1596188417Sthompsazyd_maxim2_set_channel(struct zyd_rf *rf, uint8_t chan) 1597188417Sthompsa{ 1598188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1599188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1600184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY; 1601184610Salfred static const uint32_t rfini[] = ZYD_MAXIM2_RF; 1602184610Salfred static const struct { 1603188417Sthompsa uint32_t r1, r2; 1604188417Sthompsa } rfprog[] = ZYD_MAXIM2_CHANTABLE; 1605184610Salfred uint16_t tmp; 1606188417Sthompsa int i, error; 1607184610Salfred 1608184610Salfred /* 1609184610Salfred * Do the same as we do when initializing it, except for the channel 1610184610Salfred * values coming from the two channel tables. 1611184610Salfred */ 1612184610Salfred 1613184610Salfred /* init RF-dependent PHY registers */ 1614188417Sthompsa for (i = 0; i < N(phyini); i++) 1615188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1616184610Salfred 1617188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1618188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); 1619188417Sthompsa 1620184610Salfred /* first two values taken from the chantables */ 1621188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r1); 1622188417Sthompsa if (error != 0) 1623188417Sthompsa goto fail; 1624188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r2); 1625188417Sthompsa if (error != 0) 1626188417Sthompsa goto fail; 1627184610Salfred 1628184610Salfred /* init maxim2 radio - skipping the two first values */ 1629188417Sthompsa for (i = 2; i < N(rfini); i++) { 1630188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 1631188417Sthompsa return (error); 1632184610Salfred } 1633188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1634188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); 1635188417Sthompsafail: 1636188417Sthompsa return (error); 1637188417Sthompsa#undef N 1638184610Salfred} 1639184610Salfred 1640188417Sthompsastatic int 1641188417Sthompsazyd_rf_attach(struct zyd_softc *sc, uint8_t type) 1642184610Salfred{ 1643188417Sthompsa struct zyd_rf *rf = &sc->sc_rf; 1644184610Salfred 1645188417Sthompsa rf->rf_sc = sc; 1646188417Sthompsa 1647188417Sthompsa switch (type) { 1648184610Salfred case ZYD_RF_RFMD: 1649188417Sthompsa rf->init = zyd_rfmd_init; 1650188417Sthompsa rf->switch_radio = zyd_rfmd_switch_radio; 1651188417Sthompsa rf->set_channel = zyd_rfmd_set_channel; 1652188417Sthompsa rf->width = 24; /* 24-bit RF values */ 1653184610Salfred break; 1654184610Salfred case ZYD_RF_AL2230: 1655186730Salfred case ZYD_RF_AL2230S: 1656188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211B) { 1657188417Sthompsa rf->init = zyd_al2230_init_b; 1658188417Sthompsa rf->set_channel = zyd_al2230_set_channel_b; 1659186730Salfred } else { 1660188417Sthompsa rf->init = zyd_al2230_init; 1661188417Sthompsa rf->set_channel = zyd_al2230_set_channel; 1662186730Salfred } 1663188417Sthompsa rf->switch_radio = zyd_al2230_switch_radio; 1664188417Sthompsa rf->bandedge6 = zyd_al2230_bandedge6; 1665188417Sthompsa rf->width = 24; /* 24-bit RF values */ 1666184610Salfred break; 1667184610Salfred case ZYD_RF_AL7230B: 1668188417Sthompsa rf->init = zyd_al7230B_init; 1669188417Sthompsa rf->switch_radio = zyd_al7230B_switch_radio; 1670188417Sthompsa rf->set_channel = zyd_al7230B_set_channel; 1671188417Sthompsa rf->width = 24; /* 24-bit RF values */ 1672184610Salfred break; 1673184610Salfred case ZYD_RF_AL2210: 1674188417Sthompsa rf->init = zyd_al2210_init; 1675188417Sthompsa rf->switch_radio = zyd_al2210_switch_radio; 1676188417Sthompsa rf->set_channel = zyd_al2210_set_channel; 1677188417Sthompsa rf->width = 24; /* 24-bit RF values */ 1678184610Salfred break; 1679184610Salfred case ZYD_RF_GCT: 1680188417Sthompsa rf->init = zyd_gct_init; 1681188417Sthompsa rf->switch_radio = zyd_gct_switch_radio; 1682188417Sthompsa rf->set_channel = zyd_gct_set_channel; 1683188417Sthompsa rf->width = 21; /* 21-bit RF values */ 1684184610Salfred break; 1685184610Salfred case ZYD_RF_MAXIM_NEW: 1686188417Sthompsa rf->init = zyd_maxim_init; 1687188417Sthompsa rf->switch_radio = zyd_maxim_switch_radio; 1688188417Sthompsa rf->set_channel = zyd_maxim_set_channel; 1689188417Sthompsa rf->width = 18; /* 18-bit RF values */ 1690184610Salfred break; 1691184610Salfred case ZYD_RF_MAXIM_NEW2: 1692188417Sthompsa rf->init = zyd_maxim2_init; 1693188417Sthompsa rf->switch_radio = zyd_maxim2_switch_radio; 1694188417Sthompsa rf->set_channel = zyd_maxim2_set_channel; 1695188417Sthompsa rf->width = 18; /* 18-bit RF values */ 1696184610Salfred break; 1697184610Salfred default: 1698188417Sthompsa device_printf(sc->sc_dev, 1699188417Sthompsa "sorry, radio \"%s\" is not supported yet\n", 1700188417Sthompsa zyd_rf_name(type)); 1701188417Sthompsa return (EINVAL); 1702184610Salfred } 1703188417Sthompsa return (0); 1704188417Sthompsa} 1705184610Salfred 1706188417Sthompsastatic const char * 1707188417Sthompsazyd_rf_name(uint8_t type) 1708188417Sthompsa{ 1709188417Sthompsa static const char * const zyd_rfs[] = { 1710188417Sthompsa "unknown", "unknown", "UW2451", "UCHIP", "AL2230", 1711188417Sthompsa "AL7230B", "THETA", "AL2210", "MAXIM_NEW", "GCT", 1712188417Sthompsa "AL2230S", "RALINK", "INTERSIL", "RFMD", "MAXIM_NEW2", 1713188417Sthompsa "PHILIPS" 1714188417Sthompsa }; 1715184610Salfred 1716188417Sthompsa return zyd_rfs[(type > 15) ? 0 : type]; 1717184610Salfred} 1718184610Salfred 1719188417Sthompsastatic int 1720188417Sthompsazyd_hw_init(struct zyd_softc *sc) 1721184610Salfred{ 1722188417Sthompsa int error; 1723184610Salfred const struct zyd_phy_pair *phyp; 1724188417Sthompsa struct zyd_rf *rf = &sc->sc_rf; 1725188417Sthompsa uint16_t val; 1726184610Salfred 1727184610Salfred /* specify that the plug and play is finished */ 1728188417Sthompsa zyd_write32_m(sc, ZYD_MAC_AFTER_PNP, 1); 1729188417Sthompsa zyd_read16_m(sc, ZYD_FIRMWARE_BASE_ADDR, &sc->sc_fwbase); 1730188417Sthompsa DPRINTF(sc, ZYD_DEBUG_FW, "firmware base address=0x%04x\n", 1731188417Sthompsa sc->sc_fwbase); 1732184610Salfred 1733184610Salfred /* retrieve firmware revision number */ 1734188417Sthompsa zyd_read16_m(sc, sc->sc_fwbase + ZYD_FW_FIRMWARE_REV, &sc->sc_fwrev); 1735188417Sthompsa zyd_write32_m(sc, ZYD_CR_GPI_EN, 0); 1736188417Sthompsa zyd_write32_m(sc, ZYD_MAC_CONT_WIN_LIMIT, 0x7f043f); 1737186730Salfred /* set mandatory rates - XXX assumes 802.11b/g */ 1738188417Sthompsa zyd_write32_m(sc, ZYD_MAC_MAN_RATE, 0x150f); 1739186730Salfred 1740184610Salfred /* disable interrupts */ 1741188417Sthompsa zyd_write32_m(sc, ZYD_CR_INTERRUPT, 0); 1742184610Salfred 1743188417Sthompsa if ((error = zyd_read_pod(sc)) != 0) { 1744188417Sthompsa device_printf(sc->sc_dev, "could not read EEPROM\n"); 1745188417Sthompsa goto fail; 1746184610Salfred } 1747188417Sthompsa 1748188417Sthompsa /* PHY init (resetting) */ 1749188417Sthompsa error = zyd_lock_phy(sc); 1750188417Sthompsa if (error != 0) 1751188417Sthompsa goto fail; 1752188417Sthompsa phyp = (sc->sc_macrev == ZYD_ZD1211B) ? zyd_def_phyB : zyd_def_phy; 1753188417Sthompsa for (; phyp->reg != 0; phyp++) 1754188417Sthompsa zyd_write16_m(sc, phyp->reg, phyp->val); 1755188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211 && sc->sc_fix_cr157 != 0) { 1756188417Sthompsa zyd_read16_m(sc, ZYD_EEPROM_PHY_REG, &val); 1757188417Sthompsa zyd_write32_m(sc, ZYD_CR157, val >> 8); 1758184610Salfred } 1759188417Sthompsa error = zyd_unlock_phy(sc); 1760188417Sthompsa if (error != 0) 1761188417Sthompsa goto fail; 1762184610Salfred 1763184610Salfred /* HMAC init */ 1764188417Sthompsa zyd_write32_m(sc, ZYD_MAC_ACK_EXT, 0x00000020); 1765188417Sthompsa zyd_write32_m(sc, ZYD_CR_ADDA_MBIAS_WT, 0x30000808); 1766188417Sthompsa zyd_write32_m(sc, ZYD_MAC_SNIFFER, 0x00000000); 1767188417Sthompsa zyd_write32_m(sc, ZYD_MAC_RXFILTER, 0x00000000); 1768188417Sthompsa zyd_write32_m(sc, ZYD_MAC_GHTBL, 0x00000000); 1769188417Sthompsa zyd_write32_m(sc, ZYD_MAC_GHTBH, 0x80000000); 1770188417Sthompsa zyd_write32_m(sc, ZYD_MAC_MISC, 0x000000a4); 1771188417Sthompsa zyd_write32_m(sc, ZYD_CR_ADDA_PWR_DWN, 0x0000007f); 1772188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BCNCFG, 0x00f00401); 1773188417Sthompsa zyd_write32_m(sc, ZYD_MAC_PHY_DELAY2, 0x00000000); 1774188417Sthompsa zyd_write32_m(sc, ZYD_MAC_ACK_EXT, 0x00000080); 1775188417Sthompsa zyd_write32_m(sc, ZYD_CR_ADDA_PWR_DWN, 0x00000000); 1776188417Sthompsa zyd_write32_m(sc, ZYD_MAC_SIFS_ACK_TIME, 0x00000100); 1777188417Sthompsa zyd_write32_m(sc, ZYD_CR_RX_PE_DELAY, 0x00000070); 1778188417Sthompsa zyd_write32_m(sc, ZYD_CR_PS_CTRL, 0x10000000); 1779188417Sthompsa zyd_write32_m(sc, ZYD_MAC_RTSCTSRATE, 0x02030203); 1780188417Sthompsa zyd_write32_m(sc, ZYD_MAC_AFTER_PNP, 1); 1781188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BACKOFF_PROTECT, 0x00000114); 1782188417Sthompsa zyd_write32_m(sc, ZYD_MAC_DIFS_EIFS_SIFS, 0x0a47c032); 1783188417Sthompsa zyd_write32_m(sc, ZYD_MAC_CAM_MODE, 0x3); 1784184610Salfred 1785188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211) { 1786188417Sthompsa zyd_write32_m(sc, ZYD_MAC_RETRY, 0x00000002); 1787188417Sthompsa zyd_write32_m(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0640); 1788186730Salfred } else { 1789188417Sthompsa zyd_write32_m(sc, ZYD_MACB_MAX_RETRY, 0x02020202); 1790188417Sthompsa zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL4, 0x007f003f); 1791188417Sthompsa zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL3, 0x007f003f); 1792188417Sthompsa zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL2, 0x003f001f); 1793188417Sthompsa zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL1, 0x001f000f); 1794188417Sthompsa zyd_write32_m(sc, ZYD_MACB_AIFS_CTL1, 0x00280028); 1795188417Sthompsa zyd_write32_m(sc, ZYD_MACB_AIFS_CTL2, 0x008C003C); 1796188417Sthompsa zyd_write32_m(sc, ZYD_MACB_TXOP, 0x01800824); 1797188417Sthompsa zyd_write32_m(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0eff); 1798186730Salfred } 1799186730Salfred 1800184610Salfred /* init beacon interval to 100ms */ 1801188417Sthompsa if ((error = zyd_set_beacon_interval(sc, 100)) != 0) 1802188417Sthompsa goto fail; 1803184610Salfred 1804188417Sthompsa if ((error = zyd_rf_attach(sc, sc->sc_rfrev)) != 0) { 1805188417Sthompsa device_printf(sc->sc_dev, "could not attach RF, rev 0x%x\n", 1806188417Sthompsa sc->sc_rfrev); 1807188417Sthompsa goto fail; 1808188417Sthompsa } 1809188417Sthompsa 1810188417Sthompsa /* RF chip init */ 1811188417Sthompsa error = zyd_lock_phy(sc); 1812188417Sthompsa if (error != 0) 1813188417Sthompsa goto fail; 1814188417Sthompsa error = (*rf->init)(rf); 1815188417Sthompsa if (error != 0) { 1816188417Sthompsa device_printf(sc->sc_dev, 1817188417Sthompsa "radio initialization failed, error %d\n", error); 1818188417Sthompsa goto fail; 1819188417Sthompsa } 1820188417Sthompsa error = zyd_unlock_phy(sc); 1821188417Sthompsa if (error != 0) 1822188417Sthompsa goto fail; 1823188417Sthompsa 1824188417Sthompsa if ((error = zyd_read_eeprom(sc)) != 0) { 1825188417Sthompsa device_printf(sc->sc_dev, "could not read EEPROM\n"); 1826188417Sthompsa goto fail; 1827188417Sthompsa } 1828188417Sthompsa 1829188417Sthompsafail: return (error); 1830184610Salfred} 1831184610Salfred 1832188417Sthompsastatic int 1833188417Sthompsazyd_read_pod(struct zyd_softc *sc) 1834184610Salfred{ 1835188417Sthompsa int error; 1836184610Salfred uint32_t tmp; 1837184610Salfred 1838188417Sthompsa zyd_read32_m(sc, ZYD_EEPROM_POD, &tmp); 1839188417Sthompsa sc->sc_rfrev = tmp & 0x0f; 1840188417Sthompsa sc->sc_ledtype = (tmp >> 4) & 0x01; 1841188417Sthompsa sc->sc_al2230s = (tmp >> 7) & 0x01; 1842188417Sthompsa sc->sc_cckgain = (tmp >> 8) & 0x01; 1843184610Salfred sc->sc_fix_cr157 = (tmp >> 13) & 0x01; 1844188417Sthompsa sc->sc_parev = (tmp >> 16) & 0x0f; 1845186730Salfred sc->sc_bandedge6 = (tmp >> 21) & 0x01; 1846188417Sthompsa sc->sc_newphy = (tmp >> 31) & 0x01; 1847188417Sthompsa sc->sc_txled = ((tmp & (1 << 24)) && (tmp & (1 << 29))) ? 0 : 1; 1848188417Sthompsafail: 1849188417Sthompsa return (error); 1850188417Sthompsa} 1851184610Salfred 1852188417Sthompsastatic int 1853188417Sthompsazyd_read_eeprom(struct zyd_softc *sc) 1854188417Sthompsa{ 1855188417Sthompsa uint16_t val; 1856188417Sthompsa int error, i; 1857184610Salfred 1858184610Salfred /* read Tx power calibration tables */ 1859184610Salfred for (i = 0; i < 7; i++) { 1860188417Sthompsa zyd_read16_m(sc, ZYD_EEPROM_PWR_CAL + i, &val); 1861188417Sthompsa sc->sc_pwrcal[i * 2] = val >> 8; 1862188417Sthompsa sc->sc_pwrcal[i * 2 + 1] = val & 0xff; 1863188417Sthompsa zyd_read16_m(sc, ZYD_EEPROM_PWR_INT + i, &val); 1864188417Sthompsa sc->sc_pwrint[i * 2] = val >> 8; 1865188417Sthompsa sc->sc_pwrint[i * 2 + 1] = val & 0xff; 1866188417Sthompsa zyd_read16_m(sc, ZYD_EEPROM_36M_CAL + i, &val); 1867188417Sthompsa sc->sc_ofdm36_cal[i * 2] = val >> 8; 1868188417Sthompsa sc->sc_ofdm36_cal[i * 2 + 1] = val & 0xff; 1869188417Sthompsa zyd_read16_m(sc, ZYD_EEPROM_48M_CAL + i, &val); 1870188417Sthompsa sc->sc_ofdm48_cal[i * 2] = val >> 8; 1871188417Sthompsa sc->sc_ofdm48_cal[i * 2 + 1] = val & 0xff; 1872188417Sthompsa zyd_read16_m(sc, ZYD_EEPROM_54M_CAL + i, &val); 1873188417Sthompsa sc->sc_ofdm54_cal[i * 2] = val >> 8; 1874188417Sthompsa sc->sc_ofdm54_cal[i * 2 + 1] = val & 0xff; 1875184610Salfred } 1876188417Sthompsafail: 1877188417Sthompsa return (error); 1878184610Salfred} 1879184610Salfred 1880188417Sthompsastatic int 1881188417Sthompsazyd_get_macaddr(struct zyd_softc *sc) 1882186730Salfred{ 1883186730Salfred struct usb2_device_request req; 1884188417Sthompsa usb2_error_t error; 1885186730Salfred 1886186730Salfred req.bmRequestType = UT_READ_VENDOR_DEVICE; 1887186730Salfred req.bRequest = ZYD_READFWDATAREQ; 1888186730Salfred USETW(req.wValue, ZYD_EEPROM_MAC_ADDR_P1); 1889186730Salfred USETW(req.wIndex, 0); 1890186730Salfred USETW(req.wLength, IEEE80211_ADDR_LEN); 1891186730Salfred 1892188419Sthompsa error = zyd_do_request(sc, &req, sc->sc_bssid); 1893188417Sthompsa if (error != 0) { 1894188417Sthompsa device_printf(sc->sc_dev, "could not read EEPROM: %s\n", 1895188417Sthompsa usb2_errstr(error)); 1896188417Sthompsa } 1897188417Sthompsa 1898188417Sthompsa return (error); 1899186730Salfred} 1900186730Salfred 1901188417Sthompsastatic int 1902188417Sthompsazyd_set_macaddr(struct zyd_softc *sc, const uint8_t *addr) 1903184610Salfred{ 1904188417Sthompsa int error; 1905184610Salfred uint32_t tmp; 1906184610Salfred 1907188417Sthompsa tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]; 1908188417Sthompsa zyd_write32_m(sc, ZYD_MAC_MACADRL, tmp); 1909188417Sthompsa tmp = addr[5] << 8 | addr[4]; 1910188417Sthompsa zyd_write32_m(sc, ZYD_MAC_MACADRH, tmp); 1911188417Sthompsafail: 1912188417Sthompsa return (error); 1913188417Sthompsa} 1914184610Salfred 1915188417Sthompsastatic int 1916188417Sthompsazyd_set_bssid(struct zyd_softc *sc, const uint8_t *addr) 1917188417Sthompsa{ 1918188417Sthompsa int error; 1919188417Sthompsa uint32_t tmp; 1920188417Sthompsa 1921188417Sthompsa tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]; 1922188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BSSADRL, tmp); 1923188417Sthompsa tmp = addr[5] << 8 | addr[4]; 1924188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BSSADRH, tmp); 1925188417Sthompsafail: 1926188417Sthompsa return (error); 1927184610Salfred} 1928184610Salfred 1929188417Sthompsastatic int 1930188417Sthompsazyd_switch_radio(struct zyd_softc *sc, int on) 1931184610Salfred{ 1932188417Sthompsa struct zyd_rf *rf = &sc->sc_rf; 1933188417Sthompsa int error; 1934188417Sthompsa 1935188417Sthompsa error = zyd_lock_phy(sc); 1936188417Sthompsa if (error != 0) 1937188417Sthompsa goto fail; 1938188417Sthompsa error = (*rf->switch_radio)(rf, on); 1939188417Sthompsa if (error != 0) 1940188417Sthompsa goto fail; 1941188417Sthompsa error = zyd_unlock_phy(sc); 1942188417Sthompsafail: 1943188417Sthompsa return (error); 1944184610Salfred} 1945184610Salfred 1946188417Sthompsastatic int 1947188417Sthompsazyd_set_led(struct zyd_softc *sc, int which, int on) 1948184610Salfred{ 1949188417Sthompsa int error; 1950184610Salfred uint32_t tmp; 1951184610Salfred 1952188417Sthompsa zyd_read32_m(sc, ZYD_MAC_TX_PE_CONTROL, &tmp); 1953188417Sthompsa tmp &= ~which; 1954188417Sthompsa if (on) 1955188417Sthompsa tmp |= which; 1956188417Sthompsa zyd_write32_m(sc, ZYD_MAC_TX_PE_CONTROL, tmp); 1957188417Sthompsafail: 1958188417Sthompsa return (error); 1959188417Sthompsa} 1960184610Salfred 1961188417Sthompsastatic void 1962188417Sthompsazyd_set_multi(struct zyd_softc *sc) 1963184610Salfred{ 1964188417Sthompsa int error; 1965188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 1966188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 1967188417Sthompsa struct ifmultiaddr *ifma; 1968188417Sthompsa uint32_t low, high; 1969188417Sthompsa uint8_t v; 1970184610Salfred 1971188417Sthompsa if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1972188417Sthompsa return; 1973184610Salfred 1974188417Sthompsa low = 0x00000000; 1975188417Sthompsa high = 0x80000000; 1976184610Salfred 1977188417Sthompsa if (ic->ic_opmode == IEEE80211_M_MONITOR || 1978188417Sthompsa (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) { 1979188417Sthompsa low = 0xffffffff; 1980188417Sthompsa high = 0xffffffff; 1981184610Salfred } else { 1982188417Sthompsa IF_ADDR_LOCK(ifp); 1983188417Sthompsa TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1984188417Sthompsa if (ifma->ifma_addr->sa_family != AF_LINK) 1985188417Sthompsa continue; 1986188417Sthompsa v = ((uint8_t *)LLADDR((struct sockaddr_dl *) 1987188417Sthompsa ifma->ifma_addr))[5] >> 2; 1988188417Sthompsa if (v < 32) 1989188417Sthompsa low |= 1 << v; 1990188417Sthompsa else 1991188417Sthompsa high |= 1 << (v - 32); 1992188417Sthompsa } 1993188417Sthompsa IF_ADDR_UNLOCK(ifp); 1994184610Salfred } 1995184610Salfred 1996188417Sthompsa /* reprogram multicast global hash table */ 1997188417Sthompsa zyd_write32_m(sc, ZYD_MAC_GHTBL, low); 1998188417Sthompsa zyd_write32_m(sc, ZYD_MAC_GHTBH, high); 1999188417Sthompsafail: 2000188417Sthompsa if (error != 0) 2001188417Sthompsa device_printf(sc->sc_dev, 2002188417Sthompsa "could not set multicast hash table\n"); 2003188417Sthompsa} 2004184610Salfred 2005188417Sthompsastatic void 2006188417Sthompsazyd_update_mcast(struct ifnet *ifp) 2007188417Sthompsa{ 2008188417Sthompsa struct zyd_softc *sc = ifp->if_softc; 2009184610Salfred 2010188417Sthompsa if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 2011184610Salfred return; 2012184610Salfred 2013188417Sthompsa ZYD_LOCK(sc); 2014191746Sthompsa zyd_set_multi(sc); 2015188417Sthompsa ZYD_UNLOCK(sc); 2016188417Sthompsa} 2017184610Salfred 2018188417Sthompsastatic int 2019188417Sthompsazyd_set_rxfilter(struct zyd_softc *sc) 2020188417Sthompsa{ 2021188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2022188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 2023188417Sthompsa uint32_t rxfilter; 2024184610Salfred 2025188417Sthompsa switch (ic->ic_opmode) { 2026188417Sthompsa case IEEE80211_M_STA: 2027188417Sthompsa rxfilter = ZYD_FILTER_BSS; 2028188417Sthompsa break; 2029188417Sthompsa case IEEE80211_M_IBSS: 2030188417Sthompsa case IEEE80211_M_HOSTAP: 2031188417Sthompsa rxfilter = ZYD_FILTER_HOSTAP; 2032188417Sthompsa break; 2033188417Sthompsa case IEEE80211_M_MONITOR: 2034188417Sthompsa rxfilter = ZYD_FILTER_MONITOR; 2035188417Sthompsa break; 2036188417Sthompsa default: 2037188417Sthompsa /* should not get there */ 2038188417Sthompsa return (EINVAL); 2039184610Salfred } 2040188417Sthompsa return zyd_write32(sc, ZYD_MAC_RXFILTER, rxfilter); 2041188417Sthompsa} 2042184610Salfred 2043188417Sthompsastatic void 2044188417Sthompsazyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c) 2045188417Sthompsa{ 2046188417Sthompsa int error; 2047188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2048188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 2049188417Sthompsa struct zyd_rf *rf = &sc->sc_rf; 2050188417Sthompsa uint32_t tmp; 2051188601Sthompsa int chan; 2052184610Salfred 2053188417Sthompsa chan = ieee80211_chan2ieee(ic, c); 2054188417Sthompsa if (chan == 0 || chan == IEEE80211_CHAN_ANY) { 2055188417Sthompsa /* XXX should NEVER happen */ 2056188417Sthompsa device_printf(sc->sc_dev, 2057188417Sthompsa "%s: invalid channel %x\n", __func__, chan); 2058188417Sthompsa return; 2059188417Sthompsa } 2060184610Salfred 2061188417Sthompsa error = zyd_lock_phy(sc); 2062188417Sthompsa if (error != 0) 2063188417Sthompsa goto fail; 2064184610Salfred 2065188417Sthompsa error = (*rf->set_channel)(rf, chan); 2066188417Sthompsa if (error != 0) 2067188417Sthompsa goto fail; 2068184610Salfred 2069188417Sthompsa /* update Tx power */ 2070188417Sthompsa zyd_write16_m(sc, ZYD_CR31, sc->sc_pwrint[chan - 1]); 2071184610Salfred 2072188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211B) { 2073188417Sthompsa zyd_write16_m(sc, ZYD_CR67, sc->sc_ofdm36_cal[chan - 1]); 2074188417Sthompsa zyd_write16_m(sc, ZYD_CR66, sc->sc_ofdm48_cal[chan - 1]); 2075188417Sthompsa zyd_write16_m(sc, ZYD_CR65, sc->sc_ofdm54_cal[chan - 1]); 2076188417Sthompsa zyd_write16_m(sc, ZYD_CR68, sc->sc_pwrcal[chan - 1]); 2077188417Sthompsa zyd_write16_m(sc, ZYD_CR69, 0x28); 2078188417Sthompsa zyd_write16_m(sc, ZYD_CR69, 0x2a); 2079188417Sthompsa } 2080188417Sthompsa if (sc->sc_cckgain) { 2081188417Sthompsa /* set CCK baseband gain from EEPROM */ 2082188417Sthompsa if (zyd_read32(sc, ZYD_EEPROM_PHY_REG, &tmp) == 0) 2083188417Sthompsa zyd_write16_m(sc, ZYD_CR47, tmp & 0xff); 2084188417Sthompsa } 2085188417Sthompsa if (sc->sc_bandedge6 && rf->bandedge6 != NULL) { 2086188417Sthompsa error = (*rf->bandedge6)(rf, c); 2087188417Sthompsa if (error != 0) 2088188417Sthompsa goto fail; 2089188417Sthompsa } 2090188417Sthompsa zyd_write32_m(sc, ZYD_CR_CONFIG_PHILIPS, 0); 2091184610Salfred 2092188417Sthompsa error = zyd_unlock_phy(sc); 2093188417Sthompsa if (error != 0) 2094188417Sthompsa goto fail; 2095184610Salfred 2096188417Sthompsa sc->sc_rxtap.wr_chan_freq = sc->sc_txtap.wt_chan_freq = 2097188417Sthompsa htole16(c->ic_freq); 2098188417Sthompsa sc->sc_rxtap.wr_chan_flags = sc->sc_txtap.wt_chan_flags = 2099188417Sthompsa htole16(c->ic_flags); 2100188417Sthompsafail: 2101184610Salfred return; 2102184610Salfred} 2103184610Salfred 2104184610Salfredstatic int 2105188417Sthompsazyd_set_beacon_interval(struct zyd_softc *sc, int bintval) 2106184610Salfred{ 2107188417Sthompsa int error; 2108188417Sthompsa uint32_t val; 2109184610Salfred 2110188417Sthompsa zyd_read32_m(sc, ZYD_CR_ATIM_WND_PERIOD, &val); 2111188417Sthompsa sc->sc_atim_wnd = val; 2112188417Sthompsa zyd_read32_m(sc, ZYD_CR_PRE_TBTT, &val); 2113188417Sthompsa sc->sc_pre_tbtt = val; 2114188417Sthompsa sc->sc_bcn_int = bintval; 2115184610Salfred 2116188417Sthompsa if (sc->sc_bcn_int <= 5) 2117188417Sthompsa sc->sc_bcn_int = 5; 2118188417Sthompsa if (sc->sc_pre_tbtt < 4 || sc->sc_pre_tbtt >= sc->sc_bcn_int) 2119188417Sthompsa sc->sc_pre_tbtt = sc->sc_bcn_int - 1; 2120188417Sthompsa if (sc->sc_atim_wnd >= sc->sc_pre_tbtt) 2121188417Sthompsa sc->sc_atim_wnd = sc->sc_pre_tbtt - 1; 2122184610Salfred 2123188417Sthompsa zyd_write32_m(sc, ZYD_CR_ATIM_WND_PERIOD, sc->sc_atim_wnd); 2124188417Sthompsa zyd_write32_m(sc, ZYD_CR_PRE_TBTT, sc->sc_pre_tbtt); 2125188417Sthompsa zyd_write32_m(sc, ZYD_CR_BCN_INTERVAL, sc->sc_bcn_int); 2126188417Sthompsafail: 2127188417Sthompsa return (error); 2128188417Sthompsa} 2129184610Salfred 2130188417Sthompsastatic void 2131188417Sthompsazyd_rx_data(struct usb2_xfer *xfer, int offset, uint16_t len) 2132188417Sthompsa{ 2133188417Sthompsa struct zyd_softc *sc = xfer->priv_sc; 2134188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2135188417Sthompsa struct zyd_plcphdr plcp; 2136188417Sthompsa struct zyd_rx_stat stat; 2137188417Sthompsa struct mbuf *m; 2138188417Sthompsa int rlen, rssi; 2139184610Salfred 2140188417Sthompsa if (len < ZYD_MIN_FRAGSZ) { 2141188417Sthompsa DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too short (length=%d)\n", 2142188417Sthompsa device_get_nameunit(sc->sc_dev), len); 2143188417Sthompsa ifp->if_ierrors++; 2144188417Sthompsa return; 2145188417Sthompsa } 2146188417Sthompsa usb2_copy_out(xfer->frbuffers, offset, &plcp, sizeof(plcp)); 2147188417Sthompsa usb2_copy_out(xfer->frbuffers, offset + len - sizeof(stat), 2148188417Sthompsa &stat, sizeof(stat)); 2149184610Salfred 2150188417Sthompsa if (stat.flags & ZYD_RX_ERROR) { 2151188417Sthompsa DPRINTF(sc, ZYD_DEBUG_RECV, 2152188417Sthompsa "%s: RX status indicated error (%x)\n", 2153188417Sthompsa device_get_nameunit(sc->sc_dev), stat.flags); 2154188417Sthompsa ifp->if_ierrors++; 2155188417Sthompsa return; 2156188417Sthompsa } 2157184610Salfred 2158188417Sthompsa /* compute actual frame length */ 2159188417Sthompsa rlen = len - sizeof(struct zyd_plcphdr) - 2160188417Sthompsa sizeof(struct zyd_rx_stat) - IEEE80211_CRC_LEN; 2161184610Salfred 2162188417Sthompsa /* allocate a mbuf to store the frame */ 2163188417Sthompsa if (rlen > MCLBYTES) { 2164188417Sthompsa DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too long (length=%d)\n", 2165188417Sthompsa device_get_nameunit(sc->sc_dev), rlen); 2166188417Sthompsa ifp->if_ierrors++; 2167188417Sthompsa return; 2168188417Sthompsa } else if (rlen > MHLEN) 2169188417Sthompsa m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 2170188417Sthompsa else 2171188417Sthompsa m = m_gethdr(M_DONTWAIT, MT_DATA); 2172188417Sthompsa if (m == NULL) { 2173188417Sthompsa DPRINTF(sc, ZYD_DEBUG_RECV, "%s: could not allocate rx mbuf\n", 2174188417Sthompsa device_get_nameunit(sc->sc_dev)); 2175188417Sthompsa ifp->if_ierrors++; 2176188417Sthompsa return; 2177184610Salfred } 2178188417Sthompsa m->m_pkthdr.rcvif = ifp; 2179188417Sthompsa m->m_pkthdr.len = m->m_len = rlen; 2180188417Sthompsa usb2_copy_out(xfer->frbuffers, offset + sizeof(plcp), 2181188417Sthompsa mtod(m, uint8_t *), rlen); 2182184610Salfred 2183188417Sthompsa if (bpf_peers_present(ifp->if_bpf)) { 2184188417Sthompsa struct zyd_rx_radiotap_header *tap = &sc->sc_rxtap; 2185184610Salfred 2186188417Sthompsa tap->wr_flags = 0; 2187188417Sthompsa if (stat.flags & (ZYD_RX_BADCRC16 | ZYD_RX_BADCRC32)) 2188188417Sthompsa tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; 2189188417Sthompsa /* XXX toss, no way to express errors */ 2190188417Sthompsa if (stat.flags & ZYD_RX_DECRYPTERR) 2191188417Sthompsa tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; 2192188417Sthompsa tap->wr_rate = ieee80211_plcp2rate(plcp.signal, 2193188417Sthompsa (stat.flags & ZYD_RX_OFDM) ? 2194188417Sthompsa IEEE80211_T_OFDM : IEEE80211_T_CCK); 2195188417Sthompsa tap->wr_antsignal = stat.rssi + -95; 2196188417Sthompsa tap->wr_antnoise = -95; /* XXX */ 2197184610Salfred 2198188417Sthompsa bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m); 2199188417Sthompsa } 2200188417Sthompsa rssi = (stat.rssi > 63) ? 127 : 2 * stat.rssi; 2201184610Salfred 2202188417Sthompsa sc->sc_rx_data[sc->sc_rx_count].rssi = rssi; 2203188417Sthompsa sc->sc_rx_data[sc->sc_rx_count].m = m; 2204188417Sthompsa sc->sc_rx_count++; 2205184610Salfred} 2206184610Salfred 2207184610Salfredstatic void 2208188417Sthompsazyd_bulk_read_callback(struct usb2_xfer *xfer) 2209184610Salfred{ 2210188417Sthompsa struct zyd_softc *sc = xfer->priv_sc; 2211184610Salfred struct ifnet *ifp = sc->sc_ifp; 2212184610Salfred struct ieee80211com *ic = ifp->if_l2com; 2213188417Sthompsa struct ieee80211_node *ni; 2214188417Sthompsa struct zyd_rx_desc desc; 2215188417Sthompsa struct mbuf *m; 2216188417Sthompsa uint32_t offset; 2217188417Sthompsa uint8_t rssi; 2218188417Sthompsa int8_t nf; 2219188417Sthompsa int i; 2220184610Salfred 2221188417Sthompsa sc->sc_rx_count = 0; 2222188417Sthompsa switch (USB_GET_STATE(xfer)) { 2223188417Sthompsa case USB_ST_TRANSFERRED: 2224188417Sthompsa usb2_copy_out(xfer->frbuffers, xfer->actlen - sizeof(desc), 2225188417Sthompsa &desc, sizeof(desc)); 2226184610Salfred 2227188417Sthompsa offset = 0; 2228188417Sthompsa if (UGETW(desc.tag) == ZYD_TAG_MULTIFRAME) { 2229188417Sthompsa DPRINTF(sc, ZYD_DEBUG_RECV, 2230188417Sthompsa "%s: received multi-frame transfer\n", __func__); 2231184610Salfred 2232188417Sthompsa for (i = 0; i < ZYD_MAX_RXFRAMECNT; i++) { 2233188417Sthompsa uint16_t len16 = UGETW(desc.len[i]); 2234184610Salfred 2235188417Sthompsa if (len16 == 0 || len16 > xfer->actlen) 2236188417Sthompsa break; 2237184610Salfred 2238188417Sthompsa zyd_rx_data(xfer, offset, len16); 2239184610Salfred 2240188417Sthompsa /* next frame is aligned on a 32-bit boundary */ 2241188417Sthompsa len16 = (len16 + 3) & ~3; 2242188417Sthompsa offset += len16; 2243188417Sthompsa if (len16 > xfer->actlen) 2244188417Sthompsa break; 2245188417Sthompsa xfer->actlen -= len16; 2246188417Sthompsa } 2247188417Sthompsa } else { 2248188417Sthompsa DPRINTF(sc, ZYD_DEBUG_RECV, 2249188417Sthompsa "%s: received single-frame transfer\n", __func__); 2250184610Salfred 2251188417Sthompsa zyd_rx_data(xfer, 0, xfer->actlen); 2252188417Sthompsa } 2253188417Sthompsa /* FALLTHROUGH */ 2254188417Sthompsa case USB_ST_SETUP: 2255188417Sthompsatr_setup: 2256188417Sthompsa xfer->frlengths[0] = xfer->max_data_length; 2257188417Sthompsa usb2_start_hardware(xfer); 2258184610Salfred 2259188417Sthompsa /* 2260188417Sthompsa * At the end of a USB callback it is always safe to unlock 2261188417Sthompsa * the private mutex of a device! That is why we do the 2262188417Sthompsa * "ieee80211_input" here, and not some lines up! 2263188417Sthompsa */ 2264188417Sthompsa ZYD_UNLOCK(sc); 2265188417Sthompsa for (i = 0; i < sc->sc_rx_count; i++) { 2266188417Sthompsa rssi = sc->sc_rx_data[i].rssi; 2267188417Sthompsa m = sc->sc_rx_data[i].m; 2268188417Sthompsa sc->sc_rx_data[i].m = NULL; 2269184610Salfred 2270188417Sthompsa nf = -95; /* XXX */ 2271184610Salfred 2272188417Sthompsa ni = ieee80211_find_rxnode(ic, 2273188417Sthompsa mtod(m, struct ieee80211_frame_min *)); 2274188417Sthompsa if (ni != NULL) { 2275188417Sthompsa (void)ieee80211_input(ni, m, rssi, nf, 0); 2276188417Sthompsa ieee80211_free_node(ni); 2277188417Sthompsa } else 2278188417Sthompsa (void)ieee80211_input_all(ic, m, rssi, nf, 0); 2279188417Sthompsa } 2280188417Sthompsa ZYD_LOCK(sc); 2281188417Sthompsa break; 2282184610Salfred 2283188417Sthompsa default: /* Error */ 2284188417Sthompsa DPRINTF(sc, ZYD_DEBUG_ANY, "frame error: %s\n", usb2_errstr(xfer->error)); 2285184610Salfred 2286188417Sthompsa if (xfer->error != USB_ERR_CANCELLED) { 2287188417Sthompsa /* try to clear stall first */ 2288188417Sthompsa xfer->flags.stall_pipe = 1; 2289188417Sthompsa goto tr_setup; 2290184610Salfred } 2291188417Sthompsa break; 2292184610Salfred } 2293184610Salfred} 2294184610Salfred 2295184610Salfredstatic uint8_t 2296188417Sthompsazyd_plcp_signal(int rate) 2297184610Salfred{ 2298184610Salfred switch (rate) { 2299188417Sthompsa /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ 2300184610Salfred case 12: 2301184610Salfred return (0xb); 2302184610Salfred case 18: 2303184610Salfred return (0xf); 2304184610Salfred case 24: 2305184610Salfred return (0xa); 2306184610Salfred case 36: 2307184610Salfred return (0xe); 2308184610Salfred case 48: 2309184610Salfred return (0x9); 2310184610Salfred case 72: 2311184610Salfred return (0xd); 2312184610Salfred case 96: 2313184610Salfred return (0x8); 2314184610Salfred case 108: 2315184610Salfred return (0xc); 2316188417Sthompsa /* CCK rates (NB: not IEEE std, device-specific) */ 2317188417Sthompsa case 2: 2318188417Sthompsa return (0x0); 2319188417Sthompsa case 4: 2320188417Sthompsa return (0x1); 2321188417Sthompsa case 11: 2322188417Sthompsa return (0x2); 2323188417Sthompsa case 22: 2324188417Sthompsa return (0x3); 2325184610Salfred } 2326188417Sthompsa return (0xff); /* XXX unsupported/unknown rate */ 2327184610Salfred} 2328184610Salfred 2329188417Sthompsastatic int 2330188417Sthompsazyd_tx_mgt(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) 2331184610Salfred{ 2332188417Sthompsa struct ieee80211vap *vap = ni->ni_vap; 2333188417Sthompsa struct ieee80211com *ic = ni->ni_ic; 2334188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2335188417Sthompsa struct zyd_tx_desc *desc; 2336188417Sthompsa struct zyd_tx_data *data; 2337188417Sthompsa struct ieee80211_frame *wh; 2338188417Sthompsa struct ieee80211_key *k; 2339188417Sthompsa int rate, totlen; 2340188417Sthompsa uint16_t pktlen; 2341184610Salfred 2342188417Sthompsa data = STAILQ_FIRST(&sc->tx_free); 2343188417Sthompsa STAILQ_REMOVE_HEAD(&sc->tx_free, next); 2344188417Sthompsa sc->tx_nfree--; 2345188417Sthompsa desc = &data->desc; 2346184610Salfred 2347188417Sthompsa rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2; 2348184610Salfred 2349188417Sthompsa wh = mtod(m0, struct ieee80211_frame *); 2350184610Salfred 2351188417Sthompsa if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 2352188417Sthompsa k = ieee80211_crypto_encap(ni, m0); 2353188417Sthompsa if (k == NULL) { 2354188417Sthompsa m_freem(m0); 2355188417Sthompsa return (ENOBUFS); 2356188417Sthompsa } 2357188417Sthompsa } 2358184610Salfred 2359188417Sthompsa data->ni = ni; 2360188417Sthompsa data->m = m0; 2361188417Sthompsa data->rate = rate; 2362184610Salfred 2363188417Sthompsa wh = mtod(m0, struct ieee80211_frame *); 2364184610Salfred 2365188417Sthompsa totlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN; 2366184610Salfred 2367188417Sthompsa /* fill Tx descriptor */ 2368188417Sthompsa desc->len = htole16(totlen); 2369184610Salfred 2370188417Sthompsa desc->flags = ZYD_TX_FLAG_BACKOFF; 2371188417Sthompsa if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 2372188417Sthompsa /* multicast frames are not sent at OFDM rates in 802.11b/g */ 2373188417Sthompsa if (totlen > vap->iv_rtsthreshold) { 2374188417Sthompsa desc->flags |= ZYD_TX_FLAG_RTS; 2375188417Sthompsa } else if (ZYD_RATE_IS_OFDM(rate) && 2376188417Sthompsa (ic->ic_flags & IEEE80211_F_USEPROT)) { 2377188417Sthompsa if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) 2378188417Sthompsa desc->flags |= ZYD_TX_FLAG_CTS_TO_SELF; 2379188417Sthompsa else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) 2380188417Sthompsa desc->flags |= ZYD_TX_FLAG_RTS; 2381188417Sthompsa } 2382188417Sthompsa } else 2383188417Sthompsa desc->flags |= ZYD_TX_FLAG_MULTICAST; 2384184610Salfred 2385188417Sthompsa if ((wh->i_fc[0] & 2386188417Sthompsa (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == 2387188417Sthompsa (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL)) 2388188417Sthompsa desc->flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL); 2389184610Salfred 2390188417Sthompsa desc->phy = zyd_plcp_signal(rate); 2391188417Sthompsa if (ZYD_RATE_IS_OFDM(rate)) { 2392188417Sthompsa desc->phy |= ZYD_TX_PHY_OFDM; 2393188417Sthompsa if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) 2394188417Sthompsa desc->phy |= ZYD_TX_PHY_5GHZ; 2395188417Sthompsa } else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 2396188417Sthompsa desc->phy |= ZYD_TX_PHY_SHPREAMBLE; 2397184610Salfred 2398188417Sthompsa /* actual transmit length (XXX why +10?) */ 2399188417Sthompsa pktlen = ZYD_TX_DESC_SIZE + 10; 2400188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211) 2401188417Sthompsa pktlen += totlen; 2402188417Sthompsa desc->pktlen = htole16(pktlen); 2403184610Salfred 2404188417Sthompsa desc->plcp_length = (16 * totlen + rate - 1) / rate; 2405188417Sthompsa desc->plcp_service = 0; 2406188417Sthompsa if (rate == 22) { 2407188417Sthompsa const int remainder = (16 * totlen) % 22; 2408188417Sthompsa if (remainder != 0 && remainder < 7) 2409188417Sthompsa desc->plcp_service |= ZYD_PLCP_LENGEXT; 2410184610Salfred } 2411184610Salfred 2412188417Sthompsa if (bpf_peers_present(ifp->if_bpf)) { 2413188417Sthompsa struct zyd_tx_radiotap_header *tap = &sc->sc_txtap; 2414184610Salfred 2415188417Sthompsa tap->wt_flags = 0; 2416188417Sthompsa tap->wt_rate = rate; 2417184610Salfred 2418188417Sthompsa bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); 2419184610Salfred } 2420184610Salfred 2421188417Sthompsa DPRINTF(sc, ZYD_DEBUG_XMIT, 2422188417Sthompsa "%s: sending mgt frame len=%zu rate=%u\n", 2423188417Sthompsa device_get_nameunit(sc->sc_dev), (size_t)m0->m_pkthdr.len, 2424188417Sthompsa rate); 2425184610Salfred 2426188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_q, data, next); 2427188417Sthompsa usb2_transfer_start(sc->sc_xfer[ZYD_BULK_WR]); 2428184610Salfred 2429188417Sthompsa return (0); 2430184610Salfred} 2431184610Salfred 2432184610Salfredstatic void 2433188417Sthompsazyd_bulk_write_callback(struct usb2_xfer *xfer) 2434184610Salfred{ 2435188417Sthompsa struct zyd_softc *sc = xfer->priv_sc; 2436184610Salfred struct ifnet *ifp = sc->sc_ifp; 2437184610Salfred struct ieee80211com *ic = ifp->if_l2com; 2438188417Sthompsa struct ieee80211_channel *c = ic->ic_curchan; 2439188417Sthompsa struct zyd_tx_data *data; 2440188417Sthompsa struct mbuf *m; 2441184610Salfred 2442188417Sthompsa switch (USB_GET_STATE(xfer)) { 2443188417Sthompsa case USB_ST_TRANSFERRED: 2444188417Sthompsa DPRINTF(sc, ZYD_DEBUG_ANY, "transfer complete, %u bytes\n", 2445188417Sthompsa xfer->actlen); 2446184610Salfred 2447188417Sthompsa /* free resources */ 2448188417Sthompsa data = xfer->priv_fifo; 2449188417Sthompsa zyd_tx_free(data, 0); 2450188417Sthompsa xfer->priv_fifo = NULL; 2451184610Salfred 2452188417Sthompsa ifp->if_opackets++; 2453188417Sthompsa ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2454184610Salfred 2455188417Sthompsa /* FALLTHROUGH */ 2456188417Sthompsa case USB_ST_SETUP: 2457188417Sthompsatr_setup: 2458188417Sthompsa data = STAILQ_FIRST(&sc->tx_q); 2459188417Sthompsa if (data) { 2460188417Sthompsa STAILQ_REMOVE_HEAD(&sc->tx_q, next); 2461188417Sthompsa m = data->m; 2462184610Salfred 2463188417Sthompsa if (m->m_pkthdr.len > ZYD_MAX_TXBUFSZ) { 2464188417Sthompsa DPRINTF(sc, ZYD_DEBUG_ANY, "data overflow, %u bytes\n", 2465188417Sthompsa m->m_pkthdr.len); 2466188417Sthompsa m->m_pkthdr.len = ZYD_MAX_TXBUFSZ; 2467188417Sthompsa } 2468188417Sthompsa usb2_copy_in(xfer->frbuffers, 0, &data->desc, 2469188417Sthompsa ZYD_TX_DESC_SIZE); 2470188417Sthompsa usb2_m_copy_in(xfer->frbuffers, ZYD_TX_DESC_SIZE, m, 0, 2471188417Sthompsa m->m_pkthdr.len); 2472184610Salfred 2473188417Sthompsa if (bpf_peers_present(ifp->if_bpf)) { 2474188417Sthompsa struct zyd_tx_radiotap_header *tap = &sc->sc_txtap; 2475184610Salfred 2476188417Sthompsa tap->wt_flags = 0; 2477188417Sthompsa tap->wt_rate = data->rate; 2478188417Sthompsa tap->wt_chan_freq = htole16(c->ic_freq); 2479188417Sthompsa tap->wt_chan_flags = htole16(c->ic_flags); 2480184610Salfred 2481188417Sthompsa bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m); 2482188417Sthompsa } 2483184610Salfred 2484188417Sthompsa xfer->frlengths[0] = ZYD_TX_DESC_SIZE + m->m_pkthdr.len; 2485188417Sthompsa xfer->priv_fifo = data; 2486188417Sthompsa usb2_start_hardware(xfer); 2487188417Sthompsa } 2488188417Sthompsa break; 2489184610Salfred 2490188417Sthompsa default: /* Error */ 2491188417Sthompsa DPRINTF(sc, ZYD_DEBUG_ANY, "transfer error, %s\n", 2492188417Sthompsa usb2_errstr(xfer->error)); 2493184610Salfred 2494188419Sthompsa ifp->if_oerrors++; 2495188419Sthompsa data = xfer->priv_fifo; 2496188419Sthompsa xfer->priv_fifo = NULL; 2497188419Sthompsa if (data != NULL) 2498188419Sthompsa zyd_tx_free(data, xfer->error); 2499188419Sthompsa 2500188417Sthompsa if (xfer->error == USB_ERR_STALLED) { 2501188417Sthompsa /* try to clear stall first */ 2502188417Sthompsa xfer->flags.stall_pipe = 1; 2503188417Sthompsa goto tr_setup; 2504188417Sthompsa } 2505188417Sthompsa if (xfer->error == USB_ERR_TIMEOUT) 2506188417Sthompsa device_printf(sc->sc_dev, "device timeout\n"); 2507184610Salfred break; 2508184610Salfred } 2509184610Salfred} 2510184610Salfred 2511188417Sthompsastatic int 2512188417Sthompsazyd_tx_data(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) 2513184610Salfred{ 2514188417Sthompsa struct ieee80211vap *vap = ni->ni_vap; 2515188417Sthompsa struct ieee80211com *ic = ni->ni_ic; 2516188417Sthompsa struct zyd_tx_desc *desc; 2517188417Sthompsa struct zyd_tx_data *data; 2518188417Sthompsa struct ieee80211_frame *wh; 2519188417Sthompsa const struct ieee80211_txparam *tp; 2520188417Sthompsa struct ieee80211_key *k; 2521188417Sthompsa int rate, totlen; 2522188417Sthompsa uint16_t pktlen; 2523184610Salfred 2524188417Sthompsa wh = mtod(m0, struct ieee80211_frame *); 2525188417Sthompsa data = STAILQ_FIRST(&sc->tx_free); 2526188417Sthompsa STAILQ_REMOVE_HEAD(&sc->tx_free, next); 2527188417Sthompsa sc->tx_nfree--; 2528188417Sthompsa desc = &data->desc; 2529184610Salfred 2530188417Sthompsa desc->flags = ZYD_TX_FLAG_BACKOFF; 2531188417Sthompsa tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; 2532188417Sthompsa if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { 2533188417Sthompsa rate = tp->mcastrate; 2534188417Sthompsa desc->flags |= ZYD_TX_FLAG_MULTICAST; 2535188417Sthompsa } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { 2536188417Sthompsa rate = tp->ucastrate; 2537188417Sthompsa } else { 2538188417Sthompsa (void) ieee80211_amrr_choose(ni, &ZYD_NODE(ni)->amn); 2539188417Sthompsa rate = ni->ni_txrate; 2540184610Salfred } 2541184610Salfred 2542188417Sthompsa if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 2543188417Sthompsa k = ieee80211_crypto_encap(ni, m0); 2544188417Sthompsa if (k == NULL) { 2545188417Sthompsa m_freem(m0); 2546188417Sthompsa return (ENOBUFS); 2547188417Sthompsa } 2548188417Sthompsa /* packet header may have moved, reset our local pointer */ 2549188417Sthompsa wh = mtod(m0, struct ieee80211_frame *); 2550184610Salfred } 2551184610Salfred 2552188417Sthompsa data->ni = ni; 2553188417Sthompsa data->m = m0; 2554184610Salfred 2555188417Sthompsa totlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN; 2556184610Salfred 2557188417Sthompsa /* fill Tx descriptor */ 2558188417Sthompsa desc->len = htole16(totlen); 2559184610Salfred 2560188417Sthompsa if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 2561188417Sthompsa /* multicast frames are not sent at OFDM rates in 802.11b/g */ 2562188417Sthompsa if (totlen > vap->iv_rtsthreshold) { 2563188417Sthompsa desc->flags |= ZYD_TX_FLAG_RTS; 2564188417Sthompsa } else if (ZYD_RATE_IS_OFDM(rate) && 2565188417Sthompsa (ic->ic_flags & IEEE80211_F_USEPROT)) { 2566188417Sthompsa if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) 2567188417Sthompsa desc->flags |= ZYD_TX_FLAG_CTS_TO_SELF; 2568188417Sthompsa else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) 2569188417Sthompsa desc->flags |= ZYD_TX_FLAG_RTS; 2570188417Sthompsa } 2571184610Salfred } 2572184610Salfred 2573188417Sthompsa if ((wh->i_fc[0] & 2574188417Sthompsa (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == 2575188417Sthompsa (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL)) 2576188417Sthompsa desc->flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL); 2577188417Sthompsa 2578188417Sthompsa desc->phy = zyd_plcp_signal(rate); 2579188417Sthompsa if (ZYD_RATE_IS_OFDM(rate)) { 2580188417Sthompsa desc->phy |= ZYD_TX_PHY_OFDM; 2581184610Salfred if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) 2582188417Sthompsa desc->phy |= ZYD_TX_PHY_5GHZ; 2583184610Salfred } else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 2584188417Sthompsa desc->phy |= ZYD_TX_PHY_SHPREAMBLE; 2585184610Salfred 2586184610Salfred /* actual transmit length (XXX why +10?) */ 2587184610Salfred pktlen = sizeof(struct zyd_tx_desc) + 10; 2588188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211) 2589184610Salfred pktlen += totlen; 2590188417Sthompsa desc->pktlen = htole16(pktlen); 2591184610Salfred 2592188417Sthompsa desc->plcp_length = (16 * totlen + rate - 1) / rate; 2593188417Sthompsa desc->plcp_service = 0; 2594184610Salfred if (rate == 22) { 2595188417Sthompsa const int remainder = (16 * totlen) % 22; 2596188417Sthompsa if (remainder != 0 && remainder < 7) 2597188417Sthompsa desc->plcp_service |= ZYD_PLCP_LENGEXT; 2598184610Salfred } 2599184610Salfred 2600188417Sthompsa DPRINTF(sc, ZYD_DEBUG_XMIT, 2601188417Sthompsa "%s: sending data frame len=%zu rate=%u\n", 2602188417Sthompsa device_get_nameunit(sc->sc_dev), (size_t)m0->m_pkthdr.len, 2603188417Sthompsa rate); 2604184610Salfred 2605188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_q, data, next); 2606188417Sthompsa usb2_transfer_start(sc->sc_xfer[ZYD_BULK_WR]); 2607184610Salfred 2608188417Sthompsa return (0); 2609184610Salfred} 2610184610Salfred 2611184610Salfredstatic void 2612188417Sthompsazyd_start(struct ifnet *ifp) 2613184610Salfred{ 2614188417Sthompsa struct zyd_softc *sc = ifp->if_softc; 2615188417Sthompsa struct ieee80211_node *ni; 2616184610Salfred struct mbuf *m; 2617184610Salfred 2618188417Sthompsa ZYD_LOCK(sc); 2619188417Sthompsa for (;;) { 2620188417Sthompsa IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 2621188417Sthompsa if (m == NULL) 2622184610Salfred break; 2623188417Sthompsa if (sc->tx_nfree == 0) { 2624188417Sthompsa IFQ_DRV_PREPEND(&ifp->if_snd, m); 2625188417Sthompsa ifp->if_drv_flags |= IFF_DRV_OACTIVE; 2626184610Salfred break; 2627184610Salfred } 2628188417Sthompsa ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; 2629188417Sthompsa if (zyd_tx_data(sc, m, ni) != 0) { 2630188417Sthompsa ieee80211_free_node(ni); 2631188417Sthompsa ifp->if_oerrors++; 2632188417Sthompsa break; 2633184610Salfred } 2634184610Salfred } 2635188417Sthompsa ZYD_UNLOCK(sc); 2636184610Salfred} 2637184610Salfred 2638188417Sthompsastatic int 2639188417Sthompsazyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 2640188417Sthompsa const struct ieee80211_bpf_params *params) 2641184610Salfred{ 2642188417Sthompsa struct ieee80211com *ic = ni->ni_ic; 2643188417Sthompsa struct ifnet *ifp = ic->ic_ifp; 2644188417Sthompsa struct zyd_softc *sc = ifp->if_softc; 2645184610Salfred 2646188417Sthompsa ZYD_LOCK(sc); 2647188417Sthompsa /* prevent management frames from being sent if we're not ready */ 2648188417Sthompsa if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 2649188417Sthompsa ZYD_UNLOCK(sc); 2650188417Sthompsa m_freem(m); 2651188417Sthompsa ieee80211_free_node(ni); 2652188417Sthompsa return (ENETDOWN); 2653188417Sthompsa } 2654188417Sthompsa if (sc->tx_nfree == 0) { 2655188417Sthompsa ifp->if_drv_flags |= IFF_DRV_OACTIVE; 2656188417Sthompsa ZYD_UNLOCK(sc); 2657188417Sthompsa m_freem(m); 2658188417Sthompsa ieee80211_free_node(ni); 2659188417Sthompsa return (ENOBUFS); /* XXX */ 2660188417Sthompsa } 2661188417Sthompsa 2662188417Sthompsa /* 2663188417Sthompsa * Legacy path; interpret frame contents to decide 2664188417Sthompsa * precisely how to send the frame. 2665188417Sthompsa * XXX raw path 2666188417Sthompsa */ 2667188417Sthompsa if (zyd_tx_mgt(sc, m, ni) != 0) { 2668188417Sthompsa ZYD_UNLOCK(sc); 2669188417Sthompsa ifp->if_oerrors++; 2670188417Sthompsa ieee80211_free_node(ni); 2671188417Sthompsa return (EIO); 2672188417Sthompsa } 2673188417Sthompsa ZYD_UNLOCK(sc); 2674188417Sthompsa return (0); 2675184610Salfred} 2676184610Salfred 2677184610Salfredstatic int 2678188417Sthompsazyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 2679184610Salfred{ 2680184610Salfred struct zyd_softc *sc = ifp->if_softc; 2681184610Salfred struct ieee80211com *ic = ifp->if_l2com; 2682188417Sthompsa struct ifreq *ifr = (struct ifreq *) data; 2683188417Sthompsa int error = 0, startall = 0; 2684184610Salfred 2685184610Salfred switch (cmd) { 2686184610Salfred case SIOCSIFFLAGS: 2687188417Sthompsa ZYD_LOCK(sc); 2688184610Salfred if (ifp->if_flags & IFF_UP) { 2689191746Sthompsa if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 2690191746Sthompsa zyd_init_locked(sc); 2691188417Sthompsa startall = 1; 2692191746Sthompsa } else 2693191746Sthompsa zyd_set_multi(sc); 2694184610Salfred } else { 2695191746Sthompsa if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2696191746Sthompsa zyd_stop(sc); 2697184610Salfred } 2698188417Sthompsa ZYD_UNLOCK(sc); 2699188417Sthompsa if (startall) 2700188417Sthompsa ieee80211_start_all(ic); 2701184610Salfred break; 2702184610Salfred case SIOCGIFMEDIA: 2703188417Sthompsa error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); 2704184610Salfred break; 2705188417Sthompsa case SIOCGIFADDR: 2706184610Salfred error = ether_ioctl(ifp, cmd, data); 2707184610Salfred break; 2708188417Sthompsa default: 2709188417Sthompsa error = EINVAL; 2710188417Sthompsa break; 2711184610Salfred } 2712184610Salfred return (error); 2713184610Salfred} 2714184610Salfred 2715184610Salfredstatic void 2716191746Sthompsazyd_init_locked(struct zyd_softc *sc) 2717184610Salfred{ 2718188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2719188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 2720188417Sthompsa struct usb2_config_descriptor *cd; 2721188419Sthompsa int error; 2722188417Sthompsa uint32_t val; 2723184610Salfred 2724188417Sthompsa ZYD_LOCK_ASSERT(sc, MA_OWNED); 2725184610Salfred 2726188417Sthompsa if (!(sc->sc_flags & ZYD_FLAG_INITONCE)) { 2727188417Sthompsa error = zyd_loadfirmware(sc); 2728188417Sthompsa if (error != 0) { 2729188417Sthompsa device_printf(sc->sc_dev, 2730188417Sthompsa "could not load firmware (error=%d)\n", error); 2731188417Sthompsa goto fail; 2732188417Sthompsa } 2733188417Sthompsa 2734188417Sthompsa /* reset device */ 2735188417Sthompsa cd = usb2_get_config_descriptor(sc->sc_udev); 2736188417Sthompsa error = usb2_req_set_config(sc->sc_udev, &sc->sc_mtx, 2737188417Sthompsa cd->bConfigurationValue); 2738188417Sthompsa if (error) 2739188417Sthompsa device_printf(sc->sc_dev, "reset failed, continuing\n"); 2740188417Sthompsa 2741188417Sthompsa error = zyd_hw_init(sc); 2742188417Sthompsa if (error) { 2743188417Sthompsa device_printf(sc->sc_dev, 2744188417Sthompsa "hardware initialization failed\n"); 2745188417Sthompsa goto fail; 2746188417Sthompsa } 2747188417Sthompsa 2748188417Sthompsa device_printf(sc->sc_dev, 2749188417Sthompsa "HMAC ZD1211%s, FW %02x.%02x, RF %s S%x, PA%x LED %x " 2750188417Sthompsa "BE%x NP%x Gain%x F%x\n", 2751188417Sthompsa (sc->sc_macrev == ZYD_ZD1211) ? "": "B", 2752188417Sthompsa sc->sc_fwrev >> 8, sc->sc_fwrev & 0xff, 2753188417Sthompsa zyd_rf_name(sc->sc_rfrev), sc->sc_al2230s, sc->sc_parev, 2754188417Sthompsa sc->sc_ledtype, sc->sc_bandedge6, sc->sc_newphy, 2755188417Sthompsa sc->sc_cckgain, sc->sc_fix_cr157); 2756188417Sthompsa 2757188417Sthompsa /* read regulatory domain (currently unused) */ 2758188417Sthompsa zyd_read32_m(sc, ZYD_EEPROM_SUBID, &val); 2759188417Sthompsa sc->sc_regdomain = val >> 16; 2760188417Sthompsa DPRINTF(sc, ZYD_DEBUG_INIT, "regulatory domain %x\n", 2761188417Sthompsa sc->sc_regdomain); 2762188417Sthompsa 2763188417Sthompsa /* we'll do software WEP decryption for now */ 2764188417Sthompsa DPRINTF(sc, ZYD_DEBUG_INIT, "%s: setting encryption type\n", 2765188417Sthompsa __func__); 2766188417Sthompsa zyd_write32_m(sc, ZYD_MAC_ENCRYPTION_TYPE, ZYD_ENC_SNIFFER); 2767188417Sthompsa 2768188417Sthompsa sc->sc_flags |= ZYD_FLAG_INITONCE; 2769184610Salfred } 2770184610Salfred 2771188417Sthompsa if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2772191746Sthompsa zyd_stop(sc); 2773188417Sthompsa 2774190526Ssam DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %6D\n", 2775190526Ssam IF_LLADDR(ifp), ":"); 2776190526Ssam error = zyd_set_macaddr(sc, IF_LLADDR(ifp)); 2777188417Sthompsa if (error != 0) 2778184610Salfred return; 2779184610Salfred 2780188417Sthompsa /* set basic rates */ 2781188417Sthompsa if (ic->ic_curmode == IEEE80211_MODE_11B) 2782188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BAS_RATE, 0x0003); 2783188417Sthompsa else if (ic->ic_curmode == IEEE80211_MODE_11A) 2784188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BAS_RATE, 0x1500); 2785188417Sthompsa else /* assumes 802.11b/g */ 2786188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BAS_RATE, 0xff0f); 2787184610Salfred 2788188417Sthompsa /* promiscuous mode */ 2789188417Sthompsa zyd_write32_m(sc, ZYD_MAC_SNIFFER, 0); 2790188417Sthompsa /* multicast setup */ 2791188417Sthompsa zyd_set_multi(sc); 2792188417Sthompsa /* set RX filter */ 2793188417Sthompsa error = zyd_set_rxfilter(sc); 2794188417Sthompsa if (error != 0) 2795188417Sthompsa goto fail; 2796184610Salfred 2797188417Sthompsa /* switch radio transmitter ON */ 2798188417Sthompsa error = zyd_switch_radio(sc, 1); 2799188417Sthompsa if (error != 0) 2800188417Sthompsa goto fail; 2801188417Sthompsa /* set default BSS channel */ 2802188417Sthompsa zyd_set_chan(sc, ic->ic_curchan); 2803184610Salfred 2804188417Sthompsa /* 2805188417Sthompsa * Allocate Tx and Rx xfer queues. 2806188417Sthompsa */ 2807188419Sthompsa zyd_setup_tx_list(sc); 2808184610Salfred 2809188417Sthompsa /* enable interrupts */ 2810188417Sthompsa zyd_write32_m(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK); 2811184610Salfred 2812188417Sthompsa ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2813188417Sthompsa ifp->if_drv_flags |= IFF_DRV_RUNNING; 2814189123Sthompsa usb2_transfer_set_stall(sc->sc_xfer[ZYD_BULK_WR]); 2815188417Sthompsa usb2_transfer_start(sc->sc_xfer[ZYD_BULK_RD]); 2816188417Sthompsa usb2_transfer_start(sc->sc_xfer[ZYD_INTR_RD]); 2817184610Salfred 2818188417Sthompsa return; 2819184610Salfred 2820191746Sthompsafail: zyd_stop(sc); 2821188417Sthompsa return; 2822184610Salfred} 2823184610Salfred 2824184610Salfredstatic void 2825188417Sthompsazyd_init(void *priv) 2826184610Salfred{ 2827188417Sthompsa struct zyd_softc *sc = priv; 2828188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2829188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 2830184610Salfred 2831188417Sthompsa ZYD_LOCK(sc); 2832191746Sthompsa zyd_init_locked(sc); 2833188417Sthompsa ZYD_UNLOCK(sc); 2834188417Sthompsa 2835188417Sthompsa if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2836188417Sthompsa ieee80211_start_all(ic); /* start all vap's */ 2837184610Salfred} 2838184610Salfred 2839184610Salfredstatic void 2840191746Sthompsazyd_stop(struct zyd_softc *sc) 2841184610Salfred{ 2842188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2843188417Sthompsa int error; 2844184610Salfred 2845188417Sthompsa ZYD_LOCK_ASSERT(sc, MA_OWNED); 2846184610Salfred 2847188417Sthompsa ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 2848184610Salfred 2849188417Sthompsa /* 2850188419Sthompsa * Drain all the transfers, if not already drained: 2851188417Sthompsa */ 2852188419Sthompsa ZYD_UNLOCK(sc); 2853188419Sthompsa usb2_transfer_drain(sc->sc_xfer[ZYD_BULK_WR]); 2854188419Sthompsa usb2_transfer_drain(sc->sc_xfer[ZYD_BULK_RD]); 2855188419Sthompsa ZYD_LOCK(sc); 2856188417Sthompsa 2857188419Sthompsa zyd_unsetup_tx_list(sc); 2858188417Sthompsa 2859188419Sthompsa /* Stop now if the device was never set up */ 2860188419Sthompsa if (!(sc->sc_flags & ZYD_FLAG_INITONCE)) 2861184610Salfred return; 2862184610Salfred 2863188417Sthompsa /* switch radio transmitter OFF */ 2864188417Sthompsa error = zyd_switch_radio(sc, 0); 2865188417Sthompsa if (error != 0) 2866188417Sthompsa goto fail; 2867188417Sthompsa /* disable Rx */ 2868188417Sthompsa zyd_write32_m(sc, ZYD_MAC_RXFILTER, 0); 2869188417Sthompsa /* disable interrupts */ 2870188417Sthompsa zyd_write32_m(sc, ZYD_CR_INTERRUPT, 0); 2871184610Salfred 2872188417Sthompsafail: 2873188417Sthompsa return; 2874184610Salfred} 2875184610Salfred 2876188417Sthompsastatic int 2877188417Sthompsazyd_loadfirmware(struct zyd_softc *sc) 2878184610Salfred{ 2879188417Sthompsa struct usb2_device_request req; 2880188417Sthompsa size_t size; 2881188417Sthompsa u_char *fw; 2882188417Sthompsa uint8_t stat; 2883188417Sthompsa uint16_t addr; 2884184610Salfred 2885188417Sthompsa if (sc->sc_flags & ZYD_FLAG_FWLOADED) 2886188417Sthompsa return (0); 2887184610Salfred 2888188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211) { 2889188417Sthompsa fw = (u_char *)zd1211_firmware; 2890188417Sthompsa size = sizeof(zd1211_firmware); 2891188417Sthompsa } else { 2892188417Sthompsa fw = (u_char *)zd1211b_firmware; 2893188417Sthompsa size = sizeof(zd1211b_firmware); 2894184610Salfred } 2895184610Salfred 2896188417Sthompsa req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 2897188417Sthompsa req.bRequest = ZYD_DOWNLOADREQ; 2898188417Sthompsa USETW(req.wIndex, 0); 2899184610Salfred 2900188417Sthompsa addr = ZYD_FIRMWARE_START_ADDR; 2901188417Sthompsa while (size > 0) { 2902188417Sthompsa /* 2903188417Sthompsa * When the transfer size is 4096 bytes, it is not 2904188417Sthompsa * likely to be able to transfer it. 2905188417Sthompsa * The cause is port or machine or chip? 2906188417Sthompsa */ 2907188417Sthompsa const int mlen = min(size, 64); 2908184610Salfred 2909188417Sthompsa DPRINTF(sc, ZYD_DEBUG_FW, 2910188417Sthompsa "loading firmware block: len=%d, addr=0x%x\n", mlen, addr); 2911184610Salfred 2912188417Sthompsa USETW(req.wValue, addr); 2913188417Sthompsa USETW(req.wLength, mlen); 2914188419Sthompsa if (zyd_do_request(sc, &req, fw) != 0) 2915188417Sthompsa return (EIO); 2916184610Salfred 2917188417Sthompsa addr += mlen / 2; 2918188417Sthompsa fw += mlen; 2919188417Sthompsa size -= mlen; 2920184610Salfred } 2921184610Salfred 2922188417Sthompsa /* check whether the upload succeeded */ 2923188417Sthompsa req.bmRequestType = UT_READ_VENDOR_DEVICE; 2924188417Sthompsa req.bRequest = ZYD_DOWNLOADSTS; 2925188417Sthompsa USETW(req.wValue, 0); 2926188417Sthompsa USETW(req.wIndex, 0); 2927188417Sthompsa USETW(req.wLength, sizeof(stat)); 2928188419Sthompsa if (zyd_do_request(sc, &req, &stat) != 0) 2929188417Sthompsa return (EIO); 2930184610Salfred 2931188417Sthompsa sc->sc_flags |= ZYD_FLAG_FWLOADED; 2932184610Salfred 2933188417Sthompsa return (stat & 0x80) ? (EIO) : (0); 2934184610Salfred} 2935184610Salfred 2936184610Salfredstatic void 2937188417Sthompsazyd_newassoc(struct ieee80211_node *ni, int isnew) 2938184610Salfred{ 2939188417Sthompsa struct ieee80211vap *vap = ni->ni_vap; 2940184610Salfred 2941188417Sthompsa ieee80211_amrr_node_init(&ZYD_VAP(vap)->amrr, &ZYD_NODE(ni)->amn, ni); 2942184610Salfred} 2943184610Salfred 2944188417Sthompsastatic void 2945188417Sthompsazyd_scan_start(struct ieee80211com *ic) 2946184610Salfred{ 2947191746Sthompsa struct ifnet *ifp = ic->ic_ifp; 2948191746Sthompsa struct zyd_softc *sc = ifp->if_softc; 2949184610Salfred 2950188417Sthompsa ZYD_LOCK(sc); 2951191746Sthompsa /* want broadcast address while scanning */ 2952191746Sthompsa zyd_set_bssid(sc, ifp->if_broadcastaddr); 2953188417Sthompsa ZYD_UNLOCK(sc); 2954184610Salfred} 2955184610Salfred 2956184610Salfredstatic void 2957188417Sthompsazyd_scan_end(struct ieee80211com *ic) 2958184610Salfred{ 2959188417Sthompsa struct zyd_softc *sc = ic->ic_ifp->if_softc; 2960184610Salfred 2961188417Sthompsa ZYD_LOCK(sc); 2962191746Sthompsa /* restore previous bssid */ 2963191746Sthompsa zyd_set_bssid(sc, sc->sc_bssid); 2964188417Sthompsa ZYD_UNLOCK(sc); 2965184610Salfred} 2966184610Salfred 2967184610Salfredstatic void 2968188417Sthompsazyd_set_channel(struct ieee80211com *ic) 2969184610Salfred{ 2970188417Sthompsa struct zyd_softc *sc = ic->ic_ifp->if_softc; 2971184610Salfred 2972188417Sthompsa ZYD_LOCK(sc); 2973191746Sthompsa zyd_set_chan(sc, ic->ic_curchan); 2974188417Sthompsa ZYD_UNLOCK(sc); 2975184610Salfred} 2976184610Salfred 2977188417Sthompsastatic device_method_t zyd_methods[] = { 2978188417Sthompsa /* Device interface */ 2979188417Sthompsa DEVMETHOD(device_probe, zyd_match), 2980188417Sthompsa DEVMETHOD(device_attach, zyd_attach), 2981188417Sthompsa DEVMETHOD(device_detach, zyd_detach), 2982191746Sthompsa 2983188417Sthompsa { 0, 0 } 2984188417Sthompsa}; 2985184610Salfred 2986188417Sthompsastatic driver_t zyd_driver = { 2987188417Sthompsa "zyd", 2988188417Sthompsa zyd_methods, 2989188417Sthompsa sizeof(struct zyd_softc) 2990188417Sthompsa}; 2991184610Salfred 2992188417Sthompsastatic devclass_t zyd_devclass; 2993184610Salfred 2994189275SthompsaDRIVER_MODULE(zyd, uhub, zyd_driver, zyd_devclass, NULL, 0); 2995188942SthompsaMODULE_DEPEND(zyd, usb, 1, 1, 1); 2996188417SthompsaMODULE_DEPEND(zyd, wlan, 1, 1, 1); 2997188417SthompsaMODULE_DEPEND(zyd, wlan_amrr, 1, 1, 1); 2998