if_zyd.c revision 192984
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 192984 2009-05-28 17:36:36Z 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 192984 2009-05-28 17:36:36Z 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 85192502SthompsaSYSCTL_NODE(_hw_usb, OID_AUTO, zyd, CTLFLAG_RW, 0, "USB zyd"); 86192502SthompsaSYSCTL_INT(_hw_usb_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); 159192984Sthompsastatic void zyd_rx_data(struct usb_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 207192984Sthompsastatic const struct usb_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 258192984Sthompsastatic const struct usb_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{ 321192984Sthompsa struct usb_attach_arg *uaa = device_get_ivars(dev); 322184610Salfred 323192499Sthompsa if (uaa->usb_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{ 336192984Sthompsa struct usb_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 424192468Ssam ieee80211_radiotap_attach(ic, 425192468Ssam &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), 426192468Ssam ZYD_TX_RADIOTAP_PRESENT, 427192468Ssam &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), 428192468Ssam ZYD_RX_RADIOTAP_PRESENT); 429184610Salfred 430188417Sthompsa if (bootverbose) 431188417Sthompsa ieee80211_announce(ic); 432184610Salfred 433191746Sthompsa return (0); 434191746Sthompsa 435191746Sthompsadetach: 436191746Sthompsa zyd_detach(dev); 437191746Sthompsa return (ENXIO); /* failure */ 438184610Salfred} 439184610Salfred 440188417Sthompsastatic int 441188417Sthompsazyd_detach(device_t dev) 442184610Salfred{ 443188417Sthompsa struct zyd_softc *sc = device_get_softc(dev); 444188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 445188601Sthompsa struct ieee80211com *ic; 446184610Salfred 447188419Sthompsa /* stop all USB transfers */ 448188417Sthompsa usb2_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER); 449184610Salfred 450188419Sthompsa /* free TX list, if any */ 451188419Sthompsa zyd_unsetup_tx_list(sc); 452188419Sthompsa 453188417Sthompsa if (ifp) { 454188601Sthompsa ic = ifp->if_l2com; 455188417Sthompsa ieee80211_ifdetach(ic); 456188417Sthompsa if_free(ifp); 457184610Salfred } 458188417Sthompsa mtx_destroy(&sc->sc_mtx); 459184610Salfred 460188417Sthompsa return (0); 461184610Salfred} 462184610Salfred 463188417Sthompsastatic struct ieee80211vap * 464188417Sthompsazyd_vap_create(struct ieee80211com *ic, 465188417Sthompsa const char name[IFNAMSIZ], int unit, int opmode, int flags, 466188417Sthompsa const uint8_t bssid[IEEE80211_ADDR_LEN], 467188417Sthompsa const uint8_t mac[IEEE80211_ADDR_LEN]) 468184610Salfred{ 469188417Sthompsa struct zyd_vap *zvp; 470188417Sthompsa struct ieee80211vap *vap; 471184610Salfred 472188417Sthompsa if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ 473188417Sthompsa return (NULL); 474188417Sthompsa zvp = (struct zyd_vap *) malloc(sizeof(struct zyd_vap), 475188417Sthompsa M_80211_VAP, M_NOWAIT | M_ZERO); 476188417Sthompsa if (zvp == NULL) 477188417Sthompsa return (NULL); 478188417Sthompsa vap = &zvp->vap; 479188417Sthompsa /* enable s/w bmiss handling for sta mode */ 480188417Sthompsa ieee80211_vap_setup(ic, vap, name, unit, opmode, 481188417Sthompsa flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); 482184610Salfred 483188417Sthompsa /* override state transition machine */ 484188417Sthompsa zvp->newstate = vap->iv_newstate; 485188417Sthompsa vap->iv_newstate = zyd_newstate; 486184610Salfred 487188417Sthompsa ieee80211_amrr_init(&zvp->amrr, vap, 488188417Sthompsa IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, 489188417Sthompsa IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, 490188417Sthompsa 1000 /* 1 sec */); 491184610Salfred 492188417Sthompsa /* complete setup */ 493188417Sthompsa ieee80211_vap_attach(vap, ieee80211_media_change, 494188417Sthompsa ieee80211_media_status); 495188417Sthompsa ic->ic_opmode = opmode; 496188417Sthompsa return (vap); 497184610Salfred} 498184610Salfred 499184610Salfredstatic void 500188417Sthompsazyd_vap_delete(struct ieee80211vap *vap) 501184610Salfred{ 502188417Sthompsa struct zyd_vap *zvp = ZYD_VAP(vap); 503184610Salfred 504188417Sthompsa ieee80211_amrr_cleanup(&zvp->amrr); 505188417Sthompsa ieee80211_vap_detach(vap); 506188417Sthompsa free(zvp, M_80211_VAP); 507184610Salfred} 508184610Salfred 509184610Salfredstatic void 510188417Sthompsazyd_tx_free(struct zyd_tx_data *data, int txerr) 511184610Salfred{ 512188417Sthompsa struct zyd_softc *sc = data->sc; 513184610Salfred 514188417Sthompsa if (data->m != NULL) { 515188417Sthompsa if (data->m->m_flags & M_TXCB) 516188417Sthompsa ieee80211_process_callback(data->ni, data->m, 517188417Sthompsa txerr ? ETIMEDOUT : 0); 518188417Sthompsa m_freem(data->m); 519188417Sthompsa data->m = NULL; 520188417Sthompsa 521188417Sthompsa ieee80211_free_node(data->ni); 522188417Sthompsa data->ni = NULL; 523184610Salfred } 524188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_free, data, next); 525188417Sthompsa sc->tx_nfree++; 526184610Salfred} 527184610Salfred 528188419Sthompsastatic void 529188419Sthompsazyd_setup_tx_list(struct zyd_softc *sc) 530184610Salfred{ 531188417Sthompsa struct zyd_tx_data *data; 532188417Sthompsa int i; 533184610Salfred 534188417Sthompsa sc->tx_nfree = 0; 535188417Sthompsa STAILQ_INIT(&sc->tx_q); 536188417Sthompsa STAILQ_INIT(&sc->tx_free); 537184610Salfred 538188417Sthompsa for (i = 0; i < ZYD_TX_LIST_CNT; i++) { 539188417Sthompsa data = &sc->tx_data[i]; 540184610Salfred 541188417Sthompsa data->sc = sc; 542188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_free, data, next); 543188417Sthompsa sc->tx_nfree++; 544188417Sthompsa } 545184610Salfred} 546184610Salfred 547184610Salfredstatic void 548188419Sthompsazyd_unsetup_tx_list(struct zyd_softc *sc) 549184610Salfred{ 550188417Sthompsa struct zyd_tx_data *data; 551188417Sthompsa int i; 552184610Salfred 553188419Sthompsa /* make sure any subsequent use of the queues will fail */ 554188419Sthompsa sc->tx_nfree = 0; 555188419Sthompsa STAILQ_INIT(&sc->tx_q); 556188419Sthompsa STAILQ_INIT(&sc->tx_free); 557184610Salfred 558188419Sthompsa /* free up all node references and mbufs */ 559188417Sthompsa for (i = 0; i < ZYD_TX_LIST_CNT; i++) { 560188417Sthompsa data = &sc->tx_data[i]; 561184610Salfred 562188417Sthompsa if (data->m != NULL) { 563188417Sthompsa m_freem(data->m); 564188417Sthompsa data->m = NULL; 565188417Sthompsa } 566188417Sthompsa if (data->ni != NULL) { 567188417Sthompsa ieee80211_free_node(data->ni); 568188417Sthompsa data->ni = NULL; 569188417Sthompsa } 570188417Sthompsa } 571184610Salfred} 572184610Salfred 573188417Sthompsa/* ARGUSED */ 574188417Sthompsastatic struct ieee80211_node * 575188417Sthompsazyd_node_alloc(struct ieee80211vap *vap __unused, 576188417Sthompsa const uint8_t mac[IEEE80211_ADDR_LEN] __unused) 577184610Salfred{ 578188417Sthompsa struct zyd_node *zn; 579184610Salfred 580188417Sthompsa zn = malloc(sizeof(struct zyd_node), M_80211_NODE, M_NOWAIT | M_ZERO); 581188417Sthompsa return (zn != NULL) ? (&zn->ni) : (NULL); 582184610Salfred} 583184610Salfred 584191746Sthompsastatic int 585191746Sthompsazyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 586186730Salfred{ 587188417Sthompsa struct zyd_vap *zvp = ZYD_VAP(vap); 588191746Sthompsa struct ieee80211com *ic = vap->iv_ic; 589191746Sthompsa struct zyd_softc *sc = ic->ic_ifp->if_softc; 590191746Sthompsa struct ieee80211_node *ni; 591188417Sthompsa int error; 592186730Salfred 593191746Sthompsa DPRINTF(sc, ZYD_DEBUG_STATE, "%s: %s -> %s\n", __func__, 594191746Sthompsa ieee80211_state_name[vap->iv_state], 595191746Sthompsa ieee80211_state_name[nstate]); 596191746Sthompsa 597191746Sthompsa IEEE80211_UNLOCK(ic); 598191746Sthompsa ZYD_LOCK(sc); 599191746Sthompsa switch (nstate) { 600188417Sthompsa case IEEE80211_S_AUTH: 601188417Sthompsa zyd_set_chan(sc, ic->ic_curchan); 602188417Sthompsa break; 603188417Sthompsa case IEEE80211_S_RUN: 604191746Sthompsa ni = vap->iv_bss; 605188417Sthompsa if (vap->iv_opmode == IEEE80211_M_MONITOR) 606188417Sthompsa break; 607184610Salfred 608188417Sthompsa /* turn link LED on */ 609188417Sthompsa error = zyd_set_led(sc, ZYD_LED1, 1); 610188417Sthompsa if (error != 0) 611191746Sthompsa break; 612191746Sthompsa 613188417Sthompsa /* make data LED blink upon Tx */ 614188417Sthompsa zyd_write32_m(sc, sc->sc_fwbase + ZYD_FW_LINK_STATUS, 1); 615191746Sthompsa 616188417Sthompsa IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); 617188417Sthompsa zyd_set_bssid(sc, sc->sc_bssid); 618188417Sthompsa break; 619188417Sthompsa default: 620188417Sthompsa break; 621184610Salfred } 622188417Sthompsafail: 623188417Sthompsa ZYD_UNLOCK(sc); 624188417Sthompsa IEEE80211_LOCK(ic); 625191746Sthompsa return (zvp->newstate(vap, nstate, arg)); 626184610Salfred} 627184610Salfred 628188417Sthompsa/* 629188417Sthompsa * Callback handler for interrupt transfer 630188417Sthompsa */ 631184610Salfredstatic void 632192984Sthompsazyd_intr_read_callback(struct usb_xfer *xfer) 633184610Salfred{ 634184610Salfred struct zyd_softc *sc = xfer->priv_sc; 635184610Salfred struct ifnet *ifp = sc->sc_ifp; 636184610Salfred struct ieee80211com *ic = ifp->if_l2com; 637188417Sthompsa struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 638184610Salfred struct ieee80211_node *ni; 639188417Sthompsa struct zyd_cmd *cmd = &sc->sc_ibuf; 640188417Sthompsa int datalen; 641184610Salfred 642184610Salfred switch (USB_GET_STATE(xfer)) { 643184610Salfred case USB_ST_TRANSFERRED: 644188417Sthompsa usb2_copy_out(xfer->frbuffers, 0, cmd, sizeof(*cmd)); 645184610Salfred 646188417Sthompsa switch (le16toh(cmd->code)) { 647188417Sthompsa case ZYD_NOTIF_RETRYSTATUS: 648188417Sthompsa { 649188417Sthompsa struct zyd_notif_retry *retry = 650188417Sthompsa (struct zyd_notif_retry *)cmd->data; 651184610Salfred 652188417Sthompsa DPRINTF(sc, ZYD_DEBUG_TX_PROC, 653188417Sthompsa "retry intr: rate=0x%x addr=%s count=%d (0x%x)\n", 654188417Sthompsa le16toh(retry->rate), ether_sprintf(retry->macaddr), 655188417Sthompsa le16toh(retry->count)&0xff, le16toh(retry->count)); 656184610Salfred 657188417Sthompsa /* 658188417Sthompsa * Find the node to which the packet was sent and 659188417Sthompsa * update its retry statistics. In BSS mode, this node 660188417Sthompsa * is the AP we're associated to so no lookup is 661188417Sthompsa * actually needed. 662188417Sthompsa */ 663188417Sthompsa ni = ieee80211_find_txnode(vap, retry->macaddr); 664188417Sthompsa if (ni != NULL) { 665188417Sthompsa ieee80211_amrr_tx_complete(&ZYD_NODE(ni)->amn, 666188417Sthompsa IEEE80211_AMRR_FAILURE, 1); 667188417Sthompsa ieee80211_free_node(ni); 668188417Sthompsa } 669188417Sthompsa if (le16toh(retry->count) & 0x100) 670188417Sthompsa ifp->if_oerrors++; /* too many retries */ 671188417Sthompsa break; 672188417Sthompsa } 673188417Sthompsa case ZYD_NOTIF_IORD: 674188417Sthompsa { 675188417Sthompsa struct zyd_rq *rqp; 676184610Salfred 677188417Sthompsa if (le16toh(*(uint16_t *)cmd->data) == ZYD_CR_INTERRUPT) 678188417Sthompsa break; /* HMAC interrupt */ 679184610Salfred 680188417Sthompsa datalen = xfer->actlen - sizeof(cmd->code); 681188417Sthompsa datalen -= 2; /* XXX: padding? */ 682184610Salfred 683188417Sthompsa STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) { 684188417Sthompsa int i, cnt; 685184610Salfred 686188417Sthompsa if (rqp->olen != datalen) 687188417Sthompsa continue; 688188417Sthompsa cnt = rqp->olen / sizeof(struct zyd_pair); 689188417Sthompsa for (i = 0; i < cnt; i++) { 690188417Sthompsa if (*(((const uint16_t *)rqp->idata) + i) != 691188417Sthompsa (((struct zyd_pair *)cmd->data) + i)->reg) 692188417Sthompsa break; 693184610Salfred } 694188417Sthompsa if (i != cnt) 695188417Sthompsa continue; 696188417Sthompsa /* copy answer into caller-supplied buffer */ 697188417Sthompsa bcopy(cmd->data, rqp->odata, rqp->olen); 698188417Sthompsa DPRINTF(sc, ZYD_DEBUG_CMD, 699188417Sthompsa "command %p complete, data = %*D \n", 700188417Sthompsa rqp, rqp->olen, rqp->odata, ":"); 701188417Sthompsa wakeup(rqp); /* wakeup caller */ 702188417Sthompsa break; 703184610Salfred } 704188417Sthompsa if (rqp == NULL) { 705188417Sthompsa device_printf(sc->sc_dev, 706188417Sthompsa "unexpected IORD notification %*D\n", 707188417Sthompsa datalen, cmd->data, ":"); 708188417Sthompsa } 709188417Sthompsa break; 710184610Salfred } 711188417Sthompsa default: 712188417Sthompsa device_printf(sc->sc_dev, "unknown notification %x\n", 713188417Sthompsa le16toh(cmd->code)); 714188417Sthompsa } 715184610Salfred 716188417Sthompsa /* FALLTHROUGH */ 717184610Salfred case USB_ST_SETUP: 718184610Salfredtr_setup: 719188417Sthompsa xfer->frlengths[0] = xfer->max_data_length; 720188417Sthompsa usb2_start_hardware(xfer); 721188417Sthompsa break; 722184610Salfred 723188417Sthompsa default: /* Error */ 724188417Sthompsa DPRINTF(sc, ZYD_DEBUG_CMD, "error = %s\n", 725188417Sthompsa usb2_errstr(xfer->error)); 726188417Sthompsa 727188417Sthompsa if (xfer->error != USB_ERR_CANCELLED) { 728188417Sthompsa /* try to clear stall first */ 729188417Sthompsa xfer->flags.stall_pipe = 1; 730188417Sthompsa goto tr_setup; 731184610Salfred } 732188417Sthompsa break; 733188417Sthompsa } 734188417Sthompsa} 735184610Salfred 736188417Sthompsastatic void 737192984Sthompsazyd_intr_write_callback(struct usb_xfer *xfer) 738188417Sthompsa{ 739188417Sthompsa struct zyd_softc *sc = xfer->priv_sc; 740188417Sthompsa struct zyd_rq *rqp; 741184610Salfred 742188417Sthompsa switch (USB_GET_STATE(xfer)) { 743188417Sthompsa case USB_ST_TRANSFERRED: 744189452Sthompsa DPRINTF(sc, ZYD_DEBUG_CMD, "command %p transferred\n", 745189452Sthompsa xfer->priv_fifo); 746189452Sthompsa STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) { 747189452Sthompsa /* Ensure the cached rq pointer is still valid */ 748189452Sthompsa if (rqp == xfer->priv_fifo && 749189452Sthompsa (rqp->flags & ZYD_CMD_FLAG_READ) == 0) 750189452Sthompsa wakeup(rqp); /* wakeup caller */ 751189452Sthompsa } 752184610Salfred 753188417Sthompsa /* FALLTHROUGH */ 754188417Sthompsa case USB_ST_SETUP: 755188417Sthompsatr_setup: 756188417Sthompsa STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) { 757188417Sthompsa if (rqp->flags & ZYD_CMD_FLAG_SENT) 758188417Sthompsa continue; 759184610Salfred 760188417Sthompsa usb2_copy_in(xfer->frbuffers, 0, rqp->cmd, rqp->ilen); 761184610Salfred 762188417Sthompsa xfer->frlengths[0] = rqp->ilen; 763188417Sthompsa xfer->priv_fifo = rqp; 764188417Sthompsa rqp->flags |= ZYD_CMD_FLAG_SENT; 765188417Sthompsa usb2_start_hardware(xfer); 766188417Sthompsa break; 767184610Salfred } 768184610Salfred break; 769184610Salfred 770184610Salfred default: /* Error */ 771188417Sthompsa DPRINTF(sc, ZYD_DEBUG_ANY, "error = %s\n", 772188417Sthompsa usb2_errstr(xfer->error)); 773184610Salfred 774184610Salfred if (xfer->error != USB_ERR_CANCELLED) { 775184610Salfred /* try to clear stall first */ 776188417Sthompsa xfer->flags.stall_pipe = 1; 777188417Sthompsa goto tr_setup; 778184610Salfred } 779184610Salfred break; 780184610Salfred } 781184610Salfred} 782184610Salfred 783188417Sthompsastatic int 784188417Sthompsazyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen, 785188601Sthompsa void *odata, int olen, int flags) 786184610Salfred{ 787188417Sthompsa struct zyd_cmd cmd; 788188417Sthompsa struct zyd_rq rq; 789188417Sthompsa int error; 790184610Salfred 791188417Sthompsa if (ilen > sizeof(cmd.data)) 792188417Sthompsa return (EINVAL); 793188419Sthompsa 794188417Sthompsa cmd.code = htole16(code); 795188417Sthompsa bcopy(idata, cmd.data, ilen); 796188417Sthompsa DPRINTF(sc, ZYD_DEBUG_CMD, "sending cmd %p = %*D\n", 797188417Sthompsa &rq, ilen, idata, ":"); 798184610Salfred 799188417Sthompsa rq.cmd = &cmd; 800188417Sthompsa rq.idata = idata; 801188417Sthompsa rq.odata = odata; 802188417Sthompsa rq.ilen = sizeof(uint16_t) + ilen; 803188417Sthompsa rq.olen = olen; 804188417Sthompsa rq.flags = flags; 805188417Sthompsa STAILQ_INSERT_TAIL(&sc->sc_rqh, &rq, rq); 806188417Sthompsa usb2_transfer_start(sc->sc_xfer[ZYD_INTR_RD]); 807188417Sthompsa usb2_transfer_start(sc->sc_xfer[ZYD_INTR_WR]); 808184610Salfred 809188417Sthompsa /* wait at most one second for command reply */ 810188417Sthompsa error = mtx_sleep(&rq, &sc->sc_mtx, 0 , "zydcmd", hz); 811188417Sthompsa if (error) 812188417Sthompsa device_printf(sc->sc_dev, "command timeout\n"); 813188417Sthompsa STAILQ_REMOVE(&sc->sc_rqh, &rq, zyd_rq, rq); 814188417Sthompsa DPRINTF(sc, ZYD_DEBUG_CMD, "finsihed cmd %p, error = %d \n", 815188417Sthompsa &rq, error); 816184610Salfred 817188417Sthompsa return (error); 818184610Salfred} 819184610Salfred 820184610Salfredstatic int 821188417Sthompsazyd_read16(struct zyd_softc *sc, uint16_t reg, uint16_t *val) 822184610Salfred{ 823188417Sthompsa struct zyd_pair tmp; 824188417Sthompsa int error; 825184610Salfred 826188417Sthompsa reg = htole16(reg); 827188417Sthompsa error = zyd_cmd(sc, ZYD_CMD_IORD, ®, sizeof(reg), &tmp, sizeof(tmp), 828188417Sthompsa ZYD_CMD_FLAG_READ); 829188417Sthompsa if (error == 0) 830188417Sthompsa *val = le16toh(tmp.val); 831188417Sthompsa return (error); 832184610Salfred} 833184610Salfred 834184610Salfredstatic int 835188417Sthompsazyd_read32(struct zyd_softc *sc, uint16_t reg, uint32_t *val) 836184610Salfred{ 837188417Sthompsa struct zyd_pair tmp[2]; 838188417Sthompsa uint16_t regs[2]; 839184610Salfred int error; 840184610Salfred 841188417Sthompsa regs[0] = htole16(ZYD_REG32_HI(reg)); 842188417Sthompsa regs[1] = htole16(ZYD_REG32_LO(reg)); 843188417Sthompsa error = zyd_cmd(sc, ZYD_CMD_IORD, regs, sizeof(regs), tmp, sizeof(tmp), 844188417Sthompsa ZYD_CMD_FLAG_READ); 845188417Sthompsa if (error == 0) 846188417Sthompsa *val = le16toh(tmp[0].val) << 16 | le16toh(tmp[1].val); 847188417Sthompsa return (error); 848188417Sthompsa} 849184610Salfred 850188417Sthompsastatic int 851188417Sthompsazyd_write16(struct zyd_softc *sc, uint16_t reg, uint16_t val) 852188417Sthompsa{ 853188417Sthompsa struct zyd_pair pair; 854184610Salfred 855188417Sthompsa pair.reg = htole16(reg); 856188417Sthompsa pair.val = htole16(val); 857184610Salfred 858188417Sthompsa return zyd_cmd(sc, ZYD_CMD_IOWR, &pair, sizeof(pair), NULL, 0, 0); 859188417Sthompsa} 860184610Salfred 861188417Sthompsastatic int 862188417Sthompsazyd_write32(struct zyd_softc *sc, uint16_t reg, uint32_t val) 863188417Sthompsa{ 864188417Sthompsa struct zyd_pair pair[2]; 865184610Salfred 866188417Sthompsa pair[0].reg = htole16(ZYD_REG32_HI(reg)); 867188417Sthompsa pair[0].val = htole16(val >> 16); 868188417Sthompsa pair[1].reg = htole16(ZYD_REG32_LO(reg)); 869188417Sthompsa pair[1].val = htole16(val & 0xffff); 870184610Salfred 871188417Sthompsa return zyd_cmd(sc, ZYD_CMD_IOWR, pair, sizeof(pair), NULL, 0, 0); 872184610Salfred} 873184610Salfred 874188417Sthompsastatic int 875188417Sthompsazyd_rfwrite(struct zyd_softc *sc, uint32_t val) 876184610Salfred{ 877188417Sthompsa struct zyd_rf *rf = &sc->sc_rf; 878188417Sthompsa struct zyd_rfwrite_cmd req; 879188417Sthompsa uint16_t cr203; 880188417Sthompsa int error, i; 881184610Salfred 882188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &cr203); 883188417Sthompsa cr203 &= ~(ZYD_RF_IF_LE | ZYD_RF_CLK | ZYD_RF_DATA); 884188417Sthompsa 885188417Sthompsa req.code = htole16(2); 886188417Sthompsa req.width = htole16(rf->width); 887188417Sthompsa for (i = 0; i < rf->width; i++) { 888188417Sthompsa req.bit[i] = htole16(cr203); 889188417Sthompsa if (val & (1 << (rf->width - 1 - i))) 890188417Sthompsa req.bit[i] |= htole16(ZYD_RF_DATA); 891188417Sthompsa } 892188417Sthompsa error = zyd_cmd(sc, ZYD_CMD_RFCFG, &req, 4 + 2 * rf->width, NULL, 0, 0); 893188417Sthompsafail: 894188417Sthompsa return (error); 895184610Salfred} 896184610Salfred 897188417Sthompsastatic int 898188417Sthompsazyd_rfwrite_cr(struct zyd_softc *sc, uint32_t val) 899184610Salfred{ 900188417Sthompsa int error; 901184610Salfred 902188417Sthompsa zyd_write16_m(sc, ZYD_CR244, (val >> 16) & 0xff); 903188417Sthompsa zyd_write16_m(sc, ZYD_CR243, (val >> 8) & 0xff); 904188417Sthompsa zyd_write16_m(sc, ZYD_CR242, (val >> 0) & 0xff); 905188417Sthompsafail: 906188417Sthompsa return (error); 907184610Salfred} 908184610Salfred 909188417Sthompsastatic int 910188417Sthompsazyd_lock_phy(struct zyd_softc *sc) 911184610Salfred{ 912188417Sthompsa int error; 913188417Sthompsa uint32_t tmp; 914186730Salfred 915188417Sthompsa zyd_read32_m(sc, ZYD_MAC_MISC, &tmp); 916188417Sthompsa tmp &= ~ZYD_UNLOCK_PHY_REGS; 917188417Sthompsa zyd_write32_m(sc, ZYD_MAC_MISC, tmp); 918188417Sthompsafail: 919188417Sthompsa return (error); 920184610Salfred} 921184610Salfred 922188417Sthompsastatic int 923188417Sthompsazyd_unlock_phy(struct zyd_softc *sc) 924184610Salfred{ 925188417Sthompsa int error; 926188417Sthompsa uint32_t tmp; 927184610Salfred 928188417Sthompsa zyd_read32_m(sc, ZYD_MAC_MISC, &tmp); 929188417Sthompsa tmp |= ZYD_UNLOCK_PHY_REGS; 930188417Sthompsa zyd_write32_m(sc, ZYD_MAC_MISC, tmp); 931188417Sthompsafail: 932188417Sthompsa return (error); 933184610Salfred} 934184610Salfred 935184610Salfred/* 936188417Sthompsa * RFMD RF methods. 937184610Salfred */ 938188417Sthompsastatic int 939188417Sthompsazyd_rfmd_init(struct zyd_rf *rf) 940184610Salfred{ 941188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 942188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 943184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_RFMD_PHY; 944184610Salfred static const uint32_t rfini[] = ZYD_RFMD_RF; 945188417Sthompsa int i, error; 946184610Salfred 947184610Salfred /* init RF-dependent PHY registers */ 948188417Sthompsa for (i = 0; i < N(phyini); i++) { 949188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 950184610Salfred } 951184610Salfred 952184610Salfred /* init RFMD radio */ 953188417Sthompsa for (i = 0; i < N(rfini); i++) { 954188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 955188417Sthompsa return (error); 956184610Salfred } 957188417Sthompsafail: 958188417Sthompsa return (error); 959188417Sthompsa#undef N 960184610Salfred} 961184610Salfred 962188417Sthompsastatic int 963188417Sthompsazyd_rfmd_switch_radio(struct zyd_rf *rf, int on) 964184610Salfred{ 965188417Sthompsa int error; 966188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 967188417Sthompsa 968188417Sthompsa zyd_write16_m(sc, ZYD_CR10, on ? 0x89 : 0x15); 969188417Sthompsa zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x81); 970188417Sthompsafail: 971188417Sthompsa return (error); 972184610Salfred} 973184610Salfred 974188417Sthompsastatic int 975188417Sthompsazyd_rfmd_set_channel(struct zyd_rf *rf, uint8_t chan) 976184610Salfred{ 977188417Sthompsa int error; 978188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 979184610Salfred static const struct { 980188417Sthompsa uint32_t r1, r2; 981188417Sthompsa } rfprog[] = ZYD_RFMD_CHANTABLE; 982184610Salfred 983188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r1); 984188417Sthompsa if (error != 0) 985188417Sthompsa goto fail; 986188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r2); 987188417Sthompsa if (error != 0) 988188417Sthompsa goto fail; 989184610Salfred 990188417Sthompsafail: 991188417Sthompsa return (error); 992184610Salfred} 993184610Salfred 994184610Salfred/* 995188417Sthompsa * AL2230 RF methods. 996184610Salfred */ 997188417Sthompsastatic int 998188417Sthompsazyd_al2230_init(struct zyd_rf *rf) 999184610Salfred{ 1000188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1001188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1002184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY; 1003186730Salfred static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT; 1004186730Salfred static const struct zyd_phy_pair phypll[] = { 1005188417Sthompsa { ZYD_CR251, 0x2f }, { ZYD_CR251, 0x3f }, 1006188417Sthompsa { ZYD_CR138, 0x28 }, { ZYD_CR203, 0x06 } 1007186730Salfred }; 1008186730Salfred static const uint32_t rfini1[] = ZYD_AL2230_RF_PART1; 1009186730Salfred static const uint32_t rfini2[] = ZYD_AL2230_RF_PART2; 1010186730Salfred static const uint32_t rfini3[] = ZYD_AL2230_RF_PART3; 1011188417Sthompsa int i, error; 1012184610Salfred 1013184610Salfred /* init RF-dependent PHY registers */ 1014188417Sthompsa for (i = 0; i < N(phyini); i++) 1015188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1016186730Salfred 1017188417Sthompsa if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) { 1018188417Sthompsa for (i = 0; i < N(phy2230s); i++) 1019188417Sthompsa zyd_write16_m(sc, phy2230s[i].reg, phy2230s[i].val); 1020184610Salfred } 1021188417Sthompsa 1022186730Salfred /* init AL2230 radio */ 1023188417Sthompsa for (i = 0; i < N(rfini1); i++) { 1024188417Sthompsa error = zyd_rfwrite(sc, rfini1[i]); 1025188417Sthompsa if (error != 0) 1026188417Sthompsa goto fail; 1027188417Sthompsa } 1028184610Salfred 1029188417Sthompsa if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) 1030188417Sthompsa error = zyd_rfwrite(sc, 0x000824); 1031186730Salfred else 1032188417Sthompsa error = zyd_rfwrite(sc, 0x0005a4); 1033188417Sthompsa if (error != 0) 1034188417Sthompsa goto fail; 1035186730Salfred 1036188417Sthompsa for (i = 0; i < N(rfini2); i++) { 1037188417Sthompsa error = zyd_rfwrite(sc, rfini2[i]); 1038188417Sthompsa if (error != 0) 1039188417Sthompsa goto fail; 1040188417Sthompsa } 1041186730Salfred 1042188417Sthompsa for (i = 0; i < N(phypll); i++) 1043188417Sthompsa zyd_write16_m(sc, phypll[i].reg, phypll[i].val); 1044186730Salfred 1045188417Sthompsa for (i = 0; i < N(rfini3); i++) { 1046188417Sthompsa error = zyd_rfwrite(sc, rfini3[i]); 1047188417Sthompsa if (error != 0) 1048188417Sthompsa goto fail; 1049188417Sthompsa } 1050188417Sthompsafail: 1051188417Sthompsa return (error); 1052188417Sthompsa#undef N 1053184610Salfred} 1054184610Salfred 1055188417Sthompsastatic int 1056188417Sthompsazyd_al2230_fini(struct zyd_rf *rf) 1057186730Salfred{ 1058188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1059188417Sthompsa int error, i; 1060188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1061186730Salfred static const struct zyd_phy_pair phy[] = ZYD_AL2230_PHY_FINI_PART1; 1062186730Salfred 1063188417Sthompsa for (i = 0; i < N(phy); i++) 1064188417Sthompsa zyd_write16_m(sc, phy[i].reg, phy[i].val); 1065186730Salfred 1066186730Salfred if (sc->sc_newphy != 0) 1067188417Sthompsa zyd_write16_m(sc, ZYD_CR9, 0xe1); 1068188417Sthompsa 1069188417Sthompsa zyd_write16_m(sc, ZYD_CR203, 0x6); 1070188417Sthompsafail: 1071188417Sthompsa return (error); 1072188417Sthompsa#undef N 1073186730Salfred} 1074186730Salfred 1075188417Sthompsastatic int 1076188417Sthompsazyd_al2230_init_b(struct zyd_rf *rf) 1077184610Salfred{ 1078188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1079188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1080186730Salfred static const struct zyd_phy_pair phy1[] = ZYD_AL2230_PHY_PART1; 1081186730Salfred static const struct zyd_phy_pair phy2[] = ZYD_AL2230_PHY_PART2; 1082186730Salfred static const struct zyd_phy_pair phy3[] = ZYD_AL2230_PHY_PART3; 1083186730Salfred static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT; 1084188417Sthompsa static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY_B; 1085186730Salfred static const uint32_t rfini_part1[] = ZYD_AL2230_RF_B_PART1; 1086186730Salfred static const uint32_t rfini_part2[] = ZYD_AL2230_RF_B_PART2; 1087186730Salfred static const uint32_t rfini_part3[] = ZYD_AL2230_RF_B_PART3; 1088186730Salfred static const uint32_t zyd_al2230_chtable[][3] = ZYD_AL2230_CHANTABLE; 1089188417Sthompsa int i, error; 1090184610Salfred 1091188417Sthompsa for (i = 0; i < N(phy1); i++) 1092188417Sthompsa zyd_write16_m(sc, phy1[i].reg, phy1[i].val); 1093186730Salfred 1094184610Salfred /* init RF-dependent PHY registers */ 1095188417Sthompsa for (i = 0; i < N(phyini); i++) 1096188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1097184610Salfred 1098188417Sthompsa if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) { 1099188417Sthompsa for (i = 0; i < N(phy2230s); i++) 1100188417Sthompsa zyd_write16_m(sc, phy2230s[i].reg, phy2230s[i].val); 1101188417Sthompsa } 1102186730Salfred 1103188417Sthompsa for (i = 0; i < 3; i++) { 1104188417Sthompsa error = zyd_rfwrite_cr(sc, zyd_al2230_chtable[0][i]); 1105188417Sthompsa if (error != 0) 1106188417Sthompsa return (error); 1107188417Sthompsa } 1108186730Salfred 1109188417Sthompsa for (i = 0; i < N(rfini_part1); i++) { 1110188417Sthompsa error = zyd_rfwrite_cr(sc, rfini_part1[i]); 1111188417Sthompsa if (error != 0) 1112188417Sthompsa return (error); 1113188417Sthompsa } 1114186730Salfred 1115188417Sthompsa if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) 1116188417Sthompsa error = zyd_rfwrite(sc, 0x241000); 1117186730Salfred else 1118188417Sthompsa error = zyd_rfwrite(sc, 0x25a000); 1119188417Sthompsa if (error != 0) 1120188417Sthompsa goto fail; 1121186730Salfred 1122188417Sthompsa for (i = 0; i < N(rfini_part2); i++) { 1123188417Sthompsa error = zyd_rfwrite_cr(sc, rfini_part2[i]); 1124188417Sthompsa if (error != 0) 1125188417Sthompsa return (error); 1126188417Sthompsa } 1127186730Salfred 1128188417Sthompsa for (i = 0; i < N(phy2); i++) 1129188417Sthompsa zyd_write16_m(sc, phy2[i].reg, phy2[i].val); 1130186730Salfred 1131188417Sthompsa for (i = 0; i < N(rfini_part3); i++) { 1132188417Sthompsa error = zyd_rfwrite_cr(sc, rfini_part3[i]); 1133188417Sthompsa if (error != 0) 1134188417Sthompsa return (error); 1135188417Sthompsa } 1136186730Salfred 1137188417Sthompsa for (i = 0; i < N(phy3); i++) 1138188417Sthompsa zyd_write16_m(sc, phy3[i].reg, phy3[i].val); 1139186730Salfred 1140188417Sthompsa error = zyd_al2230_fini(rf); 1141188417Sthompsafail: 1142188417Sthompsa return (error); 1143188417Sthompsa#undef N 1144184610Salfred} 1145184610Salfred 1146188417Sthompsastatic int 1147188417Sthompsazyd_al2230_switch_radio(struct zyd_rf *rf, int on) 1148184610Salfred{ 1149188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1150188417Sthompsa int error, on251 = (sc->sc_macrev == ZYD_ZD1211) ? 0x3f : 0x7f; 1151188417Sthompsa 1152188417Sthompsa zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x04); 1153188417Sthompsa zyd_write16_m(sc, ZYD_CR251, on ? on251 : 0x2f); 1154188417Sthompsafail: 1155188417Sthompsa return (error); 1156188417Sthompsa} 1157188417Sthompsa 1158188417Sthompsastatic int 1159188417Sthompsazyd_al2230_set_channel(struct zyd_rf *rf, uint8_t chan) 1160188417Sthompsa{ 1161188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1162188417Sthompsa int error, i; 1163188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1164186730Salfred static const struct zyd_phy_pair phy1[] = { 1165188417Sthompsa { ZYD_CR138, 0x28 }, { ZYD_CR203, 0x06 }, 1166186730Salfred }; 1167184610Salfred static const struct { 1168188417Sthompsa uint32_t r1, r2, r3; 1169188417Sthompsa } rfprog[] = ZYD_AL2230_CHANTABLE; 1170184610Salfred 1171188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r1); 1172188417Sthompsa if (error != 0) 1173188417Sthompsa goto fail; 1174188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r2); 1175188417Sthompsa if (error != 0) 1176188417Sthompsa goto fail; 1177188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r3); 1178188417Sthompsa if (error != 0) 1179188417Sthompsa goto fail; 1180184610Salfred 1181188417Sthompsa for (i = 0; i < N(phy1); i++) 1182188417Sthompsa zyd_write16_m(sc, phy1[i].reg, phy1[i].val); 1183188417Sthompsafail: 1184188417Sthompsa return (error); 1185188417Sthompsa#undef N 1186184610Salfred} 1187184610Salfred 1188188417Sthompsastatic int 1189188417Sthompsazyd_al2230_set_channel_b(struct zyd_rf *rf, uint8_t chan) 1190186730Salfred{ 1191188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1192188417Sthompsa int error, i; 1193188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1194186730Salfred static const struct zyd_phy_pair phy1[] = ZYD_AL2230_PHY_PART1; 1195186730Salfred static const struct { 1196188417Sthompsa uint32_t r1, r2, r3; 1197188417Sthompsa } rfprog[] = ZYD_AL2230_CHANTABLE_B; 1198186730Salfred 1199188417Sthompsa for (i = 0; i < N(phy1); i++) 1200188417Sthompsa zyd_write16_m(sc, phy1[i].reg, phy1[i].val); 1201186730Salfred 1202188417Sthompsa error = zyd_rfwrite_cr(sc, rfprog[chan - 1].r1); 1203188417Sthompsa if (error != 0) 1204188417Sthompsa goto fail; 1205188417Sthompsa error = zyd_rfwrite_cr(sc, rfprog[chan - 1].r2); 1206188417Sthompsa if (error != 0) 1207188417Sthompsa goto fail; 1208188417Sthompsa error = zyd_rfwrite_cr(sc, rfprog[chan - 1].r3); 1209188417Sthompsa if (error != 0) 1210188417Sthompsa goto fail; 1211188417Sthompsa error = zyd_al2230_fini(rf); 1212188417Sthompsafail: 1213188417Sthompsa return (error); 1214188417Sthompsa#undef N 1215186730Salfred} 1216186730Salfred 1217186730Salfred#define ZYD_AL2230_PHY_BANDEDGE6 \ 1218186730Salfred{ \ 1219188417Sthompsa { ZYD_CR128, 0x14 }, { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, \ 1220186730Salfred { ZYD_CR47, 0x1e } \ 1221186730Salfred} 1222186730Salfred 1223188417Sthompsastatic int 1224188417Sthompsazyd_al2230_bandedge6(struct zyd_rf *rf, struct ieee80211_channel *c) 1225186730Salfred{ 1226188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1227188417Sthompsa int error = 0, i; 1228188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1229188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 1230188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 1231186730Salfred struct zyd_phy_pair r[] = ZYD_AL2230_PHY_BANDEDGE6; 1232188601Sthompsa int chan = ieee80211_chan2ieee(ic, c); 1233186730Salfred 1234188417Sthompsa if (chan == 1 || chan == 11) 1235186730Salfred r[0].val = 0x12; 1236188417Sthompsa 1237188417Sthompsa for (i = 0; i < N(r); i++) 1238188417Sthompsa zyd_write16_m(sc, r[i].reg, r[i].val); 1239188417Sthompsafail: 1240188417Sthompsa return (error); 1241188417Sthompsa#undef N 1242186730Salfred} 1243186730Salfred 1244184610Salfred/* 1245184610Salfred * AL7230B RF methods. 1246184610Salfred */ 1247188417Sthompsastatic int 1248188417Sthompsazyd_al7230B_init(struct zyd_rf *rf) 1249184610Salfred{ 1250188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1251188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1252184610Salfred static const struct zyd_phy_pair phyini_1[] = ZYD_AL7230B_PHY_1; 1253184610Salfred static const struct zyd_phy_pair phyini_2[] = ZYD_AL7230B_PHY_2; 1254184610Salfred static const struct zyd_phy_pair phyini_3[] = ZYD_AL7230B_PHY_3; 1255184610Salfred static const uint32_t rfini_1[] = ZYD_AL7230B_RF_1; 1256184610Salfred static const uint32_t rfini_2[] = ZYD_AL7230B_RF_2; 1257188417Sthompsa int i, error; 1258184610Salfred 1259184610Salfred /* for AL7230B, PHY and RF need to be initialized in "phases" */ 1260184610Salfred 1261184610Salfred /* init RF-dependent PHY registers, part one */ 1262188417Sthompsa for (i = 0; i < N(phyini_1); i++) 1263188417Sthompsa zyd_write16_m(sc, phyini_1[i].reg, phyini_1[i].val); 1264188417Sthompsa 1265184610Salfred /* init AL7230B radio, part one */ 1266188417Sthompsa for (i = 0; i < N(rfini_1); i++) { 1267188417Sthompsa if ((error = zyd_rfwrite(sc, rfini_1[i])) != 0) 1268188417Sthompsa return (error); 1269184610Salfred } 1270184610Salfred /* init RF-dependent PHY registers, part two */ 1271188417Sthompsa for (i = 0; i < N(phyini_2); i++) 1272188417Sthompsa zyd_write16_m(sc, phyini_2[i].reg, phyini_2[i].val); 1273188417Sthompsa 1274184610Salfred /* init AL7230B radio, part two */ 1275188417Sthompsa for (i = 0; i < N(rfini_2); i++) { 1276188417Sthompsa if ((error = zyd_rfwrite(sc, rfini_2[i])) != 0) 1277188417Sthompsa return (error); 1278184610Salfred } 1279184610Salfred /* init RF-dependent PHY registers, part three */ 1280188417Sthompsa for (i = 0; i < N(phyini_3); i++) 1281188417Sthompsa zyd_write16_m(sc, phyini_3[i].reg, phyini_3[i].val); 1282188417Sthompsafail: 1283188417Sthompsa return (error); 1284188417Sthompsa#undef N 1285184610Salfred} 1286184610Salfred 1287188417Sthompsastatic int 1288188417Sthompsazyd_al7230B_switch_radio(struct zyd_rf *rf, int on) 1289184610Salfred{ 1290188417Sthompsa int error; 1291188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1292188417Sthompsa 1293188417Sthompsa zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x04); 1294188417Sthompsa zyd_write16_m(sc, ZYD_CR251, on ? 0x3f : 0x2f); 1295188417Sthompsafail: 1296188417Sthompsa return (error); 1297188417Sthompsa} 1298188417Sthompsa 1299188417Sthompsastatic int 1300188417Sthompsazyd_al7230B_set_channel(struct zyd_rf *rf, uint8_t chan) 1301188417Sthompsa{ 1302188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1303188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1304184610Salfred static const struct { 1305188417Sthompsa uint32_t r1, r2; 1306188417Sthompsa } rfprog[] = ZYD_AL7230B_CHANTABLE; 1307184610Salfred static const uint32_t rfsc[] = ZYD_AL7230B_RF_SETCHANNEL; 1308188417Sthompsa int i, error; 1309184610Salfred 1310188417Sthompsa zyd_write16_m(sc, ZYD_CR240, 0x57); 1311188417Sthompsa zyd_write16_m(sc, ZYD_CR251, 0x2f); 1312184610Salfred 1313188417Sthompsa for (i = 0; i < N(rfsc); i++) { 1314188417Sthompsa if ((error = zyd_rfwrite(sc, rfsc[i])) != 0) 1315188417Sthompsa return (error); 1316184610Salfred } 1317184610Salfred 1318188417Sthompsa zyd_write16_m(sc, ZYD_CR128, 0x14); 1319188417Sthompsa zyd_write16_m(sc, ZYD_CR129, 0x12); 1320188417Sthompsa zyd_write16_m(sc, ZYD_CR130, 0x10); 1321188417Sthompsa zyd_write16_m(sc, ZYD_CR38, 0x38); 1322188417Sthompsa zyd_write16_m(sc, ZYD_CR136, 0xdf); 1323184610Salfred 1324188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r1); 1325188417Sthompsa if (error != 0) 1326188417Sthompsa goto fail; 1327188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r2); 1328188417Sthompsa if (error != 0) 1329188417Sthompsa goto fail; 1330188417Sthompsa error = zyd_rfwrite(sc, 0x3c9000); 1331188417Sthompsa if (error != 0) 1332188417Sthompsa goto fail; 1333184610Salfred 1334188417Sthompsa zyd_write16_m(sc, ZYD_CR251, 0x3f); 1335188417Sthompsa zyd_write16_m(sc, ZYD_CR203, 0x06); 1336188417Sthompsa zyd_write16_m(sc, ZYD_CR240, 0x08); 1337188417Sthompsafail: 1338188417Sthompsa return (error); 1339188417Sthompsa#undef N 1340184610Salfred} 1341184610Salfred 1342184610Salfred/* 1343184610Salfred * AL2210 RF methods. 1344184610Salfred */ 1345188417Sthompsastatic int 1346188417Sthompsazyd_al2210_init(struct zyd_rf *rf) 1347184610Salfred{ 1348188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1349188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1350184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_AL2210_PHY; 1351184610Salfred static const uint32_t rfini[] = ZYD_AL2210_RF; 1352184610Salfred uint32_t tmp; 1353188417Sthompsa int i, error; 1354184610Salfred 1355188417Sthompsa zyd_write32_m(sc, ZYD_CR18, 2); 1356184610Salfred 1357184610Salfred /* init RF-dependent PHY registers */ 1358188417Sthompsa for (i = 0; i < N(phyini); i++) 1359188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1360188417Sthompsa 1361184610Salfred /* init AL2210 radio */ 1362188417Sthompsa for (i = 0; i < N(rfini); i++) { 1363188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 1364188417Sthompsa return (error); 1365184610Salfred } 1366188417Sthompsa zyd_write16_m(sc, ZYD_CR47, 0x1e); 1367188417Sthompsa zyd_read32_m(sc, ZYD_CR_RADIO_PD, &tmp); 1368188417Sthompsa zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp & ~1); 1369188417Sthompsa zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp | 1); 1370188417Sthompsa zyd_write32_m(sc, ZYD_CR_RFCFG, 0x05); 1371188417Sthompsa zyd_write32_m(sc, ZYD_CR_RFCFG, 0x00); 1372188417Sthompsa zyd_write16_m(sc, ZYD_CR47, 0x1e); 1373188417Sthompsa zyd_write32_m(sc, ZYD_CR18, 3); 1374188417Sthompsafail: 1375188417Sthompsa return (error); 1376188417Sthompsa#undef N 1377184610Salfred} 1378184610Salfred 1379188417Sthompsastatic int 1380188417Sthompsazyd_al2210_switch_radio(struct zyd_rf *rf, int on) 1381184610Salfred{ 1382188417Sthompsa /* vendor driver does nothing for this RF chip */ 1383188417Sthompsa 1384188417Sthompsa return (0); 1385188417Sthompsa} 1386188417Sthompsa 1387188417Sthompsastatic int 1388188417Sthompsazyd_al2210_set_channel(struct zyd_rf *rf, uint8_t chan) 1389188417Sthompsa{ 1390188417Sthompsa int error; 1391188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1392184610Salfred static const uint32_t rfprog[] = ZYD_AL2210_CHANTABLE; 1393184610Salfred uint32_t tmp; 1394184610Salfred 1395188417Sthompsa zyd_write32_m(sc, ZYD_CR18, 2); 1396188417Sthompsa zyd_write16_m(sc, ZYD_CR47, 0x1e); 1397188417Sthompsa zyd_read32_m(sc, ZYD_CR_RADIO_PD, &tmp); 1398188417Sthompsa zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp & ~1); 1399188417Sthompsa zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp | 1); 1400188417Sthompsa zyd_write32_m(sc, ZYD_CR_RFCFG, 0x05); 1401188417Sthompsa zyd_write32_m(sc, ZYD_CR_RFCFG, 0x00); 1402188417Sthompsa zyd_write16_m(sc, ZYD_CR47, 0x1e); 1403184610Salfred 1404184610Salfred /* actually set the channel */ 1405188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1]); 1406188417Sthompsa if (error != 0) 1407188417Sthompsa goto fail; 1408184610Salfred 1409188417Sthompsa zyd_write32_m(sc, ZYD_CR18, 3); 1410188417Sthompsafail: 1411188417Sthompsa return (error); 1412184610Salfred} 1413184610Salfred 1414184610Salfred/* 1415184610Salfred * GCT RF methods. 1416184610Salfred */ 1417188417Sthompsastatic int 1418188417Sthompsazyd_gct_init(struct zyd_rf *rf) 1419184610Salfred{ 1420188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1421188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1422184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_GCT_PHY; 1423184610Salfred static const uint32_t rfini[] = ZYD_GCT_RF; 1424188417Sthompsa int i, error; 1425184610Salfred 1426184610Salfred /* init RF-dependent PHY registers */ 1427188417Sthompsa for (i = 0; i < N(phyini); i++) 1428188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1429188417Sthompsa 1430184610Salfred /* init cgt radio */ 1431188417Sthompsa for (i = 0; i < N(rfini); i++) { 1432188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 1433188417Sthompsa return (error); 1434184610Salfred } 1435188417Sthompsafail: 1436188417Sthompsa return (error); 1437188417Sthompsa#undef N 1438184610Salfred} 1439184610Salfred 1440188417Sthompsastatic int 1441188417Sthompsazyd_gct_switch_radio(struct zyd_rf *rf, int on) 1442184610Salfred{ 1443188417Sthompsa /* vendor driver does nothing for this RF chip */ 1444188417Sthompsa 1445188417Sthompsa return (0); 1446188417Sthompsa} 1447188417Sthompsa 1448188417Sthompsastatic int 1449188417Sthompsazyd_gct_set_channel(struct zyd_rf *rf, uint8_t chan) 1450188417Sthompsa{ 1451188417Sthompsa int error; 1452188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1453184610Salfred static const uint32_t rfprog[] = ZYD_GCT_CHANTABLE; 1454184610Salfred 1455188417Sthompsa error = zyd_rfwrite(sc, 0x1c0000); 1456188417Sthompsa if (error != 0) 1457188417Sthompsa goto fail; 1458188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1]); 1459188417Sthompsa if (error != 0) 1460188417Sthompsa goto fail; 1461188417Sthompsa error = zyd_rfwrite(sc, 0x1c0008); 1462188417Sthompsafail: 1463188417Sthompsa return (error); 1464184610Salfred} 1465184610Salfred 1466184610Salfred/* 1467184610Salfred * Maxim RF methods. 1468184610Salfred */ 1469188417Sthompsastatic int 1470188417Sthompsazyd_maxim_init(struct zyd_rf *rf) 1471184610Salfred{ 1472188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1473188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1474184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY; 1475184610Salfred static const uint32_t rfini[] = ZYD_MAXIM_RF; 1476184610Salfred uint16_t tmp; 1477188417Sthompsa int i, error; 1478184610Salfred 1479184610Salfred /* init RF-dependent PHY registers */ 1480188417Sthompsa for (i = 0; i < N(phyini); i++) 1481188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1482184610Salfred 1483188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1484188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); 1485188417Sthompsa 1486184610Salfred /* init maxim radio */ 1487188417Sthompsa for (i = 0; i < N(rfini); i++) { 1488188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 1489188417Sthompsa return (error); 1490184610Salfred } 1491188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1492188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); 1493188417Sthompsafail: 1494188417Sthompsa return (error); 1495188417Sthompsa#undef N 1496184610Salfred} 1497184610Salfred 1498188417Sthompsastatic int 1499188417Sthompsazyd_maxim_switch_radio(struct zyd_rf *rf, int on) 1500184610Salfred{ 1501188417Sthompsa 1502188417Sthompsa /* vendor driver does nothing for this RF chip */ 1503188417Sthompsa return (0); 1504188417Sthompsa} 1505188417Sthompsa 1506188417Sthompsastatic int 1507188417Sthompsazyd_maxim_set_channel(struct zyd_rf *rf, uint8_t chan) 1508188417Sthompsa{ 1509188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1510188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1511184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_MAXIM_PHY; 1512184610Salfred static const uint32_t rfini[] = ZYD_MAXIM_RF; 1513184610Salfred static const struct { 1514188417Sthompsa uint32_t r1, r2; 1515188417Sthompsa } rfprog[] = ZYD_MAXIM_CHANTABLE; 1516184610Salfred uint16_t tmp; 1517188417Sthompsa int i, error; 1518184610Salfred 1519184610Salfred /* 1520184610Salfred * Do the same as we do when initializing it, except for the channel 1521184610Salfred * values coming from the two channel tables. 1522184610Salfred */ 1523184610Salfred 1524184610Salfred /* init RF-dependent PHY registers */ 1525188417Sthompsa for (i = 0; i < N(phyini); i++) 1526188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1527184610Salfred 1528188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1529188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); 1530188417Sthompsa 1531184610Salfred /* first two values taken from the chantables */ 1532188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r1); 1533188417Sthompsa if (error != 0) 1534188417Sthompsa goto fail; 1535188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r2); 1536188417Sthompsa if (error != 0) 1537188417Sthompsa goto fail; 1538184610Salfred 1539184610Salfred /* init maxim radio - skipping the two first values */ 1540188417Sthompsa for (i = 2; i < N(rfini); i++) { 1541188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 1542188417Sthompsa return (error); 1543184610Salfred } 1544188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1545188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); 1546188417Sthompsafail: 1547188417Sthompsa return (error); 1548188417Sthompsa#undef N 1549184610Salfred} 1550184610Salfred 1551184610Salfred/* 1552184610Salfred * Maxim2 RF methods. 1553184610Salfred */ 1554188417Sthompsastatic int 1555188417Sthompsazyd_maxim2_init(struct zyd_rf *rf) 1556184610Salfred{ 1557188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1558188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1559184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY; 1560184610Salfred static const uint32_t rfini[] = ZYD_MAXIM2_RF; 1561184610Salfred uint16_t tmp; 1562188417Sthompsa int i, error; 1563184610Salfred 1564184610Salfred /* init RF-dependent PHY registers */ 1565188417Sthompsa for (i = 0; i < N(phyini); i++) 1566188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1567184610Salfred 1568188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1569188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); 1570188417Sthompsa 1571184610Salfred /* init maxim2 radio */ 1572188417Sthompsa for (i = 0; i < N(rfini); i++) { 1573188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 1574188417Sthompsa return (error); 1575184610Salfred } 1576188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1577188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); 1578188417Sthompsafail: 1579188417Sthompsa return (error); 1580188417Sthompsa#undef N 1581184610Salfred} 1582184610Salfred 1583188417Sthompsastatic int 1584188417Sthompsazyd_maxim2_switch_radio(struct zyd_rf *rf, int on) 1585184610Salfred{ 1586188417Sthompsa 1587188417Sthompsa /* vendor driver does nothing for this RF chip */ 1588188417Sthompsa return (0); 1589188417Sthompsa} 1590188417Sthompsa 1591188417Sthompsastatic int 1592188417Sthompsazyd_maxim2_set_channel(struct zyd_rf *rf, uint8_t chan) 1593188417Sthompsa{ 1594188417Sthompsa#define N(a) (sizeof(a) / sizeof((a)[0])) 1595188417Sthompsa struct zyd_softc *sc = rf->rf_sc; 1596184610Salfred static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY; 1597184610Salfred static const uint32_t rfini[] = ZYD_MAXIM2_RF; 1598184610Salfred static const struct { 1599188417Sthompsa uint32_t r1, r2; 1600188417Sthompsa } rfprog[] = ZYD_MAXIM2_CHANTABLE; 1601184610Salfred uint16_t tmp; 1602188417Sthompsa int i, error; 1603184610Salfred 1604184610Salfred /* 1605184610Salfred * Do the same as we do when initializing it, except for the channel 1606184610Salfred * values coming from the two channel tables. 1607184610Salfred */ 1608184610Salfred 1609184610Salfred /* init RF-dependent PHY registers */ 1610188417Sthompsa for (i = 0; i < N(phyini); i++) 1611188417Sthompsa zyd_write16_m(sc, phyini[i].reg, phyini[i].val); 1612184610Salfred 1613188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1614188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); 1615188417Sthompsa 1616184610Salfred /* first two values taken from the chantables */ 1617188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r1); 1618188417Sthompsa if (error != 0) 1619188417Sthompsa goto fail; 1620188417Sthompsa error = zyd_rfwrite(sc, rfprog[chan - 1].r2); 1621188417Sthompsa if (error != 0) 1622188417Sthompsa goto fail; 1623184610Salfred 1624184610Salfred /* init maxim2 radio - skipping the two first values */ 1625188417Sthompsa for (i = 2; i < N(rfini); i++) { 1626188417Sthompsa if ((error = zyd_rfwrite(sc, rfini[i])) != 0) 1627188417Sthompsa return (error); 1628184610Salfred } 1629188417Sthompsa zyd_read16_m(sc, ZYD_CR203, &tmp); 1630188417Sthompsa zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); 1631188417Sthompsafail: 1632188417Sthompsa return (error); 1633188417Sthompsa#undef N 1634184610Salfred} 1635184610Salfred 1636188417Sthompsastatic int 1637188417Sthompsazyd_rf_attach(struct zyd_softc *sc, uint8_t type) 1638184610Salfred{ 1639188417Sthompsa struct zyd_rf *rf = &sc->sc_rf; 1640184610Salfred 1641188417Sthompsa rf->rf_sc = sc; 1642188417Sthompsa 1643188417Sthompsa switch (type) { 1644184610Salfred case ZYD_RF_RFMD: 1645188417Sthompsa rf->init = zyd_rfmd_init; 1646188417Sthompsa rf->switch_radio = zyd_rfmd_switch_radio; 1647188417Sthompsa rf->set_channel = zyd_rfmd_set_channel; 1648188417Sthompsa rf->width = 24; /* 24-bit RF values */ 1649184610Salfred break; 1650184610Salfred case ZYD_RF_AL2230: 1651186730Salfred case ZYD_RF_AL2230S: 1652188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211B) { 1653188417Sthompsa rf->init = zyd_al2230_init_b; 1654188417Sthompsa rf->set_channel = zyd_al2230_set_channel_b; 1655186730Salfred } else { 1656188417Sthompsa rf->init = zyd_al2230_init; 1657188417Sthompsa rf->set_channel = zyd_al2230_set_channel; 1658186730Salfred } 1659188417Sthompsa rf->switch_radio = zyd_al2230_switch_radio; 1660188417Sthompsa rf->bandedge6 = zyd_al2230_bandedge6; 1661188417Sthompsa rf->width = 24; /* 24-bit RF values */ 1662184610Salfred break; 1663184610Salfred case ZYD_RF_AL7230B: 1664188417Sthompsa rf->init = zyd_al7230B_init; 1665188417Sthompsa rf->switch_radio = zyd_al7230B_switch_radio; 1666188417Sthompsa rf->set_channel = zyd_al7230B_set_channel; 1667188417Sthompsa rf->width = 24; /* 24-bit RF values */ 1668184610Salfred break; 1669184610Salfred case ZYD_RF_AL2210: 1670188417Sthompsa rf->init = zyd_al2210_init; 1671188417Sthompsa rf->switch_radio = zyd_al2210_switch_radio; 1672188417Sthompsa rf->set_channel = zyd_al2210_set_channel; 1673188417Sthompsa rf->width = 24; /* 24-bit RF values */ 1674184610Salfred break; 1675184610Salfred case ZYD_RF_GCT: 1676188417Sthompsa rf->init = zyd_gct_init; 1677188417Sthompsa rf->switch_radio = zyd_gct_switch_radio; 1678188417Sthompsa rf->set_channel = zyd_gct_set_channel; 1679188417Sthompsa rf->width = 21; /* 21-bit RF values */ 1680184610Salfred break; 1681184610Salfred case ZYD_RF_MAXIM_NEW: 1682188417Sthompsa rf->init = zyd_maxim_init; 1683188417Sthompsa rf->switch_radio = zyd_maxim_switch_radio; 1684188417Sthompsa rf->set_channel = zyd_maxim_set_channel; 1685188417Sthompsa rf->width = 18; /* 18-bit RF values */ 1686184610Salfred break; 1687184610Salfred case ZYD_RF_MAXIM_NEW2: 1688188417Sthompsa rf->init = zyd_maxim2_init; 1689188417Sthompsa rf->switch_radio = zyd_maxim2_switch_radio; 1690188417Sthompsa rf->set_channel = zyd_maxim2_set_channel; 1691188417Sthompsa rf->width = 18; /* 18-bit RF values */ 1692184610Salfred break; 1693184610Salfred default: 1694188417Sthompsa device_printf(sc->sc_dev, 1695188417Sthompsa "sorry, radio \"%s\" is not supported yet\n", 1696188417Sthompsa zyd_rf_name(type)); 1697188417Sthompsa return (EINVAL); 1698184610Salfred } 1699188417Sthompsa return (0); 1700188417Sthompsa} 1701184610Salfred 1702188417Sthompsastatic const char * 1703188417Sthompsazyd_rf_name(uint8_t type) 1704188417Sthompsa{ 1705188417Sthompsa static const char * const zyd_rfs[] = { 1706188417Sthompsa "unknown", "unknown", "UW2451", "UCHIP", "AL2230", 1707188417Sthompsa "AL7230B", "THETA", "AL2210", "MAXIM_NEW", "GCT", 1708188417Sthompsa "AL2230S", "RALINK", "INTERSIL", "RFMD", "MAXIM_NEW2", 1709188417Sthompsa "PHILIPS" 1710188417Sthompsa }; 1711184610Salfred 1712188417Sthompsa return zyd_rfs[(type > 15) ? 0 : type]; 1713184610Salfred} 1714184610Salfred 1715188417Sthompsastatic int 1716188417Sthompsazyd_hw_init(struct zyd_softc *sc) 1717184610Salfred{ 1718188417Sthompsa int error; 1719184610Salfred const struct zyd_phy_pair *phyp; 1720188417Sthompsa struct zyd_rf *rf = &sc->sc_rf; 1721188417Sthompsa uint16_t val; 1722184610Salfred 1723184610Salfred /* specify that the plug and play is finished */ 1724188417Sthompsa zyd_write32_m(sc, ZYD_MAC_AFTER_PNP, 1); 1725188417Sthompsa zyd_read16_m(sc, ZYD_FIRMWARE_BASE_ADDR, &sc->sc_fwbase); 1726188417Sthompsa DPRINTF(sc, ZYD_DEBUG_FW, "firmware base address=0x%04x\n", 1727188417Sthompsa sc->sc_fwbase); 1728184610Salfred 1729184610Salfred /* retrieve firmware revision number */ 1730188417Sthompsa zyd_read16_m(sc, sc->sc_fwbase + ZYD_FW_FIRMWARE_REV, &sc->sc_fwrev); 1731188417Sthompsa zyd_write32_m(sc, ZYD_CR_GPI_EN, 0); 1732188417Sthompsa zyd_write32_m(sc, ZYD_MAC_CONT_WIN_LIMIT, 0x7f043f); 1733186730Salfred /* set mandatory rates - XXX assumes 802.11b/g */ 1734188417Sthompsa zyd_write32_m(sc, ZYD_MAC_MAN_RATE, 0x150f); 1735186730Salfred 1736184610Salfred /* disable interrupts */ 1737188417Sthompsa zyd_write32_m(sc, ZYD_CR_INTERRUPT, 0); 1738184610Salfred 1739188417Sthompsa if ((error = zyd_read_pod(sc)) != 0) { 1740188417Sthompsa device_printf(sc->sc_dev, "could not read EEPROM\n"); 1741188417Sthompsa goto fail; 1742184610Salfred } 1743188417Sthompsa 1744188417Sthompsa /* PHY init (resetting) */ 1745188417Sthompsa error = zyd_lock_phy(sc); 1746188417Sthompsa if (error != 0) 1747188417Sthompsa goto fail; 1748188417Sthompsa phyp = (sc->sc_macrev == ZYD_ZD1211B) ? zyd_def_phyB : zyd_def_phy; 1749188417Sthompsa for (; phyp->reg != 0; phyp++) 1750188417Sthompsa zyd_write16_m(sc, phyp->reg, phyp->val); 1751188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211 && sc->sc_fix_cr157 != 0) { 1752188417Sthompsa zyd_read16_m(sc, ZYD_EEPROM_PHY_REG, &val); 1753188417Sthompsa zyd_write32_m(sc, ZYD_CR157, val >> 8); 1754184610Salfred } 1755188417Sthompsa error = zyd_unlock_phy(sc); 1756188417Sthompsa if (error != 0) 1757188417Sthompsa goto fail; 1758184610Salfred 1759184610Salfred /* HMAC init */ 1760188417Sthompsa zyd_write32_m(sc, ZYD_MAC_ACK_EXT, 0x00000020); 1761188417Sthompsa zyd_write32_m(sc, ZYD_CR_ADDA_MBIAS_WT, 0x30000808); 1762188417Sthompsa zyd_write32_m(sc, ZYD_MAC_SNIFFER, 0x00000000); 1763188417Sthompsa zyd_write32_m(sc, ZYD_MAC_RXFILTER, 0x00000000); 1764188417Sthompsa zyd_write32_m(sc, ZYD_MAC_GHTBL, 0x00000000); 1765188417Sthompsa zyd_write32_m(sc, ZYD_MAC_GHTBH, 0x80000000); 1766188417Sthompsa zyd_write32_m(sc, ZYD_MAC_MISC, 0x000000a4); 1767188417Sthompsa zyd_write32_m(sc, ZYD_CR_ADDA_PWR_DWN, 0x0000007f); 1768188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BCNCFG, 0x00f00401); 1769188417Sthompsa zyd_write32_m(sc, ZYD_MAC_PHY_DELAY2, 0x00000000); 1770188417Sthompsa zyd_write32_m(sc, ZYD_MAC_ACK_EXT, 0x00000080); 1771188417Sthompsa zyd_write32_m(sc, ZYD_CR_ADDA_PWR_DWN, 0x00000000); 1772188417Sthompsa zyd_write32_m(sc, ZYD_MAC_SIFS_ACK_TIME, 0x00000100); 1773188417Sthompsa zyd_write32_m(sc, ZYD_CR_RX_PE_DELAY, 0x00000070); 1774188417Sthompsa zyd_write32_m(sc, ZYD_CR_PS_CTRL, 0x10000000); 1775188417Sthompsa zyd_write32_m(sc, ZYD_MAC_RTSCTSRATE, 0x02030203); 1776188417Sthompsa zyd_write32_m(sc, ZYD_MAC_AFTER_PNP, 1); 1777188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BACKOFF_PROTECT, 0x00000114); 1778188417Sthompsa zyd_write32_m(sc, ZYD_MAC_DIFS_EIFS_SIFS, 0x0a47c032); 1779188417Sthompsa zyd_write32_m(sc, ZYD_MAC_CAM_MODE, 0x3); 1780184610Salfred 1781188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211) { 1782188417Sthompsa zyd_write32_m(sc, ZYD_MAC_RETRY, 0x00000002); 1783188417Sthompsa zyd_write32_m(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0640); 1784186730Salfred } else { 1785188417Sthompsa zyd_write32_m(sc, ZYD_MACB_MAX_RETRY, 0x02020202); 1786188417Sthompsa zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL4, 0x007f003f); 1787188417Sthompsa zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL3, 0x007f003f); 1788188417Sthompsa zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL2, 0x003f001f); 1789188417Sthompsa zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL1, 0x001f000f); 1790188417Sthompsa zyd_write32_m(sc, ZYD_MACB_AIFS_CTL1, 0x00280028); 1791188417Sthompsa zyd_write32_m(sc, ZYD_MACB_AIFS_CTL2, 0x008C003C); 1792188417Sthompsa zyd_write32_m(sc, ZYD_MACB_TXOP, 0x01800824); 1793188417Sthompsa zyd_write32_m(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0eff); 1794186730Salfred } 1795186730Salfred 1796184610Salfred /* init beacon interval to 100ms */ 1797188417Sthompsa if ((error = zyd_set_beacon_interval(sc, 100)) != 0) 1798188417Sthompsa goto fail; 1799184610Salfred 1800188417Sthompsa if ((error = zyd_rf_attach(sc, sc->sc_rfrev)) != 0) { 1801188417Sthompsa device_printf(sc->sc_dev, "could not attach RF, rev 0x%x\n", 1802188417Sthompsa sc->sc_rfrev); 1803188417Sthompsa goto fail; 1804188417Sthompsa } 1805188417Sthompsa 1806188417Sthompsa /* RF chip init */ 1807188417Sthompsa error = zyd_lock_phy(sc); 1808188417Sthompsa if (error != 0) 1809188417Sthompsa goto fail; 1810188417Sthompsa error = (*rf->init)(rf); 1811188417Sthompsa if (error != 0) { 1812188417Sthompsa device_printf(sc->sc_dev, 1813188417Sthompsa "radio initialization failed, error %d\n", error); 1814188417Sthompsa goto fail; 1815188417Sthompsa } 1816188417Sthompsa error = zyd_unlock_phy(sc); 1817188417Sthompsa if (error != 0) 1818188417Sthompsa goto fail; 1819188417Sthompsa 1820188417Sthompsa if ((error = zyd_read_eeprom(sc)) != 0) { 1821188417Sthompsa device_printf(sc->sc_dev, "could not read EEPROM\n"); 1822188417Sthompsa goto fail; 1823188417Sthompsa } 1824188417Sthompsa 1825188417Sthompsafail: return (error); 1826184610Salfred} 1827184610Salfred 1828188417Sthompsastatic int 1829188417Sthompsazyd_read_pod(struct zyd_softc *sc) 1830184610Salfred{ 1831188417Sthompsa int error; 1832184610Salfred uint32_t tmp; 1833184610Salfred 1834188417Sthompsa zyd_read32_m(sc, ZYD_EEPROM_POD, &tmp); 1835188417Sthompsa sc->sc_rfrev = tmp & 0x0f; 1836188417Sthompsa sc->sc_ledtype = (tmp >> 4) & 0x01; 1837188417Sthompsa sc->sc_al2230s = (tmp >> 7) & 0x01; 1838188417Sthompsa sc->sc_cckgain = (tmp >> 8) & 0x01; 1839184610Salfred sc->sc_fix_cr157 = (tmp >> 13) & 0x01; 1840188417Sthompsa sc->sc_parev = (tmp >> 16) & 0x0f; 1841186730Salfred sc->sc_bandedge6 = (tmp >> 21) & 0x01; 1842188417Sthompsa sc->sc_newphy = (tmp >> 31) & 0x01; 1843188417Sthompsa sc->sc_txled = ((tmp & (1 << 24)) && (tmp & (1 << 29))) ? 0 : 1; 1844188417Sthompsafail: 1845188417Sthompsa return (error); 1846188417Sthompsa} 1847184610Salfred 1848188417Sthompsastatic int 1849188417Sthompsazyd_read_eeprom(struct zyd_softc *sc) 1850188417Sthompsa{ 1851188417Sthompsa uint16_t val; 1852188417Sthompsa int error, i; 1853184610Salfred 1854184610Salfred /* read Tx power calibration tables */ 1855184610Salfred for (i = 0; i < 7; i++) { 1856188417Sthompsa zyd_read16_m(sc, ZYD_EEPROM_PWR_CAL + i, &val); 1857188417Sthompsa sc->sc_pwrcal[i * 2] = val >> 8; 1858188417Sthompsa sc->sc_pwrcal[i * 2 + 1] = val & 0xff; 1859188417Sthompsa zyd_read16_m(sc, ZYD_EEPROM_PWR_INT + i, &val); 1860188417Sthompsa sc->sc_pwrint[i * 2] = val >> 8; 1861188417Sthompsa sc->sc_pwrint[i * 2 + 1] = val & 0xff; 1862188417Sthompsa zyd_read16_m(sc, ZYD_EEPROM_36M_CAL + i, &val); 1863188417Sthompsa sc->sc_ofdm36_cal[i * 2] = val >> 8; 1864188417Sthompsa sc->sc_ofdm36_cal[i * 2 + 1] = val & 0xff; 1865188417Sthompsa zyd_read16_m(sc, ZYD_EEPROM_48M_CAL + i, &val); 1866188417Sthompsa sc->sc_ofdm48_cal[i * 2] = val >> 8; 1867188417Sthompsa sc->sc_ofdm48_cal[i * 2 + 1] = val & 0xff; 1868188417Sthompsa zyd_read16_m(sc, ZYD_EEPROM_54M_CAL + i, &val); 1869188417Sthompsa sc->sc_ofdm54_cal[i * 2] = val >> 8; 1870188417Sthompsa sc->sc_ofdm54_cal[i * 2 + 1] = val & 0xff; 1871184610Salfred } 1872188417Sthompsafail: 1873188417Sthompsa return (error); 1874184610Salfred} 1875184610Salfred 1876188417Sthompsastatic int 1877188417Sthompsazyd_get_macaddr(struct zyd_softc *sc) 1878186730Salfred{ 1879192984Sthompsa struct usb_device_request req; 1880188417Sthompsa usb2_error_t error; 1881186730Salfred 1882186730Salfred req.bmRequestType = UT_READ_VENDOR_DEVICE; 1883186730Salfred req.bRequest = ZYD_READFWDATAREQ; 1884186730Salfred USETW(req.wValue, ZYD_EEPROM_MAC_ADDR_P1); 1885186730Salfred USETW(req.wIndex, 0); 1886186730Salfred USETW(req.wLength, IEEE80211_ADDR_LEN); 1887186730Salfred 1888188419Sthompsa error = zyd_do_request(sc, &req, sc->sc_bssid); 1889188417Sthompsa if (error != 0) { 1890188417Sthompsa device_printf(sc->sc_dev, "could not read EEPROM: %s\n", 1891188417Sthompsa usb2_errstr(error)); 1892188417Sthompsa } 1893188417Sthompsa 1894188417Sthompsa return (error); 1895186730Salfred} 1896186730Salfred 1897188417Sthompsastatic int 1898188417Sthompsazyd_set_macaddr(struct zyd_softc *sc, const uint8_t *addr) 1899184610Salfred{ 1900188417Sthompsa int error; 1901184610Salfred uint32_t tmp; 1902184610Salfred 1903188417Sthompsa tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]; 1904188417Sthompsa zyd_write32_m(sc, ZYD_MAC_MACADRL, tmp); 1905188417Sthompsa tmp = addr[5] << 8 | addr[4]; 1906188417Sthompsa zyd_write32_m(sc, ZYD_MAC_MACADRH, tmp); 1907188417Sthompsafail: 1908188417Sthompsa return (error); 1909188417Sthompsa} 1910184610Salfred 1911188417Sthompsastatic int 1912188417Sthompsazyd_set_bssid(struct zyd_softc *sc, const uint8_t *addr) 1913188417Sthompsa{ 1914188417Sthompsa int error; 1915188417Sthompsa uint32_t tmp; 1916188417Sthompsa 1917188417Sthompsa tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]; 1918188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BSSADRL, tmp); 1919188417Sthompsa tmp = addr[5] << 8 | addr[4]; 1920188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BSSADRH, tmp); 1921188417Sthompsafail: 1922188417Sthompsa return (error); 1923184610Salfred} 1924184610Salfred 1925188417Sthompsastatic int 1926188417Sthompsazyd_switch_radio(struct zyd_softc *sc, int on) 1927184610Salfred{ 1928188417Sthompsa struct zyd_rf *rf = &sc->sc_rf; 1929188417Sthompsa int error; 1930188417Sthompsa 1931188417Sthompsa error = zyd_lock_phy(sc); 1932188417Sthompsa if (error != 0) 1933188417Sthompsa goto fail; 1934188417Sthompsa error = (*rf->switch_radio)(rf, on); 1935188417Sthompsa if (error != 0) 1936188417Sthompsa goto fail; 1937188417Sthompsa error = zyd_unlock_phy(sc); 1938188417Sthompsafail: 1939188417Sthompsa return (error); 1940184610Salfred} 1941184610Salfred 1942188417Sthompsastatic int 1943188417Sthompsazyd_set_led(struct zyd_softc *sc, int which, int on) 1944184610Salfred{ 1945188417Sthompsa int error; 1946184610Salfred uint32_t tmp; 1947184610Salfred 1948188417Sthompsa zyd_read32_m(sc, ZYD_MAC_TX_PE_CONTROL, &tmp); 1949188417Sthompsa tmp &= ~which; 1950188417Sthompsa if (on) 1951188417Sthompsa tmp |= which; 1952188417Sthompsa zyd_write32_m(sc, ZYD_MAC_TX_PE_CONTROL, tmp); 1953188417Sthompsafail: 1954188417Sthompsa return (error); 1955188417Sthompsa} 1956184610Salfred 1957188417Sthompsastatic void 1958188417Sthompsazyd_set_multi(struct zyd_softc *sc) 1959184610Salfred{ 1960188417Sthompsa int error; 1961188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 1962188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 1963188417Sthompsa struct ifmultiaddr *ifma; 1964188417Sthompsa uint32_t low, high; 1965188417Sthompsa uint8_t v; 1966184610Salfred 1967188417Sthompsa if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1968188417Sthompsa return; 1969184610Salfred 1970188417Sthompsa low = 0x00000000; 1971188417Sthompsa high = 0x80000000; 1972184610Salfred 1973188417Sthompsa if (ic->ic_opmode == IEEE80211_M_MONITOR || 1974188417Sthompsa (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) { 1975188417Sthompsa low = 0xffffffff; 1976188417Sthompsa high = 0xffffffff; 1977184610Salfred } else { 1978188417Sthompsa IF_ADDR_LOCK(ifp); 1979188417Sthompsa TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1980188417Sthompsa if (ifma->ifma_addr->sa_family != AF_LINK) 1981188417Sthompsa continue; 1982188417Sthompsa v = ((uint8_t *)LLADDR((struct sockaddr_dl *) 1983188417Sthompsa ifma->ifma_addr))[5] >> 2; 1984188417Sthompsa if (v < 32) 1985188417Sthompsa low |= 1 << v; 1986188417Sthompsa else 1987188417Sthompsa high |= 1 << (v - 32); 1988188417Sthompsa } 1989188417Sthompsa IF_ADDR_UNLOCK(ifp); 1990184610Salfred } 1991184610Salfred 1992188417Sthompsa /* reprogram multicast global hash table */ 1993188417Sthompsa zyd_write32_m(sc, ZYD_MAC_GHTBL, low); 1994188417Sthompsa zyd_write32_m(sc, ZYD_MAC_GHTBH, high); 1995188417Sthompsafail: 1996188417Sthompsa if (error != 0) 1997188417Sthompsa device_printf(sc->sc_dev, 1998188417Sthompsa "could not set multicast hash table\n"); 1999188417Sthompsa} 2000184610Salfred 2001188417Sthompsastatic void 2002188417Sthompsazyd_update_mcast(struct ifnet *ifp) 2003188417Sthompsa{ 2004188417Sthompsa struct zyd_softc *sc = ifp->if_softc; 2005184610Salfred 2006188417Sthompsa if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 2007184610Salfred return; 2008184610Salfred 2009188417Sthompsa ZYD_LOCK(sc); 2010191746Sthompsa zyd_set_multi(sc); 2011188417Sthompsa ZYD_UNLOCK(sc); 2012188417Sthompsa} 2013184610Salfred 2014188417Sthompsastatic int 2015188417Sthompsazyd_set_rxfilter(struct zyd_softc *sc) 2016188417Sthompsa{ 2017188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2018188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 2019188417Sthompsa uint32_t rxfilter; 2020184610Salfred 2021188417Sthompsa switch (ic->ic_opmode) { 2022188417Sthompsa case IEEE80211_M_STA: 2023188417Sthompsa rxfilter = ZYD_FILTER_BSS; 2024188417Sthompsa break; 2025188417Sthompsa case IEEE80211_M_IBSS: 2026188417Sthompsa case IEEE80211_M_HOSTAP: 2027188417Sthompsa rxfilter = ZYD_FILTER_HOSTAP; 2028188417Sthompsa break; 2029188417Sthompsa case IEEE80211_M_MONITOR: 2030188417Sthompsa rxfilter = ZYD_FILTER_MONITOR; 2031188417Sthompsa break; 2032188417Sthompsa default: 2033188417Sthompsa /* should not get there */ 2034188417Sthompsa return (EINVAL); 2035184610Salfred } 2036188417Sthompsa return zyd_write32(sc, ZYD_MAC_RXFILTER, rxfilter); 2037188417Sthompsa} 2038184610Salfred 2039188417Sthompsastatic void 2040188417Sthompsazyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c) 2041188417Sthompsa{ 2042188417Sthompsa int error; 2043188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2044188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 2045188417Sthompsa struct zyd_rf *rf = &sc->sc_rf; 2046188417Sthompsa uint32_t tmp; 2047188601Sthompsa int chan; 2048184610Salfred 2049188417Sthompsa chan = ieee80211_chan2ieee(ic, c); 2050188417Sthompsa if (chan == 0 || chan == IEEE80211_CHAN_ANY) { 2051188417Sthompsa /* XXX should NEVER happen */ 2052188417Sthompsa device_printf(sc->sc_dev, 2053188417Sthompsa "%s: invalid channel %x\n", __func__, chan); 2054188417Sthompsa return; 2055188417Sthompsa } 2056184610Salfred 2057188417Sthompsa error = zyd_lock_phy(sc); 2058188417Sthompsa if (error != 0) 2059188417Sthompsa goto fail; 2060184610Salfred 2061188417Sthompsa error = (*rf->set_channel)(rf, chan); 2062188417Sthompsa if (error != 0) 2063188417Sthompsa goto fail; 2064184610Salfred 2065188417Sthompsa /* update Tx power */ 2066188417Sthompsa zyd_write16_m(sc, ZYD_CR31, sc->sc_pwrint[chan - 1]); 2067184610Salfred 2068188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211B) { 2069188417Sthompsa zyd_write16_m(sc, ZYD_CR67, sc->sc_ofdm36_cal[chan - 1]); 2070188417Sthompsa zyd_write16_m(sc, ZYD_CR66, sc->sc_ofdm48_cal[chan - 1]); 2071188417Sthompsa zyd_write16_m(sc, ZYD_CR65, sc->sc_ofdm54_cal[chan - 1]); 2072188417Sthompsa zyd_write16_m(sc, ZYD_CR68, sc->sc_pwrcal[chan - 1]); 2073188417Sthompsa zyd_write16_m(sc, ZYD_CR69, 0x28); 2074188417Sthompsa zyd_write16_m(sc, ZYD_CR69, 0x2a); 2075188417Sthompsa } 2076188417Sthompsa if (sc->sc_cckgain) { 2077188417Sthompsa /* set CCK baseband gain from EEPROM */ 2078188417Sthompsa if (zyd_read32(sc, ZYD_EEPROM_PHY_REG, &tmp) == 0) 2079188417Sthompsa zyd_write16_m(sc, ZYD_CR47, tmp & 0xff); 2080188417Sthompsa } 2081188417Sthompsa if (sc->sc_bandedge6 && rf->bandedge6 != NULL) { 2082188417Sthompsa error = (*rf->bandedge6)(rf, c); 2083188417Sthompsa if (error != 0) 2084188417Sthompsa goto fail; 2085188417Sthompsa } 2086188417Sthompsa zyd_write32_m(sc, ZYD_CR_CONFIG_PHILIPS, 0); 2087184610Salfred 2088188417Sthompsa error = zyd_unlock_phy(sc); 2089188417Sthompsa if (error != 0) 2090188417Sthompsa goto fail; 2091184610Salfred 2092188417Sthompsa sc->sc_rxtap.wr_chan_freq = sc->sc_txtap.wt_chan_freq = 2093188417Sthompsa htole16(c->ic_freq); 2094188417Sthompsa sc->sc_rxtap.wr_chan_flags = sc->sc_txtap.wt_chan_flags = 2095188417Sthompsa htole16(c->ic_flags); 2096188417Sthompsafail: 2097184610Salfred return; 2098184610Salfred} 2099184610Salfred 2100184610Salfredstatic int 2101188417Sthompsazyd_set_beacon_interval(struct zyd_softc *sc, int bintval) 2102184610Salfred{ 2103188417Sthompsa int error; 2104188417Sthompsa uint32_t val; 2105184610Salfred 2106188417Sthompsa zyd_read32_m(sc, ZYD_CR_ATIM_WND_PERIOD, &val); 2107188417Sthompsa sc->sc_atim_wnd = val; 2108188417Sthompsa zyd_read32_m(sc, ZYD_CR_PRE_TBTT, &val); 2109188417Sthompsa sc->sc_pre_tbtt = val; 2110188417Sthompsa sc->sc_bcn_int = bintval; 2111184610Salfred 2112188417Sthompsa if (sc->sc_bcn_int <= 5) 2113188417Sthompsa sc->sc_bcn_int = 5; 2114188417Sthompsa if (sc->sc_pre_tbtt < 4 || sc->sc_pre_tbtt >= sc->sc_bcn_int) 2115188417Sthompsa sc->sc_pre_tbtt = sc->sc_bcn_int - 1; 2116188417Sthompsa if (sc->sc_atim_wnd >= sc->sc_pre_tbtt) 2117188417Sthompsa sc->sc_atim_wnd = sc->sc_pre_tbtt - 1; 2118184610Salfred 2119188417Sthompsa zyd_write32_m(sc, ZYD_CR_ATIM_WND_PERIOD, sc->sc_atim_wnd); 2120188417Sthompsa zyd_write32_m(sc, ZYD_CR_PRE_TBTT, sc->sc_pre_tbtt); 2121188417Sthompsa zyd_write32_m(sc, ZYD_CR_BCN_INTERVAL, sc->sc_bcn_int); 2122188417Sthompsafail: 2123188417Sthompsa return (error); 2124188417Sthompsa} 2125184610Salfred 2126188417Sthompsastatic void 2127192984Sthompsazyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len) 2128188417Sthompsa{ 2129188417Sthompsa struct zyd_softc *sc = xfer->priv_sc; 2130188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2131192468Ssam struct ieee80211com *ic = ifp->if_l2com; 2132188417Sthompsa struct zyd_plcphdr plcp; 2133188417Sthompsa struct zyd_rx_stat stat; 2134188417Sthompsa struct mbuf *m; 2135188417Sthompsa int rlen, rssi; 2136184610Salfred 2137188417Sthompsa if (len < ZYD_MIN_FRAGSZ) { 2138188417Sthompsa DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too short (length=%d)\n", 2139188417Sthompsa device_get_nameunit(sc->sc_dev), len); 2140188417Sthompsa ifp->if_ierrors++; 2141188417Sthompsa return; 2142188417Sthompsa } 2143188417Sthompsa usb2_copy_out(xfer->frbuffers, offset, &plcp, sizeof(plcp)); 2144188417Sthompsa usb2_copy_out(xfer->frbuffers, offset + len - sizeof(stat), 2145188417Sthompsa &stat, sizeof(stat)); 2146184610Salfred 2147188417Sthompsa if (stat.flags & ZYD_RX_ERROR) { 2148188417Sthompsa DPRINTF(sc, ZYD_DEBUG_RECV, 2149188417Sthompsa "%s: RX status indicated error (%x)\n", 2150188417Sthompsa device_get_nameunit(sc->sc_dev), stat.flags); 2151188417Sthompsa ifp->if_ierrors++; 2152188417Sthompsa return; 2153188417Sthompsa } 2154184610Salfred 2155188417Sthompsa /* compute actual frame length */ 2156188417Sthompsa rlen = len - sizeof(struct zyd_plcphdr) - 2157188417Sthompsa sizeof(struct zyd_rx_stat) - IEEE80211_CRC_LEN; 2158184610Salfred 2159188417Sthompsa /* allocate a mbuf to store the frame */ 2160188417Sthompsa if (rlen > MCLBYTES) { 2161188417Sthompsa DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too long (length=%d)\n", 2162188417Sthompsa device_get_nameunit(sc->sc_dev), rlen); 2163188417Sthompsa ifp->if_ierrors++; 2164188417Sthompsa return; 2165188417Sthompsa } else if (rlen > MHLEN) 2166188417Sthompsa m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 2167188417Sthompsa else 2168188417Sthompsa m = m_gethdr(M_DONTWAIT, MT_DATA); 2169188417Sthompsa if (m == NULL) { 2170188417Sthompsa DPRINTF(sc, ZYD_DEBUG_RECV, "%s: could not allocate rx mbuf\n", 2171188417Sthompsa device_get_nameunit(sc->sc_dev)); 2172188417Sthompsa ifp->if_ierrors++; 2173188417Sthompsa return; 2174184610Salfred } 2175188417Sthompsa m->m_pkthdr.rcvif = ifp; 2176188417Sthompsa m->m_pkthdr.len = m->m_len = rlen; 2177188417Sthompsa usb2_copy_out(xfer->frbuffers, offset + sizeof(plcp), 2178188417Sthompsa mtod(m, uint8_t *), rlen); 2179184610Salfred 2180192468Ssam if (ieee80211_radiotap_active(ic)) { 2181188417Sthompsa struct zyd_rx_radiotap_header *tap = &sc->sc_rxtap; 2182184610Salfred 2183188417Sthompsa tap->wr_flags = 0; 2184188417Sthompsa if (stat.flags & (ZYD_RX_BADCRC16 | ZYD_RX_BADCRC32)) 2185188417Sthompsa tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; 2186188417Sthompsa /* XXX toss, no way to express errors */ 2187188417Sthompsa if (stat.flags & ZYD_RX_DECRYPTERR) 2188188417Sthompsa tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; 2189188417Sthompsa tap->wr_rate = ieee80211_plcp2rate(plcp.signal, 2190188417Sthompsa (stat.flags & ZYD_RX_OFDM) ? 2191188417Sthompsa IEEE80211_T_OFDM : IEEE80211_T_CCK); 2192188417Sthompsa tap->wr_antsignal = stat.rssi + -95; 2193188417Sthompsa tap->wr_antnoise = -95; /* XXX */ 2194188417Sthompsa } 2195188417Sthompsa rssi = (stat.rssi > 63) ? 127 : 2 * stat.rssi; 2196184610Salfred 2197188417Sthompsa sc->sc_rx_data[sc->sc_rx_count].rssi = rssi; 2198188417Sthompsa sc->sc_rx_data[sc->sc_rx_count].m = m; 2199188417Sthompsa sc->sc_rx_count++; 2200184610Salfred} 2201184610Salfred 2202184610Salfredstatic void 2203192984Sthompsazyd_bulk_read_callback(struct usb_xfer *xfer) 2204184610Salfred{ 2205188417Sthompsa struct zyd_softc *sc = xfer->priv_sc; 2206184610Salfred struct ifnet *ifp = sc->sc_ifp; 2207184610Salfred struct ieee80211com *ic = ifp->if_l2com; 2208188417Sthompsa struct ieee80211_node *ni; 2209188417Sthompsa struct zyd_rx_desc desc; 2210188417Sthompsa struct mbuf *m; 2211188417Sthompsa uint32_t offset; 2212188417Sthompsa uint8_t rssi; 2213188417Sthompsa int8_t nf; 2214188417Sthompsa int i; 2215184610Salfred 2216188417Sthompsa sc->sc_rx_count = 0; 2217188417Sthompsa switch (USB_GET_STATE(xfer)) { 2218188417Sthompsa case USB_ST_TRANSFERRED: 2219188417Sthompsa usb2_copy_out(xfer->frbuffers, xfer->actlen - sizeof(desc), 2220188417Sthompsa &desc, sizeof(desc)); 2221184610Salfred 2222188417Sthompsa offset = 0; 2223188417Sthompsa if (UGETW(desc.tag) == ZYD_TAG_MULTIFRAME) { 2224188417Sthompsa DPRINTF(sc, ZYD_DEBUG_RECV, 2225188417Sthompsa "%s: received multi-frame transfer\n", __func__); 2226184610Salfred 2227188417Sthompsa for (i = 0; i < ZYD_MAX_RXFRAMECNT; i++) { 2228188417Sthompsa uint16_t len16 = UGETW(desc.len[i]); 2229184610Salfred 2230188417Sthompsa if (len16 == 0 || len16 > xfer->actlen) 2231188417Sthompsa break; 2232184610Salfred 2233188417Sthompsa zyd_rx_data(xfer, offset, len16); 2234184610Salfred 2235188417Sthompsa /* next frame is aligned on a 32-bit boundary */ 2236188417Sthompsa len16 = (len16 + 3) & ~3; 2237188417Sthompsa offset += len16; 2238188417Sthompsa if (len16 > xfer->actlen) 2239188417Sthompsa break; 2240188417Sthompsa xfer->actlen -= len16; 2241188417Sthompsa } 2242188417Sthompsa } else { 2243188417Sthompsa DPRINTF(sc, ZYD_DEBUG_RECV, 2244188417Sthompsa "%s: received single-frame transfer\n", __func__); 2245184610Salfred 2246188417Sthompsa zyd_rx_data(xfer, 0, xfer->actlen); 2247188417Sthompsa } 2248188417Sthompsa /* FALLTHROUGH */ 2249188417Sthompsa case USB_ST_SETUP: 2250188417Sthompsatr_setup: 2251188417Sthompsa xfer->frlengths[0] = xfer->max_data_length; 2252188417Sthompsa usb2_start_hardware(xfer); 2253184610Salfred 2254188417Sthompsa /* 2255188417Sthompsa * At the end of a USB callback it is always safe to unlock 2256188417Sthompsa * the private mutex of a device! That is why we do the 2257188417Sthompsa * "ieee80211_input" here, and not some lines up! 2258188417Sthompsa */ 2259188417Sthompsa ZYD_UNLOCK(sc); 2260188417Sthompsa for (i = 0; i < sc->sc_rx_count; i++) { 2261188417Sthompsa rssi = sc->sc_rx_data[i].rssi; 2262188417Sthompsa m = sc->sc_rx_data[i].m; 2263188417Sthompsa sc->sc_rx_data[i].m = NULL; 2264184610Salfred 2265188417Sthompsa nf = -95; /* XXX */ 2266184610Salfred 2267188417Sthompsa ni = ieee80211_find_rxnode(ic, 2268188417Sthompsa mtod(m, struct ieee80211_frame_min *)); 2269188417Sthompsa if (ni != NULL) { 2270192468Ssam (void)ieee80211_input(ni, m, rssi, nf); 2271188417Sthompsa ieee80211_free_node(ni); 2272188417Sthompsa } else 2273192468Ssam (void)ieee80211_input_all(ic, m, rssi, nf); 2274188417Sthompsa } 2275188417Sthompsa ZYD_LOCK(sc); 2276188417Sthompsa break; 2277184610Salfred 2278188417Sthompsa default: /* Error */ 2279188417Sthompsa DPRINTF(sc, ZYD_DEBUG_ANY, "frame error: %s\n", usb2_errstr(xfer->error)); 2280184610Salfred 2281188417Sthompsa if (xfer->error != USB_ERR_CANCELLED) { 2282188417Sthompsa /* try to clear stall first */ 2283188417Sthompsa xfer->flags.stall_pipe = 1; 2284188417Sthompsa goto tr_setup; 2285184610Salfred } 2286188417Sthompsa break; 2287184610Salfred } 2288184610Salfred} 2289184610Salfred 2290184610Salfredstatic uint8_t 2291188417Sthompsazyd_plcp_signal(int rate) 2292184610Salfred{ 2293184610Salfred switch (rate) { 2294188417Sthompsa /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ 2295184610Salfred case 12: 2296184610Salfred return (0xb); 2297184610Salfred case 18: 2298184610Salfred return (0xf); 2299184610Salfred case 24: 2300184610Salfred return (0xa); 2301184610Salfred case 36: 2302184610Salfred return (0xe); 2303184610Salfred case 48: 2304184610Salfred return (0x9); 2305184610Salfred case 72: 2306184610Salfred return (0xd); 2307184610Salfred case 96: 2308184610Salfred return (0x8); 2309184610Salfred case 108: 2310184610Salfred return (0xc); 2311188417Sthompsa /* CCK rates (NB: not IEEE std, device-specific) */ 2312188417Sthompsa case 2: 2313188417Sthompsa return (0x0); 2314188417Sthompsa case 4: 2315188417Sthompsa return (0x1); 2316188417Sthompsa case 11: 2317188417Sthompsa return (0x2); 2318188417Sthompsa case 22: 2319188417Sthompsa return (0x3); 2320184610Salfred } 2321188417Sthompsa return (0xff); /* XXX unsupported/unknown rate */ 2322184610Salfred} 2323184610Salfred 2324188417Sthompsastatic int 2325188417Sthompsazyd_tx_mgt(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) 2326184610Salfred{ 2327188417Sthompsa struct ieee80211vap *vap = ni->ni_vap; 2328188417Sthompsa struct ieee80211com *ic = ni->ni_ic; 2329188417Sthompsa struct zyd_tx_desc *desc; 2330188417Sthompsa struct zyd_tx_data *data; 2331188417Sthompsa struct ieee80211_frame *wh; 2332188417Sthompsa struct ieee80211_key *k; 2333188417Sthompsa int rate, totlen; 2334188417Sthompsa uint16_t pktlen; 2335184610Salfred 2336188417Sthompsa data = STAILQ_FIRST(&sc->tx_free); 2337188417Sthompsa STAILQ_REMOVE_HEAD(&sc->tx_free, next); 2338188417Sthompsa sc->tx_nfree--; 2339188417Sthompsa desc = &data->desc; 2340184610Salfred 2341188417Sthompsa rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2; 2342184610Salfred 2343188417Sthompsa wh = mtod(m0, struct ieee80211_frame *); 2344184610Salfred 2345188417Sthompsa if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 2346188417Sthompsa k = ieee80211_crypto_encap(ni, m0); 2347188417Sthompsa if (k == NULL) { 2348188417Sthompsa m_freem(m0); 2349188417Sthompsa return (ENOBUFS); 2350188417Sthompsa } 2351188417Sthompsa } 2352184610Salfred 2353188417Sthompsa data->ni = ni; 2354188417Sthompsa data->m = m0; 2355188417Sthompsa data->rate = rate; 2356184610Salfred 2357188417Sthompsa wh = mtod(m0, struct ieee80211_frame *); 2358184610Salfred 2359188417Sthompsa totlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN; 2360184610Salfred 2361188417Sthompsa /* fill Tx descriptor */ 2362188417Sthompsa desc->len = htole16(totlen); 2363184610Salfred 2364188417Sthompsa desc->flags = ZYD_TX_FLAG_BACKOFF; 2365188417Sthompsa if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 2366188417Sthompsa /* multicast frames are not sent at OFDM rates in 802.11b/g */ 2367188417Sthompsa if (totlen > vap->iv_rtsthreshold) { 2368188417Sthompsa desc->flags |= ZYD_TX_FLAG_RTS; 2369188417Sthompsa } else if (ZYD_RATE_IS_OFDM(rate) && 2370188417Sthompsa (ic->ic_flags & IEEE80211_F_USEPROT)) { 2371188417Sthompsa if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) 2372188417Sthompsa desc->flags |= ZYD_TX_FLAG_CTS_TO_SELF; 2373188417Sthompsa else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) 2374188417Sthompsa desc->flags |= ZYD_TX_FLAG_RTS; 2375188417Sthompsa } 2376188417Sthompsa } else 2377188417Sthompsa desc->flags |= ZYD_TX_FLAG_MULTICAST; 2378184610Salfred 2379188417Sthompsa if ((wh->i_fc[0] & 2380188417Sthompsa (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == 2381188417Sthompsa (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL)) 2382188417Sthompsa desc->flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL); 2383184610Salfred 2384188417Sthompsa desc->phy = zyd_plcp_signal(rate); 2385188417Sthompsa if (ZYD_RATE_IS_OFDM(rate)) { 2386188417Sthompsa desc->phy |= ZYD_TX_PHY_OFDM; 2387188417Sthompsa if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) 2388188417Sthompsa desc->phy |= ZYD_TX_PHY_5GHZ; 2389188417Sthompsa } else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 2390188417Sthompsa desc->phy |= ZYD_TX_PHY_SHPREAMBLE; 2391184610Salfred 2392188417Sthompsa /* actual transmit length (XXX why +10?) */ 2393188417Sthompsa pktlen = ZYD_TX_DESC_SIZE + 10; 2394188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211) 2395188417Sthompsa pktlen += totlen; 2396188417Sthompsa desc->pktlen = htole16(pktlen); 2397184610Salfred 2398188417Sthompsa desc->plcp_length = (16 * totlen + rate - 1) / rate; 2399188417Sthompsa desc->plcp_service = 0; 2400188417Sthompsa if (rate == 22) { 2401188417Sthompsa const int remainder = (16 * totlen) % 22; 2402188417Sthompsa if (remainder != 0 && remainder < 7) 2403188417Sthompsa desc->plcp_service |= ZYD_PLCP_LENGEXT; 2404184610Salfred } 2405184610Salfred 2406192468Ssam if (ieee80211_radiotap_active_vap(vap)) { 2407188417Sthompsa struct zyd_tx_radiotap_header *tap = &sc->sc_txtap; 2408184610Salfred 2409188417Sthompsa tap->wt_flags = 0; 2410188417Sthompsa tap->wt_rate = rate; 2411184610Salfred 2412192468Ssam ieee80211_radiotap_tx(vap, m0); 2413184610Salfred } 2414184610Salfred 2415188417Sthompsa DPRINTF(sc, ZYD_DEBUG_XMIT, 2416188417Sthompsa "%s: sending mgt frame len=%zu rate=%u\n", 2417188417Sthompsa device_get_nameunit(sc->sc_dev), (size_t)m0->m_pkthdr.len, 2418188417Sthompsa rate); 2419184610Salfred 2420188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_q, data, next); 2421188417Sthompsa usb2_transfer_start(sc->sc_xfer[ZYD_BULK_WR]); 2422184610Salfred 2423188417Sthompsa return (0); 2424184610Salfred} 2425184610Salfred 2426184610Salfredstatic void 2427192984Sthompsazyd_bulk_write_callback(struct usb_xfer *xfer) 2428184610Salfred{ 2429188417Sthompsa struct zyd_softc *sc = xfer->priv_sc; 2430184610Salfred struct ifnet *ifp = sc->sc_ifp; 2431192468Ssam struct ieee80211vap *vap; 2432188417Sthompsa struct zyd_tx_data *data; 2433188417Sthompsa struct mbuf *m; 2434184610Salfred 2435188417Sthompsa switch (USB_GET_STATE(xfer)) { 2436188417Sthompsa case USB_ST_TRANSFERRED: 2437188417Sthompsa DPRINTF(sc, ZYD_DEBUG_ANY, "transfer complete, %u bytes\n", 2438188417Sthompsa xfer->actlen); 2439184610Salfred 2440188417Sthompsa /* free resources */ 2441188417Sthompsa data = xfer->priv_fifo; 2442188417Sthompsa zyd_tx_free(data, 0); 2443188417Sthompsa xfer->priv_fifo = NULL; 2444184610Salfred 2445188417Sthompsa ifp->if_opackets++; 2446188417Sthompsa ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2447184610Salfred 2448188417Sthompsa /* FALLTHROUGH */ 2449188417Sthompsa case USB_ST_SETUP: 2450188417Sthompsatr_setup: 2451188417Sthompsa data = STAILQ_FIRST(&sc->tx_q); 2452188417Sthompsa if (data) { 2453188417Sthompsa STAILQ_REMOVE_HEAD(&sc->tx_q, next); 2454188417Sthompsa m = data->m; 2455184610Salfred 2456188417Sthompsa if (m->m_pkthdr.len > ZYD_MAX_TXBUFSZ) { 2457188417Sthompsa DPRINTF(sc, ZYD_DEBUG_ANY, "data overflow, %u bytes\n", 2458188417Sthompsa m->m_pkthdr.len); 2459188417Sthompsa m->m_pkthdr.len = ZYD_MAX_TXBUFSZ; 2460188417Sthompsa } 2461188417Sthompsa usb2_copy_in(xfer->frbuffers, 0, &data->desc, 2462188417Sthompsa ZYD_TX_DESC_SIZE); 2463188417Sthompsa usb2_m_copy_in(xfer->frbuffers, ZYD_TX_DESC_SIZE, m, 0, 2464188417Sthompsa m->m_pkthdr.len); 2465184610Salfred 2466192468Ssam vap = data->ni->ni_vap; 2467192468Ssam if (ieee80211_radiotap_active_vap(vap)) { 2468188417Sthompsa struct zyd_tx_radiotap_header *tap = &sc->sc_txtap; 2469184610Salfred 2470188417Sthompsa tap->wt_flags = 0; 2471188417Sthompsa tap->wt_rate = data->rate; 2472184610Salfred 2473192468Ssam ieee80211_radiotap_tx(vap, m); 2474188417Sthompsa } 2475184610Salfred 2476188417Sthompsa xfer->frlengths[0] = ZYD_TX_DESC_SIZE + m->m_pkthdr.len; 2477188417Sthompsa xfer->priv_fifo = data; 2478188417Sthompsa usb2_start_hardware(xfer); 2479188417Sthompsa } 2480188417Sthompsa break; 2481184610Salfred 2482188417Sthompsa default: /* Error */ 2483188417Sthompsa DPRINTF(sc, ZYD_DEBUG_ANY, "transfer error, %s\n", 2484188417Sthompsa usb2_errstr(xfer->error)); 2485184610Salfred 2486188419Sthompsa ifp->if_oerrors++; 2487188419Sthompsa data = xfer->priv_fifo; 2488188419Sthompsa xfer->priv_fifo = NULL; 2489188419Sthompsa if (data != NULL) 2490188419Sthompsa zyd_tx_free(data, xfer->error); 2491188419Sthompsa 2492188417Sthompsa if (xfer->error == USB_ERR_STALLED) { 2493188417Sthompsa /* try to clear stall first */ 2494188417Sthompsa xfer->flags.stall_pipe = 1; 2495188417Sthompsa goto tr_setup; 2496188417Sthompsa } 2497188417Sthompsa if (xfer->error == USB_ERR_TIMEOUT) 2498188417Sthompsa device_printf(sc->sc_dev, "device timeout\n"); 2499184610Salfred break; 2500184610Salfred } 2501184610Salfred} 2502184610Salfred 2503188417Sthompsastatic int 2504188417Sthompsazyd_tx_data(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) 2505184610Salfred{ 2506188417Sthompsa struct ieee80211vap *vap = ni->ni_vap; 2507188417Sthompsa struct ieee80211com *ic = ni->ni_ic; 2508188417Sthompsa struct zyd_tx_desc *desc; 2509188417Sthompsa struct zyd_tx_data *data; 2510188417Sthompsa struct ieee80211_frame *wh; 2511188417Sthompsa const struct ieee80211_txparam *tp; 2512188417Sthompsa struct ieee80211_key *k; 2513188417Sthompsa int rate, totlen; 2514188417Sthompsa uint16_t pktlen; 2515184610Salfred 2516188417Sthompsa wh = mtod(m0, struct ieee80211_frame *); 2517188417Sthompsa data = STAILQ_FIRST(&sc->tx_free); 2518188417Sthompsa STAILQ_REMOVE_HEAD(&sc->tx_free, next); 2519188417Sthompsa sc->tx_nfree--; 2520188417Sthompsa desc = &data->desc; 2521184610Salfred 2522188417Sthompsa desc->flags = ZYD_TX_FLAG_BACKOFF; 2523188417Sthompsa tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; 2524188417Sthompsa if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { 2525188417Sthompsa rate = tp->mcastrate; 2526188417Sthompsa desc->flags |= ZYD_TX_FLAG_MULTICAST; 2527188417Sthompsa } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { 2528188417Sthompsa rate = tp->ucastrate; 2529188417Sthompsa } else { 2530188417Sthompsa (void) ieee80211_amrr_choose(ni, &ZYD_NODE(ni)->amn); 2531188417Sthompsa rate = ni->ni_txrate; 2532184610Salfred } 2533184610Salfred 2534188417Sthompsa if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 2535188417Sthompsa k = ieee80211_crypto_encap(ni, m0); 2536188417Sthompsa if (k == NULL) { 2537188417Sthompsa m_freem(m0); 2538188417Sthompsa return (ENOBUFS); 2539188417Sthompsa } 2540188417Sthompsa /* packet header may have moved, reset our local pointer */ 2541188417Sthompsa wh = mtod(m0, struct ieee80211_frame *); 2542184610Salfred } 2543184610Salfred 2544188417Sthompsa data->ni = ni; 2545188417Sthompsa data->m = m0; 2546184610Salfred 2547188417Sthompsa totlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN; 2548184610Salfred 2549188417Sthompsa /* fill Tx descriptor */ 2550188417Sthompsa desc->len = htole16(totlen); 2551184610Salfred 2552188417Sthompsa if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 2553188417Sthompsa /* multicast frames are not sent at OFDM rates in 802.11b/g */ 2554188417Sthompsa if (totlen > vap->iv_rtsthreshold) { 2555188417Sthompsa desc->flags |= ZYD_TX_FLAG_RTS; 2556188417Sthompsa } else if (ZYD_RATE_IS_OFDM(rate) && 2557188417Sthompsa (ic->ic_flags & IEEE80211_F_USEPROT)) { 2558188417Sthompsa if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) 2559188417Sthompsa desc->flags |= ZYD_TX_FLAG_CTS_TO_SELF; 2560188417Sthompsa else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) 2561188417Sthompsa desc->flags |= ZYD_TX_FLAG_RTS; 2562188417Sthompsa } 2563184610Salfred } 2564184610Salfred 2565188417Sthompsa if ((wh->i_fc[0] & 2566188417Sthompsa (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == 2567188417Sthompsa (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL)) 2568188417Sthompsa desc->flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL); 2569188417Sthompsa 2570188417Sthompsa desc->phy = zyd_plcp_signal(rate); 2571188417Sthompsa if (ZYD_RATE_IS_OFDM(rate)) { 2572188417Sthompsa desc->phy |= ZYD_TX_PHY_OFDM; 2573184610Salfred if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) 2574188417Sthompsa desc->phy |= ZYD_TX_PHY_5GHZ; 2575184610Salfred } else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 2576188417Sthompsa desc->phy |= ZYD_TX_PHY_SHPREAMBLE; 2577184610Salfred 2578184610Salfred /* actual transmit length (XXX why +10?) */ 2579184610Salfred pktlen = sizeof(struct zyd_tx_desc) + 10; 2580188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211) 2581184610Salfred pktlen += totlen; 2582188417Sthompsa desc->pktlen = htole16(pktlen); 2583184610Salfred 2584188417Sthompsa desc->plcp_length = (16 * totlen + rate - 1) / rate; 2585188417Sthompsa desc->plcp_service = 0; 2586184610Salfred if (rate == 22) { 2587188417Sthompsa const int remainder = (16 * totlen) % 22; 2588188417Sthompsa if (remainder != 0 && remainder < 7) 2589188417Sthompsa desc->plcp_service |= ZYD_PLCP_LENGEXT; 2590184610Salfred } 2591184610Salfred 2592188417Sthompsa DPRINTF(sc, ZYD_DEBUG_XMIT, 2593188417Sthompsa "%s: sending data frame len=%zu rate=%u\n", 2594188417Sthompsa device_get_nameunit(sc->sc_dev), (size_t)m0->m_pkthdr.len, 2595188417Sthompsa rate); 2596184610Salfred 2597188417Sthompsa STAILQ_INSERT_TAIL(&sc->tx_q, data, next); 2598188417Sthompsa usb2_transfer_start(sc->sc_xfer[ZYD_BULK_WR]); 2599184610Salfred 2600188417Sthompsa return (0); 2601184610Salfred} 2602184610Salfred 2603184610Salfredstatic void 2604188417Sthompsazyd_start(struct ifnet *ifp) 2605184610Salfred{ 2606188417Sthompsa struct zyd_softc *sc = ifp->if_softc; 2607188417Sthompsa struct ieee80211_node *ni; 2608184610Salfred struct mbuf *m; 2609184610Salfred 2610188417Sthompsa ZYD_LOCK(sc); 2611188417Sthompsa for (;;) { 2612188417Sthompsa IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 2613188417Sthompsa if (m == NULL) 2614184610Salfred break; 2615188417Sthompsa if (sc->tx_nfree == 0) { 2616188417Sthompsa IFQ_DRV_PREPEND(&ifp->if_snd, m); 2617188417Sthompsa ifp->if_drv_flags |= IFF_DRV_OACTIVE; 2618184610Salfred break; 2619184610Salfred } 2620188417Sthompsa ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; 2621188417Sthompsa if (zyd_tx_data(sc, m, ni) != 0) { 2622188417Sthompsa ieee80211_free_node(ni); 2623188417Sthompsa ifp->if_oerrors++; 2624188417Sthompsa break; 2625184610Salfred } 2626184610Salfred } 2627188417Sthompsa ZYD_UNLOCK(sc); 2628184610Salfred} 2629184610Salfred 2630188417Sthompsastatic int 2631188417Sthompsazyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 2632188417Sthompsa const struct ieee80211_bpf_params *params) 2633184610Salfred{ 2634188417Sthompsa struct ieee80211com *ic = ni->ni_ic; 2635188417Sthompsa struct ifnet *ifp = ic->ic_ifp; 2636188417Sthompsa struct zyd_softc *sc = ifp->if_softc; 2637184610Salfred 2638188417Sthompsa ZYD_LOCK(sc); 2639188417Sthompsa /* prevent management frames from being sent if we're not ready */ 2640188417Sthompsa if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 2641188417Sthompsa ZYD_UNLOCK(sc); 2642188417Sthompsa m_freem(m); 2643188417Sthompsa ieee80211_free_node(ni); 2644188417Sthompsa return (ENETDOWN); 2645188417Sthompsa } 2646188417Sthompsa if (sc->tx_nfree == 0) { 2647188417Sthompsa ifp->if_drv_flags |= IFF_DRV_OACTIVE; 2648188417Sthompsa ZYD_UNLOCK(sc); 2649188417Sthompsa m_freem(m); 2650188417Sthompsa ieee80211_free_node(ni); 2651188417Sthompsa return (ENOBUFS); /* XXX */ 2652188417Sthompsa } 2653188417Sthompsa 2654188417Sthompsa /* 2655188417Sthompsa * Legacy path; interpret frame contents to decide 2656188417Sthompsa * precisely how to send the frame. 2657188417Sthompsa * XXX raw path 2658188417Sthompsa */ 2659188417Sthompsa if (zyd_tx_mgt(sc, m, ni) != 0) { 2660188417Sthompsa ZYD_UNLOCK(sc); 2661188417Sthompsa ifp->if_oerrors++; 2662188417Sthompsa ieee80211_free_node(ni); 2663188417Sthompsa return (EIO); 2664188417Sthompsa } 2665188417Sthompsa ZYD_UNLOCK(sc); 2666188417Sthompsa return (0); 2667184610Salfred} 2668184610Salfred 2669184610Salfredstatic int 2670188417Sthompsazyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 2671184610Salfred{ 2672184610Salfred struct zyd_softc *sc = ifp->if_softc; 2673184610Salfred struct ieee80211com *ic = ifp->if_l2com; 2674188417Sthompsa struct ifreq *ifr = (struct ifreq *) data; 2675188417Sthompsa int error = 0, startall = 0; 2676184610Salfred 2677184610Salfred switch (cmd) { 2678184610Salfred case SIOCSIFFLAGS: 2679188417Sthompsa ZYD_LOCK(sc); 2680184610Salfred if (ifp->if_flags & IFF_UP) { 2681191746Sthompsa if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 2682191746Sthompsa zyd_init_locked(sc); 2683188417Sthompsa startall = 1; 2684191746Sthompsa } else 2685191746Sthompsa zyd_set_multi(sc); 2686184610Salfred } else { 2687191746Sthompsa if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2688191746Sthompsa zyd_stop(sc); 2689184610Salfred } 2690188417Sthompsa ZYD_UNLOCK(sc); 2691188417Sthompsa if (startall) 2692188417Sthompsa ieee80211_start_all(ic); 2693184610Salfred break; 2694184610Salfred case SIOCGIFMEDIA: 2695188417Sthompsa error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); 2696184610Salfred break; 2697188417Sthompsa case SIOCGIFADDR: 2698184610Salfred error = ether_ioctl(ifp, cmd, data); 2699184610Salfred break; 2700188417Sthompsa default: 2701188417Sthompsa error = EINVAL; 2702188417Sthompsa break; 2703184610Salfred } 2704184610Salfred return (error); 2705184610Salfred} 2706184610Salfred 2707184610Salfredstatic void 2708191746Sthompsazyd_init_locked(struct zyd_softc *sc) 2709184610Salfred{ 2710188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2711188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 2712192984Sthompsa struct usb_config_descriptor *cd; 2713188419Sthompsa int error; 2714188417Sthompsa uint32_t val; 2715184610Salfred 2716188417Sthompsa ZYD_LOCK_ASSERT(sc, MA_OWNED); 2717184610Salfred 2718188417Sthompsa if (!(sc->sc_flags & ZYD_FLAG_INITONCE)) { 2719188417Sthompsa error = zyd_loadfirmware(sc); 2720188417Sthompsa if (error != 0) { 2721188417Sthompsa device_printf(sc->sc_dev, 2722188417Sthompsa "could not load firmware (error=%d)\n", error); 2723188417Sthompsa goto fail; 2724188417Sthompsa } 2725188417Sthompsa 2726188417Sthompsa /* reset device */ 2727188417Sthompsa cd = usb2_get_config_descriptor(sc->sc_udev); 2728188417Sthompsa error = usb2_req_set_config(sc->sc_udev, &sc->sc_mtx, 2729188417Sthompsa cd->bConfigurationValue); 2730188417Sthompsa if (error) 2731188417Sthompsa device_printf(sc->sc_dev, "reset failed, continuing\n"); 2732188417Sthompsa 2733188417Sthompsa error = zyd_hw_init(sc); 2734188417Sthompsa if (error) { 2735188417Sthompsa device_printf(sc->sc_dev, 2736188417Sthompsa "hardware initialization failed\n"); 2737188417Sthompsa goto fail; 2738188417Sthompsa } 2739188417Sthompsa 2740188417Sthompsa device_printf(sc->sc_dev, 2741188417Sthompsa "HMAC ZD1211%s, FW %02x.%02x, RF %s S%x, PA%x LED %x " 2742188417Sthompsa "BE%x NP%x Gain%x F%x\n", 2743188417Sthompsa (sc->sc_macrev == ZYD_ZD1211) ? "": "B", 2744188417Sthompsa sc->sc_fwrev >> 8, sc->sc_fwrev & 0xff, 2745188417Sthompsa zyd_rf_name(sc->sc_rfrev), sc->sc_al2230s, sc->sc_parev, 2746188417Sthompsa sc->sc_ledtype, sc->sc_bandedge6, sc->sc_newphy, 2747188417Sthompsa sc->sc_cckgain, sc->sc_fix_cr157); 2748188417Sthompsa 2749188417Sthompsa /* read regulatory domain (currently unused) */ 2750188417Sthompsa zyd_read32_m(sc, ZYD_EEPROM_SUBID, &val); 2751188417Sthompsa sc->sc_regdomain = val >> 16; 2752188417Sthompsa DPRINTF(sc, ZYD_DEBUG_INIT, "regulatory domain %x\n", 2753188417Sthompsa sc->sc_regdomain); 2754188417Sthompsa 2755188417Sthompsa /* we'll do software WEP decryption for now */ 2756188417Sthompsa DPRINTF(sc, ZYD_DEBUG_INIT, "%s: setting encryption type\n", 2757188417Sthompsa __func__); 2758188417Sthompsa zyd_write32_m(sc, ZYD_MAC_ENCRYPTION_TYPE, ZYD_ENC_SNIFFER); 2759188417Sthompsa 2760188417Sthompsa sc->sc_flags |= ZYD_FLAG_INITONCE; 2761184610Salfred } 2762184610Salfred 2763188417Sthompsa if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2764191746Sthompsa zyd_stop(sc); 2765188417Sthompsa 2766190526Ssam DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %6D\n", 2767190526Ssam IF_LLADDR(ifp), ":"); 2768190526Ssam error = zyd_set_macaddr(sc, IF_LLADDR(ifp)); 2769188417Sthompsa if (error != 0) 2770184610Salfred return; 2771184610Salfred 2772188417Sthompsa /* set basic rates */ 2773188417Sthompsa if (ic->ic_curmode == IEEE80211_MODE_11B) 2774188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BAS_RATE, 0x0003); 2775188417Sthompsa else if (ic->ic_curmode == IEEE80211_MODE_11A) 2776188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BAS_RATE, 0x1500); 2777188417Sthompsa else /* assumes 802.11b/g */ 2778188417Sthompsa zyd_write32_m(sc, ZYD_MAC_BAS_RATE, 0xff0f); 2779184610Salfred 2780188417Sthompsa /* promiscuous mode */ 2781188417Sthompsa zyd_write32_m(sc, ZYD_MAC_SNIFFER, 0); 2782188417Sthompsa /* multicast setup */ 2783188417Sthompsa zyd_set_multi(sc); 2784188417Sthompsa /* set RX filter */ 2785188417Sthompsa error = zyd_set_rxfilter(sc); 2786188417Sthompsa if (error != 0) 2787188417Sthompsa goto fail; 2788184610Salfred 2789188417Sthompsa /* switch radio transmitter ON */ 2790188417Sthompsa error = zyd_switch_radio(sc, 1); 2791188417Sthompsa if (error != 0) 2792188417Sthompsa goto fail; 2793188417Sthompsa /* set default BSS channel */ 2794188417Sthompsa zyd_set_chan(sc, ic->ic_curchan); 2795184610Salfred 2796188417Sthompsa /* 2797188417Sthompsa * Allocate Tx and Rx xfer queues. 2798188417Sthompsa */ 2799188419Sthompsa zyd_setup_tx_list(sc); 2800184610Salfred 2801188417Sthompsa /* enable interrupts */ 2802188417Sthompsa zyd_write32_m(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK); 2803184610Salfred 2804188417Sthompsa ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2805188417Sthompsa ifp->if_drv_flags |= IFF_DRV_RUNNING; 2806189123Sthompsa usb2_transfer_set_stall(sc->sc_xfer[ZYD_BULK_WR]); 2807188417Sthompsa usb2_transfer_start(sc->sc_xfer[ZYD_BULK_RD]); 2808188417Sthompsa usb2_transfer_start(sc->sc_xfer[ZYD_INTR_RD]); 2809184610Salfred 2810188417Sthompsa return; 2811184610Salfred 2812191746Sthompsafail: zyd_stop(sc); 2813188417Sthompsa return; 2814184610Salfred} 2815184610Salfred 2816184610Salfredstatic void 2817188417Sthompsazyd_init(void *priv) 2818184610Salfred{ 2819188417Sthompsa struct zyd_softc *sc = priv; 2820188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2821188417Sthompsa struct ieee80211com *ic = ifp->if_l2com; 2822184610Salfred 2823188417Sthompsa ZYD_LOCK(sc); 2824191746Sthompsa zyd_init_locked(sc); 2825188417Sthompsa ZYD_UNLOCK(sc); 2826188417Sthompsa 2827188417Sthompsa if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2828188417Sthompsa ieee80211_start_all(ic); /* start all vap's */ 2829184610Salfred} 2830184610Salfred 2831184610Salfredstatic void 2832191746Sthompsazyd_stop(struct zyd_softc *sc) 2833184610Salfred{ 2834188417Sthompsa struct ifnet *ifp = sc->sc_ifp; 2835188417Sthompsa int error; 2836184610Salfred 2837188417Sthompsa ZYD_LOCK_ASSERT(sc, MA_OWNED); 2838184610Salfred 2839188417Sthompsa ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 2840184610Salfred 2841188417Sthompsa /* 2842188419Sthompsa * Drain all the transfers, if not already drained: 2843188417Sthompsa */ 2844188419Sthompsa ZYD_UNLOCK(sc); 2845188419Sthompsa usb2_transfer_drain(sc->sc_xfer[ZYD_BULK_WR]); 2846188419Sthompsa usb2_transfer_drain(sc->sc_xfer[ZYD_BULK_RD]); 2847188419Sthompsa ZYD_LOCK(sc); 2848188417Sthompsa 2849188419Sthompsa zyd_unsetup_tx_list(sc); 2850188417Sthompsa 2851188419Sthompsa /* Stop now if the device was never set up */ 2852188419Sthompsa if (!(sc->sc_flags & ZYD_FLAG_INITONCE)) 2853184610Salfred return; 2854184610Salfred 2855188417Sthompsa /* switch radio transmitter OFF */ 2856188417Sthompsa error = zyd_switch_radio(sc, 0); 2857188417Sthompsa if (error != 0) 2858188417Sthompsa goto fail; 2859188417Sthompsa /* disable Rx */ 2860188417Sthompsa zyd_write32_m(sc, ZYD_MAC_RXFILTER, 0); 2861188417Sthompsa /* disable interrupts */ 2862188417Sthompsa zyd_write32_m(sc, ZYD_CR_INTERRUPT, 0); 2863184610Salfred 2864188417Sthompsafail: 2865188417Sthompsa return; 2866184610Salfred} 2867184610Salfred 2868188417Sthompsastatic int 2869188417Sthompsazyd_loadfirmware(struct zyd_softc *sc) 2870184610Salfred{ 2871192984Sthompsa struct usb_device_request req; 2872188417Sthompsa size_t size; 2873188417Sthompsa u_char *fw; 2874188417Sthompsa uint8_t stat; 2875188417Sthompsa uint16_t addr; 2876184610Salfred 2877188417Sthompsa if (sc->sc_flags & ZYD_FLAG_FWLOADED) 2878188417Sthompsa return (0); 2879184610Salfred 2880188417Sthompsa if (sc->sc_macrev == ZYD_ZD1211) { 2881188417Sthompsa fw = (u_char *)zd1211_firmware; 2882188417Sthompsa size = sizeof(zd1211_firmware); 2883188417Sthompsa } else { 2884188417Sthompsa fw = (u_char *)zd1211b_firmware; 2885188417Sthompsa size = sizeof(zd1211b_firmware); 2886184610Salfred } 2887184610Salfred 2888188417Sthompsa req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 2889188417Sthompsa req.bRequest = ZYD_DOWNLOADREQ; 2890188417Sthompsa USETW(req.wIndex, 0); 2891184610Salfred 2892188417Sthompsa addr = ZYD_FIRMWARE_START_ADDR; 2893188417Sthompsa while (size > 0) { 2894188417Sthompsa /* 2895188417Sthompsa * When the transfer size is 4096 bytes, it is not 2896188417Sthompsa * likely to be able to transfer it. 2897188417Sthompsa * The cause is port or machine or chip? 2898188417Sthompsa */ 2899188417Sthompsa const int mlen = min(size, 64); 2900184610Salfred 2901188417Sthompsa DPRINTF(sc, ZYD_DEBUG_FW, 2902188417Sthompsa "loading firmware block: len=%d, addr=0x%x\n", mlen, addr); 2903184610Salfred 2904188417Sthompsa USETW(req.wValue, addr); 2905188417Sthompsa USETW(req.wLength, mlen); 2906188419Sthompsa if (zyd_do_request(sc, &req, fw) != 0) 2907188417Sthompsa return (EIO); 2908184610Salfred 2909188417Sthompsa addr += mlen / 2; 2910188417Sthompsa fw += mlen; 2911188417Sthompsa size -= mlen; 2912184610Salfred } 2913184610Salfred 2914188417Sthompsa /* check whether the upload succeeded */ 2915188417Sthompsa req.bmRequestType = UT_READ_VENDOR_DEVICE; 2916188417Sthompsa req.bRequest = ZYD_DOWNLOADSTS; 2917188417Sthompsa USETW(req.wValue, 0); 2918188417Sthompsa USETW(req.wIndex, 0); 2919188417Sthompsa USETW(req.wLength, sizeof(stat)); 2920188419Sthompsa if (zyd_do_request(sc, &req, &stat) != 0) 2921188417Sthompsa return (EIO); 2922184610Salfred 2923188417Sthompsa sc->sc_flags |= ZYD_FLAG_FWLOADED; 2924184610Salfred 2925188417Sthompsa return (stat & 0x80) ? (EIO) : (0); 2926184610Salfred} 2927184610Salfred 2928184610Salfredstatic void 2929188417Sthompsazyd_newassoc(struct ieee80211_node *ni, int isnew) 2930184610Salfred{ 2931188417Sthompsa struct ieee80211vap *vap = ni->ni_vap; 2932184610Salfred 2933188417Sthompsa ieee80211_amrr_node_init(&ZYD_VAP(vap)->amrr, &ZYD_NODE(ni)->amn, ni); 2934184610Salfred} 2935184610Salfred 2936188417Sthompsastatic void 2937188417Sthompsazyd_scan_start(struct ieee80211com *ic) 2938184610Salfred{ 2939191746Sthompsa struct ifnet *ifp = ic->ic_ifp; 2940191746Sthompsa struct zyd_softc *sc = ifp->if_softc; 2941184610Salfred 2942188417Sthompsa ZYD_LOCK(sc); 2943191746Sthompsa /* want broadcast address while scanning */ 2944191746Sthompsa zyd_set_bssid(sc, ifp->if_broadcastaddr); 2945188417Sthompsa ZYD_UNLOCK(sc); 2946184610Salfred} 2947184610Salfred 2948184610Salfredstatic void 2949188417Sthompsazyd_scan_end(struct ieee80211com *ic) 2950184610Salfred{ 2951188417Sthompsa struct zyd_softc *sc = ic->ic_ifp->if_softc; 2952184610Salfred 2953188417Sthompsa ZYD_LOCK(sc); 2954191746Sthompsa /* restore previous bssid */ 2955191746Sthompsa zyd_set_bssid(sc, sc->sc_bssid); 2956188417Sthompsa ZYD_UNLOCK(sc); 2957184610Salfred} 2958184610Salfred 2959184610Salfredstatic void 2960188417Sthompsazyd_set_channel(struct ieee80211com *ic) 2961184610Salfred{ 2962188417Sthompsa struct zyd_softc *sc = ic->ic_ifp->if_softc; 2963184610Salfred 2964188417Sthompsa ZYD_LOCK(sc); 2965191746Sthompsa zyd_set_chan(sc, ic->ic_curchan); 2966188417Sthompsa ZYD_UNLOCK(sc); 2967184610Salfred} 2968184610Salfred 2969188417Sthompsastatic device_method_t zyd_methods[] = { 2970188417Sthompsa /* Device interface */ 2971188417Sthompsa DEVMETHOD(device_probe, zyd_match), 2972188417Sthompsa DEVMETHOD(device_attach, zyd_attach), 2973188417Sthompsa DEVMETHOD(device_detach, zyd_detach), 2974191746Sthompsa 2975188417Sthompsa { 0, 0 } 2976188417Sthompsa}; 2977184610Salfred 2978188417Sthompsastatic driver_t zyd_driver = { 2979188417Sthompsa "zyd", 2980188417Sthompsa zyd_methods, 2981188417Sthompsa sizeof(struct zyd_softc) 2982188417Sthompsa}; 2983184610Salfred 2984188417Sthompsastatic devclass_t zyd_devclass; 2985184610Salfred 2986189275SthompsaDRIVER_MODULE(zyd, uhub, zyd_driver, zyd_devclass, NULL, 0); 2987188942SthompsaMODULE_DEPEND(zyd, usb, 1, 1, 1); 2988188417SthompsaMODULE_DEPEND(zyd, wlan, 1, 1, 1); 2989188417SthompsaMODULE_DEPEND(zyd, wlan_amrr, 1, 1, 1); 2990