Home | History | Annotate | Line # | Download | only in usb
      1 /*	$NetBSD: if_otus.c,v 1.46 2026/08/29 01:59:50 maya Exp $	*/
      2 /*	$OpenBSD: if_otus.c,v 1.18 2010/08/27 17:08:00 jsg Exp $	*/
      3 
      4 /*-
      5  * Copyright (c) 2009 Damien Bergamini <damien.bergamini (at) free.fr>
      6  *
      7  * Permission to use, copy, modify, and distribute this software for any
      8  * purpose with or without fee is hereby granted, provided that the above
      9  * copyright notice and this permission notice appear in all copies.
     10  *
     11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18  */
     19 
     20 /*-
     21  * Driver for Atheros AR9001U chipset.
     22  * http://www.atheros.com/pt/bulletins/AR9001USBBulletin.pdf
     23  */
     24 
     25 #include <sys/cdefs.h>
     26 __KERNEL_RCSID(0, "$NetBSD: if_otus.c,v 1.46 2026/08/29 01:59:50 maya Exp $");
     27 
     28 #ifdef _KERNEL_OPT
     29 #include "opt_usb.h"
     30 #endif
     31 
     32 #include <sys/param.h>
     33 #include <sys/sockio.h>
     34 #include <sys/mbuf.h>
     35 #include <sys/kernel.h>
     36 #include <sys/kmem.h>
     37 #include <sys/kthread.h>
     38 #include <sys/systm.h>
     39 #include <sys/callout.h>
     40 #include <sys/device.h>
     41 #include <sys/proc.h>
     42 #include <sys/bus.h>
     43 #include <sys/endian.h>
     44 #include <sys/intr.h>
     45 
     46 #include <net/bpf.h>
     47 #include <net/if.h>
     48 #include <net/if_arp.h>
     49 #include <net/if_dl.h>
     50 #include <net/if_ether.h>
     51 #include <net/if_media.h>
     52 #include <net/if_types.h>
     53 
     54 #include <netinet/in.h>
     55 #include <netinet/in_systm.h>
     56 #include <netinet/in_var.h>
     57 #include <netinet/ip.h>
     58 
     59 #include <net80211/ieee80211_var.h>
     60 #include <net80211/ieee80211_amrr.h>
     61 #include <net80211/ieee80211_radiotap.h>
     62 
     63 #include <dev/firmload.h>
     64 
     65 #include <dev/usb/usb.h>
     66 #include <dev/usb/usbdi.h>
     67 #include <dev/usb/usbdi_util.h>
     68 #include <dev/usb/usbdivar.h>
     69 #include <dev/usb/usbdevs.h>
     70 
     71 #include <dev/usb/if_otusreg.h>
     72 #include <dev/usb/if_otusvar.h>
     73 
     74 #ifdef OTUS_DEBUG
     75 
     76 #define	DBG_INIT	__BIT(0)
     77 #define	DBG_FN		__BIT(1)
     78 #define	DBG_TX		__BIT(2)
     79 #define	DBG_RX		__BIT(3)
     80 #define	DBG_STM		__BIT(4)
     81 #define	DBG_CHAN	__BIT(5)
     82 #define	DBG_REG		__BIT(6)
     83 #define	DBG_CMD		__BIT(7)
     84 #define	DBG_ALL		0xffffffffU
     85 #define DBG_NO_SC	(struct otus_softc *)NULL
     86 
     87 unsigned int otus_debug = 0;
     88 #define DPRINTFN(n, s, ...) do { \
     89 	if (otus_debug & (n)) { \
     90 		if ((s) != NULL) \
     91 			printf("%s: ", device_xname((s)->sc_dev)); \
     92 		else \
     93 			printf("otus0: "); \
     94 		printf("%s: ", __func__); \
     95 		printf(__VA_ARGS__); \
     96 	} \
     97 } while (0)
     98 
     99 #else	/* ! OTUS_DEBUG */
    100 
    101 #define DPRINTFN(n, ...) \
    102 	do { } while (0)
    103 
    104 #endif	/* OTUS_DEBUG */
    105 
    106 Static int	otus_match(device_t, cfdata_t, void *);
    107 Static void	otus_attach(device_t, device_t, void *);
    108 Static int	otus_detach(device_t, int);
    109 Static int	otus_activate(device_t, devact_t);
    110 Static void	otus_attachhook(device_t);
    111 Static void	otus_get_chanlist(struct otus_softc *);
    112 Static int	otus_load_firmware(struct otus_softc *, const char *,
    113 		    uint32_t);
    114 Static int	otus_open_pipes(struct otus_softc *);
    115 Static void	otus_close_pipes(struct otus_softc *);
    116 Static int	otus_alloc_tx_cmd(struct otus_softc *);
    117 Static void	otus_free_tx_cmd(struct otus_softc *);
    118 Static int	otus_alloc_tx_data_list(struct otus_softc *);
    119 Static void	otus_free_tx_data_list(struct otus_softc *);
    120 Static int	otus_alloc_rx_data_list(struct otus_softc *);
    121 Static void	otus_free_rx_data_list(struct otus_softc *);
    122 Static void	otus_next_scan(void *);
    123 Static void	otus_task(void *);
    124 Static void	otus_do_async(struct otus_softc *,
    125 		    void (*)(struct otus_softc *, void *), void *, int);
    126 Static int	otus_newstate(struct ieee80211com *, enum ieee80211_state,
    127 		    int);
    128 Static void	otus_newstate_cb(struct otus_softc *, void *);
    129 Static int	otus_cmd(struct otus_softc *, uint8_t, const void *, int,
    130 		    void *);
    131 Static void	otus_write(struct otus_softc *, uint32_t, uint32_t);
    132 Static int	otus_write_barrier(struct otus_softc *);
    133 Static struct	ieee80211_node *otus_node_alloc(struct ieee80211_node_table *);
    134 Static int	otus_media_change(struct ifnet *);
    135 Static int	otus_read_eeprom(struct otus_softc *);
    136 Static void	otus_newassoc(struct ieee80211_node *, int);
    137 Static void	otus_intr(struct usbd_xfer *, void *, usbd_status);
    138 Static void	otus_cmd_rxeof(struct otus_softc *, uint8_t *, int);
    139 Static void	otus_sub_rxeof(struct otus_softc *, uint8_t *, int);
    140 Static void	otus_rxeof(struct usbd_xfer *, void *, usbd_status);
    141 Static void	otus_txeof(struct usbd_xfer *, void *, usbd_status);
    142 Static int	otus_tx(struct otus_softc *, struct mbuf *,
    143 		    struct ieee80211_node *, struct otus_tx_data *);
    144 Static void	otus_start(struct ifnet *);
    145 Static void	otus_watchdog(struct ifnet *);
    146 Static int	otus_ioctl(struct ifnet *, u_long, void *);
    147 Static int	otus_set_multi(struct otus_softc *);
    148 #ifdef HAVE_EDCA
    149 Static void	otus_updateedca(struct ieee80211com *);
    150 Static void	otus_updateedca_cb(struct otus_softc *, void *);
    151 #endif
    152 Static void	otus_updateedca_cb_locked(struct otus_softc *);
    153 Static void	otus_updateslot(struct ifnet *);
    154 Static void	otus_updateslot_cb(struct otus_softc *, void *);
    155 Static void	otus_updateslot_cb_locked(struct otus_softc *);
    156 Static int	otus_init_mac(struct otus_softc *);
    157 Static uint32_t	otus_phy_get_def(struct otus_softc *, uint32_t);
    158 Static int	otus_set_board_values(struct otus_softc *,
    159 		    struct ieee80211_channel *);
    160 Static int	otus_program_phy(struct otus_softc *,
    161 		    struct ieee80211_channel *);
    162 Static int	otus_set_rf_bank4(struct otus_softc *,
    163 		    struct ieee80211_channel *);
    164 Static void	otus_get_delta_slope(uint32_t, uint32_t *, uint32_t *);
    165 Static int	otus_set_chan(struct otus_softc *, struct ieee80211_channel *,
    166 		    int);
    167 #ifdef notyet
    168 Static int	otus_set_key(struct ieee80211com *, struct ieee80211_node *,
    169 		    struct ieee80211_key *);
    170 Static void	otus_set_key_cb(struct otus_softc *, void *);
    171 Static void	otus_delete_key(struct ieee80211com *, struct ieee80211_node *,
    172 		    struct ieee80211_key *);
    173 Static void	otus_delete_key_cb(struct otus_softc *, void *);
    174 #endif /* notyet */
    175 Static void	otus_calib_to(void *);
    176 Static int	otus_set_bssid(struct otus_softc *, const uint8_t *);
    177 Static int	otus_set_macaddr(struct otus_softc *, const uint8_t *);
    178 #ifdef notyet
    179 Static void	otus_led_newstate_type1(struct otus_softc *);
    180 Static void	otus_led_newstate_type2(struct otus_softc *);
    181 #endif /* notyet */
    182 Static void	otus_led_newstate_type3(struct otus_softc *);
    183 Static int	otus_init(struct ifnet *);
    184 Static void	otus_stop(struct ifnet *);
    185 Static void	otus_wait_async(struct otus_softc *);
    186 
    187 /* List of supported channels. */
    188 static const uint8_t ar_chans[] = {
    189 	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
    190 	36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124,
    191 	128, 132, 136, 140, 149, 153, 157, 161, 165, 34, 38, 42, 46
    192 };
    193 
    194 /*
    195  * This data is automatically generated from the "otus.ini" file.
    196  * It is stored in a different way though, to reduce kernel's .rodata
    197  * section overhead (5.1KB instead of 8.5KB).
    198  */
    199 
    200 /* NB: apply AR_PHY(). */
    201 static const uint16_t ar5416_phy_regs[] = {
    202 	0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008,
    203 	0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f, 0x010, 0x011,
    204 	0x012, 0x013, 0x014, 0x015, 0x016, 0x017, 0x018, 0x01a, 0x01b,
    205 	0x040, 0x041, 0x042, 0x043, 0x045, 0x046, 0x047, 0x048, 0x049,
    206 	0x04a, 0x04b, 0x04d, 0x04e, 0x04f, 0x051, 0x052, 0x053, 0x055,
    207 	0x056, 0x058, 0x059, 0x05c, 0x05d, 0x05e, 0x05f, 0x060, 0x061,
    208 	0x062, 0x063, 0x064, 0x065, 0x066, 0x067, 0x068, 0x069, 0x06a,
    209 	0x06b, 0x06c, 0x06d, 0x070, 0x071, 0x072, 0x073, 0x074, 0x075,
    210 	0x076, 0x077, 0x078, 0x079, 0x07a, 0x07b, 0x07c, 0x07f, 0x080,
    211 	0x081, 0x082, 0x083, 0x084, 0x085, 0x086, 0x087, 0x088, 0x089,
    212 	0x08a, 0x08b, 0x08c, 0x08d, 0x08e, 0x08f, 0x090, 0x091, 0x092,
    213 	0x093, 0x094, 0x095, 0x096, 0x097, 0x098, 0x099, 0x09a, 0x09b,
    214 	0x09c, 0x09d, 0x09e, 0x09f, 0x0a0, 0x0a1, 0x0a2, 0x0a3, 0x0a4,
    215 	0x0a5, 0x0a6, 0x0a7, 0x0a8, 0x0a9, 0x0aa, 0x0ab, 0x0ac, 0x0ad,
    216 	0x0ae, 0x0af, 0x0b0, 0x0b1, 0x0b2, 0x0b3, 0x0b4, 0x0b5, 0x0b6,
    217 	0x0b7, 0x0b8, 0x0b9, 0x0ba, 0x0bb, 0x0bc, 0x0bd, 0x0be, 0x0bf,
    218 	0x0c0, 0x0c1, 0x0c2, 0x0c3, 0x0c4, 0x0c5, 0x0c6, 0x0c7, 0x0c8,
    219 	0x0c9, 0x0ca, 0x0cb, 0x0cc, 0x0cd, 0x0ce, 0x0cf, 0x0d0, 0x0d1,
    220 	0x0d2, 0x0d3, 0x0d4, 0x0d5, 0x0d6, 0x0d7, 0x0d8, 0x0d9, 0x0da,
    221 	0x0db, 0x0dc, 0x0dd, 0x0de, 0x0df, 0x0e0, 0x0e1, 0x0e2, 0x0e3,
    222 	0x0e4, 0x0e5, 0x0e6, 0x0e7, 0x0e8, 0x0e9, 0x0ea, 0x0eb, 0x0ec,
    223 	0x0ed, 0x0ee, 0x0ef, 0x0f0, 0x0f1, 0x0f2, 0x0f3, 0x0f4, 0x0f5,
    224 	0x0f6, 0x0f7, 0x0f8, 0x0f9, 0x0fa, 0x0fb, 0x0fc, 0x0fd, 0x0fe,
    225 	0x0ff, 0x100, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109,
    226 	0x10a, 0x10b, 0x10c, 0x10d, 0x10e, 0x10f, 0x13c, 0x13d, 0x13e,
    227 	0x13f, 0x280, 0x281, 0x282, 0x283, 0x284, 0x285, 0x286, 0x287,
    228 	0x288, 0x289, 0x28a, 0x28b, 0x28c, 0x28d, 0x28e, 0x28f, 0x290,
    229 	0x291, 0x292, 0x293, 0x294, 0x295, 0x296, 0x297, 0x298, 0x299,
    230 	0x29a, 0x29b, 0x29d, 0x29e, 0x29f, 0x2c0, 0x2c1, 0x2c2, 0x2c3,
    231 	0x2c4, 0x2c5, 0x2c6, 0x2c7, 0x2c8, 0x2c9, 0x2ca, 0x2cb, 0x2cc,
    232 	0x2cd, 0x2ce, 0x2cf, 0x2d0, 0x2d1, 0x2d2, 0x2d3, 0x2d4, 0x2d5,
    233 	0x2d6, 0x2e2, 0x2e3, 0x2e4, 0x2e5, 0x2e6, 0x2e7, 0x2e8, 0x2e9,
    234 	0x2ea, 0x2eb, 0x2ec, 0x2ed, 0x2ee, 0x2ef, 0x2f0, 0x2f1, 0x2f2,
    235 	0x2f3, 0x2f4, 0x2f5, 0x2f6, 0x2f7, 0x2f8, 0x412, 0x448, 0x458,
    236 	0x683, 0x69b, 0x812, 0x848, 0x858, 0xa83, 0xa9b, 0xc19, 0xc57,
    237 	0xc5a, 0xc6f, 0xe9c, 0xed7, 0xed8, 0xed9, 0xeda, 0xedb, 0xedc,
    238 	0xedd, 0xede, 0xedf, 0xee0, 0xee1
    239 };
    240 
    241 static const uint32_t ar5416_phy_vals_5ghz_20mhz[] = {
    242 	0x00000007, 0x00000300, 0x00000000, 0xad848e19, 0x7d14e000,
    243 	0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e,
    244 	0x0a020001, 0x0000a000, 0x00000000, 0x00000e0e, 0x00000007,
    245 	0x00200400, 0x206a002e, 0x1372161e, 0x001a6a65, 0x1284233c,
    246 	0x6c48b4e4, 0x00000859, 0x7ec80d2e, 0x31395c5e, 0x0004dd10,
    247 	0x409a4190, 0x050cb081, 0x00000000, 0x00000000, 0x00000000,
    248 	0x00000000, 0x000007d0, 0x00000118, 0x10000fff, 0x0510081c,
    249 	0xd0058a15, 0x00000001, 0x00000004, 0x3f3f3f3f, 0x3f3f3f3f,
    250 	0x0000007f, 0xdfb81020, 0x9280b212, 0x00020028, 0x5d50e188,
    251 	0x00081fff, 0x00009b40, 0x00001120, 0x190fb515, 0x00000000,
    252 	0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    253 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    254 	0x00000000, 0x00000007, 0x001fff00, 0x006f00c4, 0x03051000,
    255 	0x00000820, 0x038919be, 0x06336f77, 0x60f6532c, 0x08f186c8,
    256 	0x00046384, 0x00000000, 0x00000000, 0x00000000, 0x00000200,
    257 	0x64646464, 0x3c787878, 0x000000aa, 0x00000000, 0x00001042,
    258 	0x00000000, 0x00000040, 0x00000080, 0x000001a1, 0x000001e1,
    259 	0x00000021, 0x00000061, 0x00000168, 0x000001a8, 0x000001e8,
    260 	0x00000028, 0x00000068, 0x00000189, 0x000001c9, 0x00000009,
    261 	0x00000049, 0x00000089, 0x00000170, 0x000001b0, 0x000001f0,
    262 	0x00000030, 0x00000070, 0x00000191, 0x000001d1, 0x00000011,
    263 	0x00000051, 0x00000091, 0x000001b8, 0x000001f8, 0x00000038,
    264 	0x00000078, 0x00000199, 0x000001d9, 0x00000019, 0x00000059,
    265 	0x00000099, 0x000000d9, 0x000000f9, 0x000000f9, 0x000000f9,
    266 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    267 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    268 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    269 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    270 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x00000000,
    271 	0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005,
    272 	0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,
    273 	0x0000000d, 0x00000010, 0x00000011, 0x00000012, 0x00000013,
    274 	0x00000014, 0x00000015, 0x00000018, 0x00000019, 0x0000001a,
    275 	0x0000001b, 0x0000001c, 0x0000001d, 0x00000020, 0x00000021,
    276 	0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000028,
    277 	0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d,
    278 	0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034,
    279 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    280 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    281 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    282 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    283 	0x00000035, 0x00000010, 0x0000001a, 0x00000000, 0x00000000,
    284 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    285 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    286 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    287 	0x00000000, 0x00000008, 0x00000440, 0xd6be4788, 0x012e8160,
    288 	0x40806333, 0x00106c10, 0x009c4060, 0x1883800a, 0x018830c6,
    289 	0x00000400, 0x000009b5, 0x00000000, 0x00000108, 0x3f3f3f3f,
    290 	0x3f3f3f3f, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc,
    291 	0x00000001, 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01,
    292 	0xdfa91f01, 0x00418a11, 0x00000000, 0x09249126, 0x0a1a9caa,
    293 	0x1ce739ce, 0x051701ce, 0x18010000, 0x30032602, 0x48073e06,
    294 	0x560b4c0a, 0x641a600f, 0x7a4f6e1b, 0x8c5b7e5a, 0x9d0f96cf,
    295 	0xb51fa69f, 0xcb3fbd07, 0x0000d7bf, 0x00000000, 0x00000000,
    296 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    297 	0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff, 0x79a8aa1f,
    298 	0x08000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x1ce739ce, 0x000001ce,
    299 	0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    300 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    301 	0x00000000, 0x00000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f,
    302 	0x00000000, 0x1ce739ce, 0x000000c0, 0x00180a65, 0x0510001c,
    303 	0x00009b40, 0x012e8160, 0x09249126, 0x00180a65, 0x0510001c,
    304 	0x00009b40, 0x012e8160, 0x09249126, 0x0001c600, 0x004b6a8e,
    305 	0x000003ce, 0x00181400, 0x00820820, 0x066c420f, 0x0f282207,
    306 	0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803,
    307 	0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0
    308 };
    309 
    310 #ifdef notyet
    311 static const uint32_t ar5416_phy_vals_5ghz_40mhz[] = {
    312 	0x00000007, 0x000003c4, 0x00000000, 0xad848e19, 0x7d14e000,
    313 	0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e,
    314 	0x0a020001, 0x0000a000, 0x00000000, 0x00000e0e, 0x00000007,
    315 	0x00200400, 0x206a002e, 0x13721c1e, 0x001a6a65, 0x1284233c,
    316 	0x6c48b4e4, 0x00000859, 0x7ec80d2e, 0x31395c5e, 0x0004dd10,
    317 	0x409a4190, 0x050cb081, 0x00000000, 0x00000000, 0x00000000,
    318 	0x00000000, 0x000007d0, 0x00000230, 0x10000fff, 0x0510081c,
    319 	0xd0058a15, 0x00000001, 0x00000004, 0x3f3f3f3f, 0x3f3f3f3f,
    320 	0x0000007f, 0xdfb81020, 0x9280b212, 0x00020028, 0x5d50e188,
    321 	0x00081fff, 0x00009b40, 0x00001120, 0x190fb515, 0x00000000,
    322 	0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    323 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    324 	0x00000000, 0x00000007, 0x001fff00, 0x006f00c4, 0x03051000,
    325 	0x00000820, 0x038919be, 0x06336f77, 0x60f6532c, 0x08f186c8,
    326 	0x00046384, 0x00000000, 0x00000000, 0x00000000, 0x00000200,
    327 	0x64646464, 0x3c787878, 0x000000aa, 0x00000000, 0x00001042,
    328 	0x00000000, 0x00000040, 0x00000080, 0x000001a1, 0x000001e1,
    329 	0x00000021, 0x00000061, 0x00000168, 0x000001a8, 0x000001e8,
    330 	0x00000028, 0x00000068, 0x00000189, 0x000001c9, 0x00000009,
    331 	0x00000049, 0x00000089, 0x00000170, 0x000001b0, 0x000001f0,
    332 	0x00000030, 0x00000070, 0x00000191, 0x000001d1, 0x00000011,
    333 	0x00000051, 0x00000091, 0x000001b8, 0x000001f8, 0x00000038,
    334 	0x00000078, 0x00000199, 0x000001d9, 0x00000019, 0x00000059,
    335 	0x00000099, 0x000000d9, 0x000000f9, 0x000000f9, 0x000000f9,
    336 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    337 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    338 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    339 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    340 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x00000000,
    341 	0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005,
    342 	0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,
    343 	0x0000000d, 0x00000010, 0x00000011, 0x00000012, 0x00000013,
    344 	0x00000014, 0x00000015, 0x00000018, 0x00000019, 0x0000001a,
    345 	0x0000001b, 0x0000001c, 0x0000001d, 0x00000020, 0x00000021,
    346 	0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000028,
    347 	0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d,
    348 	0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034,
    349 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    350 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    351 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    352 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    353 	0x00000035, 0x00000010, 0x0000001a, 0x00000000, 0x00000000,
    354 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    355 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    356 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    357 	0x00000000, 0x00000008, 0x00000440, 0xd6be4788, 0x012e8160,
    358 	0x40806333, 0x00106c10, 0x009c4060, 0x1883800a, 0x018830c6,
    359 	0x00000400, 0x000009b5, 0x00000000, 0x00000210, 0x3f3f3f3f,
    360 	0x3f3f3f3f, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc,
    361 	0x00000001, 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01,
    362 	0xdfa91f01, 0x00418a11, 0x00000000, 0x09249126, 0x0a1a9caa,
    363 	0x1ce739ce, 0x051701ce, 0x18010000, 0x30032602, 0x48073e06,
    364 	0x560b4c0a, 0x641a600f, 0x7a4f6e1b, 0x8c5b7e5a, 0x9d0f96cf,
    365 	0xb51fa69f, 0xcb3fbcbf, 0x0000d7bf, 0x00000000, 0x00000000,
    366 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    367 	0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff, 0x79a8aa1f,
    368 	0x08000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x1ce739ce, 0x000001ce,
    369 	0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    370 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    371 	0x00000000, 0x00000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f,
    372 	0x00000000, 0x1ce739ce, 0x000000c0, 0x00180a65, 0x0510001c,
    373 	0x00009b40, 0x012e8160, 0x09249126, 0x00180a65, 0x0510001c,
    374 	0x00009b40, 0x012e8160, 0x09249126, 0x0001c600, 0x004b6a8e,
    375 	0x000003ce, 0x00181400, 0x00820820, 0x066c420f, 0x0f282207,
    376 	0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803,
    377 	0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0
    378 };
    379 #endif
    380 
    381 #ifdef notyet
    382 static const uint32_t ar5416_phy_vals_2ghz_40mhz[] = {
    383 	0x00000007, 0x000003c4, 0x00000000, 0xad848e19, 0x7d14e000,
    384 	0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e,
    385 	0x0a020001, 0x0000a000, 0x00000000, 0x00000e0e, 0x00000007,
    386 	0x00200400, 0x206a002e, 0x13721c24, 0x00197a68, 0x1284233c,
    387 	0x6c48b0e4, 0x00000859, 0x7ec80d2e, 0x31395c5e, 0x0004dd20,
    388 	0x409a4190, 0x050cb081, 0x00000000, 0x00000000, 0x00000000,
    389 	0x00000000, 0x00000898, 0x00000268, 0x10000fff, 0x0510001c,
    390 	0xd0058a15, 0x00000001, 0x00000004, 0x3f3f3f3f, 0x3f3f3f3f,
    391 	0x0000007f, 0xdfb81020, 0x9280b212, 0x00020028, 0x5d50e188,
    392 	0x00081fff, 0x00009b40, 0x00001120, 0x190fb515, 0x00000000,
    393 	0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    394 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    395 	0x00000000, 0x00000007, 0x001fff00, 0x006f00c4, 0x03051000,
    396 	0x00000820, 0x038919be, 0x06336f77, 0x60f6532c, 0x08f186c8,
    397 	0x00046384, 0x00000000, 0x00000000, 0x00000000, 0x00000200,
    398 	0x64646464, 0x3c787878, 0x000000aa, 0x00000000, 0x00001042,
    399 	0x00000000, 0x00000040, 0x00000080, 0x00000141, 0x00000181,
    400 	0x000001c1, 0x00000001, 0x00000041, 0x000001a8, 0x000001e8,
    401 	0x00000028, 0x00000068, 0x000000a8, 0x00000169, 0x000001a9,
    402 	0x000001e9, 0x00000029, 0x00000069, 0x00000190, 0x000001d0,
    403 	0x00000010, 0x00000050, 0x00000090, 0x00000151, 0x00000191,
    404 	0x000001d1, 0x00000011, 0x00000051, 0x00000198, 0x000001d8,
    405 	0x00000018, 0x00000058, 0x00000098, 0x00000159, 0x00000199,
    406 	0x000001d9, 0x00000019, 0x00000059, 0x00000099, 0x000000d9,
    407 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    408 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    409 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    410 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    411 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x00000000,
    412 	0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005,
    413 	0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,
    414 	0x0000000d, 0x00000010, 0x00000011, 0x00000012, 0x00000013,
    415 	0x00000014, 0x00000015, 0x00000018, 0x00000019, 0x0000001a,
    416 	0x0000001b, 0x0000001c, 0x0000001d, 0x00000020, 0x00000021,
    417 	0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000028,
    418 	0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d,
    419 	0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034,
    420 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    421 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    422 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    423 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    424 	0x00000035, 0x00000010, 0x0000001a, 0x00000000, 0x00000000,
    425 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    426 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    427 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    428 	0x00000000, 0x0000000e, 0x00000440, 0xd03e4788, 0x012a8160,
    429 	0x40806333, 0x00106c10, 0x009c4060, 0x1883800a, 0x018830c6,
    430 	0x00000400, 0x000009b5, 0x00000000, 0x00000210, 0x3f3f3f3f,
    431 	0x3f3f3f3f, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc,
    432 	0x00000001, 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01,
    433 	0xdfa91f01, 0x00418a11, 0x00000000, 0x09249126, 0x0a1a7caa,
    434 	0x1ce739ce, 0x051701ce, 0x18010000, 0x2e032402, 0x4a0a3c06,
    435 	0x621a540b, 0x764f6c1b, 0x845b7a5a, 0x950f8ccf, 0xa5cf9b4f,
    436 	0xbddfaf1f, 0xd1ffc93f, 0x00000000, 0x00000000, 0x00000000,
    437 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    438 	0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff, 0x79a8aa1f,
    439 	0x08000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x1ce739ce, 0x000001ce,
    440 	0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    441 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    442 	0x00000000, 0x00000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f,
    443 	0x00000000, 0x1ce739ce, 0x000000c0, 0x00180a68, 0x0510001c,
    444 	0x00009b40, 0x012a8160, 0x09249126, 0x00180a68, 0x0510001c,
    445 	0x00009b40, 0x012a8160, 0x09249126, 0x0001c600, 0x004b6a8e,
    446 	0x000003ce, 0x00181400, 0x00820820, 0x066c420f, 0x0f282207,
    447 	0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803,
    448 	0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0
    449 };
    450 #endif
    451 
    452 static const uint32_t ar5416_phy_vals_2ghz_20mhz[] = {
    453 	0x00000007, 0x00000300, 0x00000000, 0xad848e19, 0x7d14e000,
    454 	0x9c0a9f6b, 0x00000090, 0x00000000, 0x02020200, 0x00000e0e,
    455 	0x0a020001, 0x0000a000, 0x00000000, 0x00000e0e, 0x00000007,
    456 	0x00200400, 0x206a002e, 0x137216a4, 0x00197a68, 0x1284233c,
    457 	0x6c48b0e4, 0x00000859, 0x7ec80d2e, 0x31395c5e, 0x0004dd20,
    458 	0x409a4190, 0x050cb081, 0x00000000, 0x00000000, 0x00000000,
    459 	0x00000000, 0x00000898, 0x00000134, 0x10000fff, 0x0510001c,
    460 	0xd0058a15, 0x00000001, 0x00000004, 0x3f3f3f3f, 0x3f3f3f3f,
    461 	0x0000007f, 0xdfb81020, 0x9280b212, 0x00020028, 0x5d50e188,
    462 	0x00081fff, 0x00009b40, 0x00001120, 0x190fb515, 0x00000000,
    463 	0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    464 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    465 	0x00000000, 0x00000007, 0x001fff00, 0x006f00c4, 0x03051000,
    466 	0x00000820, 0x038919be, 0x06336f77, 0x60f6532c, 0x08f186c8,
    467 	0x00046384, 0x00000000, 0x00000000, 0x00000000, 0x00000200,
    468 	0x64646464, 0x3c787878, 0x000000aa, 0x00000000, 0x00001042,
    469 	0x00000000, 0x00000040, 0x00000080, 0x00000141, 0x00000181,
    470 	0x000001c1, 0x00000001, 0x00000041, 0x000001a8, 0x000001e8,
    471 	0x00000028, 0x00000068, 0x000000a8, 0x00000169, 0x000001a9,
    472 	0x000001e9, 0x00000029, 0x00000069, 0x00000190, 0x000001d0,
    473 	0x00000010, 0x00000050, 0x00000090, 0x00000151, 0x00000191,
    474 	0x000001d1, 0x00000011, 0x00000051, 0x00000198, 0x000001d8,
    475 	0x00000018, 0x00000058, 0x00000098, 0x00000159, 0x00000199,
    476 	0x000001d9, 0x00000019, 0x00000059, 0x00000099, 0x000000d9,
    477 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    478 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    479 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    480 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9,
    481 	0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0x00000000,
    482 	0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005,
    483 	0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,
    484 	0x0000000d, 0x00000010, 0x00000011, 0x00000012, 0x00000013,
    485 	0x00000014, 0x00000015, 0x00000018, 0x00000019, 0x0000001a,
    486 	0x0000001b, 0x0000001c, 0x0000001d, 0x00000020, 0x00000021,
    487 	0x00000022, 0x00000023, 0x00000024, 0x00000025, 0x00000028,
    488 	0x00000029, 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d,
    489 	0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034,
    490 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    491 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    492 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    493 	0x00000035, 0x00000035, 0x00000035, 0x00000035, 0x00000035,
    494 	0x00000035, 0x00000010, 0x0000001a, 0x00000000, 0x00000000,
    495 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    496 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    497 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    498 	0x00000000, 0x0000000e, 0x00000440, 0xd03e4788, 0x012a8160,
    499 	0x40806333, 0x00106c10, 0x009c4060, 0x1883800a, 0x018830c6,
    500 	0x00000400, 0x000009b5, 0x00000000, 0x00000108, 0x3f3f3f3f,
    501 	0x3f3f3f3f, 0x13c889af, 0x38490a20, 0x00007bb6, 0x0fff3ffc,
    502 	0x00000001, 0x0000a000, 0x00000000, 0x0cc75380, 0x0f0f0f01,
    503 	0xdfa91f01, 0x00418a11, 0x00000000, 0x09249126, 0x0a1a7caa,
    504 	0x1ce739ce, 0x051701ce, 0x18010000, 0x2e032402, 0x4a0a3c06,
    505 	0x621a540b, 0x764f6c1b, 0x845b7a5a, 0x950f8ccf, 0xa5cf9b4f,
    506 	0xbddfaf1f, 0xd1ffc93f, 0x00000000, 0x00000000, 0x00000000,
    507 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    508 	0x3fffffff, 0x3fffffff, 0x3fffffff, 0x0003ffff, 0x79a8aa1f,
    509 	0x08000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x1ce739ce, 0x000001ce,
    510 	0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    511 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    512 	0x00000000, 0x00000000, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f,
    513 	0x00000000, 0x1ce739ce, 0x000000c0, 0x00180a68, 0x0510001c,
    514 	0x00009b40, 0x012a8160, 0x09249126, 0x00180a68, 0x0510001c,
    515 	0x00009b40, 0x012a8160, 0x09249126, 0x0001c600, 0x004b6a8e,
    516 	0x000003ce, 0x00181400, 0x00820820, 0x066c420f, 0x0f282207,
    517 	0x17601685, 0x1f801104, 0x37a00c03, 0x3fc40883, 0x57c00803,
    518 	0x5fd80682, 0x7fe00482, 0x7f3c7bba, 0xf3307ff0
    519 };
    520 
    521 /* NB: apply AR_PHY(). */
    522 static const uint8_t ar5416_banks_regs[] = {
    523 	0x2c, 0x38, 0x2c, 0x3b, 0x2c, 0x38, 0x3c, 0x2c, 0x3a, 0x2c, 0x39,
    524 	0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
    525 	0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
    526 	0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
    527 	0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
    528 	0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x38, 0x2c, 0x2c,
    529 	0x2c, 0x3c
    530 };
    531 
    532 static const uint32_t ar5416_banks_vals_5ghz[] = {
    533 	0x1e5795e5, 0x02008020, 0x02108421, 0x00000008, 0x0e73ff17,
    534 	0x00000420, 0x01400018, 0x000001a1, 0x00000001, 0x00000013,
    535 	0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    536 	0x00000000, 0x00004000, 0x00006c00, 0x00002c00, 0x00004800,
    537 	0x00004000, 0x00006000, 0x00001000, 0x00004000, 0x00007c00,
    538 	0x00007c00, 0x00007c00, 0x00007c00, 0x00007c00, 0x00087c00,
    539 	0x00007c00, 0x00005400, 0x00000c00, 0x00001800, 0x00007c00,
    540 	0x00006c00, 0x00006c00, 0x00007c00, 0x00002c00, 0x00003c00,
    541 	0x00003800, 0x00001c00, 0x00000800, 0x00000408, 0x00004c15,
    542 	0x00004188, 0x0000201e, 0x00010408, 0x00000801, 0x00000c08,
    543 	0x0000181e, 0x00001016, 0x00002800, 0x00004010, 0x0000081c,
    544 	0x00000115, 0x00000015, 0x00000066, 0x0000001c, 0x00000000,
    545 	0x00000004, 0x00000015, 0x0000001f, 0x00000000, 0x000000a0,
    546 	0x00000000, 0x00000040, 0x0000001c
    547 };
    548 
    549 static const uint32_t ar5416_banks_vals_2ghz[] = {
    550 	0x1e5795e5, 0x02008020, 0x02108421, 0x00000008, 0x0e73ff17,
    551 	0x00000420, 0x01c00018, 0x000001a1, 0x00000001, 0x00000013,
    552 	0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    553 	0x00000000, 0x00004000, 0x00006c00, 0x00002c00, 0x00004800,
    554 	0x00004000, 0x00006000, 0x00001000, 0x00004000, 0x00007c00,
    555 	0x00007c00, 0x00007c00, 0x00007c00, 0x00007c00, 0x00087c00,
    556 	0x00007c00, 0x00005400, 0x00000c00, 0x00001800, 0x00007c00,
    557 	0x00006c00, 0x00006c00, 0x00007c00, 0x00002c00, 0x00003c00,
    558 	0x00003800, 0x00001c00, 0x00000800, 0x00000408, 0x00004c15,
    559 	0x00004188, 0x0000201e, 0x00010408, 0x00000801, 0x00000c08,
    560 	0x0000181e, 0x00001016, 0x00002800, 0x00004010, 0x0000081c,
    561 	0x00000115, 0x00000015, 0x00000066, 0x0000001c, 0x00000000,
    562 	0x00000004, 0x00000015, 0x0000001f, 0x00000400, 0x000000a0,
    563 	0x00000000, 0x00000040, 0x0000001c
    564 };
    565 
    566 static const struct usb_devno otus_devs[] = {
    567 	{ USB_VENDOR_ACCTON,		USB_PRODUCT_ACCTON_WN7512 },
    568 	{ USB_VENDOR_ATHEROS2,		USB_PRODUCT_ATHEROS2_3CRUSBN275 },
    569 	{ USB_VENDOR_ATHEROS2,		USB_PRODUCT_ATHEROS2_TG121N },
    570 	{ USB_VENDOR_ATHEROS2,		USB_PRODUCT_ATHEROS2_AR9170 },
    571 	{ USB_VENDOR_ATHEROS2,		USB_PRODUCT_ATHEROS2_WN612 },
    572 	{ USB_VENDOR_ATHEROS2,		USB_PRODUCT_ATHEROS2_WN821NV2 },
    573 	{ USB_VENDOR_AVM,		USB_PRODUCT_AVM_FRITZWLAN },
    574 	{ USB_VENDOR_CACE,		USB_PRODUCT_CACE_AIRPCAPNX },
    575 	{ USB_VENDOR_DLINK2,		USB_PRODUCT_DLINK2_DWA130D1 },
    576 	{ USB_VENDOR_DLINK2,		USB_PRODUCT_DLINK2_DWA160A1 },
    577 	{ USB_VENDOR_DLINK2,		USB_PRODUCT_DLINK2_DWA160A2 },
    578 	{ USB_VENDOR_IODATA,		USB_PRODUCT_IODATA_WNGDNUS2 },
    579 	{ USB_VENDOR_NEC,		USB_PRODUCT_NEC_WL300NUG },
    580 	{ USB_VENDOR_NETGEAR,		USB_PRODUCT_NETGEAR_WN111V2 },
    581 	{ USB_VENDOR_NETGEAR,		USB_PRODUCT_NETGEAR_WNA1000 },
    582 	{ USB_VENDOR_NETGEAR,		USB_PRODUCT_NETGEAR_WNDA3100 },
    583 	{ USB_VENDOR_PLANEX2,		USB_PRODUCT_PLANEX2_GW_US300 },
    584 	{ USB_VENDOR_WISTRONNEWEB,	USB_PRODUCT_WISTRONNEWEB_O8494 },
    585 	{ USB_VENDOR_WISTRONNEWEB,	USB_PRODUCT_WISTRONNEWEB_WNC0600 },
    586 	{ USB_VENDOR_ZCOM,		USB_PRODUCT_ZCOM_UB81 },
    587 	{ USB_VENDOR_ZCOM,		USB_PRODUCT_ZCOM_UB82 },
    588 	{ USB_VENDOR_ZYDAS,		USB_PRODUCT_ZYDAS_ZD1221 },
    589 	{ USB_VENDOR_ZYXEL,		USB_PRODUCT_ZYXEL_NWD271N }
    590 };
    591 
    592 CFATTACH_DECL_NEW(otus, sizeof(struct otus_softc), otus_match, otus_attach,
    593     otus_detach, otus_activate);
    594 
    595 Static int
    596 otus_match(device_t parent, cfdata_t match, void *aux)
    597 {
    598 	struct usb_attach_arg *uaa;
    599 
    600 	uaa = aux;
    601 
    602 	DPRINTFN(DBG_FN, DBG_NO_SC,
    603 	    "otus_match: vendor=%#x product=%#x revision=%#x\n",
    604 		    uaa->uaa_vendor, uaa->uaa_product, uaa->uaa_release);
    605 
    606 	return usb_lookup(otus_devs, uaa->uaa_vendor, uaa->uaa_product) != NULL ?
    607 	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
    608 }
    609 
    610 Static void
    611 otus_attach(device_t parent, device_t self, void *aux)
    612 {
    613 	struct otus_softc *sc;
    614 	struct usb_attach_arg *uaa;
    615 	char *devinfop;
    616 	int error;
    617 
    618 	sc = device_private(self);
    619 
    620 	DPRINTFN(DBG_FN, sc, "\n");
    621 
    622 	sc->sc_dev = self;
    623 	uaa = aux;
    624 	sc->sc_udev = uaa->uaa_device;
    625 
    626 	aprint_naive("\n");
    627 	aprint_normal("\n");
    628 
    629 	devinfop = usbd_devinfo_alloc(sc->sc_udev, 0);
    630 	aprint_normal_dev(sc->sc_dev, "%s\n", devinfop);
    631 	usbd_devinfo_free(devinfop);
    632 
    633 	cv_init(&sc->sc_task_cv, "otustsk");
    634 	cv_init(&sc->sc_cmd_cv, "otuscmd");
    635 	mutex_init(&sc->sc_cmd_mtx,   MUTEX_DEFAULT, IPL_NONE);
    636 	mutex_init(&sc->sc_task_mtx,  MUTEX_DEFAULT, IPL_NET);
    637 	mutex_init(&sc->sc_tx_mtx,    MUTEX_DEFAULT, IPL_NONE);
    638 	mutex_init(&sc->sc_write_mtx, MUTEX_DEFAULT, IPL_NONE);
    639 
    640 	usb_init_task(&sc->sc_task, otus_task, sc, 0);
    641 
    642 	callout_init(&sc->sc_scan_to, 0);
    643 	callout_setfunc(&sc->sc_scan_to, otus_next_scan, sc);
    644 	callout_init(&sc->sc_calib_to, 0);
    645 	callout_setfunc(&sc->sc_calib_to, otus_calib_to, sc);
    646 
    647 	sc->sc_amrr.amrr_min_success_threshold =  1;
    648 	sc->sc_amrr.amrr_max_success_threshold = 10;
    649 
    650 	if (usbd_set_config_no(sc->sc_udev, 1, 0) != 0) {
    651 		aprint_error_dev(sc->sc_dev,
    652 		    "could not set configuration no\n");
    653 		return;
    654 	}
    655 
    656 	/* Get the first interface handle. */
    657 	error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
    658 	if (error != 0) {
    659 		aprint_error_dev(sc->sc_dev,
    660 		    "could not get interface handle\n");
    661 		return;
    662 	}
    663 
    664 	if ((error = otus_open_pipes(sc)) != 0) {
    665 		aprint_error_dev(sc->sc_dev, "could not open pipes\n");
    666 		return;
    667 	}
    668 
    669 	/*
    670 	 * We need the firmware loaded from file system to complete the attach.
    671 	 */
    672 	config_mountroot(self, otus_attachhook);
    673 
    674 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
    675 }
    676 
    677 Static void
    678 otus_wait_async(struct otus_softc *sc)
    679 {
    680 
    681 	DPRINTFN(DBG_FN, sc, "\n");
    682 
    683 	mutex_spin_enter(&sc->sc_task_mtx);
    684 	while (sc->sc_cmdq.queued > 0)
    685 		cv_wait(&sc->sc_task_cv, &sc->sc_task_mtx);
    686 	mutex_spin_exit(&sc->sc_task_mtx);
    687 }
    688 
    689 Static int
    690 otus_detach(device_t self, int flags)
    691 {
    692 	struct otus_softc *sc;
    693 	struct ifnet *ifp;
    694 	int s;
    695 
    696 	sc = device_private(self);
    697 
    698 	DPRINTFN(DBG_FN, sc, "\n");
    699 
    700 	s = splusb();
    701 
    702 	sc->sc_dying = 1;
    703 
    704 	ifp = sc->sc_ic.ic_ifp;
    705 	if (ifp != NULL)	/* Failed to attach properly */
    706 		otus_stop(ifp);
    707 
    708 	usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER, NULL);
    709 	callout_destroy(&sc->sc_scan_to);
    710 	callout_destroy(&sc->sc_calib_to);
    711 
    712 	if (ifp && ifp->if_flags != 0) { /* if_attach() has been called. */
    713 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
    714 		bpf_detach(ifp);
    715 		ieee80211_ifdetach(&sc->sc_ic);
    716 		if_detach(ifp);
    717 	}
    718 	otus_close_pipes(sc);
    719 	splx(s);
    720 
    721 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
    722 
    723 	mutex_destroy(&sc->sc_write_mtx);
    724 	mutex_destroy(&sc->sc_tx_mtx);
    725 	mutex_destroy(&sc->sc_task_mtx);
    726 	mutex_destroy(&sc->sc_cmd_mtx);
    727 	cv_destroy(&sc->sc_task_cv);
    728 	cv_destroy(&sc->sc_cmd_cv);
    729 
    730 	return 0;
    731 }
    732 
    733 Static int
    734 otus_activate(device_t self, devact_t act)
    735 {
    736 	struct otus_softc *sc;
    737 
    738 	sc = device_private(self);
    739 
    740 	DPRINTFN(DBG_FN, sc, "%d\n", act);
    741 
    742 	switch (act) {
    743 	case DVACT_DEACTIVATE:
    744 		sc->sc_dying = 1;
    745 		if_deactivate(sc->sc_ic.ic_ifp);
    746 		return 0;
    747 	default:
    748 		return EOPNOTSUPP;
    749 	}
    750 }
    751 
    752 Static void
    753 otus_attachhook(device_t arg)
    754 {
    755 	struct otus_softc *sc;
    756 	struct ieee80211com *ic;
    757 	struct ifnet *ifp;
    758 	usb_device_request_t req;
    759 	uint32_t in, out;
    760 	int error;
    761 
    762 	sc = device_private(arg);
    763 
    764 	DPRINTFN(DBG_FN, sc, "\n");
    765 
    766 	ic = &sc->sc_ic;
    767 	ifp = &sc->sc_if;
    768 
    769 	error = otus_load_firmware(sc, "otus-init", AR_FW_INIT_ADDR);
    770 	if (error != 0) {
    771 		aprint_error_dev(sc->sc_dev, "could not load init firmware\n");
    772 		return;
    773 	}
    774 	usbd_delay_ms(sc->sc_udev, 1000);
    775 
    776 	error = otus_load_firmware(sc, "otus-main", AR_FW_MAIN_ADDR);
    777 	if (error != 0) {
    778 		aprint_error_dev(sc->sc_dev, "could not load main firmware\n");
    779 		return;
    780 	}
    781 
    782 	/* Tell device that firmware transfer is complete. */
    783 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    784 	req.bRequest = AR_FW_DOWNLOAD_COMPLETE;
    785 	USETW(req.wValue, 0);
    786 	USETW(req.wIndex, 0);
    787 	USETW(req.wLength, 0);
    788 	if (usbd_do_request(sc->sc_udev, &req, NULL) != 0) {
    789 		aprint_error_dev(sc->sc_dev,
    790 		    "firmware initialization failed\n");
    791 		return;
    792 	}
    793 
    794 	/* Send an ECHO command to check that everything is settled. */
    795 	in = 0xbadc0ffe;
    796 	if (otus_cmd(sc, AR_CMD_ECHO, &in, sizeof(in), &out) != 0) {
    797 		aprint_error_dev(sc->sc_dev, "echo command failed\n");
    798 		return;
    799 	}
    800 	if (in != out) {
    801 		aprint_error_dev(sc->sc_dev,
    802 		    "echo reply mismatch: 0x%08x!=0x%08x\n", in, out);
    803 		return;
    804 	}
    805 
    806 	/* Read entire EEPROM. */
    807 	if (otus_read_eeprom(sc) != 0) {
    808 		aprint_error_dev(sc->sc_dev, "could not read EEPROM\n");
    809 		return;
    810 	}
    811 
    812 	sc->sc_txmask = sc->sc_eeprom.baseEepHeader.txMask;
    813 	sc->sc_rxmask = sc->sc_eeprom.baseEepHeader.rxMask;
    814 	sc->sc_capflags = sc->sc_eeprom.baseEepHeader.opCapFlags;
    815 	IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_eeprom.baseEepHeader.macAddr);
    816 	sc->sc_led_newstate = otus_led_newstate_type3;	/* XXX */
    817 
    818 	aprint_normal_dev(sc->sc_dev,
    819 	    "MAC/BBP AR9170, RF AR%X, MIMO %dT%dR, address %s\n",
    820 	    (sc->sc_capflags & AR5416_OPFLAGS_11A) ?
    821 		0x9104 : ((sc->sc_txmask == 0x5) ? 0x9102 : 0x9101),
    822 	    (sc->sc_txmask == 0x5) ? 2 : 1, (sc->sc_rxmask == 0x5) ? 2 : 1,
    823 	    ether_sprintf(ic->ic_myaddr));
    824 
    825 	/*
    826 	 * Setup the 802.11 device.
    827 	 */
    828 	ic->ic_ifp = ifp;
    829 	ic->ic_phytype = IEEE80211_T_OFDM;	/* not only, but not used */
    830 	ic->ic_opmode = IEEE80211_M_STA;	/* default to BSS mode */
    831 	ic->ic_state = IEEE80211_S_INIT;
    832 
    833 	/* Set device capabilities. */
    834 	ic->ic_caps =
    835 	    IEEE80211_C_MONITOR |	/* monitor mode supported */
    836 	    IEEE80211_C_SHPREAMBLE |	/* short preamble supported */
    837 	    IEEE80211_C_SHSLOT |	/* short slot time supported */
    838 	    IEEE80211_C_WPA;		/* 802.11i */
    839 
    840 	if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) {
    841 		/* Set supported .11b and .11g rates. */
    842 		ic->ic_sup_rates[IEEE80211_MODE_11B] =
    843 		    ieee80211_std_rateset_11b;
    844 		ic->ic_sup_rates[IEEE80211_MODE_11G] =
    845 		    ieee80211_std_rateset_11g;
    846 	}
    847 	if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) {
    848 		/* Set supported .11a rates. */
    849 		ic->ic_sup_rates[IEEE80211_MODE_11A] =
    850 		    ieee80211_std_rateset_11a;
    851 	}
    852 
    853 	/* Build the list of supported channels. */
    854 	otus_get_chanlist(sc);
    855 
    856 	ifp->if_softc = sc;
    857 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    858 	ifp->if_init  = otus_init;
    859 	ifp->if_ioctl = otus_ioctl;
    860 	ifp->if_start = otus_start;
    861 	ifp->if_watchdog = otus_watchdog;
    862 	IFQ_SET_READY(&ifp->if_snd);
    863 	memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
    864 
    865 	if_initialize(ifp);
    866 
    867 	ieee80211_ifattach(ic);
    868 
    869 	ic->ic_node_alloc = otus_node_alloc;
    870 	ic->ic_newassoc	  = otus_newassoc;
    871 	ic->ic_updateslot = otus_updateslot;
    872 #ifdef HAVE_EDCA
    873 	ic->ic_updateedca = otus_updateedca;
    874 #endif /* HAVE_EDCA */
    875 #ifdef notyet
    876 	ic->ic_set_key = otus_set_key;
    877 	ic->ic_delete_key = otus_delete_key;
    878 #endif /* notyet */
    879 
    880 	/* Override state transition machine. */
    881 	sc->sc_newstate = ic->ic_newstate;
    882 	ic->ic_newstate = otus_newstate;
    883 
    884 	/* XXX media locking needs revisiting */
    885 	mutex_init(&sc->sc_media_mtx, MUTEX_DEFAULT, IPL_SOFTUSB);
    886 	ieee80211_media_init_with_lock(ic,
    887 	    otus_media_change, ieee80211_media_status, &sc->sc_media_mtx);
    888 
    889 	bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
    890 	    sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
    891 	    &sc->sc_drvbpf);
    892 
    893 	sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
    894 	sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
    895 	sc->sc_rxtap.wr_ihdr.it_present = htole32(OTUS_RX_RADIOTAP_PRESENT);
    896 
    897 	sc->sc_txtap_len = sizeof(sc->sc_txtapu);
    898 	sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
    899 	sc->sc_txtap.wt_ihdr.it_present = htole32(OTUS_TX_RADIOTAP_PRESENT);
    900 
    901 	ifp->if_percpuq = if_percpuq_create(ifp);
    902 	if_register(ifp);
    903 
    904 	ieee80211_announce(ic);
    905 }
    906 
    907 Static void
    908 otus_get_chanlist(struct otus_softc *sc)
    909 {
    910 	struct ieee80211com *ic;
    911 	uint8_t chan;
    912 	int i;
    913 
    914 #ifdef OTUS_DEBUG
    915 	/* XXX regulatory domain. */
    916 	uint16_t domain = le16toh(sc->sc_eeprom.baseEepHeader.regDmn[0]);
    917 
    918 	DPRINTFN(DBG_FN | DBG_INIT, sc, "regdomain=0x%04x\n", domain);
    919 #endif
    920 
    921 	ic = &sc->sc_ic;
    922 	if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) {
    923 		for (i = 0; i < 14; i++) {
    924 			chan = ar_chans[i];
    925 			ic->ic_channels[chan].ic_freq =
    926 			    ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
    927 			ic->ic_channels[chan].ic_flags =
    928 			    IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
    929 			    IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
    930 		}
    931 	}
    932 	if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) {
    933 		for (i = 14; i < __arraycount(ar_chans); i++) {
    934 			chan = ar_chans[i];
    935 			ic->ic_channels[chan].ic_freq =
    936 			    ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);
    937 			ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;
    938 		}
    939 	}
    940 }
    941 
    942 Static int
    943 otus_load_firmware(struct otus_softc *sc, const char *name, uint32_t addr)
    944 {
    945 	usb_device_request_t req;
    946 	firmware_handle_t fh;
    947 	uint8_t *ptr;
    948 	uint8_t *fw;
    949 	size_t size;
    950 	int mlen, error;
    951 
    952 	DPRINTFN(DBG_FN, sc, "\n");
    953 
    954 	if ((error = firmware_open("if_otus", name, &fh)) != 0)
    955 		return error;
    956 
    957 	size = firmware_get_size(fh);
    958 	if ((fw = firmware_malloc(size)) == NULL) {
    959 		firmware_close(fh);
    960 		return ENOMEM;
    961 	}
    962 	if ((error = firmware_read(fh, 0, fw, size)) != 0)
    963 		firmware_free(fw, size);
    964 	firmware_close(fh);
    965 	if (error)
    966 		return error;
    967 
    968 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    969 	req.bRequest = AR_FW_DOWNLOAD;
    970 	USETW(req.wIndex, 0);
    971 
    972 	ptr = fw;
    973 	addr >>= 8;
    974 	while (size > 0) {
    975 		mlen = MIN(size, 4096);
    976 
    977 		USETW(req.wValue, addr);
    978 		USETW(req.wLength, mlen);
    979 		if (usbd_do_request(sc->sc_udev, &req, ptr) != 0) {
    980 			error = EIO;
    981 			break;
    982 		}
    983 		addr += mlen >> 8;
    984 		ptr  += mlen;
    985 		size -= mlen;
    986 	}
    987 	free(fw, M_DEVBUF);
    988 	return error;
    989 }
    990 
    991 Static int
    992 otus_open_pipes(struct otus_softc *sc)
    993 {
    994 	usb_endpoint_descriptor_t *ed;
    995 	int i, error;
    996 
    997 	DPRINTFN(DBG_FN, sc, "\n");
    998 
    999 	error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_RX_NO, 0,
   1000 	    &sc->sc_data_rx_pipe);
   1001 	if (error != 0) {
   1002 		aprint_error_dev(sc->sc_dev, "could not open Rx bulk pipe\n");
   1003 		goto fail;
   1004 	}
   1005 
   1006 	ed = usbd_get_endpoint_descriptor(sc->sc_iface, AR_EPT_INTR_RX_NO);
   1007 	if (ed == NULL) {
   1008 		aprint_error_dev(sc->sc_dev,
   1009 		    "could not retrieve Rx intr pipe descriptor\n");
   1010 		goto fail;
   1011 	}
   1012 	sc->sc_ibuf_size = UGETW(ed->wMaxPacketSize);
   1013 	if (sc->sc_ibuf_size == 0) {
   1014 		aprint_error_dev(sc->sc_dev,
   1015 		    "invalid Rx intr pipe descriptor\n");
   1016 		goto fail;
   1017 	}
   1018 	sc->sc_ibuf = kmem_alloc(sc->sc_ibuf_size, KM_SLEEP);
   1019 	error = usbd_open_pipe_intr(sc->sc_iface, AR_EPT_INTR_RX_NO,
   1020 	    USBD_SHORT_XFER_OK, &sc->sc_cmd_rx_pipe, sc, sc->sc_ibuf,
   1021 	    sc->sc_ibuf_size, otus_intr, USBD_DEFAULT_INTERVAL);
   1022 	if (error != 0) {
   1023 		aprint_error_dev(sc->sc_dev, "could not open Rx intr pipe\n");
   1024 		goto fail;
   1025 	}
   1026 
   1027 	error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_TX_NO, 0,
   1028 	    &sc->sc_data_tx_pipe);
   1029 	if (error != 0) {
   1030 		aprint_error_dev(sc->sc_dev, "could not open Tx bulk pipe\n");
   1031 		goto fail;
   1032 	}
   1033 
   1034 	error = usbd_open_pipe(sc->sc_iface, AR_EPT_INTR_TX_NO, 0,
   1035 	    &sc->sc_cmd_tx_pipe);
   1036 	if (error != 0) {
   1037 		aprint_error_dev(sc->sc_dev, "could not open Tx intr pipe\n");
   1038 		goto fail;
   1039 	}
   1040 
   1041 	if (otus_alloc_tx_cmd(sc) != 0) {
   1042 		aprint_error_dev(sc->sc_dev,
   1043 		    "could not allocate command xfer\n");
   1044 		goto fail;
   1045 	}
   1046 
   1047 	if (otus_alloc_tx_data_list(sc)) {
   1048 		aprint_error_dev(sc->sc_dev, "could not allocate Tx xfers\n");
   1049 		goto fail;
   1050 	}
   1051 
   1052 	if (otus_alloc_rx_data_list(sc)) {
   1053 		aprint_error_dev(sc->sc_dev, "could not allocate Rx xfers\n");
   1054 		goto fail;
   1055 	}
   1056 
   1057 	for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++) {
   1058 		struct otus_rx_data *data = &sc->sc_rx_data[i];
   1059 
   1060 		usbd_setup_xfer(data->xfer, data, data->buf, OTUS_RXBUFSZ,
   1061 		    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, otus_rxeof);
   1062 		error = usbd_transfer(data->xfer);
   1063 		if (error != USBD_IN_PROGRESS && error != 0) {
   1064 			aprint_error_dev(sc->sc_dev,
   1065 			    "could not queue Rx xfer\n");
   1066 			goto fail;
   1067 		}
   1068 	}
   1069 	return 0;
   1070 
   1071  fail:	otus_close_pipes(sc);
   1072 	return error;
   1073 }
   1074 
   1075 Static void
   1076 otus_close_pipes(struct otus_softc *sc)
   1077 {
   1078 
   1079 	DPRINTFN(DBG_FN, sc, "\n");
   1080 
   1081 	otus_free_tx_cmd(sc);
   1082 	otus_free_tx_data_list(sc);
   1083 	otus_free_rx_data_list(sc);
   1084 
   1085 	if (sc->sc_data_rx_pipe != NULL)
   1086 		usbd_close_pipe(sc->sc_data_rx_pipe);
   1087 	if (sc->sc_cmd_rx_pipe != NULL) {
   1088 		usbd_abort_pipe(sc->sc_cmd_rx_pipe);
   1089 		usbd_close_pipe(sc->sc_cmd_rx_pipe);
   1090 	}
   1091 	if (sc->sc_ibuf != NULL)
   1092 		kmem_free(sc->sc_ibuf, sc->sc_ibuf_size);
   1093 	if (sc->sc_data_tx_pipe != NULL)
   1094 		usbd_close_pipe(sc->sc_data_tx_pipe);
   1095 	if (sc->sc_cmd_tx_pipe != NULL)
   1096 		usbd_close_pipe(sc->sc_cmd_tx_pipe);
   1097 }
   1098 
   1099 Static int
   1100 otus_alloc_tx_cmd(struct otus_softc *sc)
   1101 {
   1102 	struct otus_tx_cmd *cmd;
   1103 
   1104 	DPRINTFN(DBG_FN, sc, "\n");
   1105 
   1106 	cmd = &sc->sc_tx_cmd;
   1107 
   1108 	int error = usbd_create_xfer(sc->sc_cmd_tx_pipe, OTUS_MAX_TXCMDSZ,
   1109 	    USBD_FORCE_SHORT_XFER, 0, &cmd->xfer);
   1110 	if (error)
   1111 		return error;
   1112 
   1113 	cmd->buf = usbd_get_buffer(cmd->xfer);
   1114 
   1115 	return 0;
   1116 }
   1117 
   1118 Static void
   1119 otus_free_tx_cmd(struct otus_softc *sc)
   1120 {
   1121 
   1122 	DPRINTFN(DBG_FN, sc, "\n");
   1123 
   1124 	if (sc->sc_cmd_tx_pipe == NULL)
   1125 		return;
   1126 
   1127 	/* Make sure no transfers are pending. */
   1128 	usbd_abort_pipe(sc->sc_cmd_tx_pipe);
   1129 
   1130 	mutex_enter(&sc->sc_cmd_mtx);
   1131 	if (sc->sc_tx_cmd.xfer != NULL)
   1132 		usbd_destroy_xfer(sc->sc_tx_cmd.xfer);
   1133 	sc->sc_tx_cmd.xfer = NULL;
   1134 	sc->sc_tx_cmd.buf  = NULL;
   1135 	mutex_exit(&sc->sc_cmd_mtx);
   1136 }
   1137 
   1138 Static int
   1139 otus_alloc_tx_data_list(struct otus_softc *sc)
   1140 {
   1141 	struct otus_tx_data *data;
   1142 	int i, error;
   1143 
   1144 	DPRINTFN(DBG_FN, sc, "\n");
   1145 
   1146 	mutex_enter(&sc->sc_tx_mtx);
   1147 	error = 0;
   1148 	TAILQ_INIT(&sc->sc_tx_free_list);
   1149 	for (i = 0; i < OTUS_TX_DATA_LIST_COUNT; i++) {
   1150 		data = &sc->sc_tx_data[i];
   1151 
   1152 		data->sc = sc;	/* Backpointer for callbacks. */
   1153 
   1154 		error = usbd_create_xfer(sc->sc_data_tx_pipe, OTUS_TXBUFSZ,
   1155 		    USBD_FORCE_SHORT_XFER, 0, &data->xfer);
   1156 		if (error) {
   1157 			aprint_error_dev(sc->sc_dev,
   1158 			    "could not allocate xfer\n");
   1159 			break;
   1160 		}
   1161 		data->buf = usbd_get_buffer(data->xfer);
   1162 		/* Append this Tx buffer to our free list. */
   1163 		TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
   1164 	}
   1165 	if (error != 0)
   1166 		otus_free_tx_data_list(sc);
   1167 	mutex_exit(&sc->sc_tx_mtx);
   1168 	return error;
   1169 }
   1170 
   1171 Static void
   1172 otus_free_tx_data_list(struct otus_softc *sc)
   1173 {
   1174 	int i;
   1175 
   1176 	DPRINTFN(DBG_FN, sc, "\n");
   1177 
   1178 	if (sc->sc_data_tx_pipe == NULL)
   1179 		return;
   1180 
   1181 	/* Make sure no transfers are pending. */
   1182 	usbd_abort_pipe(sc->sc_data_tx_pipe);
   1183 
   1184 	for (i = 0; i < OTUS_TX_DATA_LIST_COUNT; i++) {
   1185 		if (sc->sc_tx_data[i].xfer != NULL)
   1186 			usbd_destroy_xfer(sc->sc_tx_data[i].xfer);
   1187 	}
   1188 }
   1189 
   1190 Static int
   1191 otus_alloc_rx_data_list(struct otus_softc *sc)
   1192 {
   1193 	struct otus_rx_data *data;
   1194 	int i, error;
   1195 
   1196 	DPRINTFN(DBG_FN, sc, "\n");
   1197 
   1198 	for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++) {
   1199 		data = &sc->sc_rx_data[i];
   1200 
   1201 		data->sc = sc;	/* Backpointer for callbacks. */
   1202 
   1203 		error = usbd_create_xfer(sc->sc_data_rx_pipe, OTUS_RXBUFSZ,
   1204 		   0, 0, &data->xfer);
   1205 
   1206 		if (error) {
   1207 			aprint_error_dev(sc->sc_dev,
   1208 			    "could not allocate xfer\n");
   1209 			goto fail;
   1210 		}
   1211 		data->buf = usbd_get_buffer(data->xfer);
   1212 	}
   1213 	return 0;
   1214 
   1215 fail:	otus_free_rx_data_list(sc);
   1216 	return error;
   1217 }
   1218 
   1219 Static void
   1220 otus_free_rx_data_list(struct otus_softc *sc)
   1221 {
   1222 	int i;
   1223 
   1224 	DPRINTFN(DBG_FN, sc, "\n");
   1225 
   1226 	if (sc->sc_data_rx_pipe == NULL)
   1227 		return;
   1228 
   1229 	/* Make sure no transfers are pending. */
   1230 	usbd_abort_pipe(sc->sc_data_rx_pipe);
   1231 
   1232 	for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++)
   1233 		if (sc->sc_rx_data[i].xfer != NULL)
   1234 			usbd_destroy_xfer(sc->sc_rx_data[i].xfer);
   1235 }
   1236 
   1237 Static void
   1238 otus_next_scan(void *arg)
   1239 {
   1240 	struct otus_softc *sc;
   1241 
   1242 	sc = arg;
   1243 
   1244 	DPRINTFN(DBG_FN, sc, "\n");
   1245 
   1246 	if (sc->sc_dying)
   1247 		return;
   1248 
   1249 	if (sc->sc_ic.ic_state == IEEE80211_S_SCAN)
   1250 		ieee80211_next_scan(&sc->sc_ic);
   1251 }
   1252 
   1253 Static void
   1254 otus_task(void *arg)
   1255 {
   1256 	struct otus_softc *sc;
   1257 	struct otus_host_cmd_ring *ring;
   1258 	struct otus_host_cmd *cmd;
   1259 
   1260 	sc = arg;
   1261 
   1262 	DPRINTFN(DBG_FN, sc, "\n");
   1263 
   1264 	/* Process host commands. */
   1265 	mutex_spin_enter(&sc->sc_task_mtx);
   1266 	ring = &sc->sc_cmdq;
   1267 	while (ring->next != ring->cur) {
   1268 		cmd = &ring->cmd[ring->next];
   1269 		mutex_spin_exit(&sc->sc_task_mtx);
   1270 
   1271 		/* Callback. */
   1272 		DPRINTFN(DBG_CMD, sc, "cb=%p queued=%d\n", cmd->cb,
   1273 		    ring->queued);
   1274 		cmd->cb(sc, cmd->data);
   1275 
   1276 		mutex_spin_enter(&sc->sc_task_mtx);
   1277 		ring->queued--;
   1278 		ring->next = (ring->next + 1) % OTUS_HOST_CMD_RING_COUNT;
   1279 	}
   1280 	cv_signal(&sc->sc_task_cv);
   1281 	mutex_spin_exit(&sc->sc_task_mtx);
   1282 }
   1283 
   1284 Static void
   1285 otus_do_async(struct otus_softc *sc, void (*cb)(struct otus_softc *, void *),
   1286     void *arg, int len)
   1287 {
   1288 	struct otus_host_cmd_ring *ring;
   1289 	struct otus_host_cmd *cmd;
   1290 	bool sched = false;
   1291 
   1292 	DPRINTFN(DBG_FN, sc, "cb=%p\n", cb);
   1293 
   1294 	mutex_spin_enter(&sc->sc_task_mtx);
   1295 	ring = &sc->sc_cmdq;
   1296 	cmd = &ring->cmd[ring->cur];
   1297 	cmd->cb = cb;
   1298 	KASSERT(len <= sizeof(cmd->data));
   1299 	memcpy(cmd->data, arg, len);
   1300 	ring->cur = (ring->cur + 1) % OTUS_HOST_CMD_RING_COUNT;
   1301 
   1302 	/* If there is no pending command already, schedule a task. */
   1303 	if (++ring->queued == 1) {
   1304 		sched = true;
   1305 	}
   1306 	cv_signal(&sc->sc_task_cv);
   1307 	mutex_spin_exit(&sc->sc_task_mtx);
   1308 	if (sched)
   1309 		usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
   1310 }
   1311 
   1312 Static int
   1313 otus_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
   1314 {
   1315 	struct otus_softc *sc;
   1316 	struct otus_cmd_newstate cmd;
   1317 
   1318 	sc = ic->ic_ifp->if_softc;
   1319 
   1320 	DPRINTFN(DBG_FN | DBG_STM, sc, "nstate=%s(%d), arg=%d\n",
   1321 	    ieee80211_state_name[nstate], nstate, arg);
   1322 
   1323 	/* Do it in a process context. */
   1324 	cmd.state = nstate;
   1325 	cmd.arg = arg;
   1326 	otus_do_async(sc, otus_newstate_cb, &cmd, sizeof(cmd));
   1327 	return 0;
   1328 }
   1329 
   1330 Static void
   1331 otus_newstate_cb(struct otus_softc *sc, void *arg)
   1332 {
   1333 	struct otus_cmd_newstate *cmd;
   1334 	struct ieee80211com *ic;
   1335 	struct ieee80211_node *ni;
   1336 	enum ieee80211_state nstate;
   1337 	int s;
   1338 
   1339 	cmd = arg;
   1340 	ic = &sc->sc_ic;
   1341 	ni = ic->ic_bss;
   1342 	nstate = cmd->state;
   1343 
   1344 #ifdef OTUS_DEBUG
   1345 	enum ieee80211_state ostate = ostate = ic->ic_state;
   1346 	DPRINTFN(DBG_FN | DBG_STM, sc, "%s(%d)->%s(%d)\n",
   1347 	    ieee80211_state_name[ostate], ostate,
   1348 	    ieee80211_state_name[nstate], nstate);
   1349 #endif
   1350 
   1351 	s = splnet();
   1352 
   1353 	callout_halt(&sc->sc_scan_to, NULL);
   1354 	callout_halt(&sc->sc_calib_to, NULL);
   1355 
   1356 	mutex_enter(&sc->sc_write_mtx);
   1357 
   1358 	switch (nstate) {
   1359 	case IEEE80211_S_INIT:
   1360 		break;
   1361 
   1362 	case IEEE80211_S_SCAN:
   1363 		otus_set_chan(sc, ic->ic_curchan, 0);
   1364 		if (!sc->sc_dying)
   1365 			callout_schedule(&sc->sc_scan_to, hz / 5);
   1366 		break;
   1367 
   1368 	case IEEE80211_S_AUTH:
   1369 	case IEEE80211_S_ASSOC:
   1370 		otus_set_chan(sc, ic->ic_curchan, 0);
   1371 		break;
   1372 
   1373 	case IEEE80211_S_RUN:
   1374 		otus_set_chan(sc, ic->ic_curchan, 1);
   1375 
   1376 		switch (ic->ic_opmode) {
   1377 		case IEEE80211_M_STA:
   1378 			otus_updateslot_cb_locked(sc);
   1379 			otus_set_bssid(sc, ni->ni_bssid);
   1380 
   1381 			/* Fake a join to init the Tx rate. */
   1382 			otus_newassoc(ni, 1);
   1383 
   1384 			/* Start calibration timer. */
   1385 			if (!sc->sc_dying)
   1386 				callout_schedule(&sc->sc_calib_to, hz);
   1387 			break;
   1388 
   1389 		case IEEE80211_M_IBSS:
   1390 		case IEEE80211_M_AHDEMO:
   1391 		case IEEE80211_M_HOSTAP:
   1392 		case IEEE80211_M_MONITOR:
   1393 			break;
   1394 		}
   1395 		break;
   1396 	}
   1397 	(void)sc->sc_newstate(ic, nstate, cmd->arg);
   1398 	sc->sc_led_newstate(sc);
   1399 	mutex_exit(&sc->sc_write_mtx);
   1400 
   1401 	splx(s);
   1402 }
   1403 
   1404 Static int
   1405 otus_cmd(struct otus_softc *sc, uint8_t code, const void *idata, int ilen,
   1406     void *odata)
   1407 {
   1408 	struct otus_tx_cmd *cmd;
   1409 	struct ar_cmd_hdr *hdr;
   1410 	int xferlen, error;
   1411 
   1412 	DPRINTFN(DBG_FN, sc, "\n");
   1413 
   1414 	cmd = &sc->sc_tx_cmd;
   1415 
   1416 	mutex_enter(&sc->sc_cmd_mtx);
   1417 
   1418 	/* Always bulk-out a multiple of 4 bytes. */
   1419 	xferlen = roundup2(sizeof(*hdr) + ilen, 4);
   1420 
   1421 	hdr = (void *)cmd->buf;
   1422 	if (hdr == NULL) {	/* we may have been freed while detaching */
   1423 		mutex_exit(&sc->sc_cmd_mtx);
   1424 		DPRINTFN(DBG_CMD, sc, "tx_cmd freed with commands pending\n");
   1425 		return 0;
   1426 	}
   1427 	hdr->code  = code;
   1428 	hdr->len   = ilen;
   1429 	hdr->token = ++cmd->token;	/* Don't care about endianness. */
   1430 	KASSERT(sizeof(hdr) + ilen <= OTUS_MAX_TXCMDSZ);
   1431 	memcpy(cmd->buf + sizeof(hdr[0]), idata, ilen);
   1432 
   1433 	DPRINTFN(DBG_CMD, sc, "sending command code=0x%02x len=%d token=%d\n",
   1434 	    code, ilen, hdr->token);
   1435 
   1436 	cmd->odata = odata;
   1437 	cmd->done = 0;
   1438 	usbd_setup_xfer(cmd->xfer, cmd, cmd->buf, xferlen,
   1439 	    USBD_FORCE_SHORT_XFER, OTUS_CMD_TIMEOUT, NULL);
   1440 	error = usbd_sync_transfer(cmd->xfer);
   1441 	if (error != 0) {
   1442 		mutex_exit(&sc->sc_cmd_mtx);
   1443 #if defined(DIAGNOSTIC) || defined(OTUS_DEBUG)	/* XXX: kill some noise */
   1444 		aprint_error_dev(sc->sc_dev,
   1445 		    "could not send command %#x (error=%s)\n",
   1446 		    code, usbd_errstr(error));
   1447 #endif
   1448 		return EIO;
   1449 	}
   1450 	if (!cmd->done)
   1451 		error = cv_timedwait_sig(&sc->sc_cmd_cv, &sc->sc_cmd_mtx, hz);
   1452 	cmd->odata = NULL;	/* In case answer is received too late. */
   1453 	mutex_exit(&sc->sc_cmd_mtx);
   1454 	if (error != 0) {
   1455 		aprint_error_dev(sc->sc_dev,
   1456 		    "timeout waiting for command 0x%02x reply\n", code);
   1457 	}
   1458 	return error;
   1459 }
   1460 
   1461 Static void
   1462 otus_write(struct otus_softc *sc, uint32_t reg, uint32_t val)
   1463 {
   1464 
   1465 	DPRINTFN(DBG_FN | DBG_REG, sc, "reg=%#x, val=%#x\n", reg, val);
   1466 
   1467 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   1468 	KASSERT(sc->sc_write_idx < __arraycount(sc->sc_write_buf));
   1469 
   1470 	sc->sc_write_buf[sc->sc_write_idx].reg = htole32(reg);
   1471 	sc->sc_write_buf[sc->sc_write_idx].val = htole32(val);
   1472 
   1473 	if (++sc->sc_write_idx >= __arraycount(sc->sc_write_buf))
   1474 		(void)otus_write_barrier(sc);
   1475 }
   1476 
   1477 Static int
   1478 otus_write_barrier(struct otus_softc *sc)
   1479 {
   1480 	int error;
   1481 
   1482 	DPRINTFN(DBG_FN, sc, "\n");
   1483 
   1484 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   1485 	KASSERT(sc->sc_write_idx <= __arraycount(sc->sc_write_buf));
   1486 
   1487 	if (sc->sc_write_idx == 0)
   1488 		return 0;	/* Nothing to flush. */
   1489 
   1490 	error = otus_cmd(sc, AR_CMD_WREG, sc->sc_write_buf,
   1491 	    sizeof(sc->sc_write_buf[0]) * sc->sc_write_idx, NULL);
   1492 
   1493 	sc->sc_write_idx = 0;
   1494 	if (error)
   1495 		DPRINTFN(DBG_REG, sc, "error=%d\n", error);
   1496 	return error;
   1497 }
   1498 
   1499 Static struct ieee80211_node *
   1500 otus_node_alloc(struct ieee80211_node_table *ntp)
   1501 {
   1502 	struct otus_node *on;
   1503 
   1504 	DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
   1505 
   1506 	on = malloc(sizeof(*on), M_DEVBUF, M_NOWAIT | M_ZERO);
   1507 	return on ? &on->ni : NULL;
   1508 }
   1509 
   1510 Static int
   1511 otus_media_change(struct ifnet *ifp)
   1512 {
   1513 	struct otus_softc *sc;
   1514 	struct ieee80211com *ic;
   1515 	uint8_t rate, ridx;
   1516 	int error;
   1517 
   1518 	sc = ifp->if_softc;
   1519 
   1520 	DPRINTFN(DBG_FN, sc, "\n");
   1521 
   1522 	error = ieee80211_media_change(ifp);
   1523 	if (error != ENETRESET)
   1524 		return error;
   1525 
   1526 	ic = &sc->sc_ic;
   1527 	if (ic->ic_fixed_rate != -1) {
   1528 		rate = ic->ic_sup_rates[ic->ic_curmode].
   1529 		    rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
   1530 		for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++)
   1531 			if (otus_rates[ridx].rate == rate)
   1532 				break;
   1533 		sc->sc_fixed_ridx = ridx;
   1534 	}
   1535 
   1536 	if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
   1537 		error = otus_init(ifp);
   1538 
   1539 	return error;
   1540 }
   1541 
   1542 Static int
   1543 otus_read_eeprom(struct otus_softc *sc)
   1544 {
   1545 	uint32_t regs[8], reg;
   1546 	uint8_t *eep;
   1547 	int i, j, error;
   1548 
   1549 	DPRINTFN(DBG_FN, sc, "\n");
   1550 
   1551 	KASSERT(sizeof(sc->sc_eeprom) % 32 == 0);
   1552 
   1553 	/* Read EEPROM by blocks of 32 bytes. */
   1554 	eep = (uint8_t *)&sc->sc_eeprom;
   1555 	reg = AR_EEPROM_OFFSET;
   1556 	for (i = 0; i < sizeof(sc->sc_eeprom) / 32; i++) {
   1557 		for (j = 0; j < 8; j++, reg += 4)
   1558 			regs[j] = htole32(reg);
   1559 		error = otus_cmd(sc, AR_CMD_RREG, regs, sizeof(regs), eep);
   1560 		if (error != 0)
   1561 			break;
   1562 		eep += 32;
   1563 	}
   1564 	return error;
   1565 }
   1566 
   1567 Static void
   1568 otus_newassoc(struct ieee80211_node *ni, int isnew)
   1569 {
   1570 	struct ieee80211_rateset *rs;
   1571 	struct otus_softc *sc;
   1572 	struct otus_node *on;
   1573 	uint8_t rate;
   1574 	int ridx, i;
   1575 
   1576 	sc = ni->ni_ic->ic_ifp->if_softc;
   1577 
   1578 	DPRINTFN(DBG_FN, sc, "isnew=%d addr=%s\n",
   1579 	    isnew, ether_sprintf(ni->ni_macaddr));
   1580 
   1581 	on = (void *)ni;
   1582 	ieee80211_amrr_node_init(&sc->sc_amrr, &on->amn);
   1583 	/* Start at lowest available bit-rate, AMRR will raise. */
   1584 	ni->ni_txrate = 0;
   1585 	rs = &ni->ni_rates;
   1586 	for (i = 0; i < rs->rs_nrates; i++) {
   1587 		rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
   1588 		/* Convert 802.11 rate to hardware rate index. */
   1589 		for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++)
   1590 			if (otus_rates[ridx].rate == rate)
   1591 				break;
   1592 		on->ridx[i] = ridx;
   1593 		DPRINTFN(DBG_INIT, sc, "rate=0x%02x ridx=%d\n",
   1594 		    rs->rs_rates[i], on->ridx[i]);
   1595 	}
   1596 }
   1597 
   1598 /* ARGSUSED */
   1599 Static void
   1600 otus_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
   1601 {
   1602 #if 0
   1603 	struct otus_softc *sc;
   1604 	int len;
   1605 
   1606 	sc = priv;
   1607 
   1608 	DPRINTFN(DBG_FN, sc, "\n");
   1609 
   1610 	/*
   1611 	 * The Rx intr pipe is unused with current firmware.  Notifications
   1612 	 * and replies to commands are sent through the Rx bulk pipe instead
   1613 	 * (with a magic PLCP header.)
   1614 	 */
   1615 	if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
   1616 		DPRINTFN(DBG_INTR, sc, "status=%d\n", status);
   1617 		if (status == USBD_STALLED)
   1618 			usbd_clear_endpoint_stall_async(sc->sc_cmd_rx_pipe);
   1619 		return;
   1620 	}
   1621 	usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
   1622 
   1623 	otus_cmd_rxeof(sc, sc->sc_ibuf, len);
   1624 #endif
   1625 }
   1626 
   1627 Static void
   1628 otus_cmd_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
   1629 {
   1630 	struct ieee80211com *ic;
   1631 	struct otus_tx_cmd *cmd;
   1632 	struct ar_cmd_hdr *hdr;
   1633 	int s;
   1634 
   1635 	DPRINTFN(DBG_FN, sc, "\n");
   1636 
   1637 	ic = &sc->sc_ic;
   1638 
   1639 	if (__predict_false(len < sizeof(*hdr))) {
   1640 		DPRINTFN(DBG_RX, sc, "cmd too small %d\n", len);
   1641 		return;
   1642 	}
   1643 	hdr = (void *)buf;
   1644 	if (__predict_false(sizeof(*hdr) + hdr->len > len ||
   1645 	    sizeof(*hdr) + hdr->len > 64)) {
   1646 		DPRINTFN(DBG_RX, sc, "cmd too large %d\n", hdr->len);
   1647 		return;
   1648 	}
   1649 
   1650 	if ((hdr->code & 0xc0) != 0xc0) {
   1651 		DPRINTFN(DBG_RX, sc, "received reply code=0x%02x len=%d token=%d\n",
   1652 		    hdr->code, hdr->len, hdr->token);
   1653 		mutex_enter(&sc->sc_cmd_mtx);
   1654 		cmd = &sc->sc_tx_cmd;
   1655 		if (__predict_false(hdr->token != cmd->token)) {
   1656 			mutex_exit(&sc->sc_cmd_mtx);
   1657 			return;
   1658 		}
   1659 		/* Copy answer into caller's supplied buffer. */
   1660 		if (cmd->odata != NULL)
   1661 			memcpy(cmd->odata, &hdr[1], hdr->len);
   1662 		cmd->done = 1;
   1663 		cv_signal(&sc->sc_cmd_cv);
   1664 		mutex_exit(&sc->sc_cmd_mtx);
   1665 		return;
   1666 	}
   1667 
   1668 	/* Received unsolicited notification. */
   1669 	DPRINTFN(DBG_RX, sc, "received notification code=0x%02x len=%d\n",
   1670 	    hdr->code, hdr->len);
   1671 	switch (hdr->code & 0x3f) {
   1672 	case AR_EVT_BEACON:
   1673 		break;
   1674 	case AR_EVT_TX_COMP:
   1675 	{
   1676 		struct ar_evt_tx_comp *tx;
   1677 		struct ieee80211_node *ni;
   1678 		struct otus_node *on;
   1679 
   1680 		tx = (void *)&hdr[1];
   1681 
   1682 		DPRINTFN(DBG_RX, sc, "tx completed %s status=%d phy=%#x\n",
   1683 		    ether_sprintf(tx->macaddr), le16toh(tx->status),
   1684 		    le32toh(tx->phy));
   1685 		s = splnet();
   1686 #ifdef notyet
   1687 #ifndef IEEE80211_STA_ONLY
   1688 		if (ic->ic_opmode != IEEE80211_M_STA) {
   1689 			ni = ieee80211_find_node(ic, tx->macaddr);
   1690 			if (__predict_false(ni == NULL)) {
   1691 				splx(s);
   1692 				break;
   1693 			}
   1694 		} else
   1695 #endif
   1696 #endif
   1697 			ni = ic->ic_bss;
   1698 		/* Update rate control statistics. */
   1699 		on = (void *)ni;
   1700 		/* NB: we do not set the TX_MAC_RATE_PROBING flag. */
   1701 		if (__predict_true(tx->status != 0))
   1702 			on->amn.amn_retrycnt++;
   1703 		splx(s);
   1704 		break;
   1705 	}
   1706 	case AR_EVT_TBTT:
   1707 		break;
   1708 	}
   1709 }
   1710 
   1711 Static void
   1712 otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
   1713 {
   1714 	struct ieee80211com *ic;
   1715 	struct ifnet *ifp;
   1716 	struct ieee80211_node *ni;
   1717 	struct ar_rx_tail *tail;
   1718 	struct ieee80211_frame *wh;
   1719 	struct mbuf *m;
   1720 	uint8_t *plcp;
   1721 	int s, mlen, align;
   1722 
   1723 	DPRINTFN(DBG_FN, sc, "\n");
   1724 
   1725 	ic = &sc->sc_ic;
   1726 	ifp = ic->ic_ifp;
   1727 
   1728 	if (__predict_false(len < AR_PLCP_HDR_LEN)) {
   1729 		DPRINTFN(DBG_RX, sc, "sub-xfer too short %d\n", len);
   1730 		return;
   1731 	}
   1732 	plcp = buf;
   1733 
   1734 	/* All bits in the PLCP header are set to 1 for non-MPDU. */
   1735 	if (memcmp(plcp, AR_PLCP_HDR_INTR, AR_PLCP_HDR_LEN) == 0) {
   1736 		otus_cmd_rxeof(sc, plcp + AR_PLCP_HDR_LEN,
   1737 		    len - AR_PLCP_HDR_LEN);
   1738 		return;
   1739 	}
   1740 
   1741 	/* Received MPDU. */
   1742 	if (__predict_false(len < AR_PLCP_HDR_LEN + sizeof(*tail))) {
   1743 		DPRINTFN(DBG_RX, sc, "MPDU too short %d\n", len);
   1744 		if_statinc(ifp, if_ierrors);
   1745 		return;
   1746 	}
   1747 	tail = (void *)(plcp + len - sizeof(*tail));
   1748 	wh = (void *)(plcp + AR_PLCP_HDR_LEN);
   1749 
   1750 	/* Discard error frames. */
   1751 	if (__predict_false((tail->error & sc->sc_rx_error_msk) != 0)) {
   1752 		DPRINTFN(DBG_RX, sc, "error frame 0x%02x\n", tail->error);
   1753 		if (tail->error & AR_RX_ERROR_FCS) {
   1754 			DPRINTFN(DBG_RX, sc, "bad FCS\n");
   1755 		} else if (tail->error & AR_RX_ERROR_MMIC) {
   1756 			/* Report Michael MIC failures to net80211. */
   1757 			ieee80211_notify_michael_failure(ic, wh, 0 /* XXX: keyix */);
   1758 		}
   1759 		if_statinc(ifp, if_ierrors);
   1760 		return;
   1761 	}
   1762 	/* Compute MPDU's length. */
   1763 	mlen = len - AR_PLCP_HDR_LEN - sizeof(*tail);
   1764 	if (__predict_false(mlen < IEEE80211_CRC_LEN)) {
   1765 		if_statinc(ifp, if_ierrors);
   1766 		return;
   1767 	}
   1768 	mlen -= IEEE80211_CRC_LEN;	/* strip 802.11 FCS */
   1769 	/* Make sure there's room for an 802.11 header. */
   1770 	/*
   1771 	 * XXX: This will drop most control packets.  Do we really
   1772 	 * want this in IEEE80211_M_MONITOR mode?
   1773 	 */
   1774 	if (__predict_false(mlen < sizeof(*wh))) {
   1775 		if_statinc(ifp, if_ierrors);
   1776 		return;
   1777 	}
   1778 
   1779 	/* Provide a 32-bit aligned protocol header to the stack. */
   1780 	align = (ieee80211_has_qos(wh) ^ ieee80211_has_addr4(wh)) ? 2 : 0;
   1781 
   1782 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1783 	if (__predict_false(m == NULL)) {
   1784 		if_statinc(ifp, if_ierrors);
   1785 		return;
   1786 	}
   1787 	if (align + mlen > MHLEN) {
   1788 		if (__predict_true(align + mlen <= MCLBYTES))
   1789 			MCLGET(m, M_DONTWAIT);
   1790 		if (__predict_false(!(m->m_flags & M_EXT))) {
   1791 			if_statinc(ifp, if_ierrors);
   1792 			m_freem(m);
   1793 			return;
   1794 		}
   1795 	}
   1796 	/* Finalize mbuf. */
   1797 	m_set_rcvif(m, ifp);
   1798 	m->m_data += align;
   1799 	memcpy(mtod(m, void *), wh, mlen);
   1800 	m->m_pkthdr.len = m->m_len = mlen;
   1801 
   1802 	s = splnet();
   1803 	if (__predict_false(sc->sc_drvbpf != NULL)) {
   1804 		struct otus_rx_radiotap_header *tap;
   1805 
   1806 		tap = &sc->sc_rxtap;
   1807 		tap->wr_flags = 0;
   1808 		tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
   1809 		tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
   1810 		tap->wr_antsignal = tail->rssi;
   1811 		tap->wr_rate = 2;	/* In case it can't be found below. */
   1812 		switch (tail->status & AR_RX_STATUS_MT_MASK) {
   1813 		case AR_RX_STATUS_MT_CCK:
   1814 			switch (plcp[0]) {
   1815 			case  10: tap->wr_rate =   2; break;
   1816 			case  20: tap->wr_rate =   4; break;
   1817 			case  55: tap->wr_rate =  11; break;
   1818 			case 110: tap->wr_rate =  22; break;
   1819 			}
   1820 			if (tail->status & AR_RX_STATUS_SHPREAMBLE)
   1821 				tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
   1822 			break;
   1823 		case AR_RX_STATUS_MT_OFDM:
   1824 			switch (plcp[0] & 0xf) {
   1825 			case 0xb: tap->wr_rate =  12; break;
   1826 			case 0xf: tap->wr_rate =  18; break;
   1827 			case 0xa: tap->wr_rate =  24; break;
   1828 			case 0xe: tap->wr_rate =  36; break;
   1829 			case 0x9: tap->wr_rate =  48; break;
   1830 			case 0xd: tap->wr_rate =  72; break;
   1831 			case 0x8: tap->wr_rate =  96; break;
   1832 			case 0xc: tap->wr_rate = 108; break;
   1833 			}
   1834 			break;
   1835 		}
   1836 		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m, BPF_D_IN);
   1837 	}
   1838 
   1839 	ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
   1840 
   1841 	/* push the frame up to the 802.11 stack */
   1842 	ieee80211_input(ic, m, ni, tail->rssi, 0);
   1843 
   1844 	/* Node is no longer needed. */
   1845 	ieee80211_free_node(ni);
   1846 	splx(s);
   1847 }
   1848 
   1849 Static void
   1850 otus_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
   1851 {
   1852 	struct otus_rx_data *data;
   1853 	struct otus_softc *sc;
   1854 	uint8_t *buf;
   1855 	struct ar_rx_head *head;
   1856 	uint16_t hlen;
   1857 	int len;
   1858 
   1859 	data = priv;
   1860 	sc = data->sc;
   1861 
   1862 	DPRINTFN(DBG_FN, sc, "\n");
   1863 
   1864 	buf = data->buf;
   1865 
   1866 	if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
   1867 		DPRINTFN(DBG_RX, sc, "RX status=%d\n", status);
   1868 		if (status == USBD_STALLED)
   1869 			usbd_clear_endpoint_stall_async(sc->sc_data_rx_pipe);
   1870 		else if (status != USBD_CANCELLED) {
   1871 			DPRINTFN(DBG_RX, sc,
   1872 			    "otus_rxeof: goto resubmit: status=%d\n", status);
   1873 			goto resubmit;
   1874 		}
   1875 		return;
   1876 	}
   1877 	usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
   1878 
   1879 	while (len >= sizeof(*head)) {
   1880 		head = (void *)buf;
   1881 		if (__predict_false(head->tag != htole16(AR_RX_HEAD_TAG))) {
   1882 			DPRINTFN(DBG_RX, sc, "tag not valid %#x\n",
   1883 			    le16toh(head->tag));
   1884 			break;
   1885 		}
   1886 		hlen = le16toh(head->len);
   1887 		if (__predict_false(sizeof(*head) + hlen > len)) {
   1888 			DPRINTFN(DBG_RX, sc, "xfer too short %d/%d\n",
   1889 			    len, hlen);
   1890 			break;
   1891 		}
   1892 		/* Process sub-xfer. */
   1893 		otus_sub_rxeof(sc, (uint8_t *)&head[1], hlen);
   1894 
   1895 		/* Next sub-xfer is aligned on a 32-bit boundary. */
   1896 		hlen = roundup2(sizeof(*head) + hlen, 4);
   1897 		buf += hlen;
   1898 		len -= hlen;
   1899 	}
   1900 
   1901  resubmit:
   1902 	usbd_setup_xfer(xfer, data, data->buf, OTUS_RXBUFSZ,
   1903 	    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, otus_rxeof);
   1904 	(void)usbd_transfer(data->xfer);
   1905 }
   1906 
   1907 Static void
   1908 otus_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
   1909 {
   1910 	struct otus_tx_data *data;
   1911 	struct otus_softc *sc;
   1912 	struct ieee80211com *ic;
   1913 	struct ifnet *ifp;
   1914 	int s;
   1915 
   1916 	data = priv;
   1917 	sc = data->sc;
   1918 
   1919 	DPRINTFN(DBG_FN, sc, "\n");
   1920 
   1921 	/* Put this Tx buffer back to the free list. */
   1922 	mutex_enter(&sc->sc_tx_mtx);
   1923 	TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
   1924 	mutex_exit(&sc->sc_tx_mtx);
   1925 
   1926 	ic = &sc->sc_ic;
   1927 	ifp = ic->ic_ifp;
   1928 	if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
   1929 		DPRINTFN(DBG_TX, sc, "TX status=%d\n", status);
   1930 		if (status == USBD_STALLED)
   1931 			usbd_clear_endpoint_stall_async(sc->sc_data_tx_pipe);
   1932 		if_statinc(ifp, if_oerrors);
   1933 		return;
   1934 	}
   1935 	if_statinc(ifp, if_opackets);
   1936 
   1937 	s = splnet();
   1938 	sc->sc_tx_timer = 0;
   1939 	ifp->if_flags &= ~IFF_OACTIVE;	/* XXX: do after freeing Tx buffer? */
   1940 	otus_start(ifp);
   1941 	splx(s);
   1942 }
   1943 
   1944 Static int
   1945 otus_tx(struct otus_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
   1946     struct otus_tx_data *data)
   1947 {
   1948 	struct ieee80211com *ic;
   1949 	struct otus_node *on;
   1950 	struct ieee80211_frame *wh;
   1951 	struct ieee80211_key *k;
   1952 	struct ar_tx_head *head;
   1953 	uint32_t phyctl;
   1954 	uint16_t macctl, qos;
   1955 	uint8_t qid;
   1956 	int error, ridx, hasqos, xferlen;
   1957 
   1958 	DPRINTFN(DBG_FN, sc, "\n");
   1959 
   1960 	ic = &sc->sc_ic;
   1961 	on = (void *)ni;
   1962 
   1963 	wh = mtod(m, struct ieee80211_frame *);
   1964 	if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {
   1965 		/* XXX: derived from upgt_tx_task() and ural_tx_data() */
   1966 		k = ieee80211_crypto_encap(ic, ni, m);
   1967 		if (k == NULL)
   1968 			return ENOBUFS;
   1969 
   1970 		/* Packet header may have moved, reset our local pointer. */
   1971 		wh = mtod(m, struct ieee80211_frame *);
   1972 	}
   1973 
   1974 #ifdef HAVE_EDCA
   1975 	if ((hasqos = ieee80211_has_qos(wh))) {
   1976 		qos = ieee80211_get_qos(wh);
   1977 		qid = ieee80211_up_to_ac(ic, qos & IEEE80211_QOS_TID);
   1978 	} else {
   1979 		qos = 0;
   1980 		qid = WME_AC_BE;
   1981 	}
   1982 #else
   1983 	hasqos = 0;
   1984 	qos = 0;
   1985 	qid = WME_AC_BE;
   1986 #endif
   1987 
   1988 	/* Pickup a rate index. */
   1989 	if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
   1990 	    (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA)
   1991 		ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
   1992 		    OTUS_RIDX_OFDM6 : OTUS_RIDX_CCK1;
   1993 	else if (ic->ic_fixed_rate != -1)
   1994 		ridx = sc->sc_fixed_ridx;
   1995 	else
   1996 		ridx = on->ridx[ni->ni_txrate];
   1997 
   1998 	phyctl = 0;
   1999 	macctl = AR_TX_MAC_BACKOFF | AR_TX_MAC_HW_DUR | AR_TX_MAC_QID(qid);
   2000 
   2001 	if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
   2002 	    (hasqos && ((qos & IEEE80211_QOS_ACKPOLICY_MASK) ==
   2003 	     IEEE80211_QOS_ACKPOLICY_NOACK)))
   2004 		macctl |= AR_TX_MAC_NOACK;
   2005 
   2006 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
   2007 		if (m->m_pkthdr.len + IEEE80211_CRC_LEN >= ic->ic_rtsthreshold)
   2008 			macctl |= AR_TX_MAC_RTS;
   2009 		else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
   2010 		    ridx >= OTUS_RIDX_OFDM6) {
   2011 			if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
   2012 				macctl |= AR_TX_MAC_CTS;
   2013 			else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
   2014 				macctl |= AR_TX_MAC_RTS;
   2015 		}
   2016 	}
   2017 
   2018 	phyctl |= AR_TX_PHY_MCS(otus_rates[ridx].mcs);
   2019 	if (ridx >= OTUS_RIDX_OFDM6) {
   2020 		phyctl |= AR_TX_PHY_MT_OFDM;
   2021 		if (ridx <= OTUS_RIDX_OFDM24)
   2022 			phyctl |= AR_TX_PHY_ANTMSK(sc->sc_txmask);
   2023 		else
   2024 			phyctl |= AR_TX_PHY_ANTMSK(1);
   2025 	} else {	/* CCK */
   2026 		phyctl |= AR_TX_PHY_MT_CCK;
   2027 		phyctl |= AR_TX_PHY_ANTMSK(sc->sc_txmask);
   2028 	}
   2029 
   2030 	/* Update rate control stats for frames that are ACK'ed. */
   2031 	if (!(macctl & AR_TX_MAC_NOACK))
   2032 		on->amn.amn_txcnt++;
   2033 
   2034 	/* Fill Tx descriptor. */
   2035 	head = (void *)data->buf;
   2036 	head->len = htole16(m->m_pkthdr.len + IEEE80211_CRC_LEN);
   2037 	head->macctl = htole16(macctl);
   2038 	head->phyctl = htole32(phyctl);
   2039 
   2040 	if (__predict_false(sc->sc_drvbpf != NULL)) {
   2041 		struct otus_tx_radiotap_header *tap = &sc->sc_txtap;
   2042 
   2043 		tap->wt_flags = 0;
   2044 		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
   2045 			tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
   2046 		tap->wt_rate = otus_rates[ridx].rate;
   2047 		tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
   2048 		tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
   2049 
   2050 		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m, BPF_D_OUT);
   2051 	}
   2052 
   2053 	xferlen = sizeof(*head) + m->m_pkthdr.len;
   2054 	m_copydata(m, 0, m->m_pkthdr.len, (void *)&head[1]);
   2055 
   2056 	DPRINTFN(DBG_TX, sc, "queued len=%d mac=0x%04x phy=0x%08x rate=%d\n",
   2057 	    head->len, head->macctl, head->phyctl, otus_rates[ridx].rate);
   2058 
   2059 	usbd_setup_xfer(data->xfer, data, data->buf, xferlen,
   2060 	    USBD_FORCE_SHORT_XFER, OTUS_TX_TIMEOUT, otus_txeof);
   2061 	error = usbd_transfer(data->xfer);
   2062 	if (__predict_false(
   2063 		    error != USBD_NORMAL_COMPLETION &&
   2064 		    error != USBD_IN_PROGRESS)) {
   2065 		DPRINTFN(DBG_TX, sc, "transfer failed %d\n", error);
   2066 		return error;
   2067 	}
   2068 	return 0;
   2069 }
   2070 
   2071 Static void
   2072 otus_start(struct ifnet *ifp)
   2073 {
   2074 	struct otus_softc *sc;
   2075 	struct ieee80211com *ic;
   2076 	struct otus_tx_data *data;
   2077 	struct ether_header *eh;
   2078 	struct ieee80211_node *ni;
   2079 	struct mbuf *m;
   2080 
   2081 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
   2082 		return;
   2083 
   2084 	sc = ifp->if_softc;
   2085 	ic = &sc->sc_ic;
   2086 
   2087 	DPRINTFN(DBG_FN, sc, "\n");
   2088 
   2089 	data = NULL;
   2090 	for (;;) {
   2091 		/*
   2092 		 * Grab a Tx buffer if we don't already have one.  If
   2093 		 * one isn't available, bail out.
   2094 		 * NB: We must obtain this Tx buffer _before_
   2095 		 * dequeueing anything as one may not be available
   2096 		 * later.  Both must be done inside a single lock.
   2097 		 */
   2098 		mutex_enter(&sc->sc_tx_mtx);
   2099 		if (data == NULL && !TAILQ_EMPTY(&sc->sc_tx_free_list)) {
   2100 			data = TAILQ_FIRST(&sc->sc_tx_free_list);
   2101 			TAILQ_REMOVE(&sc->sc_tx_free_list, data, next);
   2102 		}
   2103 		mutex_exit(&sc->sc_tx_mtx);
   2104 
   2105 		if (data == NULL) {
   2106 			ifp->if_flags |= IFF_OACTIVE;
   2107 			DPRINTFN(DBG_TX, sc, "empty sc_tx_free_list\n");
   2108 			return;
   2109 		}
   2110 
   2111 		/* Send pending management frames first. */
   2112 		IF_DEQUEUE(&ic->ic_mgtq, m);
   2113 		if (m != NULL) {
   2114 			ni = M_GETCTX(m, struct ieee80211_node *);
   2115 			M_CLEARCTX(m);
   2116 			goto sendit;
   2117 		}
   2118 
   2119 		if (ic->ic_state != IEEE80211_S_RUN)
   2120 			break;
   2121 
   2122 		/* Encapsulate and send data frames. */
   2123 		IFQ_DEQUEUE(&ifp->if_snd, m);
   2124 		if (m == NULL)
   2125 			break;
   2126 
   2127 		if (m->m_len < (int)sizeof(*eh) &&
   2128 		    (m = m_pullup(m, sizeof(*eh))) == NULL) {
   2129 			if_statinc(ifp, if_oerrors);
   2130 			continue;
   2131 		}
   2132 
   2133 		eh = mtod(m, struct ether_header *);
   2134 		ni = ieee80211_find_txnode(ic, eh->ether_dhost);
   2135 		if (ni == NULL) {
   2136 			m_freem(m);
   2137 			if_statinc(ifp, if_oerrors);
   2138 			continue;
   2139 		}
   2140 
   2141 		bpf_mtap(ifp, m, BPF_D_OUT);
   2142 
   2143 		if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
   2144 			/* original m was freed by ieee80211_encap() */
   2145 			ieee80211_free_node(ni);
   2146 			if_statinc(ifp, if_oerrors);
   2147 			continue;
   2148 		}
   2149  sendit:
   2150 		bpf_mtap3(ic->ic_rawbpf, m, BPF_D_OUT);
   2151 
   2152 		if (otus_tx(sc, m, ni, data) != 0) {
   2153 			m_freem(m);
   2154 			ieee80211_free_node(ni);
   2155 			if_statinc(ifp, if_oerrors);
   2156 			continue;
   2157 		}
   2158 
   2159 		data = NULL;	/* we're finished with this data buffer */
   2160 		m_freem(m);
   2161 		ieee80211_free_node(ni);
   2162 		sc->sc_tx_timer = 5;
   2163 		ifp->if_timer = 1;
   2164 	}
   2165 
   2166 	/*
   2167 	 * If here, we have a Tx buffer, but ran out of mbufs to
   2168 	 * transmit.  Put the Tx buffer back to the free list.
   2169 	 */
   2170 	mutex_enter(&sc->sc_tx_mtx);
   2171 	TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
   2172 	mutex_exit(&sc->sc_tx_mtx);
   2173 }
   2174 
   2175 Static void
   2176 otus_watchdog(struct ifnet *ifp)
   2177 {
   2178 	struct otus_softc *sc;
   2179 
   2180 	sc = ifp->if_softc;
   2181 
   2182 	DPRINTFN(DBG_FN, sc, "\n");
   2183 
   2184 	ifp->if_timer = 0;
   2185 
   2186 	if (sc->sc_tx_timer > 0) {
   2187 		if (--sc->sc_tx_timer == 0) {
   2188 			aprint_error_dev(sc->sc_dev, "device timeout\n");
   2189 			/* otus_init(ifp); XXX needs a process context! */
   2190 			if_statinc(ifp, if_oerrors);
   2191 			return;
   2192 		}
   2193 		ifp->if_timer = 1;
   2194 	}
   2195 	ieee80211_watchdog(&sc->sc_ic);
   2196 }
   2197 
   2198 Static int
   2199 otus_ioctl(struct ifnet *ifp, u_long cmd, void *data)
   2200 {
   2201 	struct otus_softc *sc;
   2202 	struct ieee80211com *ic;
   2203 	int s, error = 0;
   2204 
   2205 	sc = ifp->if_softc;
   2206 
   2207 	DPRINTFN(DBG_FN, sc, "%#lx\n", cmd);
   2208 
   2209 	ic = &sc->sc_ic;
   2210 
   2211 	s = splnet();
   2212 
   2213 	switch (cmd) {
   2214 	case SIOCSIFADDR:
   2215 		ifp->if_flags |= IFF_UP;
   2216 #ifdef INET
   2217 		struct ifaddr *ifa = data;
   2218 		if (ifa->ifa_addr->sa_family == AF_INET)
   2219 			arp_ifinit(&ic->ic_ac, ifa);
   2220 #endif
   2221 		/* FALLTHROUGH */
   2222 	case SIOCSIFFLAGS:
   2223 		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
   2224 			break;
   2225 
   2226 		switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
   2227 		case IFF_UP | IFF_RUNNING:
   2228 			if (((ifp->if_flags ^ sc->sc_if_flags) &
   2229 				(IFF_ALLMULTI | IFF_PROMISC)) != 0)
   2230 				otus_set_multi(sc);
   2231 			break;
   2232 		case IFF_UP:
   2233 			otus_init(ifp);
   2234 			break;
   2235 
   2236 		case IFF_RUNNING:
   2237 			otus_stop(ifp);
   2238 			break;
   2239 		case 0:
   2240 		default:
   2241 			break;
   2242 		}
   2243 		sc->sc_if_flags = ifp->if_flags;
   2244 		break;
   2245 
   2246 	case SIOCADDMULTI:
   2247 	case SIOCDELMULTI:
   2248 		if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
   2249 			/* setup multicast filter, etc */
   2250 			/* XXX: ??? */
   2251 			error = 0;
   2252 		}
   2253 		break;
   2254 
   2255 	case SIOCS80211CHANNEL:
   2256 		/*
   2257 		 * This allows for fast channel switching in monitor mode
   2258 		 * (used by kismet). In IBSS mode, we must explicitly reset
   2259 		 * the interface to generate a new beacon frame.
   2260 		 */
   2261 		error = ieee80211_ioctl(ic, cmd, data);
   2262 
   2263 		DPRINTFN(DBG_CHAN, sc,
   2264 		    "ic_curchan=%d ic_ibss_chan=%d ic_des_chan=%d ni_chan=%d error=%d\n",
   2265 		    ieee80211_chan2ieee(ic, ic->ic_curchan),
   2266 		    ieee80211_chan2ieee(ic, ic->ic_ibss_chan),
   2267 		    ieee80211_chan2ieee(ic, ic->ic_des_chan),
   2268 		    ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
   2269 		    error);
   2270 
   2271 		if (error == ENETRESET &&
   2272 		    ic->ic_opmode == IEEE80211_M_MONITOR) {
   2273 			if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
   2274 			    (IFF_UP | IFF_RUNNING)) {
   2275 				mutex_enter(&sc->sc_write_mtx);
   2276 				otus_set_chan(sc, ic->ic_curchan, 0);
   2277 				mutex_exit(&sc->sc_write_mtx);
   2278 			}
   2279 			error = 0;
   2280 		}
   2281 		break;
   2282 
   2283 	default:
   2284 		error = ieee80211_ioctl(ic, cmd, data);
   2285 	}
   2286 	if (error == ENETRESET) {
   2287 		if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
   2288 		    (IFF_UP | IFF_RUNNING))
   2289 			otus_init(ifp);
   2290 		error = 0;
   2291 	}
   2292 	splx(s);
   2293 	return error;
   2294 }
   2295 
   2296 Static int
   2297 otus_set_multi(struct otus_softc *sc)
   2298 {
   2299 	struct ethercom *ec = &sc->sc_ec;
   2300 	struct ifnet *ifp;
   2301 	struct ether_multi *enm;
   2302 	struct ether_multistep step;
   2303 	uint32_t lo, hi;
   2304 	uint8_t bit;
   2305 	int error;
   2306 
   2307 	DPRINTFN(DBG_FN, sc, "\n");
   2308 
   2309 	ifp = sc->sc_ic.ic_ifp;
   2310 	if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
   2311 		lo = hi = 0xffffffff;
   2312 		goto done;
   2313 	}
   2314 	lo = hi = 0;
   2315 	ETHER_LOCK(ec);
   2316 	ETHER_FIRST_MULTI(step, ec, enm);
   2317 	while (enm != NULL) {
   2318 		if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
   2319 			ifp->if_flags |= IFF_ALLMULTI;
   2320 			lo = hi = 0xffffffff;
   2321 			goto done;
   2322 		}
   2323 		bit = enm->enm_addrlo[5] >> 2;
   2324 		if (bit < 32)
   2325 			lo |= 1 << bit;
   2326 		else
   2327 			hi |= 1 << (bit - 32);
   2328 		ETHER_NEXT_MULTI(step, enm);
   2329 	}
   2330  done:
   2331 	ETHER_UNLOCK(ec);
   2332 	mutex_enter(&sc->sc_write_mtx);
   2333 	hi |= 1 << 31;	/* Make sure the broadcast bit is set. */
   2334 	otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L, lo);
   2335 	otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H, hi);
   2336 	error = otus_write_barrier(sc);
   2337 	mutex_exit(&sc->sc_write_mtx);
   2338 	return error;
   2339 }
   2340 
   2341 #ifdef HAVE_EDCA
   2342 Static void
   2343 otus_updateedca(struct ieee80211com *ic)
   2344 {
   2345 
   2346 	DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
   2347 
   2348 	/* Do it in a process context. */
   2349 	otus_do_async(ic->ic_ifp->if_softc, otus_updateedca_cb, NULL, 0);
   2350 }
   2351 
   2352 Static void
   2353 otus_updateedca_cb(struct otus_softc *sc, void *arg __used)
   2354 {
   2355 
   2356 	DPRINTFN(DBG_FN, sc, "\n");
   2357 
   2358 	mutex_enter(&sc->sc_write_mtx);
   2359 	otus_updateedca_cb_locked(sc);
   2360 	mutex_exit(&sc->sc_write_mtx);
   2361 }
   2362 #endif
   2363 
   2364 Static void
   2365 otus_updateedca_cb_locked(struct otus_softc *sc)
   2366 {
   2367 #ifdef HAVE_EDCA
   2368 	struct ieee80211com *ic;
   2369 #endif
   2370 	const struct ieee80211_edca_ac_params *edca;
   2371 	int s;
   2372 
   2373 	DPRINTFN(DBG_FN, sc, "\n");
   2374 
   2375 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   2376 
   2377 	s = splnet();
   2378 
   2379 #ifdef HAVE_EDCA
   2380 	ic = &sc->sc_ic;
   2381 	edca = (ic->ic_flags & IEEE80211_F_QOS) ?
   2382 	    ic->ic_edca_ac : otus_edca_def;
   2383 #else
   2384 	edca = otus_edca_def;
   2385 #endif /* HAVE_EDCA */
   2386 
   2387 #define EXP2(val)	((1 << (val)) - 1)
   2388 #define AIFS(val)	((val) * 9 + 10)
   2389 
   2390 	/* Set CWmin/CWmax values. */
   2391 	otus_write(sc, AR_MAC_REG_AC0_CW,
   2392 	    EXP2(edca[WME_AC_BE].ac_ecwmax) << 16 |
   2393 	    EXP2(edca[WME_AC_BE].ac_ecwmin));
   2394 	otus_write(sc, AR_MAC_REG_AC1_CW,
   2395 	    EXP2(edca[WME_AC_BK].ac_ecwmax) << 16 |
   2396 	    EXP2(edca[WME_AC_BK].ac_ecwmin));
   2397 	otus_write(sc, AR_MAC_REG_AC2_CW,
   2398 	    EXP2(edca[WME_AC_VI].ac_ecwmax) << 16 |
   2399 	    EXP2(edca[WME_AC_VI].ac_ecwmin));
   2400 	otus_write(sc, AR_MAC_REG_AC3_CW,
   2401 	    EXP2(edca[WME_AC_VO].ac_ecwmax) << 16 |
   2402 	    EXP2(edca[WME_AC_VO].ac_ecwmin));
   2403 	otus_write(sc, AR_MAC_REG_AC4_CW,		/* Special TXQ. */
   2404 	    EXP2(edca[WME_AC_VO].ac_ecwmax) << 16 |
   2405 	    EXP2(edca[WME_AC_VO].ac_ecwmin));
   2406 
   2407 	/* Set AIFSN values. */
   2408 	otus_write(sc, AR_MAC_REG_AC1_AC0_AIFS,
   2409 	    AIFS(edca[WME_AC_VI].ac_aifsn) << 24 |
   2410 	    AIFS(edca[WME_AC_BK].ac_aifsn) << 12 |
   2411 	    AIFS(edca[WME_AC_BE].ac_aifsn));
   2412 	otus_write(sc, AR_MAC_REG_AC3_AC2_AIFS,
   2413 	    AIFS(edca[WME_AC_VO].ac_aifsn) << 16 |	/* Special TXQ. */
   2414 	    AIFS(edca[WME_AC_VO].ac_aifsn) <<  4 |
   2415 	    AIFS(edca[WME_AC_VI].ac_aifsn) >>  8);
   2416 
   2417 	/* Set TXOP limit. */
   2418 	otus_write(sc, AR_MAC_REG_AC1_AC0_TXOP,
   2419 	    edca[WME_AC_BK].ac_txoplimit << 16 |
   2420 	    edca[WME_AC_BE].ac_txoplimit);
   2421 	otus_write(sc, AR_MAC_REG_AC3_AC2_TXOP,
   2422 	    edca[WME_AC_VO].ac_txoplimit << 16 |
   2423 	    edca[WME_AC_VI].ac_txoplimit);
   2424 #undef AIFS
   2425 #undef EXP2
   2426 
   2427 	splx(s);
   2428 
   2429 	(void)otus_write_barrier(sc);
   2430 }
   2431 
   2432 Static void
   2433 otus_updateslot(struct ifnet *ifp)
   2434 {
   2435 	struct otus_softc *sc;
   2436 
   2437 	sc = ifp->if_softc;
   2438 
   2439 	DPRINTFN(DBG_FN, sc, "\n");
   2440 
   2441 	/* Do it in a process context. */
   2442 	otus_do_async(sc, otus_updateslot_cb, NULL, 0);
   2443 }
   2444 
   2445 /* ARGSUSED */
   2446 Static void
   2447 otus_updateslot_cb(struct otus_softc *sc, void *arg)
   2448 {
   2449 
   2450 	DPRINTFN(DBG_FN, sc, "\n");
   2451 
   2452 	mutex_enter(&sc->sc_write_mtx);
   2453 	otus_updateslot_cb_locked(sc);
   2454 	mutex_exit(&sc->sc_write_mtx);
   2455 }
   2456 
   2457 Static void
   2458 otus_updateslot_cb_locked(struct otus_softc *sc)
   2459 {
   2460 	uint32_t slottime;
   2461 
   2462 	DPRINTFN(DBG_FN, sc, "\n");
   2463 
   2464 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   2465 
   2466 	slottime = (sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
   2467 	otus_write(sc, AR_MAC_REG_SLOT_TIME, slottime << 10);
   2468 	(void)otus_write_barrier(sc);
   2469 }
   2470 
   2471 Static int
   2472 otus_init_mac(struct otus_softc *sc)
   2473 {
   2474 	int error;
   2475 
   2476 	DPRINTFN(DBG_FN | DBG_INIT, sc, "\n");
   2477 
   2478 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   2479 
   2480 	otus_write(sc, AR_MAC_REG_ACK_EXTENSION, 0x40);
   2481 	otus_write(sc, AR_MAC_REG_RETRY_MAX, 0);
   2482 	otus_write(sc, AR_MAC_REG_SNIFFER, AR_MAC_REG_SNIFFER_DEFAULTS);
   2483 	otus_write(sc, AR_MAC_REG_RX_THRESHOLD, 0xc1f80);
   2484 	otus_write(sc, AR_MAC_REG_RX_PE_DELAY, 0x70);
   2485 	otus_write(sc, AR_MAC_REG_EIFS_AND_SIFS, 0xa144000);
   2486 	otus_write(sc, AR_MAC_REG_SLOT_TIME, 9 << 10);
   2487 
   2488 	/* CF-END mode */
   2489 	otus_write(sc, 0x1c3b2c, 0x19000000);
   2490 
   2491 	/* NAV protects ACK only (in TXOP). */
   2492 	otus_write(sc, 0x1c3b38, 0x201);
   2493 
   2494 	/* Set beacon PHY CTRL's TPC to 0x7, TA1=1 */
   2495 	/* OTUS set AM to 0x1 */
   2496 	otus_write(sc, AR_MAC_REG_BCN_HT1, 0x8000170);
   2497 
   2498 	otus_write(sc, AR_MAC_REG_BACKOFF_PROTECT, 0x105);
   2499 
   2500 	/* AGG test code*/
   2501 	/* Aggregation MAX number and timeout */
   2502 	otus_write(sc, AR_MAC_REG_AMPDU_FACTOR, 0x10000a);
   2503 
   2504 	/* Filter any control frames, BAR is bit 24. */
   2505 	otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, AR_MAC_REG_FTF_DEFAULTS);
   2506 
   2507 	/* Enable deaggregator, response in sniffer mode */
   2508 	otus_write(sc, 0x1c3c40, 0x1 | 1 << 30);	/* XXX: was 0x1 */
   2509 
   2510 	/* rate sets */
   2511 	otus_write(sc, AR_MAC_REG_BASIC_RATE, 0x150f);
   2512 	otus_write(sc, AR_MAC_REG_MANDATORY_RATE, 0x150f);
   2513 	otus_write(sc, AR_MAC_REG_RTS_CTS_RATE, 0x10b01bb);
   2514 
   2515 	/* MIMO response control */
   2516 	otus_write(sc, 0x1c3694, 0x4003c1e);	/* bit 26~28  otus-AM */
   2517 
   2518 	/* Switch MAC to OTUS interface. */
   2519 	otus_write(sc, 0x1c3600, 0x3);
   2520 
   2521 	otus_write(sc, AR_MAC_REG_AMPDU_RX_THRESH, 0xffff);
   2522 
   2523 	/* set PHY register read timeout (??) */
   2524 	otus_write(sc, AR_MAC_REG_MISC_680, 0xf00008);
   2525 
   2526 	/* Disable Rx TimeOut, workaround for BB. */
   2527 	otus_write(sc, AR_MAC_REG_RX_TIMEOUT, 0x0);
   2528 
   2529 	/* Set clock frequency to 88/80MHz. */
   2530 	otus_write(sc, AR_PWR_REG_CLOCK_SEL,
   2531 	    AR_PWR_CLK_AHB_80_88MHZ | AR_PWR_CLK_DAC_160_INV_DLY);
   2532 
   2533 	/* Set WLAN DMA interrupt mode: generate intr per packet. */
   2534 	otus_write(sc, AR_MAC_REG_TXRX_MPI, 0x110011);
   2535 
   2536 	otus_write(sc, AR_MAC_REG_FCS_SELECT, AR_MAC_FCS_FIFO_PROT);
   2537 
   2538 	/* Disables the CF_END frame, undocumented register */
   2539 	otus_write(sc, AR_MAC_REG_TXOP_NOT_ENOUGH_INDICATION, 0x141e0f48);
   2540 
   2541 	/* Disable HW decryption for now. */
   2542 	otus_write(sc, AR_MAC_REG_ENCRYPTION,
   2543 	    AR_MAC_REG_ENCRYPTION_DEFAULTS | AR_MAC_REG_ENCRYPTION_RX_SOFTWARE);
   2544 
   2545 	/*
   2546 	 * XXX: should these be elsewhere?
   2547 	 */
   2548 	/* Enable LED0 and LED1. */
   2549 	otus_write(sc, AR_GPIO_REG_PORT_TYPE, 3);
   2550 	otus_write(sc, AR_GPIO_REG_DATA,
   2551 	    AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON);
   2552 
   2553 	/* Set USB Rx stream mode maximum frame number to 2. */
   2554 	otus_write(sc, AR_USB_REG_MAX_AGG_UPLOAD, (1 << 2));
   2555 
   2556 	/* Set USB Rx stream mode timeout to 10us. */
   2557 	otus_write(sc, AR_USB_REG_UPLOAD_TIME_CTL, 0x80);
   2558 
   2559 	if ((error = otus_write_barrier(sc)) != 0)
   2560 		return error;
   2561 
   2562 	/* Set default EDCA parameters. */
   2563 	otus_updateedca_cb_locked(sc);
   2564 	return 0;
   2565 }
   2566 
   2567 /*
   2568  * Return default value for PHY register based on current operating mode.
   2569  */
   2570 Static uint32_t
   2571 otus_phy_get_def(struct otus_softc *sc, uint32_t reg)
   2572 {
   2573 	int i;
   2574 
   2575 	DPRINTFN(DBG_FN, sc, "\n");
   2576 
   2577 	for (i = 0; i < __arraycount(ar5416_phy_regs); i++)
   2578 		if (AR_PHY(ar5416_phy_regs[i]) == reg)
   2579 			return sc->sc_phy_vals[i];
   2580 	return 0;	/* Register not found. */
   2581 }
   2582 
   2583 /*
   2584  * Update PHY's programming based on vendor-specific data stored in EEPROM.
   2585  * This is for FEM-type devices only.
   2586  */
   2587 Static int
   2588 otus_set_board_values(struct otus_softc *sc, struct ieee80211_channel *c)
   2589 {
   2590 	const struct ModalEepHeader *eep;
   2591 	uint32_t tmp, offset;
   2592 
   2593 	DPRINTFN(DBG_FN, sc, "\n");
   2594 
   2595 	if (IEEE80211_IS_CHAN_5GHZ(c))
   2596 		eep = &sc->sc_eeprom.modalHeader[0];
   2597 	else
   2598 		eep = &sc->sc_eeprom.modalHeader[1];
   2599 
   2600 	/* Offset of chain 2. */
   2601 	offset = 2 * 0x1000;
   2602 
   2603 	tmp = le32toh(eep->antCtrlCommon);
   2604 	otus_write(sc, AR_PHY_SWITCH_COM, tmp);
   2605 
   2606 	tmp = le32toh(eep->antCtrlChain[0]);
   2607 	otus_write(sc, AR_PHY_SWITCH_CHAIN_0, tmp);
   2608 
   2609 	tmp = le32toh(eep->antCtrlChain[1]);
   2610 	otus_write(sc, AR_PHY_SWITCH_CHAIN_0 + offset, tmp);
   2611 
   2612 	if (1 /* sc->sc_sco == AR_SCO_SCN */) {
   2613 		tmp = otus_phy_get_def(sc, AR_PHY_SETTLING);
   2614 		tmp &= ~(0x7f << 7);
   2615 		tmp |= (eep->switchSettling & 0x7f) << 7;
   2616 		otus_write(sc, AR_PHY_SETTLING, tmp);
   2617 	}
   2618 
   2619 	tmp = otus_phy_get_def(sc, AR_PHY_DESIRED_SZ);
   2620 	tmp &= ~0xffff;
   2621 	tmp |= eep->pgaDesiredSize << 8 | eep->adcDesiredSize;
   2622 	otus_write(sc, AR_PHY_DESIRED_SZ, tmp);
   2623 
   2624 	tmp = eep->txEndToXpaOff << 24 | eep->txEndToXpaOff << 16 |
   2625 	      eep->txFrameToXpaOn << 8 | eep->txFrameToXpaOn;
   2626 	otus_write(sc, AR_PHY_RF_CTL4, tmp);
   2627 
   2628 	tmp = otus_phy_get_def(sc, AR_PHY_RF_CTL3);
   2629 	tmp &= ~(0xff << 16);
   2630 	tmp |= eep->txEndToRxOn << 16;
   2631 	otus_write(sc, AR_PHY_RF_CTL3, tmp);
   2632 
   2633 	tmp = otus_phy_get_def(sc, AR_PHY_CCA);
   2634 	tmp &= ~(0x7f << 12);
   2635 	tmp |= (eep->thresh62 & 0x7f) << 12;
   2636 	otus_write(sc, AR_PHY_CCA, tmp);
   2637 
   2638 	tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN);
   2639 	tmp &= ~(0x3f << 12);
   2640 	tmp |= (eep->txRxAttenCh[0] & 0x3f) << 12;
   2641 	otus_write(sc, AR_PHY_RXGAIN, tmp);
   2642 
   2643 	tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN + offset);
   2644 	tmp &= ~(0x3f << 12);
   2645 	tmp |= (eep->txRxAttenCh[1] & 0x3f) << 12;
   2646 	otus_write(sc, AR_PHY_RXGAIN + offset, tmp);
   2647 
   2648 	tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ);
   2649 	tmp &= ~(0x3f << 18);
   2650 	tmp |= (eep->rxTxMarginCh[0] & 0x3f) << 18;
   2651 	if (IEEE80211_IS_CHAN_5GHZ(c)) {
   2652 		tmp &= ~(0xf << 10);
   2653 		tmp |= (eep->bswMargin[0] & 0xf) << 10;
   2654 	}
   2655 	otus_write(sc, AR_PHY_GAIN_2GHZ, tmp);
   2656 
   2657 	tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ + offset);
   2658 	tmp &= ~(0x3f << 18);
   2659 	tmp |= (eep->rxTxMarginCh[1] & 0x3f) << 18;
   2660 	otus_write(sc, AR_PHY_GAIN_2GHZ + offset, tmp);
   2661 
   2662 	tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4);
   2663 	tmp &= ~(0x3f << 5 | 0x1f);
   2664 	tmp |= (eep->iqCalICh[0] & 0x3f) << 5 | (eep->iqCalQCh[0] & 0x1f);
   2665 	otus_write(sc, AR_PHY_TIMING_CTRL4, tmp);
   2666 
   2667 	tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4 + offset);
   2668 	tmp &= ~(0x3f << 5 | 0x1f);
   2669 	tmp |= (eep->iqCalICh[1] & 0x3f) << 5 | (eep->iqCalQCh[1] & 0x1f);
   2670 	otus_write(sc, AR_PHY_TIMING_CTRL4 + offset, tmp);
   2671 
   2672 	tmp = otus_phy_get_def(sc, AR_PHY_TPCRG1);
   2673 	tmp &= ~(0xf << 16);
   2674 	tmp |= (eep->xpd & 0xf) << 16;
   2675 	otus_write(sc, AR_PHY_TPCRG1, tmp);
   2676 
   2677 	return otus_write_barrier(sc);
   2678 }
   2679 
   2680 Static int
   2681 otus_program_phy(struct otus_softc *sc, struct ieee80211_channel *c)
   2682 {
   2683 	const uint32_t *vals;
   2684 	int error, i;
   2685 
   2686 	DPRINTFN(DBG_FN, sc, "\n");
   2687 
   2688 	/* Select PHY programming based on band and bandwidth. */
   2689 	if (IEEE80211_IS_CHAN_2GHZ(c))
   2690 		vals = ar5416_phy_vals_2ghz_20mhz;
   2691 	else
   2692 		vals = ar5416_phy_vals_5ghz_20mhz;
   2693 	for (i = 0; i < __arraycount(ar5416_phy_regs); i++)
   2694 		otus_write(sc, AR_PHY(ar5416_phy_regs[i]), vals[i]);
   2695 	sc->sc_phy_vals = vals;
   2696 
   2697 	if (sc->sc_eeprom.baseEepHeader.deviceType == 0x80)	/* FEM */
   2698 		if ((error = otus_set_board_values(sc, c)) != 0)
   2699 			return error;
   2700 
   2701 	/* Initial Tx power settings. */
   2702 	otus_write(sc, AR_PHY_POWER_TX_RATE_MAX, 0x7f);
   2703 	otus_write(sc, AR_PHY_POWER_TX_RATE1, 0x3f3f3f3f);
   2704 	otus_write(sc, AR_PHY_POWER_TX_RATE2, 0x3f3f3f3f);
   2705 	otus_write(sc, AR_PHY_POWER_TX_RATE3, 0x3f3f3f3f);
   2706 	otus_write(sc, AR_PHY_POWER_TX_RATE4, 0x3f3f3f3f);
   2707 	otus_write(sc, AR_PHY_POWER_TX_RATE5, 0x3f3f3f3f);
   2708 	otus_write(sc, AR_PHY_POWER_TX_RATE6, 0x3f3f3f3f);
   2709 	otus_write(sc, AR_PHY_POWER_TX_RATE7, 0x3f3f3f3f);
   2710 	otus_write(sc, AR_PHY_POWER_TX_RATE8, 0x3f3f3f3f);
   2711 	otus_write(sc, AR_PHY_POWER_TX_RATE9, 0x3f3f3f3f);
   2712 
   2713 	if (IEEE80211_IS_CHAN_2GHZ(c))
   2714 		otus_write(sc, 0x1d4014, 0x5163);
   2715 	else
   2716 		otus_write(sc, 0x1d4014, 0x5143);
   2717 
   2718 	return otus_write_barrier(sc);
   2719 }
   2720 
   2721 static __inline uint8_t
   2722 otus_reverse_bits(uint8_t v)
   2723 {
   2724 
   2725 	v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
   2726 	v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
   2727 	v = ((v >> 4) & 0x0f) | ((v & 0x0f) << 4);
   2728 	return v;
   2729 }
   2730 
   2731 Static int
   2732 otus_set_rf_bank4(struct otus_softc *sc, struct ieee80211_channel *c)
   2733 {
   2734 	uint8_t chansel, d0, d1;
   2735 	uint16_t data;
   2736 	int error;
   2737 
   2738 	DPRINTFN(DBG_FN, sc, "\n");
   2739 
   2740 	d0 = 0;
   2741 	if (IEEE80211_IS_CHAN_5GHZ(c)) {
   2742 		chansel = (c->ic_freq - 4800) / 5;
   2743 		if (chansel & 1)
   2744 			d0 |= AR_BANK4_AMODE_REFSEL(2);
   2745 		else
   2746 			d0 |= AR_BANK4_AMODE_REFSEL(1);
   2747 	} else {
   2748 		d0 |= AR_BANK4_AMODE_REFSEL(2);
   2749 		if (c->ic_freq == 2484) {	/* CH 14 */
   2750 			d0 |= AR_BANK4_BMODE_LF_SYNTH_FREQ;
   2751 			chansel = 10 + (c->ic_freq - 2274) / 5;
   2752 		} else
   2753 			chansel = 16 + (c->ic_freq - 2272) / 5;
   2754 		chansel <<= 2;
   2755 	}
   2756 	d0 |= AR_BANK4_ADDR(1) | AR_BANK4_CHUP;
   2757 	d1 = otus_reverse_bits(chansel);
   2758 
   2759 	/* Write bits 0-4 of d0 and d1. */
   2760 	data = (d1 & 0x1f) << 5 | (d0 & 0x1f);
   2761 	otus_write(sc, AR_PHY(44), data);
   2762 	/* Write bits 5-7 of d0 and d1. */
   2763 	data = (d1 >> 5) << 5 | (d0 >> 5);
   2764 	otus_write(sc, AR_PHY(58), data);
   2765 
   2766 	if ((error = otus_write_barrier(sc)) == 0)
   2767 		usbd_delay_ms(sc->sc_udev, 10);
   2768 
   2769 	return error;
   2770 }
   2771 
   2772 Static void
   2773 otus_get_delta_slope(uint32_t coeff, uint32_t *exponent, uint32_t *mantissa)
   2774 {
   2775 #define COEFF_SCALE_SHIFT	24
   2776 	uint32_t exp, man;
   2777 
   2778 	DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
   2779 
   2780 	/* exponent = 14 - floor(log2(coeff)) */
   2781 	for (exp = 31; exp > 0; exp--)
   2782 		if (coeff & (1 << exp))
   2783 			break;
   2784 	KASSERT(exp != 0);
   2785 	exp = 14 - (exp - COEFF_SCALE_SHIFT);
   2786 
   2787 	/* mantissa = floor(coeff * 2^exponent + 0.5) */
   2788 	man = coeff + (1 << (COEFF_SCALE_SHIFT - exp - 1));
   2789 
   2790 	*mantissa = man >> (COEFF_SCALE_SHIFT - exp);
   2791 	*exponent = exp - 16;
   2792 #undef COEFF_SCALE_SHIFT
   2793 }
   2794 
   2795 Static int
   2796 otus_set_chan(struct otus_softc *sc, struct ieee80211_channel *c, int assoc)
   2797 {
   2798 	struct ar_cmd_frequency cmd;
   2799 	struct ar_rsp_frequency rsp;
   2800 	const uint32_t *vals;
   2801 	uint32_t coeff, exp, man, tmp;
   2802 	uint8_t code;
   2803 	int error, i;
   2804 
   2805 	DPRINTFN(DBG_FN, sc, "\n");
   2806 
   2807 
   2808 #ifdef OTUS_DEBUG
   2809 	struct ieee80211com *ic = &sc->sc_ic;
   2810 	int chan = ieee80211_chan2ieee(ic, c);
   2811 
   2812 	DPRINTFN(DBG_CHAN, sc, "setting channel %d (%dMHz)\n",
   2813 	    chan, c->ic_freq);
   2814 #endif
   2815 
   2816 	tmp = IEEE80211_IS_CHAN_2GHZ(c) ? 0x105 : 0x104;
   2817 	otus_write(sc, AR_MAC_REG_DYNAMIC_SIFS_ACK, tmp);
   2818 	if ((error = otus_write_barrier(sc)) != 0)
   2819 		return error;
   2820 
   2821 	/* Disable BB Heavy Clip. */
   2822 	otus_write(sc, AR_PHY_HEAVY_CLIP_ENABLE, 0x200);
   2823 	if ((error = otus_write_barrier(sc)) != 0)
   2824 		return error;
   2825 
   2826 	/* XXX Is that FREQ_START ? */
   2827 	error = otus_cmd(sc, AR_CMD_FREQ_STRAT, NULL, 0, NULL);
   2828 	if (error != 0)
   2829 		return error;
   2830 
   2831 	/* Reprogram PHY and RF on channel band or bandwidth changes. */
   2832 	if (sc->sc_bb_reset || c->ic_flags != sc->sc_curchan->ic_flags) {
   2833 		DPRINTFN(DBG_CHAN, sc, "band switch\n");
   2834 
   2835 		/* Cold/Warm reset BB/ADDA. */
   2836 		otus_write(sc, 0x1d4004, sc->sc_bb_reset ? 0x800 : 0x400);
   2837 		if ((error = otus_write_barrier(sc)) != 0)
   2838 			return error;
   2839 
   2840 		otus_write(sc, 0x1d4004, 0);
   2841 		if ((error = otus_write_barrier(sc)) != 0)
   2842 			return error;
   2843 		sc->sc_bb_reset = 0;
   2844 
   2845 		if ((error = otus_program_phy(sc, c)) != 0) {
   2846 			aprint_error_dev(sc->sc_dev,
   2847 			    "could not program PHY\n");
   2848 			return error;
   2849 		}
   2850 
   2851 		/* Select RF programming based on band. */
   2852 		if (IEEE80211_IS_CHAN_5GHZ(c))
   2853 			vals = ar5416_banks_vals_5ghz;
   2854 		else
   2855 			vals = ar5416_banks_vals_2ghz;
   2856 		for (i = 0; i < __arraycount(ar5416_banks_regs); i++)
   2857 			otus_write(sc, AR_PHY(ar5416_banks_regs[i]), vals[i]);
   2858 		if ((error = otus_write_barrier(sc)) != 0) {
   2859 			aprint_error_dev(sc->sc_dev, "could not program RF\n");
   2860 			return error;
   2861 		}
   2862 		code = AR_CMD_RF_INIT;
   2863 	} else {
   2864 		code = AR_CMD_FREQUENCY;
   2865 	}
   2866 
   2867 	if ((error = otus_set_rf_bank4(sc, c)) != 0)
   2868 		return error;
   2869 
   2870 	tmp = (sc->sc_txmask == 0x5) ? 0x340 : 0x240;
   2871 	otus_write(sc, AR_PHY_TURBO, tmp);
   2872 	if ((error = otus_write_barrier(sc)) != 0)
   2873 		return error;
   2874 
   2875 	/* Send firmware command to set channel. */
   2876 	cmd.freq = htole32((uint32_t)c->ic_freq * 1000);
   2877 	cmd.dynht2040 = htole32(0);
   2878 	cmd.htena = htole32(1);
   2879 
   2880 	/* Set Delta Slope (exponent and mantissa). */
   2881 	coeff = (100 << 24) / c->ic_freq;
   2882 	otus_get_delta_slope(coeff, &exp, &man);
   2883 	cmd.dsc_exp = htole32(exp);
   2884 	cmd.dsc_man = htole32(man);
   2885 	DPRINTFN(DBG_CHAN, sc, "ds coeff=%u exp=%u man=%u\n",
   2886 	    coeff, exp, man);
   2887 
   2888 	/* For Short GI, coeff is 9/10 that of normal coeff. */
   2889 	coeff = (9 * coeff) / 10;
   2890 	otus_get_delta_slope(coeff, &exp, &man);
   2891 	cmd.dsc_shgi_exp = htole32(exp);
   2892 	cmd.dsc_shgi_man = htole32(man);
   2893 	DPRINTFN(DBG_CHAN, sc, "ds shgi coeff=%u exp=%u man=%u\n",
   2894 	    coeff, exp, man);
   2895 
   2896 	/* Set wait time for AGC and noise calibration (100 or 200ms). */
   2897 	cmd.check_loop_count = assoc ? htole32(2000) : htole32(1000);
   2898 	DPRINTFN(DBG_CHAN, sc, "%s\n",
   2899 	    code == AR_CMD_RF_INIT ? "RF_INIT" : "FREQUENCY");
   2900 	error = otus_cmd(sc, code, &cmd, sizeof(cmd), &rsp);
   2901 	if (error != 0)
   2902 		return error;
   2903 
   2904 	if ((rsp.status & htole32(AR_CAL_ERR_AGC | AR_CAL_ERR_NF_VAL)) != 0) {
   2905 		DPRINTFN(DBG_CHAN, sc, "status=%#x\n", le32toh(rsp.status));
   2906 		/* Force cold reset on next channel. */
   2907 		sc->sc_bb_reset = 1;
   2908 	}
   2909 
   2910 #ifdef OTUS_DEBUG
   2911 	if (otus_debug & DBG_CHAN) {
   2912 		DPRINTFN(DBG_CHAN, sc, "calibration status=%#x\n",
   2913 		    le32toh(rsp.status));
   2914 		for (i = 0; i < 2; i++) {	/* 2 Rx chains */
   2915 			/* Sign-extend 9-bit NF values. */
   2916 			DPRINTFN(DBG_CHAN, sc, "noisefloor chain %d=%d\n",
   2917 			    i, (((int32_t)le32toh(rsp.nf[i])) << 4) >> 23);
   2918 			DPRINTFN(DBG_CHAN, sc, "noisefloor ext chain %d=%d\n",
   2919 			    i, ((int32_t)le32toh(rsp.nf_ext[i])) >> 23);
   2920 		}
   2921 	}
   2922 #endif
   2923 	sc->sc_curchan = c;
   2924 	return 0;
   2925 }
   2926 
   2927 #ifdef notyet
   2928 Static int
   2929 otus_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
   2930     struct ieee80211_key *k)
   2931 {
   2932 	struct otus_softc *sc;
   2933 	struct otus_cmd_key cmd;
   2934 
   2935 	sc = ic->ic_ifp->if_softc;
   2936 
   2937 	DPRINTFN(DBG_FN, sc, "\n");
   2938 
   2939 	/* Defer setting of WEP keys until interface is brought up. */
   2940 	if ((ic->ic_ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
   2941 	    (IFF_UP | IFF_RUNNING))
   2942 		return 0;
   2943 
   2944 	/* Do it in a process context. */
   2945 	cmd.key = *k;
   2946 	cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
   2947 	otus_do_async(sc, otus_set_key_cb, &cmd, sizeof(cmd));
   2948 	return 0;
   2949 }
   2950 
   2951 Static void
   2952 otus_set_key_cb(struct otus_softc *sc, void *arg)
   2953 {
   2954 	struct otus_cmd_key *cmd;
   2955 	struct ieee80211_key *k;
   2956 	struct ar_cmd_ekey key;
   2957 	uint16_t cipher;
   2958 	int error;
   2959 
   2960 	DPRINTFN(DBG_FN, sc, "\n");
   2961 
   2962 	cmd = arg;
   2963 	k = &cmd->key;
   2964 
   2965 	memset(&key, 0, sizeof(key));
   2966 	if (k->k_flags & IEEE80211_KEY_GROUP) {
   2967 		key.uid = htole16(k->k_id);
   2968 		IEEE80211_ADDR_COPY(key.macaddr, sc->sc_ic.ic_myaddr);
   2969 		key.macaddr[0] |= 0x80;
   2970 	} else {
   2971 		key.uid = htole16(OTUS_UID(cmd->associd));
   2972 		IEEE80211_ADDR_COPY(key.macaddr, ni->ni_macaddr);
   2973 	}
   2974 	key.kix = htole16(0);
   2975 	/* Map net80211 cipher to hardware. */
   2976 	switch (k->k_cipher) {
   2977 	case IEEE80211_CIPHER_WEP40:
   2978 		cipher = AR_CIPHER_WEP64;
   2979 		break;
   2980 	case IEEE80211_CIPHER_WEP104:
   2981 		cipher = AR_CIPHER_WEP128;
   2982 		break;
   2983 	case IEEE80211_CIPHER_TKIP:
   2984 		cipher = AR_CIPHER_TKIP;
   2985 		break;
   2986 	case IEEE80211_CIPHER_CCMP:
   2987 		cipher = AR_CIPHER_AES;
   2988 		break;
   2989 	default:
   2990 		return;
   2991 	}
   2992 	key.cipher = htole16(cipher);
   2993 	memcpy(key.key, k->k_key, MIN(k->k_len, 16));
   2994 	error = otus_cmd(sc, AR_CMD_EKEY, &key, sizeof(key), NULL);
   2995 	if (error != 0 || k->k_cipher != IEEE80211_CIPHER_TKIP)
   2996 		return;
   2997 
   2998 	/* TKIP: set Tx/Rx MIC Key. */
   2999 	key.kix = htole16(1);
   3000 	memcpy(key.key, k->k_key + 16, 16);
   3001 	(void)otus_cmd(sc, AR_CMD_EKEY, &key, sizeof(key), NULL);
   3002 }
   3003 
   3004 Static void
   3005 otus_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
   3006     struct ieee80211_key *k)
   3007 {
   3008 	struct otus_softc *sc;
   3009 	struct otus_cmd_key cmd;
   3010 
   3011 	sc = ic->ic_ifp->if_softc;
   3012 
   3013 	DPRINTFN(DBG_FN, sc, "\n");
   3014 
   3015 	if (!(ic->ic_ifp->if_flags & IFF_RUNNING) ||
   3016 	    ic->ic_state != IEEE80211_S_RUN)
   3017 		return;	/* Nothing to do. */
   3018 
   3019 	/* Do it in a process context. */
   3020 	cmd.key = *k;
   3021 	cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
   3022 	otus_do_async(sc, otus_delete_key_cb, &cmd, sizeof(cmd));
   3023 }
   3024 
   3025 Static void
   3026 otus_delete_key_cb(struct otus_softc *sc, void *arg)
   3027 {
   3028 	struct otus_cmd_key *cmd;
   3029 	struct ieee80211_key *k;
   3030 	uint32_t uid;
   3031 
   3032 	DPRINTFN(DBG_FN, sc, "\n");
   3033 
   3034 	cmd = arg;
   3035 	k = &cmd->key;
   3036 	if (k->k_flags & IEEE80211_KEY_GROUP)
   3037 		uid = htole32(k->k_id);
   3038 	else
   3039 		uid = htole32(OTUS_UID(cmd->associd));
   3040 	(void)otus_cmd(sc, AR_CMD_DKEY, &uid, sizeof(uid), NULL);
   3041 }
   3042 #endif /* notyet */
   3043 
   3044 Static void
   3045 otus_calib_to(void *arg)
   3046 {
   3047 	struct otus_softc *sc;
   3048 	struct ieee80211com *ic;
   3049 	struct ieee80211_node *ni;
   3050 	struct otus_node *on;
   3051 	int s;
   3052 
   3053 	sc = arg;
   3054 
   3055 	DPRINTFN(DBG_FN, sc, "\n");
   3056 
   3057 	if (sc->sc_dying)
   3058 		return;
   3059 
   3060 	s = splnet();
   3061 	ic = &sc->sc_ic;
   3062 	ni = ic->ic_bss;
   3063 	on = (void *)ni;
   3064 	ieee80211_amrr_choose(&sc->sc_amrr, ni, &on->amn);
   3065 	splx(s);
   3066 
   3067 	if (!sc->sc_dying)
   3068 		callout_schedule(&sc->sc_calib_to, hz);
   3069 }
   3070 
   3071 Static int
   3072 otus_set_bssid(struct otus_softc *sc, const uint8_t *bssid)
   3073 {
   3074 
   3075 	DPRINTFN(DBG_FN, sc, "\n");
   3076 
   3077 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   3078 
   3079 	otus_write(sc, AR_MAC_REG_BSSID_L,
   3080 	    bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24);
   3081 	otus_write(sc, AR_MAC_REG_BSSID_H,
   3082 	    bssid[4] | bssid[5] << 8);
   3083 	return otus_write_barrier(sc);
   3084 }
   3085 
   3086 Static int
   3087 otus_set_macaddr(struct otus_softc *sc, const uint8_t *addr)
   3088 {
   3089 
   3090 	DPRINTFN(DBG_FN, sc, "\n");
   3091 
   3092 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   3093 
   3094 	otus_write(sc, AR_MAC_REG_MAC_ADDR_L,
   3095 	    addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
   3096 	otus_write(sc, AR_MAC_REG_MAC_ADDR_H,
   3097 	    addr[4] | addr[5] << 8);
   3098 	return otus_write_barrier(sc);
   3099 }
   3100 
   3101 #ifdef notyet
   3102 /* Default single-LED. */
   3103 Static void
   3104 otus_led_newstate_type1(struct otus_softc *sc)
   3105 {
   3106 
   3107 	DPRINTFN(DBG_FN, sc, "\n");
   3108 
   3109 	/* TBD */
   3110 }
   3111 
   3112 /* NETGEAR, dual-LED. */
   3113 Static void
   3114 otus_led_newstate_type2(struct otus_softc *sc)
   3115 {
   3116 
   3117 	DPRINTFN(DBG_FN, sc, "\n");
   3118 
   3119 	/* TBD */
   3120 }
   3121 #endif /* notyet */
   3122 
   3123 /*
   3124  * NETGEAR, single-LED/3 colors (blue, red, purple.)
   3125  */
   3126 Static void
   3127 otus_led_newstate_type3(struct otus_softc *sc)
   3128 {
   3129 	struct ieee80211com *ic;
   3130 	uint32_t led_state;
   3131 
   3132 	DPRINTFN(DBG_FN, sc, "\n");
   3133 
   3134 	ic = &sc->sc_ic;
   3135 	led_state = sc->sc_led_state;
   3136 	switch (ic->ic_state) {
   3137 	case IEEE80211_S_INIT:
   3138 		led_state = 0;
   3139 		break;
   3140 	case IEEE80211_S_SCAN:
   3141 		led_state ^= AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON;
   3142 		led_state &= ~(IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) ?
   3143 		    AR_GPIO_REG_DATA_LED1_ON : AR_GPIO_REG_DATA_LED0_ON);
   3144 		break;
   3145 	case IEEE80211_S_AUTH:
   3146 	case IEEE80211_S_ASSOC:
   3147 		/* XXX: Turn both LEDs on for AUTH and ASSOC? */
   3148 		led_state = AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON;
   3149 		break;
   3150 	case IEEE80211_S_RUN:
   3151 		led_state = IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) ?
   3152 		    AR_GPIO_REG_DATA_LED0_ON : AR_GPIO_REG_DATA_LED1_ON;
   3153 		break;
   3154 	}
   3155 	if (led_state != sc->sc_led_state) {
   3156 		otus_write(sc, AR_GPIO_REG_DATA, led_state);
   3157 		if (otus_write_barrier(sc) == 0)
   3158 			sc->sc_led_state = led_state;
   3159 	}
   3160 }
   3161 
   3162 Static int
   3163 otus_init(struct ifnet *ifp)
   3164 {
   3165 	struct otus_softc *sc;
   3166 	struct ieee80211com *ic;
   3167 	uint32_t filter, pm_mode, sniffer;
   3168 	int error;
   3169 
   3170 	sc = ifp->if_softc;
   3171 
   3172 	DPRINTFN(DBG_FN | DBG_INIT, sc, "\n");
   3173 
   3174 	ic = &sc->sc_ic;
   3175 
   3176 	mutex_enter(&sc->sc_write_mtx);
   3177 
   3178 	/* Init host command ring. */
   3179 	mutex_spin_enter(&sc->sc_task_mtx);
   3180 	sc->sc_cmdq.cur = sc->sc_cmdq.next = sc->sc_cmdq.queued = 0;
   3181 	mutex_spin_exit(&sc->sc_task_mtx);
   3182 
   3183 	if ((error = otus_init_mac(sc)) != 0) {
   3184 		mutex_exit(&sc->sc_write_mtx);
   3185 		aprint_error_dev(sc->sc_dev, "could not initialize MAC\n");
   3186 		return error;
   3187 	}
   3188 
   3189 	IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
   3190 	(void)otus_set_macaddr(sc, ic->ic_myaddr);
   3191 
   3192 	pm_mode = AR_MAC_REG_POWERMGT_DEFAULTS;
   3193 	sniffer = AR_MAC_REG_SNIFFER_DEFAULTS;
   3194 	filter = AR_MAC_REG_FTF_DEFAULTS;
   3195 	sc->sc_rx_error_msk = ~0;
   3196 
   3197 	switch (ic->ic_opmode) {
   3198 #ifdef notyet
   3199 #ifndef IEEE80211_STA_ONLY
   3200 	case IEEE80211_M_HOSTAP:
   3201 		pm_mode |= AR_MAC_REG_POWERMGT_AP;
   3202 		break;
   3203 	case IEEE80211_M_IBSS:
   3204 		pm_mode |= AR_MAC_REG_POWERMGT_IBSS;	/* XXX: was 0x0 */
   3205 		break;
   3206 #endif
   3207 #endif
   3208 	case IEEE80211_M_STA:
   3209 		pm_mode |= AR_MAC_REG_POWERMGT_STA;
   3210 		break;
   3211 	case IEEE80211_M_MONITOR:
   3212 		sc->sc_rx_error_msk = ~AR_RX_ERROR_BAD_RA;
   3213 		filter = AR_MAC_REG_FTF_MONITOR;
   3214 		sniffer |= AR_MAC_REG_SNIFFER_ENABLE_PROMISC;
   3215 		break;
   3216 	default:
   3217 		aprint_error_dev(sc->sc_dev, "bad opmode: %d", ic->ic_opmode);
   3218 		return EOPNOTSUPP;	/* XXX: ??? */
   3219 	}
   3220 	otus_write(sc, AR_MAC_REG_POWERMANAGEMENT, pm_mode);
   3221 	otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, filter);
   3222 	otus_write(sc, AR_MAC_REG_SNIFFER, sniffer);
   3223 	(void)otus_write_barrier(sc);
   3224 
   3225 	sc->sc_bb_reset = 1;	/* Force cold reset. */
   3226 	if ((error = otus_set_chan(sc, ic->ic_curchan, 0)) != 0) {
   3227 		mutex_exit(&sc->sc_write_mtx);
   3228 		aprint_error_dev(sc->sc_dev, "could not set channel\n");
   3229 		return error;
   3230 	}
   3231 
   3232 	/* Start Rx. */
   3233 	otus_write(sc, AR_MAC_REG_DMA, AR_MAC_REG_DMA_ENABLE);
   3234 	(void)otus_write_barrier(sc);
   3235 	mutex_exit(&sc->sc_write_mtx);
   3236 
   3237 	ifp->if_flags &= ~IFF_OACTIVE;
   3238 	ifp->if_flags |= IFF_RUNNING;
   3239 
   3240 	if (ic->ic_opmode == IEEE80211_M_MONITOR)
   3241 		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
   3242 	else
   3243 		ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
   3244 
   3245 	return 0;
   3246 }
   3247 
   3248 Static void
   3249 otus_stop(struct ifnet *ifp)
   3250 {
   3251 	struct otus_softc *sc;
   3252 	struct ieee80211com *ic;
   3253 	int s;
   3254 
   3255 	sc = ifp->if_softc;
   3256 
   3257 	DPRINTFN(DBG_FN, sc, "\n");
   3258 
   3259 	ic = &sc->sc_ic;
   3260 
   3261 	sc->sc_tx_timer = 0;
   3262 	ifp->if_timer = 0;
   3263 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   3264 
   3265 	callout_halt(&sc->sc_scan_to, NULL);
   3266 	callout_halt(&sc->sc_calib_to, NULL);
   3267 
   3268 	s = splusb();
   3269 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
   3270 	otus_wait_async(sc);
   3271 	splx(s);
   3272 
   3273 	/* Stop Rx. */
   3274 	mutex_enter(&sc->sc_write_mtx);
   3275 	otus_write(sc, AR_MAC_REG_DMA, AR_MAC_REG_DMA_OFF);
   3276 	(void)otus_write_barrier(sc);
   3277 	mutex_exit(&sc->sc_write_mtx);
   3278 }
   3279