Home | History | Annotate | Line # | Download | only in usb
if_otus.c revision 1.42
      1 /*	$NetBSD: if_otus.c,v 1.42 2020/03/13 18:17:40 christos 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.42 2020/03/13 18:17:40 christos 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: %#08x!=%#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_attach(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 	ieee80211_media_init(ic, otus_media_change, ieee80211_media_status);
    884 
    885 	bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
    886 	    sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
    887 	    &sc->sc_drvbpf);
    888 
    889 	sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
    890 	sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
    891 	sc->sc_rxtap.wr_ihdr.it_present = htole32(OTUS_RX_RADIOTAP_PRESENT);
    892 
    893 	sc->sc_txtap_len = sizeof(sc->sc_txtapu);
    894 	sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
    895 	sc->sc_txtap.wt_ihdr.it_present = htole32(OTUS_TX_RADIOTAP_PRESENT);
    896 
    897 	ieee80211_announce(ic);
    898 }
    899 
    900 Static void
    901 otus_get_chanlist(struct otus_softc *sc)
    902 {
    903 	struct ieee80211com *ic;
    904 	uint8_t chan;
    905 	int i;
    906 
    907 #ifdef OTUS_DEBUG
    908 	/* XXX regulatory domain. */
    909 	uint16_t domain = le16toh(sc->sc_eeprom.baseEepHeader.regDmn[0]);
    910 
    911 	DPRINTFN(DBG_FN | DBG_INIT, sc, "regdomain=%#04x\n", domain);
    912 #endif
    913 
    914 	ic = &sc->sc_ic;
    915 	if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11G) {
    916 		for (i = 0; i < 14; i++) {
    917 			chan = ar_chans[i];
    918 			ic->ic_channels[chan].ic_freq =
    919 			    ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
    920 			ic->ic_channels[chan].ic_flags =
    921 			    IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
    922 			    IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
    923 		}
    924 	}
    925 	if (sc->sc_eeprom.baseEepHeader.opCapFlags & AR5416_OPFLAGS_11A) {
    926 		for (i = 14; i < __arraycount(ar_chans); i++) {
    927 			chan = ar_chans[i];
    928 			ic->ic_channels[chan].ic_freq =
    929 			    ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);
    930 			ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;
    931 		}
    932 	}
    933 }
    934 
    935 Static int
    936 otus_load_firmware(struct otus_softc *sc, const char *name, uint32_t addr)
    937 {
    938 	usb_device_request_t req;
    939 	firmware_handle_t fh;
    940 	uint8_t *ptr;
    941 	uint8_t *fw;
    942 	size_t size;
    943 	int mlen, error;
    944 
    945 	DPRINTFN(DBG_FN, sc, "\n");
    946 
    947 	if ((error = firmware_open("if_otus", name, &fh)) != 0)
    948 		return error;
    949 
    950 	size = firmware_get_size(fh);
    951 	if ((fw = firmware_malloc(size)) == NULL) {
    952 		firmware_close(fh);
    953 		return ENOMEM;
    954 	}
    955 	if ((error = firmware_read(fh, 0, fw, size)) != 0)
    956 		firmware_free(fw, size);
    957 	firmware_close(fh);
    958 	if (error)
    959 		return error;
    960 
    961 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    962 	req.bRequest = AR_FW_DOWNLOAD;
    963 	USETW(req.wIndex, 0);
    964 
    965 	ptr = fw;
    966 	addr >>= 8;
    967 	while (size > 0) {
    968 		mlen = MIN(size, 4096);
    969 
    970 		USETW(req.wValue, addr);
    971 		USETW(req.wLength, mlen);
    972 		if (usbd_do_request(sc->sc_udev, &req, ptr) != 0) {
    973 			error = EIO;
    974 			break;
    975 		}
    976 		addr += mlen >> 8;
    977 		ptr  += mlen;
    978 		size -= mlen;
    979 	}
    980 	free(fw, M_DEVBUF);
    981 	return error;
    982 }
    983 
    984 Static int
    985 otus_open_pipes(struct otus_softc *sc)
    986 {
    987 	usb_endpoint_descriptor_t *ed;
    988 	int i, error;
    989 
    990 	DPRINTFN(DBG_FN, sc, "\n");
    991 
    992 	error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_RX_NO, 0,
    993 	    &sc->sc_data_rx_pipe);
    994 	if (error != 0) {
    995 		aprint_error_dev(sc->sc_dev, "could not open Rx bulk pipe\n");
    996 		goto fail;
    997 	}
    998 
    999 	ed = usbd_get_endpoint_descriptor(sc->sc_iface, AR_EPT_INTR_RX_NO);
   1000 	if (ed == NULL) {
   1001 		aprint_error_dev(sc->sc_dev,
   1002 		    "could not retrieve Rx intr pipe descriptor\n");
   1003 		goto fail;
   1004 	}
   1005 	sc->sc_ibuf_size = UGETW(ed->wMaxPacketSize);
   1006 	if (sc->sc_ibuf_size == 0) {
   1007 		aprint_error_dev(sc->sc_dev,
   1008 		    "invalid Rx intr pipe descriptor\n");
   1009 		goto fail;
   1010 	}
   1011 	sc->sc_ibuf = kmem_alloc(sc->sc_ibuf_size, KM_SLEEP);
   1012 	error = usbd_open_pipe_intr(sc->sc_iface, AR_EPT_INTR_RX_NO,
   1013 	    USBD_SHORT_XFER_OK, &sc->sc_cmd_rx_pipe, sc, sc->sc_ibuf,
   1014 	    sc->sc_ibuf_size, otus_intr, USBD_DEFAULT_INTERVAL);
   1015 	if (error != 0) {
   1016 		aprint_error_dev(sc->sc_dev, "could not open Rx intr pipe\n");
   1017 		goto fail;
   1018 	}
   1019 
   1020 	error = usbd_open_pipe(sc->sc_iface, AR_EPT_BULK_TX_NO, 0,
   1021 	    &sc->sc_data_tx_pipe);
   1022 	if (error != 0) {
   1023 		aprint_error_dev(sc->sc_dev, "could not open Tx bulk pipe\n");
   1024 		goto fail;
   1025 	}
   1026 
   1027 	error = usbd_open_pipe(sc->sc_iface, AR_EPT_INTR_TX_NO, 0,
   1028 	    &sc->sc_cmd_tx_pipe);
   1029 	if (error != 0) {
   1030 		aprint_error_dev(sc->sc_dev, "could not open Tx intr pipe\n");
   1031 		goto fail;
   1032 	}
   1033 
   1034 	if (otus_alloc_tx_cmd(sc) != 0) {
   1035 		aprint_error_dev(sc->sc_dev,
   1036 		    "could not allocate command xfer\n");
   1037 		goto fail;
   1038 	}
   1039 
   1040 	if (otus_alloc_tx_data_list(sc)) {
   1041 		aprint_error_dev(sc->sc_dev, "could not allocate Tx xfers\n");
   1042 		goto fail;
   1043 	}
   1044 
   1045 	if (otus_alloc_rx_data_list(sc)) {
   1046 		aprint_error_dev(sc->sc_dev, "could not allocate Rx xfers\n");
   1047 		goto fail;
   1048 	}
   1049 
   1050 	for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++) {
   1051 		struct otus_rx_data *data = &sc->sc_rx_data[i];
   1052 
   1053 		usbd_setup_xfer(data->xfer, data, data->buf, OTUS_RXBUFSZ,
   1054 		    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, otus_rxeof);
   1055 		error = usbd_transfer(data->xfer);
   1056 		if (error != USBD_IN_PROGRESS && error != 0) {
   1057 			aprint_error_dev(sc->sc_dev,
   1058 			    "could not queue Rx xfer\n");
   1059 			goto fail;
   1060 		}
   1061 	}
   1062 	return 0;
   1063 
   1064  fail:	otus_close_pipes(sc);
   1065 	return error;
   1066 }
   1067 
   1068 Static void
   1069 otus_close_pipes(struct otus_softc *sc)
   1070 {
   1071 
   1072 	DPRINTFN(DBG_FN, sc, "\n");
   1073 
   1074 	otus_free_tx_cmd(sc);
   1075 	otus_free_tx_data_list(sc);
   1076 	otus_free_rx_data_list(sc);
   1077 
   1078 	if (sc->sc_data_rx_pipe != NULL)
   1079 		usbd_close_pipe(sc->sc_data_rx_pipe);
   1080 	if (sc->sc_cmd_rx_pipe != NULL) {
   1081 		usbd_abort_pipe(sc->sc_cmd_rx_pipe);
   1082 		usbd_close_pipe(sc->sc_cmd_rx_pipe);
   1083 	}
   1084 	if (sc->sc_ibuf != NULL)
   1085 		kmem_free(sc->sc_ibuf, sc->sc_ibuf_size);
   1086 	if (sc->sc_data_tx_pipe != NULL)
   1087 		usbd_close_pipe(sc->sc_data_tx_pipe);
   1088 	if (sc->sc_cmd_tx_pipe != NULL)
   1089 		usbd_close_pipe(sc->sc_cmd_tx_pipe);
   1090 }
   1091 
   1092 Static int
   1093 otus_alloc_tx_cmd(struct otus_softc *sc)
   1094 {
   1095 	struct otus_tx_cmd *cmd;
   1096 
   1097 	DPRINTFN(DBG_FN, sc, "\n");
   1098 
   1099 	cmd = &sc->sc_tx_cmd;
   1100 
   1101 	int error = usbd_create_xfer(sc->sc_cmd_tx_pipe, OTUS_MAX_TXCMDSZ,
   1102 	    USBD_FORCE_SHORT_XFER, 0, &cmd->xfer);
   1103 	if (error)
   1104 		return error;
   1105 
   1106 	cmd->buf = usbd_get_buffer(cmd->xfer);
   1107 
   1108 	return 0;
   1109 }
   1110 
   1111 Static void
   1112 otus_free_tx_cmd(struct otus_softc *sc)
   1113 {
   1114 
   1115 	DPRINTFN(DBG_FN, sc, "\n");
   1116 
   1117 	if (sc->sc_cmd_tx_pipe == NULL)
   1118 		return;
   1119 
   1120 	/* Make sure no transfers are pending. */
   1121 	usbd_abort_pipe(sc->sc_cmd_tx_pipe);
   1122 
   1123 	mutex_enter(&sc->sc_cmd_mtx);
   1124 	if (sc->sc_tx_cmd.xfer != NULL)
   1125 		usbd_destroy_xfer(sc->sc_tx_cmd.xfer);
   1126 	sc->sc_tx_cmd.xfer = NULL;
   1127 	sc->sc_tx_cmd.buf  = NULL;
   1128 	mutex_exit(&sc->sc_cmd_mtx);
   1129 }
   1130 
   1131 Static int
   1132 otus_alloc_tx_data_list(struct otus_softc *sc)
   1133 {
   1134 	struct otus_tx_data *data;
   1135 	int i, error;
   1136 
   1137 	DPRINTFN(DBG_FN, sc, "\n");
   1138 
   1139 	mutex_enter(&sc->sc_tx_mtx);
   1140 	error = 0;
   1141 	TAILQ_INIT(&sc->sc_tx_free_list);
   1142 	for (i = 0; i < OTUS_TX_DATA_LIST_COUNT; i++) {
   1143 		data = &sc->sc_tx_data[i];
   1144 
   1145 		data->sc = sc;	/* Backpointer for callbacks. */
   1146 
   1147 		error = usbd_create_xfer(sc->sc_data_tx_pipe, OTUS_TXBUFSZ,
   1148 		    USBD_FORCE_SHORT_XFER, 0, &data->xfer);
   1149 		if (error) {
   1150 			aprint_error_dev(sc->sc_dev,
   1151 			    "could not allocate xfer\n");
   1152 			break;
   1153 		}
   1154 		data->buf = usbd_get_buffer(data->xfer);
   1155 		/* Append this Tx buffer to our free list. */
   1156 		TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
   1157 	}
   1158 	if (error != 0)
   1159 		otus_free_tx_data_list(sc);
   1160 	mutex_exit(&sc->sc_tx_mtx);
   1161 	return error;
   1162 }
   1163 
   1164 Static void
   1165 otus_free_tx_data_list(struct otus_softc *sc)
   1166 {
   1167 	int i;
   1168 
   1169 	DPRINTFN(DBG_FN, sc, "\n");
   1170 
   1171 	if (sc->sc_data_tx_pipe == NULL)
   1172 		return;
   1173 
   1174 	/* Make sure no transfers are pending. */
   1175 	usbd_abort_pipe(sc->sc_data_tx_pipe);
   1176 
   1177 	for (i = 0; i < OTUS_TX_DATA_LIST_COUNT; i++) {
   1178 		if (sc->sc_tx_data[i].xfer != NULL)
   1179 			usbd_destroy_xfer(sc->sc_tx_data[i].xfer);
   1180 	}
   1181 }
   1182 
   1183 Static int
   1184 otus_alloc_rx_data_list(struct otus_softc *sc)
   1185 {
   1186 	struct otus_rx_data *data;
   1187 	int i, error;
   1188 
   1189 	DPRINTFN(DBG_FN, sc, "\n");
   1190 
   1191 	for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++) {
   1192 		data = &sc->sc_rx_data[i];
   1193 
   1194 		data->sc = sc;	/* Backpointer for callbacks. */
   1195 
   1196 		error = usbd_create_xfer(sc->sc_data_rx_pipe, OTUS_RXBUFSZ,
   1197 		   0, 0, &data->xfer);
   1198 
   1199 		if (error) {
   1200 			aprint_error_dev(sc->sc_dev,
   1201 			    "could not allocate xfer\n");
   1202 			goto fail;
   1203 		}
   1204 		data->buf = usbd_get_buffer(data->xfer);
   1205 	}
   1206 	return 0;
   1207 
   1208 fail:	otus_free_rx_data_list(sc);
   1209 	return error;
   1210 }
   1211 
   1212 Static void
   1213 otus_free_rx_data_list(struct otus_softc *sc)
   1214 {
   1215 	int i;
   1216 
   1217 	DPRINTFN(DBG_FN, sc, "\n");
   1218 
   1219 	if (sc->sc_data_rx_pipe == NULL)
   1220 		return;
   1221 
   1222 	/* Make sure no transfers are pending. */
   1223 	usbd_abort_pipe(sc->sc_data_rx_pipe);
   1224 
   1225 	for (i = 0; i < OTUS_RX_DATA_LIST_COUNT; i++)
   1226 		if (sc->sc_rx_data[i].xfer != NULL)
   1227 			usbd_destroy_xfer(sc->sc_rx_data[i].xfer);
   1228 }
   1229 
   1230 Static void
   1231 otus_next_scan(void *arg)
   1232 {
   1233 	struct otus_softc *sc;
   1234 
   1235 	sc = arg;
   1236 
   1237 	DPRINTFN(DBG_FN, sc, "\n");
   1238 
   1239 	if (sc->sc_dying)
   1240 		return;
   1241 
   1242 	if (sc->sc_ic.ic_state == IEEE80211_S_SCAN)
   1243 		ieee80211_next_scan(&sc->sc_ic);
   1244 }
   1245 
   1246 Static void
   1247 otus_task(void *arg)
   1248 {
   1249 	struct otus_softc *sc;
   1250 	struct otus_host_cmd_ring *ring;
   1251 	struct otus_host_cmd *cmd;
   1252 
   1253 	sc = arg;
   1254 
   1255 	DPRINTFN(DBG_FN, sc, "\n");
   1256 
   1257 	/* Process host commands. */
   1258 	mutex_spin_enter(&sc->sc_task_mtx);
   1259 	ring = &sc->sc_cmdq;
   1260 	while (ring->next != ring->cur) {
   1261 		cmd = &ring->cmd[ring->next];
   1262 		mutex_spin_exit(&sc->sc_task_mtx);
   1263 
   1264 		/* Callback. */
   1265 		DPRINTFN(DBG_CMD, sc, "cb=%p queued=%d\n", cmd->cb,
   1266 		    ring->queued);
   1267 		cmd->cb(sc, cmd->data);
   1268 
   1269 		mutex_spin_enter(&sc->sc_task_mtx);
   1270 		ring->queued--;
   1271 		ring->next = (ring->next + 1) % OTUS_HOST_CMD_RING_COUNT;
   1272 	}
   1273 	cv_signal(&sc->sc_task_cv);
   1274 	mutex_spin_exit(&sc->sc_task_mtx);
   1275 }
   1276 
   1277 Static void
   1278 otus_do_async(struct otus_softc *sc, void (*cb)(struct otus_softc *, void *),
   1279     void *arg, int len)
   1280 {
   1281 	struct otus_host_cmd_ring *ring;
   1282 	struct otus_host_cmd *cmd;
   1283 	bool sched = false;
   1284 
   1285 	DPRINTFN(DBG_FN, sc, "cb=%p\n", cb);
   1286 
   1287 	mutex_spin_enter(&sc->sc_task_mtx);
   1288 	ring = &sc->sc_cmdq;
   1289 	cmd = &ring->cmd[ring->cur];
   1290 	cmd->cb = cb;
   1291 	KASSERT(len <= sizeof(cmd->data));
   1292 	memcpy(cmd->data, arg, len);
   1293 	ring->cur = (ring->cur + 1) % OTUS_HOST_CMD_RING_COUNT;
   1294 
   1295 	/* If there is no pending command already, schedule a task. */
   1296 	if (++ring->queued == 1) {
   1297 		sched = true;
   1298 	}
   1299 	cv_signal(&sc->sc_task_cv);
   1300 	mutex_spin_exit(&sc->sc_task_mtx);
   1301 	if (sched)
   1302 		usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
   1303 }
   1304 
   1305 Static int
   1306 otus_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
   1307 {
   1308 	struct otus_softc *sc;
   1309 	struct otus_cmd_newstate cmd;
   1310 
   1311 	sc = ic->ic_ifp->if_softc;
   1312 
   1313 	DPRINTFN(DBG_FN | DBG_STM, sc, "nstate=%s(%d), arg=%d\n",
   1314 	    ieee80211_state_name[nstate], nstate, arg);
   1315 
   1316 	/* Do it in a process context. */
   1317 	cmd.state = nstate;
   1318 	cmd.arg = arg;
   1319 	otus_do_async(sc, otus_newstate_cb, &cmd, sizeof(cmd));
   1320 	return 0;
   1321 }
   1322 
   1323 Static void
   1324 otus_newstate_cb(struct otus_softc *sc, void *arg)
   1325 {
   1326 	struct otus_cmd_newstate *cmd;
   1327 	struct ieee80211com *ic;
   1328 	struct ieee80211_node *ni;
   1329 	enum ieee80211_state nstate;
   1330 	int s;
   1331 
   1332 	cmd = arg;
   1333 	ic = &sc->sc_ic;
   1334 	ni = ic->ic_bss;
   1335 	nstate = cmd->state;
   1336 
   1337 #ifdef OTUS_DEBUG
   1338 	enum ieee80211_state ostate = ostate = ic->ic_state;
   1339 	DPRINTFN(DBG_FN | DBG_STM, sc, "%s(%d)->%s(%d)\n",
   1340 	    ieee80211_state_name[ostate], ostate,
   1341 	    ieee80211_state_name[nstate], nstate);
   1342 #endif
   1343 
   1344 	s = splnet();
   1345 
   1346 	callout_halt(&sc->sc_scan_to, NULL);
   1347 	callout_halt(&sc->sc_calib_to, NULL);
   1348 
   1349 	mutex_enter(&sc->sc_write_mtx);
   1350 
   1351 	switch (nstate) {
   1352 	case IEEE80211_S_INIT:
   1353 		break;
   1354 
   1355 	case IEEE80211_S_SCAN:
   1356 		otus_set_chan(sc, ic->ic_curchan, 0);
   1357 		if (!sc->sc_dying)
   1358 			callout_schedule(&sc->sc_scan_to, hz / 5);
   1359 		break;
   1360 
   1361 	case IEEE80211_S_AUTH:
   1362 	case IEEE80211_S_ASSOC:
   1363 		otus_set_chan(sc, ic->ic_curchan, 0);
   1364 		break;
   1365 
   1366 	case IEEE80211_S_RUN:
   1367 		otus_set_chan(sc, ic->ic_curchan, 1);
   1368 
   1369 		switch (ic->ic_opmode) {
   1370 		case IEEE80211_M_STA:
   1371 			otus_updateslot_cb_locked(sc);
   1372 			otus_set_bssid(sc, ni->ni_bssid);
   1373 
   1374 			/* Fake a join to init the Tx rate. */
   1375 			otus_newassoc(ni, 1);
   1376 
   1377 			/* Start calibration timer. */
   1378 			if (!sc->sc_dying)
   1379 				callout_schedule(&sc->sc_calib_to, hz);
   1380 			break;
   1381 
   1382 		case IEEE80211_M_IBSS:
   1383 		case IEEE80211_M_AHDEMO:
   1384 		case IEEE80211_M_HOSTAP:
   1385 		case IEEE80211_M_MONITOR:
   1386 			break;
   1387 		}
   1388 		break;
   1389 	}
   1390 	(void)sc->sc_newstate(ic, nstate, cmd->arg);
   1391 	sc->sc_led_newstate(sc);
   1392 	mutex_exit(&sc->sc_write_mtx);
   1393 
   1394 	splx(s);
   1395 }
   1396 
   1397 Static int
   1398 otus_cmd(struct otus_softc *sc, uint8_t code, const void *idata, int ilen,
   1399     void *odata)
   1400 {
   1401 	struct otus_tx_cmd *cmd;
   1402 	struct ar_cmd_hdr *hdr;
   1403 	int xferlen, error;
   1404 
   1405 	DPRINTFN(DBG_FN, sc, "\n");
   1406 
   1407 	cmd = &sc->sc_tx_cmd;
   1408 
   1409 	mutex_enter(&sc->sc_cmd_mtx);
   1410 
   1411 	/* Always bulk-out a multiple of 4 bytes. */
   1412 	xferlen = roundup2(sizeof(*hdr) + ilen, 4);
   1413 
   1414 	hdr = (void *)cmd->buf;
   1415 	if (hdr == NULL) {	/* we may have been freed while detaching */
   1416 		mutex_exit(&sc->sc_cmd_mtx);
   1417 		DPRINTFN(DBG_CMD, sc, "tx_cmd freed with commands pending\n");
   1418 		return 0;
   1419 	}
   1420 	hdr->code  = code;
   1421 	hdr->len   = ilen;
   1422 	hdr->token = ++cmd->token;	/* Don't care about endianness. */
   1423 	KASSERT(sizeof(hdr) + ilen <= OTUS_MAX_TXCMDSZ);
   1424 	memcpy(cmd->buf + sizeof(hdr[0]), idata, ilen);
   1425 
   1426 	DPRINTFN(DBG_CMD, sc, "sending command code=%#02x len=%d token=%d\n",
   1427 	    code, ilen, hdr->token);
   1428 
   1429 	cmd->odata = odata;
   1430 	cmd->done = 0;
   1431 	usbd_setup_xfer(cmd->xfer, cmd, cmd->buf, xferlen,
   1432 	    USBD_FORCE_SHORT_XFER, OTUS_CMD_TIMEOUT, NULL);
   1433 	error = usbd_sync_transfer(cmd->xfer);
   1434 	if (error != 0) {
   1435 		mutex_exit(&sc->sc_cmd_mtx);
   1436 #if defined(DIAGNOSTIC) || defined(OTUS_DEBUG)	/* XXX: kill some noise */
   1437 		aprint_error_dev(sc->sc_dev,
   1438 		    "could not send command %#x (error=%s)\n",
   1439 		    code, usbd_errstr(error));
   1440 #endif
   1441 		return EIO;
   1442 	}
   1443 	if (!cmd->done)
   1444 		error = cv_timedwait_sig(&sc->sc_cmd_cv, &sc->sc_cmd_mtx, hz);
   1445 	cmd->odata = NULL;	/* In case answer is received too late. */
   1446 	mutex_exit(&sc->sc_cmd_mtx);
   1447 	if (error != 0) {
   1448 		aprint_error_dev(sc->sc_dev,
   1449 		    "timeout waiting for command %#02x reply\n", code);
   1450 	}
   1451 	return error;
   1452 }
   1453 
   1454 Static void
   1455 otus_write(struct otus_softc *sc, uint32_t reg, uint32_t val)
   1456 {
   1457 
   1458 	DPRINTFN(DBG_FN | DBG_REG, sc, "reg=%#x, val=%#x\n", reg, val);
   1459 
   1460 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   1461 	KASSERT(sc->sc_write_idx < __arraycount(sc->sc_write_buf));
   1462 
   1463 	sc->sc_write_buf[sc->sc_write_idx].reg = htole32(reg);
   1464 	sc->sc_write_buf[sc->sc_write_idx].val = htole32(val);
   1465 
   1466 	if (++sc->sc_write_idx >= __arraycount(sc->sc_write_buf))
   1467 		(void)otus_write_barrier(sc);
   1468 }
   1469 
   1470 Static int
   1471 otus_write_barrier(struct otus_softc *sc)
   1472 {
   1473 	int error;
   1474 
   1475 	DPRINTFN(DBG_FN, sc, "\n");
   1476 
   1477 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   1478 	KASSERT(sc->sc_write_idx <= __arraycount(sc->sc_write_buf));
   1479 
   1480 	if (sc->sc_write_idx == 0)
   1481 		return 0;	/* Nothing to flush. */
   1482 
   1483 	error = otus_cmd(sc, AR_CMD_WREG, sc->sc_write_buf,
   1484 	    sizeof(sc->sc_write_buf[0]) * sc->sc_write_idx, NULL);
   1485 
   1486 	sc->sc_write_idx = 0;
   1487 	if (error)
   1488 		DPRINTFN(DBG_REG, sc, "error=%d\n", error);
   1489 	return error;
   1490 }
   1491 
   1492 Static struct ieee80211_node *
   1493 otus_node_alloc(struct ieee80211_node_table *ntp)
   1494 {
   1495 	struct otus_node *on;
   1496 
   1497 	DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
   1498 
   1499 	on = malloc(sizeof(*on), M_DEVBUF, M_NOWAIT | M_ZERO);
   1500 	return on ? &on->ni : NULL;
   1501 }
   1502 
   1503 Static int
   1504 otus_media_change(struct ifnet *ifp)
   1505 {
   1506 	struct otus_softc *sc;
   1507 	struct ieee80211com *ic;
   1508 	uint8_t rate, ridx;
   1509 	int error;
   1510 
   1511 	sc = ifp->if_softc;
   1512 
   1513 	DPRINTFN(DBG_FN, sc, "\n");
   1514 
   1515 	error = ieee80211_media_change(ifp);
   1516 	if (error != ENETRESET)
   1517 		return error;
   1518 
   1519 	ic = &sc->sc_ic;
   1520 	if (ic->ic_fixed_rate != -1) {
   1521 		rate = ic->ic_sup_rates[ic->ic_curmode].
   1522 		    rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
   1523 		for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++)
   1524 			if (otus_rates[ridx].rate == rate)
   1525 				break;
   1526 		sc->sc_fixed_ridx = ridx;
   1527 	}
   1528 
   1529 	if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
   1530 		error = otus_init(ifp);
   1531 
   1532 	return error;
   1533 }
   1534 
   1535 Static int
   1536 otus_read_eeprom(struct otus_softc *sc)
   1537 {
   1538 	uint32_t regs[8], reg;
   1539 	uint8_t *eep;
   1540 	int i, j, error;
   1541 
   1542 	DPRINTFN(DBG_FN, sc, "\n");
   1543 
   1544 	KASSERT(sizeof(sc->sc_eeprom) % 32 == 0);
   1545 
   1546 	/* Read EEPROM by blocks of 32 bytes. */
   1547 	eep = (uint8_t *)&sc->sc_eeprom;
   1548 	reg = AR_EEPROM_OFFSET;
   1549 	for (i = 0; i < sizeof(sc->sc_eeprom) / 32; i++) {
   1550 		for (j = 0; j < 8; j++, reg += 4)
   1551 			regs[j] = htole32(reg);
   1552 		error = otus_cmd(sc, AR_CMD_RREG, regs, sizeof(regs), eep);
   1553 		if (error != 0)
   1554 			break;
   1555 		eep += 32;
   1556 	}
   1557 	return error;
   1558 }
   1559 
   1560 Static void
   1561 otus_newassoc(struct ieee80211_node *ni, int isnew)
   1562 {
   1563 	struct ieee80211_rateset *rs;
   1564 	struct otus_softc *sc;
   1565 	struct otus_node *on;
   1566 	uint8_t rate;
   1567 	int ridx, i;
   1568 
   1569 	sc = ni->ni_ic->ic_ifp->if_softc;
   1570 
   1571 	DPRINTFN(DBG_FN, sc, "isnew=%d addr=%s\n",
   1572 	    isnew, ether_sprintf(ni->ni_macaddr));
   1573 
   1574 	on = (void *)ni;
   1575 	ieee80211_amrr_node_init(&sc->sc_amrr, &on->amn);
   1576 	/* Start at lowest available bit-rate, AMRR will raise. */
   1577 	ni->ni_txrate = 0;
   1578 	rs = &ni->ni_rates;
   1579 	for (i = 0; i < rs->rs_nrates; i++) {
   1580 		rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
   1581 		/* Convert 802.11 rate to hardware rate index. */
   1582 		for (ridx = 0; ridx <= OTUS_RIDX_MAX; ridx++)
   1583 			if (otus_rates[ridx].rate == rate)
   1584 				break;
   1585 		on->ridx[i] = ridx;
   1586 		DPRINTFN(DBG_INIT, sc, "rate=%#02x ridx=%d\n",
   1587 		    rs->rs_rates[i], on->ridx[i]);
   1588 	}
   1589 }
   1590 
   1591 /* ARGSUSED */
   1592 Static void
   1593 otus_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
   1594 {
   1595 #if 0
   1596 	struct otus_softc *sc;
   1597 	int len;
   1598 
   1599 	sc = priv;
   1600 
   1601 	DPRINTFN(DBG_FN, sc, "\n");
   1602 
   1603 	/*
   1604 	 * The Rx intr pipe is unused with current firmware.  Notifications
   1605 	 * and replies to commands are sent through the Rx bulk pipe instead
   1606 	 * (with a magic PLCP header.)
   1607 	 */
   1608 	if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
   1609 		DPRINTFN(DBG_INTR, sc, "status=%d\n", status);
   1610 		if (status == USBD_STALLED)
   1611 			usbd_clear_endpoint_stall_async(sc->sc_cmd_rx_pipe);
   1612 		return;
   1613 	}
   1614 	usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
   1615 
   1616 	otus_cmd_rxeof(sc, sc->sc_ibuf, len);
   1617 #endif
   1618 }
   1619 
   1620 Static void
   1621 otus_cmd_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
   1622 {
   1623 	struct ieee80211com *ic;
   1624 	struct otus_tx_cmd *cmd;
   1625 	struct ar_cmd_hdr *hdr;
   1626 	int s;
   1627 
   1628 	DPRINTFN(DBG_FN, sc, "\n");
   1629 
   1630 	ic = &sc->sc_ic;
   1631 
   1632 	if (__predict_false(len < sizeof(*hdr))) {
   1633 		DPRINTFN(DBG_RX, sc, "cmd too small %d\n", len);
   1634 		return;
   1635 	}
   1636 	hdr = (void *)buf;
   1637 	if (__predict_false(sizeof(*hdr) + hdr->len > len ||
   1638 	    sizeof(*hdr) + hdr->len > 64)) {
   1639 		DPRINTFN(DBG_RX, sc, "cmd too large %d\n", hdr->len);
   1640 		return;
   1641 	}
   1642 
   1643 	if ((hdr->code & 0xc0) != 0xc0) {
   1644 		DPRINTFN(DBG_RX, sc, "received reply code=%#02x len=%d token=%d\n",
   1645 		    hdr->code, hdr->len, hdr->token);
   1646 		mutex_enter(&sc->sc_cmd_mtx);
   1647 		cmd = &sc->sc_tx_cmd;
   1648 		if (__predict_false(hdr->token != cmd->token)) {
   1649 			mutex_exit(&sc->sc_cmd_mtx);
   1650 			return;
   1651 		}
   1652 		/* Copy answer into caller's supplied buffer. */
   1653 		if (cmd->odata != NULL)
   1654 			memcpy(cmd->odata, &hdr[1], hdr->len);
   1655 		cmd->done = 1;
   1656 		cv_signal(&sc->sc_cmd_cv);
   1657 		mutex_exit(&sc->sc_cmd_mtx);
   1658 		return;
   1659 	}
   1660 
   1661 	/* Received unsolicited notification. */
   1662 	DPRINTFN(DBG_RX, sc, "received notification code=%#02x len=%d\n",
   1663 	    hdr->code, hdr->len);
   1664 	switch (hdr->code & 0x3f) {
   1665 	case AR_EVT_BEACON:
   1666 		break;
   1667 	case AR_EVT_TX_COMP:
   1668 	{
   1669 		struct ar_evt_tx_comp *tx;
   1670 		struct ieee80211_node *ni;
   1671 		struct otus_node *on;
   1672 
   1673 		tx = (void *)&hdr[1];
   1674 
   1675 		DPRINTFN(DBG_RX, sc, "tx completed %s status=%d phy=%#x\n",
   1676 		    ether_sprintf(tx->macaddr), le16toh(tx->status),
   1677 		    le32toh(tx->phy));
   1678 		s = splnet();
   1679 #ifdef notyet
   1680 #ifndef IEEE80211_STA_ONLY
   1681 		if (ic->ic_opmode != IEEE80211_M_STA) {
   1682 			ni = ieee80211_find_node(ic, tx->macaddr);
   1683 			if (__predict_false(ni == NULL)) {
   1684 				splx(s);
   1685 				break;
   1686 			}
   1687 		} else
   1688 #endif
   1689 #endif
   1690 			ni = ic->ic_bss;
   1691 		/* Update rate control statistics. */
   1692 		on = (void *)ni;
   1693 		/* NB: we do not set the TX_MAC_RATE_PROBING flag. */
   1694 		if (__predict_true(tx->status != 0))
   1695 			on->amn.amn_retrycnt++;
   1696 		splx(s);
   1697 		break;
   1698 	}
   1699 	case AR_EVT_TBTT:
   1700 		break;
   1701 	}
   1702 }
   1703 
   1704 Static void
   1705 otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
   1706 {
   1707 	struct ieee80211com *ic;
   1708 	struct ifnet *ifp;
   1709 	struct ieee80211_node *ni;
   1710 	struct ar_rx_tail *tail;
   1711 	struct ieee80211_frame *wh;
   1712 	struct mbuf *m;
   1713 	uint8_t *plcp;
   1714 	int s, mlen, align;
   1715 
   1716 	DPRINTFN(DBG_FN, sc, "\n");
   1717 
   1718 	ic = &sc->sc_ic;
   1719 	ifp = ic->ic_ifp;
   1720 
   1721 	if (__predict_false(len < AR_PLCP_HDR_LEN)) {
   1722 		DPRINTFN(DBG_RX, sc, "sub-xfer too short %d\n", len);
   1723 		return;
   1724 	}
   1725 	plcp = buf;
   1726 
   1727 	/* All bits in the PLCP header are set to 1 for non-MPDU. */
   1728 	if (memcmp(plcp, AR_PLCP_HDR_INTR, AR_PLCP_HDR_LEN) == 0) {
   1729 		otus_cmd_rxeof(sc, plcp + AR_PLCP_HDR_LEN,
   1730 		    len - AR_PLCP_HDR_LEN);
   1731 		return;
   1732 	}
   1733 
   1734 	/* Received MPDU. */
   1735 	if (__predict_false(len < AR_PLCP_HDR_LEN + sizeof(*tail))) {
   1736 		DPRINTFN(DBG_RX, sc, "MPDU too short %d\n", len);
   1737 		if_statinc(ifp, if_ierrors);
   1738 		return;
   1739 	}
   1740 	tail = (void *)(plcp + len - sizeof(*tail));
   1741 	wh = (void *)(plcp + AR_PLCP_HDR_LEN);
   1742 
   1743 	/* Discard error frames. */
   1744 	if (__predict_false((tail->error & sc->sc_rx_error_msk) != 0)) {
   1745 		DPRINTFN(DBG_RX, sc, "error frame %#02x\n", tail->error);
   1746 		if (tail->error & AR_RX_ERROR_FCS) {
   1747 			DPRINTFN(DBG_RX, sc, "bad FCS\n");
   1748 		} else if (tail->error & AR_RX_ERROR_MMIC) {
   1749 			/* Report Michael MIC failures to net80211. */
   1750 			ieee80211_notify_michael_failure(ic, wh, 0 /* XXX: keyix */);
   1751 		}
   1752 		if_statinc(ifp, if_ierrors);
   1753 		return;
   1754 	}
   1755 	/* Compute MPDU's length. */
   1756 	mlen = len - AR_PLCP_HDR_LEN - sizeof(*tail);
   1757 	mlen -= IEEE80211_CRC_LEN;	/* strip 802.11 FCS */
   1758 	/* Make sure there's room for an 802.11 header. */
   1759 	/*
   1760 	 * XXX: This will drop most control packets.  Do we really
   1761 	 * want this in IEEE80211_M_MONITOR mode?
   1762 	 */
   1763 	if (__predict_false(mlen < sizeof(*wh))) {
   1764 		if_statinc(ifp, if_ierrors);
   1765 		return;
   1766 	}
   1767 
   1768 	/* Provide a 32-bit aligned protocol header to the stack. */
   1769 	align = (ieee80211_has_qos(wh) ^ ieee80211_has_addr4(wh)) ? 2 : 0;
   1770 
   1771 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1772 	if (__predict_false(m == NULL)) {
   1773 		if_statinc(ifp, if_ierrors);
   1774 		return;
   1775 	}
   1776 	if (align + mlen > MHLEN) {
   1777 		MCLGET(m, M_DONTWAIT);
   1778 		if (__predict_false(!(m->m_flags & M_EXT))) {
   1779 			if_statinc(ifp, if_ierrors);
   1780 			m_freem(m);
   1781 			return;
   1782 		}
   1783 	}
   1784 	/* Finalize mbuf. */
   1785 	m_set_rcvif(m, ifp);
   1786 	m->m_data += align;
   1787 	memcpy(mtod(m, void *), wh, mlen);
   1788 	m->m_pkthdr.len = m->m_len = mlen;
   1789 
   1790 	s = splnet();
   1791 	if (__predict_false(sc->sc_drvbpf != NULL)) {
   1792 		struct otus_rx_radiotap_header *tap;
   1793 
   1794 		tap = &sc->sc_rxtap;
   1795 		tap->wr_flags = 0;
   1796 		tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
   1797 		tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
   1798 		tap->wr_antsignal = tail->rssi;
   1799 		tap->wr_rate = 2;	/* In case it can't be found below. */
   1800 		switch (tail->status & AR_RX_STATUS_MT_MASK) {
   1801 		case AR_RX_STATUS_MT_CCK:
   1802 			switch (plcp[0]) {
   1803 			case  10: tap->wr_rate =   2; break;
   1804 			case  20: tap->wr_rate =   4; break;
   1805 			case  55: tap->wr_rate =  11; break;
   1806 			case 110: tap->wr_rate =  22; break;
   1807 			}
   1808 			if (tail->status & AR_RX_STATUS_SHPREAMBLE)
   1809 				tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
   1810 			break;
   1811 		case AR_RX_STATUS_MT_OFDM:
   1812 			switch (plcp[0] & 0xf) {
   1813 			case 0xb: tap->wr_rate =  12; break;
   1814 			case 0xf: tap->wr_rate =  18; break;
   1815 			case 0xa: tap->wr_rate =  24; break;
   1816 			case 0xe: tap->wr_rate =  36; break;
   1817 			case 0x9: tap->wr_rate =  48; break;
   1818 			case 0xd: tap->wr_rate =  72; break;
   1819 			case 0x8: tap->wr_rate =  96; break;
   1820 			case 0xc: tap->wr_rate = 108; break;
   1821 			}
   1822 			break;
   1823 		}
   1824 		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m, BPF_D_IN);
   1825 	}
   1826 
   1827 	ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
   1828 
   1829 	/* push the frame up to the 802.11 stack */
   1830 	ieee80211_input(ic, m, ni, tail->rssi, 0);
   1831 
   1832 	/* Node is no longer needed. */
   1833 	ieee80211_free_node(ni);
   1834 	splx(s);
   1835 }
   1836 
   1837 Static void
   1838 otus_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
   1839 {
   1840 	struct otus_rx_data *data;
   1841 	struct otus_softc *sc;
   1842 	uint8_t *buf;
   1843 	struct ar_rx_head *head;
   1844 	uint16_t hlen;
   1845 	int len;
   1846 
   1847 	data = priv;
   1848 	sc = data->sc;
   1849 
   1850 	DPRINTFN(DBG_FN, sc, "\n");
   1851 
   1852 	buf = data->buf;
   1853 
   1854 	if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
   1855 		DPRINTFN(DBG_RX, sc, "RX status=%d\n", status);
   1856 		if (status == USBD_STALLED)
   1857 			usbd_clear_endpoint_stall_async(sc->sc_data_rx_pipe);
   1858 		else if (status != USBD_CANCELLED) {
   1859 			DPRINTFN(DBG_RX, sc,
   1860 			    "otus_rxeof: goto resubmit: status=%d\n", status);
   1861 			goto resubmit;
   1862 		}
   1863 		return;
   1864 	}
   1865 	usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
   1866 
   1867 	while (len >= sizeof(*head)) {
   1868 		head = (void *)buf;
   1869 		if (__predict_false(head->tag != htole16(AR_RX_HEAD_TAG))) {
   1870 			DPRINTFN(DBG_RX, sc, "tag not valid %#x\n",
   1871 			    le16toh(head->tag));
   1872 			break;
   1873 		}
   1874 		hlen = le16toh(head->len);
   1875 		if (__predict_false(sizeof(*head) + hlen > len)) {
   1876 			DPRINTFN(DBG_RX, sc, "xfer too short %d/%d\n",
   1877 			    len, hlen);
   1878 			break;
   1879 		}
   1880 		/* Process sub-xfer. */
   1881 		otus_sub_rxeof(sc, (uint8_t *)&head[1], hlen);
   1882 
   1883 		/* Next sub-xfer is aligned on a 32-bit boundary. */
   1884 		hlen = roundup2(sizeof(*head) + hlen, 4);
   1885 		buf += hlen;
   1886 		len -= hlen;
   1887 	}
   1888 
   1889  resubmit:
   1890 	usbd_setup_xfer(xfer, data, data->buf, OTUS_RXBUFSZ,
   1891 	    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, otus_rxeof);
   1892 	(void)usbd_transfer(data->xfer);
   1893 }
   1894 
   1895 Static void
   1896 otus_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
   1897 {
   1898 	struct otus_tx_data *data;
   1899 	struct otus_softc *sc;
   1900 	struct ieee80211com *ic;
   1901 	struct ifnet *ifp;
   1902 	int s;
   1903 
   1904 	data = priv;
   1905 	sc = data->sc;
   1906 
   1907 	DPRINTFN(DBG_FN, sc, "\n");
   1908 
   1909 	/* Put this Tx buffer back to the free list. */
   1910 	mutex_enter(&sc->sc_tx_mtx);
   1911 	TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
   1912 	mutex_exit(&sc->sc_tx_mtx);
   1913 
   1914 	ic = &sc->sc_ic;
   1915 	ifp = ic->ic_ifp;
   1916 	if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
   1917 		DPRINTFN(DBG_TX, sc, "TX status=%d\n", status);
   1918 		if (status == USBD_STALLED)
   1919 			usbd_clear_endpoint_stall_async(sc->sc_data_tx_pipe);
   1920 		if_statinc(ifp, if_oerrors);
   1921 		return;
   1922 	}
   1923 	if_statinc(ifp, if_opackets);
   1924 
   1925 	s = splnet();
   1926 	sc->sc_tx_timer = 0;
   1927 	ifp->if_flags &= ~IFF_OACTIVE;	/* XXX: do after freeing Tx buffer? */
   1928 	otus_start(ifp);
   1929 	splx(s);
   1930 }
   1931 
   1932 Static int
   1933 otus_tx(struct otus_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
   1934     struct otus_tx_data *data)
   1935 {
   1936 	struct ieee80211com *ic;
   1937 	struct otus_node *on;
   1938 	struct ieee80211_frame *wh;
   1939 	struct ieee80211_key *k;
   1940 	struct ar_tx_head *head;
   1941 	uint32_t phyctl;
   1942 	uint16_t macctl, qos;
   1943 	uint8_t qid;
   1944 	int error, ridx, hasqos, xferlen;
   1945 
   1946 	DPRINTFN(DBG_FN, sc, "\n");
   1947 
   1948 	ic = &sc->sc_ic;
   1949 	on = (void *)ni;
   1950 
   1951 	wh = mtod(m, struct ieee80211_frame *);
   1952 	if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {
   1953 		/* XXX: derived from upgt_tx_task() and ural_tx_data() */
   1954 		k = ieee80211_crypto_encap(ic, ni, m);
   1955 		if (k == NULL)
   1956 			return ENOBUFS;
   1957 
   1958 		/* Packet header may have moved, reset our local pointer. */
   1959 		wh = mtod(m, struct ieee80211_frame *);
   1960 	}
   1961 
   1962 #ifdef HAVE_EDCA
   1963 	if ((hasqos = ieee80211_has_qos(wh))) {
   1964 		qos = ieee80211_get_qos(wh);
   1965 		qid = ieee80211_up_to_ac(ic, qos & IEEE80211_QOS_TID);
   1966 	} else {
   1967 		qos = 0;
   1968 		qid = WME_AC_BE;
   1969 	}
   1970 #else
   1971 	hasqos = 0;
   1972 	qos = 0;
   1973 	qid = WME_AC_BE;
   1974 #endif
   1975 
   1976 	/* Pickup a rate index. */
   1977 	if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
   1978 	    (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA)
   1979 		ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
   1980 		    OTUS_RIDX_OFDM6 : OTUS_RIDX_CCK1;
   1981 	else if (ic->ic_fixed_rate != -1)
   1982 		ridx = sc->sc_fixed_ridx;
   1983 	else
   1984 		ridx = on->ridx[ni->ni_txrate];
   1985 
   1986 	phyctl = 0;
   1987 	macctl = AR_TX_MAC_BACKOFF | AR_TX_MAC_HW_DUR | AR_TX_MAC_QID(qid);
   1988 
   1989 	if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
   1990 	    (hasqos && ((qos & IEEE80211_QOS_ACKPOLICY_MASK) ==
   1991 	     IEEE80211_QOS_ACKPOLICY_NOACK)))
   1992 		macctl |= AR_TX_MAC_NOACK;
   1993 
   1994 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
   1995 		if (m->m_pkthdr.len + IEEE80211_CRC_LEN >= ic->ic_rtsthreshold)
   1996 			macctl |= AR_TX_MAC_RTS;
   1997 		else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
   1998 		    ridx >= OTUS_RIDX_OFDM6) {
   1999 			if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
   2000 				macctl |= AR_TX_MAC_CTS;
   2001 			else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
   2002 				macctl |= AR_TX_MAC_RTS;
   2003 		}
   2004 	}
   2005 
   2006 	phyctl |= AR_TX_PHY_MCS(otus_rates[ridx].mcs);
   2007 	if (ridx >= OTUS_RIDX_OFDM6) {
   2008 		phyctl |= AR_TX_PHY_MT_OFDM;
   2009 		if (ridx <= OTUS_RIDX_OFDM24)
   2010 			phyctl |= AR_TX_PHY_ANTMSK(sc->sc_txmask);
   2011 		else
   2012 			phyctl |= AR_TX_PHY_ANTMSK(1);
   2013 	} else {	/* CCK */
   2014 		phyctl |= AR_TX_PHY_MT_CCK;
   2015 		phyctl |= AR_TX_PHY_ANTMSK(sc->sc_txmask);
   2016 	}
   2017 
   2018 	/* Update rate control stats for frames that are ACK'ed. */
   2019 	if (!(macctl & AR_TX_MAC_NOACK))
   2020 		on->amn.amn_txcnt++;
   2021 
   2022 	/* Fill Tx descriptor. */
   2023 	head = (void *)data->buf;
   2024 	head->len = htole16(m->m_pkthdr.len + IEEE80211_CRC_LEN);
   2025 	head->macctl = htole16(macctl);
   2026 	head->phyctl = htole32(phyctl);
   2027 
   2028 	if (__predict_false(sc->sc_drvbpf != NULL)) {
   2029 		struct otus_tx_radiotap_header *tap = &sc->sc_txtap;
   2030 
   2031 		tap->wt_flags = 0;
   2032 		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
   2033 			tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
   2034 		tap->wt_rate = otus_rates[ridx].rate;
   2035 		tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
   2036 		tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
   2037 
   2038 		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m, BPF_D_OUT);
   2039 	}
   2040 
   2041 	xferlen = sizeof(*head) + m->m_pkthdr.len;
   2042 	m_copydata(m, 0, m->m_pkthdr.len, (void *)&head[1]);
   2043 
   2044 	DPRINTFN(DBG_TX, sc, "queued len=%d mac=%#04x phy=%#08x rate=%d\n",
   2045 	    head->len, head->macctl, head->phyctl, otus_rates[ridx].rate);
   2046 
   2047 	usbd_setup_xfer(data->xfer, data, data->buf, xferlen,
   2048 	    USBD_FORCE_SHORT_XFER, OTUS_TX_TIMEOUT, otus_txeof);
   2049 	error = usbd_transfer(data->xfer);
   2050 	if (__predict_false(
   2051 		    error != USBD_NORMAL_COMPLETION &&
   2052 		    error != USBD_IN_PROGRESS)) {
   2053 		DPRINTFN(DBG_TX, sc, "transfer failed %d\n", error);
   2054 		return error;
   2055 	}
   2056 	return 0;
   2057 }
   2058 
   2059 Static void
   2060 otus_start(struct ifnet *ifp)
   2061 {
   2062 	struct otus_softc *sc;
   2063 	struct ieee80211com *ic;
   2064 	struct otus_tx_data *data;
   2065 	struct ether_header *eh;
   2066 	struct ieee80211_node *ni;
   2067 	struct mbuf *m;
   2068 
   2069 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
   2070 		return;
   2071 
   2072 	sc = ifp->if_softc;
   2073 	ic = &sc->sc_ic;
   2074 
   2075 	DPRINTFN(DBG_FN, sc, "\n");
   2076 
   2077 	data = NULL;
   2078 	for (;;) {
   2079 		/*
   2080 		 * Grab a Tx buffer if we don't already have one.  If
   2081 		 * one isn't available, bail out.
   2082 		 * NB: We must obtain this Tx buffer _before_
   2083 		 * dequeueing anything as one may not be available
   2084 		 * later.  Both must be done inside a single lock.
   2085 		 */
   2086 		mutex_enter(&sc->sc_tx_mtx);
   2087 		if (data == NULL && !TAILQ_EMPTY(&sc->sc_tx_free_list)) {
   2088 			data = TAILQ_FIRST(&sc->sc_tx_free_list);
   2089 			TAILQ_REMOVE(&sc->sc_tx_free_list, data, next);
   2090 		}
   2091 		mutex_exit(&sc->sc_tx_mtx);
   2092 
   2093 		if (data == NULL) {
   2094 			ifp->if_flags |= IFF_OACTIVE;
   2095 			DPRINTFN(DBG_TX, sc, "empty sc_tx_free_list\n");
   2096 			return;
   2097 		}
   2098 
   2099 		/* Send pending management frames first. */
   2100 		IF_DEQUEUE(&ic->ic_mgtq, m);
   2101 		if (m != NULL) {
   2102 			ni = M_GETCTX(m, struct ieee80211_node *);
   2103 			M_CLEARCTX(m);
   2104 			goto sendit;
   2105 		}
   2106 
   2107 		if (ic->ic_state != IEEE80211_S_RUN)
   2108 			break;
   2109 
   2110 		/* Encapsulate and send data frames. */
   2111 		IFQ_DEQUEUE(&ifp->if_snd, m);
   2112 		if (m == NULL)
   2113 			break;
   2114 
   2115 		if (m->m_len < (int)sizeof(*eh) &&
   2116 		    (m = m_pullup(m, sizeof(*eh))) == NULL) {
   2117 			if_statinc(ifp, if_oerrors);
   2118 			continue;
   2119 		}
   2120 
   2121 		eh = mtod(m, struct ether_header *);
   2122 		ni = ieee80211_find_txnode(ic, eh->ether_dhost);
   2123 		if (ni == NULL) {
   2124 			m_freem(m);
   2125 			if_statinc(ifp, if_oerrors);
   2126 			continue;
   2127 		}
   2128 
   2129 		bpf_mtap(ifp, m, BPF_D_OUT);
   2130 
   2131 		if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
   2132 			/* original m was freed by ieee80211_encap() */
   2133 			ieee80211_free_node(ni);
   2134 			if_statinc(ifp, if_oerrors);
   2135 			continue;
   2136 		}
   2137  sendit:
   2138 		bpf_mtap3(ic->ic_rawbpf, m, BPF_D_OUT);
   2139 
   2140 		if (otus_tx(sc, m, ni, data) != 0) {
   2141 			m_freem(m);
   2142 			ieee80211_free_node(ni);
   2143 			if_statinc(ifp, if_oerrors);
   2144 			continue;
   2145 		}
   2146 
   2147 		data = NULL;	/* we're finished with this data buffer */
   2148 		m_freem(m);
   2149 		ieee80211_free_node(ni);
   2150 		sc->sc_tx_timer = 5;
   2151 		ifp->if_timer = 1;
   2152 	}
   2153 
   2154 	/*
   2155 	 * If here, we have a Tx buffer, but ran out of mbufs to
   2156 	 * transmit.  Put the Tx buffer back to the free list.
   2157 	 */
   2158 	mutex_enter(&sc->sc_tx_mtx);
   2159 	TAILQ_INSERT_TAIL(&sc->sc_tx_free_list, data, next);
   2160 	mutex_exit(&sc->sc_tx_mtx);
   2161 }
   2162 
   2163 Static void
   2164 otus_watchdog(struct ifnet *ifp)
   2165 {
   2166 	struct otus_softc *sc;
   2167 
   2168 	sc = ifp->if_softc;
   2169 
   2170 	DPRINTFN(DBG_FN, sc, "\n");
   2171 
   2172 	ifp->if_timer = 0;
   2173 
   2174 	if (sc->sc_tx_timer > 0) {
   2175 		if (--sc->sc_tx_timer == 0) {
   2176 			aprint_error_dev(sc->sc_dev, "device timeout\n");
   2177 			/* otus_init(ifp); XXX needs a process context! */
   2178 			if_statinc(ifp, if_oerrors);
   2179 			return;
   2180 		}
   2181 		ifp->if_timer = 1;
   2182 	}
   2183 	ieee80211_watchdog(&sc->sc_ic);
   2184 }
   2185 
   2186 Static int
   2187 otus_ioctl(struct ifnet *ifp, u_long cmd, void *data)
   2188 {
   2189 	struct otus_softc *sc;
   2190 	struct ieee80211com *ic;
   2191 	int s, error = 0;
   2192 
   2193 	sc = ifp->if_softc;
   2194 
   2195 	DPRINTFN(DBG_FN, sc, "%#lx\n", cmd);
   2196 
   2197 	ic = &sc->sc_ic;
   2198 
   2199 	s = splnet();
   2200 
   2201 	switch (cmd) {
   2202 	case SIOCSIFADDR:
   2203 		ifp->if_flags |= IFF_UP;
   2204 #ifdef INET
   2205 		struct ifaddr *ifa = data;
   2206 		if (ifa->ifa_addr->sa_family == AF_INET)
   2207 			arp_ifinit(&ic->ic_ac, ifa);
   2208 #endif
   2209 		/* FALLTHROUGH */
   2210 	case SIOCSIFFLAGS:
   2211 		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
   2212 			break;
   2213 
   2214 		switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
   2215 		case IFF_UP | IFF_RUNNING:
   2216 			if (((ifp->if_flags ^ sc->sc_if_flags) &
   2217 				(IFF_ALLMULTI | IFF_PROMISC)) != 0)
   2218 				otus_set_multi(sc);
   2219 			break;
   2220 		case IFF_UP:
   2221 			otus_init(ifp);
   2222 			break;
   2223 
   2224 		case IFF_RUNNING:
   2225 			otus_stop(ifp);
   2226 			break;
   2227 		case 0:
   2228 		default:
   2229 			break;
   2230 		}
   2231 		sc->sc_if_flags = ifp->if_flags;
   2232 		break;
   2233 
   2234 	case SIOCADDMULTI:
   2235 	case SIOCDELMULTI:
   2236 		if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
   2237 			/* setup multicast filter, etc */
   2238 			/* XXX: ??? */
   2239 			error = 0;
   2240 		}
   2241 		break;
   2242 
   2243 	case SIOCS80211CHANNEL:
   2244 		/*
   2245 		 * This allows for fast channel switching in monitor mode
   2246 		 * (used by kismet). In IBSS mode, we must explicitly reset
   2247 		 * the interface to generate a new beacon frame.
   2248 		 */
   2249 		error = ieee80211_ioctl(ic, cmd, data);
   2250 
   2251 		DPRINTFN(DBG_CHAN, sc,
   2252 		    "ic_curchan=%d ic_ibss_chan=%d ic_des_chan=%d ni_chan=%d error=%d\n",
   2253 		    ieee80211_chan2ieee(ic, ic->ic_curchan),
   2254 		    ieee80211_chan2ieee(ic, ic->ic_ibss_chan),
   2255 		    ieee80211_chan2ieee(ic, ic->ic_des_chan),
   2256 		    ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
   2257 		    error);
   2258 
   2259 		if (error == ENETRESET &&
   2260 		    ic->ic_opmode == IEEE80211_M_MONITOR) {
   2261 			if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
   2262 			    (IFF_UP | IFF_RUNNING)) {
   2263 				mutex_enter(&sc->sc_write_mtx);
   2264 				otus_set_chan(sc, ic->ic_curchan, 0);
   2265 				mutex_exit(&sc->sc_write_mtx);
   2266 			}
   2267 			error = 0;
   2268 		}
   2269 		break;
   2270 
   2271 	default:
   2272 		error = ieee80211_ioctl(ic, cmd, data);
   2273 	}
   2274 	if (error == ENETRESET) {
   2275 		if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
   2276 		    (IFF_UP | IFF_RUNNING))
   2277 			otus_init(ifp);
   2278 		error = 0;
   2279 	}
   2280 	splx(s);
   2281 	return error;
   2282 }
   2283 
   2284 Static int
   2285 otus_set_multi(struct otus_softc *sc)
   2286 {
   2287 	struct ethercom *ec = &sc->sc_ec;
   2288 	struct ifnet *ifp;
   2289 	struct ether_multi *enm;
   2290 	struct ether_multistep step;
   2291 	uint32_t lo, hi;
   2292 	uint8_t bit;
   2293 	int error;
   2294 
   2295 	DPRINTFN(DBG_FN, sc, "\n");
   2296 
   2297 	ifp = sc->sc_ic.ic_ifp;
   2298 	if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
   2299 		lo = hi = 0xffffffff;
   2300 		goto done;
   2301 	}
   2302 	lo = hi = 0;
   2303 	ETHER_LOCK(ec);
   2304 	ETHER_FIRST_MULTI(step, ec, enm);
   2305 	while (enm != NULL) {
   2306 		if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
   2307 			ifp->if_flags |= IFF_ALLMULTI;
   2308 			lo = hi = 0xffffffff;
   2309 			goto done;
   2310 		}
   2311 		bit = enm->enm_addrlo[5] >> 2;
   2312 		if (bit < 32)
   2313 			lo |= 1 << bit;
   2314 		else
   2315 			hi |= 1 << (bit - 32);
   2316 		ETHER_NEXT_MULTI(step, enm);
   2317 	}
   2318  done:
   2319 	ETHER_UNLOCK(ec);
   2320 	mutex_enter(&sc->sc_write_mtx);
   2321 	hi |= 1 << 31;	/* Make sure the broadcast bit is set. */
   2322 	otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L, lo);
   2323 	otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H, hi);
   2324 	error = otus_write_barrier(sc);
   2325 	mutex_exit(&sc->sc_write_mtx);
   2326 	return error;
   2327 }
   2328 
   2329 #ifdef HAVE_EDCA
   2330 Static void
   2331 otus_updateedca(struct ieee80211com *ic)
   2332 {
   2333 
   2334 	DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
   2335 
   2336 	/* Do it in a process context. */
   2337 	otus_do_async(ic->ic_ifp->if_softc, otus_updateedca_cb, NULL, 0);
   2338 }
   2339 
   2340 Static void
   2341 otus_updateedca_cb(struct otus_softc *sc, void *arg __used)
   2342 {
   2343 
   2344 	DPRINTFN(DBG_FN, sc, "\n");
   2345 
   2346 	mutex_enter(&sc->sc_write_mtx);
   2347 	otus_updateedca_cb_locked(sc);
   2348 	mutex_exit(&sc->sc_write_mtx);
   2349 }
   2350 #endif
   2351 
   2352 Static void
   2353 otus_updateedca_cb_locked(struct otus_softc *sc)
   2354 {
   2355 #ifdef HAVE_EDCA
   2356 	struct ieee80211com *ic;
   2357 #endif
   2358 	const struct ieee80211_edca_ac_params *edca;
   2359 	int s;
   2360 
   2361 	DPRINTFN(DBG_FN, sc, "\n");
   2362 
   2363 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   2364 
   2365 	s = splnet();
   2366 
   2367 #ifdef HAVE_EDCA
   2368 	ic = &sc->sc_ic;
   2369 	edca = (ic->ic_flags & IEEE80211_F_QOS) ?
   2370 	    ic->ic_edca_ac : otus_edca_def;
   2371 #else
   2372 	edca = otus_edca_def;
   2373 #endif /* HAVE_EDCA */
   2374 
   2375 #define EXP2(val)	((1 << (val)) - 1)
   2376 #define AIFS(val)	((val) * 9 + 10)
   2377 
   2378 	/* Set CWmin/CWmax values. */
   2379 	otus_write(sc, AR_MAC_REG_AC0_CW,
   2380 	    EXP2(edca[WME_AC_BE].ac_ecwmax) << 16 |
   2381 	    EXP2(edca[WME_AC_BE].ac_ecwmin));
   2382 	otus_write(sc, AR_MAC_REG_AC1_CW,
   2383 	    EXP2(edca[WME_AC_BK].ac_ecwmax) << 16 |
   2384 	    EXP2(edca[WME_AC_BK].ac_ecwmin));
   2385 	otus_write(sc, AR_MAC_REG_AC2_CW,
   2386 	    EXP2(edca[WME_AC_VI].ac_ecwmax) << 16 |
   2387 	    EXP2(edca[WME_AC_VI].ac_ecwmin));
   2388 	otus_write(sc, AR_MAC_REG_AC3_CW,
   2389 	    EXP2(edca[WME_AC_VO].ac_ecwmax) << 16 |
   2390 	    EXP2(edca[WME_AC_VO].ac_ecwmin));
   2391 	otus_write(sc, AR_MAC_REG_AC4_CW,		/* Special TXQ. */
   2392 	    EXP2(edca[WME_AC_VO].ac_ecwmax) << 16 |
   2393 	    EXP2(edca[WME_AC_VO].ac_ecwmin));
   2394 
   2395 	/* Set AIFSN values. */
   2396 	otus_write(sc, AR_MAC_REG_AC1_AC0_AIFS,
   2397 	    AIFS(edca[WME_AC_VI].ac_aifsn) << 24 |
   2398 	    AIFS(edca[WME_AC_BK].ac_aifsn) << 12 |
   2399 	    AIFS(edca[WME_AC_BE].ac_aifsn));
   2400 	otus_write(sc, AR_MAC_REG_AC3_AC2_AIFS,
   2401 	    AIFS(edca[WME_AC_VO].ac_aifsn) << 16 |	/* Special TXQ. */
   2402 	    AIFS(edca[WME_AC_VO].ac_aifsn) <<  4 |
   2403 	    AIFS(edca[WME_AC_VI].ac_aifsn) >>  8);
   2404 
   2405 	/* Set TXOP limit. */
   2406 	otus_write(sc, AR_MAC_REG_AC1_AC0_TXOP,
   2407 	    edca[WME_AC_BK].ac_txoplimit << 16 |
   2408 	    edca[WME_AC_BE].ac_txoplimit);
   2409 	otus_write(sc, AR_MAC_REG_AC3_AC2_TXOP,
   2410 	    edca[WME_AC_VO].ac_txoplimit << 16 |
   2411 	    edca[WME_AC_VI].ac_txoplimit);
   2412 #undef AIFS
   2413 #undef EXP2
   2414 
   2415 	splx(s);
   2416 
   2417 	(void)otus_write_barrier(sc);
   2418 }
   2419 
   2420 Static void
   2421 otus_updateslot(struct ifnet *ifp)
   2422 {
   2423 	struct otus_softc *sc;
   2424 
   2425 	sc = ifp->if_softc;
   2426 
   2427 	DPRINTFN(DBG_FN, sc, "\n");
   2428 
   2429 	/* Do it in a process context. */
   2430 	otus_do_async(sc, otus_updateslot_cb, NULL, 0);
   2431 }
   2432 
   2433 /* ARGSUSED */
   2434 Static void
   2435 otus_updateslot_cb(struct otus_softc *sc, void *arg)
   2436 {
   2437 
   2438 	DPRINTFN(DBG_FN, sc, "\n");
   2439 
   2440 	mutex_enter(&sc->sc_write_mtx);
   2441 	otus_updateslot_cb_locked(sc);
   2442 	mutex_exit(&sc->sc_write_mtx);
   2443 }
   2444 
   2445 Static void
   2446 otus_updateslot_cb_locked(struct otus_softc *sc)
   2447 {
   2448 	uint32_t slottime;
   2449 
   2450 	DPRINTFN(DBG_FN, sc, "\n");
   2451 
   2452 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   2453 
   2454 	slottime = (sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
   2455 	otus_write(sc, AR_MAC_REG_SLOT_TIME, slottime << 10);
   2456 	(void)otus_write_barrier(sc);
   2457 }
   2458 
   2459 Static int
   2460 otus_init_mac(struct otus_softc *sc)
   2461 {
   2462 	int error;
   2463 
   2464 	DPRINTFN(DBG_FN | DBG_INIT, sc, "\n");
   2465 
   2466 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   2467 
   2468 	otus_write(sc, AR_MAC_REG_ACK_EXTENSION, 0x40);
   2469 	otus_write(sc, AR_MAC_REG_RETRY_MAX, 0);
   2470 	otus_write(sc, AR_MAC_REG_SNIFFER, AR_MAC_REG_SNIFFER_DEFAULTS);
   2471 	otus_write(sc, AR_MAC_REG_RX_THRESHOLD, 0xc1f80);
   2472 	otus_write(sc, AR_MAC_REG_RX_PE_DELAY, 0x70);
   2473 	otus_write(sc, AR_MAC_REG_EIFS_AND_SIFS, 0xa144000);
   2474 	otus_write(sc, AR_MAC_REG_SLOT_TIME, 9 << 10);
   2475 
   2476 	/* CF-END mode */
   2477 	otus_write(sc, 0x1c3b2c, 0x19000000);
   2478 
   2479 	/* NAV protects ACK only (in TXOP). */
   2480 	otus_write(sc, 0x1c3b38, 0x201);
   2481 
   2482 	/* Set beacon PHY CTRL's TPC to 0x7, TA1=1 */
   2483 	/* OTUS set AM to 0x1 */
   2484 	otus_write(sc, AR_MAC_REG_BCN_HT1, 0x8000170);
   2485 
   2486 	otus_write(sc, AR_MAC_REG_BACKOFF_PROTECT, 0x105);
   2487 
   2488 	/* AGG test code*/
   2489 	/* Aggregation MAX number and timeout */
   2490 	otus_write(sc, AR_MAC_REG_AMPDU_FACTOR, 0x10000a);
   2491 
   2492 	/* Filter any control frames, BAR is bit 24. */
   2493 	otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, AR_MAC_REG_FTF_DEFAULTS);
   2494 
   2495 	/* Enable deaggregator, response in sniffer mode */
   2496 	otus_write(sc, 0x1c3c40, 0x1 | 1 << 30);	/* XXX: was 0x1 */
   2497 
   2498 	/* rate sets */
   2499 	otus_write(sc, AR_MAC_REG_BASIC_RATE, 0x150f);
   2500 	otus_write(sc, AR_MAC_REG_MANDATORY_RATE, 0x150f);
   2501 	otus_write(sc, AR_MAC_REG_RTS_CTS_RATE, 0x10b01bb);
   2502 
   2503 	/* MIMO response control */
   2504 	otus_write(sc, 0x1c3694, 0x4003c1e);	/* bit 26~28  otus-AM */
   2505 
   2506 	/* Switch MAC to OTUS interface. */
   2507 	otus_write(sc, 0x1c3600, 0x3);
   2508 
   2509 	otus_write(sc, AR_MAC_REG_AMPDU_RX_THRESH, 0xffff);
   2510 
   2511 	/* set PHY register read timeout (??) */
   2512 	otus_write(sc, AR_MAC_REG_MISC_680, 0xf00008);
   2513 
   2514 	/* Disable Rx TimeOut, workaround for BB. */
   2515 	otus_write(sc, AR_MAC_REG_RX_TIMEOUT, 0x0);
   2516 
   2517 	/* Set clock frequency to 88/80MHz. */
   2518 	otus_write(sc, AR_PWR_REG_CLOCK_SEL,
   2519 	    AR_PWR_CLK_AHB_80_88MHZ | AR_PWR_CLK_DAC_160_INV_DLY);
   2520 
   2521 	/* Set WLAN DMA interrupt mode: generate intr per packet. */
   2522 	otus_write(sc, AR_MAC_REG_TXRX_MPI, 0x110011);
   2523 
   2524 	otus_write(sc, AR_MAC_REG_FCS_SELECT, AR_MAC_FCS_FIFO_PROT);
   2525 
   2526 	/* Disables the CF_END frame, undocumented register */
   2527 	otus_write(sc, AR_MAC_REG_TXOP_NOT_ENOUGH_INDICATION, 0x141e0f48);
   2528 
   2529 	/* Disable HW decryption for now. */
   2530 	otus_write(sc, AR_MAC_REG_ENCRYPTION,
   2531 	    AR_MAC_REG_ENCRYPTION_DEFAULTS | AR_MAC_REG_ENCRYPTION_RX_SOFTWARE);
   2532 
   2533 	/*
   2534 	 * XXX: should these be elsewhere?
   2535 	 */
   2536 	/* Enable LED0 and LED1. */
   2537 	otus_write(sc, AR_GPIO_REG_PORT_TYPE, 3);
   2538 	otus_write(sc, AR_GPIO_REG_DATA,
   2539 	    AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON);
   2540 
   2541 	/* Set USB Rx stream mode maximum frame number to 2. */
   2542 	otus_write(sc, AR_USB_REG_MAX_AGG_UPLOAD, (1 << 2));
   2543 
   2544 	/* Set USB Rx stream mode timeout to 10us. */
   2545 	otus_write(sc, AR_USB_REG_UPLOAD_TIME_CTL, 0x80);
   2546 
   2547 	if ((error = otus_write_barrier(sc)) != 0)
   2548 		return error;
   2549 
   2550 	/* Set default EDCA parameters. */
   2551 	otus_updateedca_cb_locked(sc);
   2552 	return 0;
   2553 }
   2554 
   2555 /*
   2556  * Return default value for PHY register based on current operating mode.
   2557  */
   2558 Static uint32_t
   2559 otus_phy_get_def(struct otus_softc *sc, uint32_t reg)
   2560 {
   2561 	int i;
   2562 
   2563 	DPRINTFN(DBG_FN, sc, "\n");
   2564 
   2565 	for (i = 0; i < __arraycount(ar5416_phy_regs); i++)
   2566 		if (AR_PHY(ar5416_phy_regs[i]) == reg)
   2567 			return sc->sc_phy_vals[i];
   2568 	return 0;	/* Register not found. */
   2569 }
   2570 
   2571 /*
   2572  * Update PHY's programming based on vendor-specific data stored in EEPROM.
   2573  * This is for FEM-type devices only.
   2574  */
   2575 Static int
   2576 otus_set_board_values(struct otus_softc *sc, struct ieee80211_channel *c)
   2577 {
   2578 	const struct ModalEepHeader *eep;
   2579 	uint32_t tmp, offset;
   2580 
   2581 	DPRINTFN(DBG_FN, sc, "\n");
   2582 
   2583 	if (IEEE80211_IS_CHAN_5GHZ(c))
   2584 		eep = &sc->sc_eeprom.modalHeader[0];
   2585 	else
   2586 		eep = &sc->sc_eeprom.modalHeader[1];
   2587 
   2588 	/* Offset of chain 2. */
   2589 	offset = 2 * 0x1000;
   2590 
   2591 	tmp = le32toh(eep->antCtrlCommon);
   2592 	otus_write(sc, AR_PHY_SWITCH_COM, tmp);
   2593 
   2594 	tmp = le32toh(eep->antCtrlChain[0]);
   2595 	otus_write(sc, AR_PHY_SWITCH_CHAIN_0, tmp);
   2596 
   2597 	tmp = le32toh(eep->antCtrlChain[1]);
   2598 	otus_write(sc, AR_PHY_SWITCH_CHAIN_0 + offset, tmp);
   2599 
   2600 	if (1 /* sc->sc_sco == AR_SCO_SCN */) {
   2601 		tmp = otus_phy_get_def(sc, AR_PHY_SETTLING);
   2602 		tmp &= ~(0x7f << 7);
   2603 		tmp |= (eep->switchSettling & 0x7f) << 7;
   2604 		otus_write(sc, AR_PHY_SETTLING, tmp);
   2605 	}
   2606 
   2607 	tmp = otus_phy_get_def(sc, AR_PHY_DESIRED_SZ);
   2608 	tmp &= ~0xffff;
   2609 	tmp |= eep->pgaDesiredSize << 8 | eep->adcDesiredSize;
   2610 	otus_write(sc, AR_PHY_DESIRED_SZ, tmp);
   2611 
   2612 	tmp = eep->txEndToXpaOff << 24 | eep->txEndToXpaOff << 16 |
   2613 	      eep->txFrameToXpaOn << 8 | eep->txFrameToXpaOn;
   2614 	otus_write(sc, AR_PHY_RF_CTL4, tmp);
   2615 
   2616 	tmp = otus_phy_get_def(sc, AR_PHY_RF_CTL3);
   2617 	tmp &= ~(0xff << 16);
   2618 	tmp |= eep->txEndToRxOn << 16;
   2619 	otus_write(sc, AR_PHY_RF_CTL3, tmp);
   2620 
   2621 	tmp = otus_phy_get_def(sc, AR_PHY_CCA);
   2622 	tmp &= ~(0x7f << 12);
   2623 	tmp |= (eep->thresh62 & 0x7f) << 12;
   2624 	otus_write(sc, AR_PHY_CCA, tmp);
   2625 
   2626 	tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN);
   2627 	tmp &= ~(0x3f << 12);
   2628 	tmp |= (eep->txRxAttenCh[0] & 0x3f) << 12;
   2629 	otus_write(sc, AR_PHY_RXGAIN, tmp);
   2630 
   2631 	tmp = otus_phy_get_def(sc, AR_PHY_RXGAIN + offset);
   2632 	tmp &= ~(0x3f << 12);
   2633 	tmp |= (eep->txRxAttenCh[1] & 0x3f) << 12;
   2634 	otus_write(sc, AR_PHY_RXGAIN + offset, tmp);
   2635 
   2636 	tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ);
   2637 	tmp &= ~(0x3f << 18);
   2638 	tmp |= (eep->rxTxMarginCh[0] & 0x3f) << 18;
   2639 	if (IEEE80211_IS_CHAN_5GHZ(c)) {
   2640 		tmp &= ~(0xf << 10);
   2641 		tmp |= (eep->bswMargin[0] & 0xf) << 10;
   2642 	}
   2643 	otus_write(sc, AR_PHY_GAIN_2GHZ, tmp);
   2644 
   2645 	tmp = otus_phy_get_def(sc, AR_PHY_GAIN_2GHZ + offset);
   2646 	tmp &= ~(0x3f << 18);
   2647 	tmp |= (eep->rxTxMarginCh[1] & 0x3f) << 18;
   2648 	otus_write(sc, AR_PHY_GAIN_2GHZ + offset, tmp);
   2649 
   2650 	tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4);
   2651 	tmp &= ~(0x3f << 5 | 0x1f);
   2652 	tmp |= (eep->iqCalICh[0] & 0x3f) << 5 | (eep->iqCalQCh[0] & 0x1f);
   2653 	otus_write(sc, AR_PHY_TIMING_CTRL4, tmp);
   2654 
   2655 	tmp = otus_phy_get_def(sc, AR_PHY_TIMING_CTRL4 + offset);
   2656 	tmp &= ~(0x3f << 5 | 0x1f);
   2657 	tmp |= (eep->iqCalICh[1] & 0x3f) << 5 | (eep->iqCalQCh[1] & 0x1f);
   2658 	otus_write(sc, AR_PHY_TIMING_CTRL4 + offset, tmp);
   2659 
   2660 	tmp = otus_phy_get_def(sc, AR_PHY_TPCRG1);
   2661 	tmp &= ~(0xf << 16);
   2662 	tmp |= (eep->xpd & 0xf) << 16;
   2663 	otus_write(sc, AR_PHY_TPCRG1, tmp);
   2664 
   2665 	return otus_write_barrier(sc);
   2666 }
   2667 
   2668 Static int
   2669 otus_program_phy(struct otus_softc *sc, struct ieee80211_channel *c)
   2670 {
   2671 	const uint32_t *vals;
   2672 	int error, i;
   2673 
   2674 	DPRINTFN(DBG_FN, sc, "\n");
   2675 
   2676 	/* Select PHY programming based on band and bandwidth. */
   2677 	if (IEEE80211_IS_CHAN_2GHZ(c))
   2678 		vals = ar5416_phy_vals_2ghz_20mhz;
   2679 	else
   2680 		vals = ar5416_phy_vals_5ghz_20mhz;
   2681 	for (i = 0; i < __arraycount(ar5416_phy_regs); i++)
   2682 		otus_write(sc, AR_PHY(ar5416_phy_regs[i]), vals[i]);
   2683 	sc->sc_phy_vals = vals;
   2684 
   2685 	if (sc->sc_eeprom.baseEepHeader.deviceType == 0x80)	/* FEM */
   2686 		if ((error = otus_set_board_values(sc, c)) != 0)
   2687 			return error;
   2688 
   2689 	/* Initial Tx power settings. */
   2690 	otus_write(sc, AR_PHY_POWER_TX_RATE_MAX, 0x7f);
   2691 	otus_write(sc, AR_PHY_POWER_TX_RATE1, 0x3f3f3f3f);
   2692 	otus_write(sc, AR_PHY_POWER_TX_RATE2, 0x3f3f3f3f);
   2693 	otus_write(sc, AR_PHY_POWER_TX_RATE3, 0x3f3f3f3f);
   2694 	otus_write(sc, AR_PHY_POWER_TX_RATE4, 0x3f3f3f3f);
   2695 	otus_write(sc, AR_PHY_POWER_TX_RATE5, 0x3f3f3f3f);
   2696 	otus_write(sc, AR_PHY_POWER_TX_RATE6, 0x3f3f3f3f);
   2697 	otus_write(sc, AR_PHY_POWER_TX_RATE7, 0x3f3f3f3f);
   2698 	otus_write(sc, AR_PHY_POWER_TX_RATE8, 0x3f3f3f3f);
   2699 	otus_write(sc, AR_PHY_POWER_TX_RATE9, 0x3f3f3f3f);
   2700 
   2701 	if (IEEE80211_IS_CHAN_2GHZ(c))
   2702 		otus_write(sc, 0x1d4014, 0x5163);
   2703 	else
   2704 		otus_write(sc, 0x1d4014, 0x5143);
   2705 
   2706 	return otus_write_barrier(sc);
   2707 }
   2708 
   2709 static __inline uint8_t
   2710 otus_reverse_bits(uint8_t v)
   2711 {
   2712 
   2713 	v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
   2714 	v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
   2715 	v = ((v >> 4) & 0x0f) | ((v & 0x0f) << 4);
   2716 	return v;
   2717 }
   2718 
   2719 Static int
   2720 otus_set_rf_bank4(struct otus_softc *sc, struct ieee80211_channel *c)
   2721 {
   2722 	uint8_t chansel, d0, d1;
   2723 	uint16_t data;
   2724 	int error;
   2725 
   2726 	DPRINTFN(DBG_FN, sc, "\n");
   2727 
   2728 	d0 = 0;
   2729 	if (IEEE80211_IS_CHAN_5GHZ(c)) {
   2730 		chansel = (c->ic_freq - 4800) / 5;
   2731 		if (chansel & 1)
   2732 			d0 |= AR_BANK4_AMODE_REFSEL(2);
   2733 		else
   2734 			d0 |= AR_BANK4_AMODE_REFSEL(1);
   2735 	} else {
   2736 		d0 |= AR_BANK4_AMODE_REFSEL(2);
   2737 		if (c->ic_freq == 2484) {	/* CH 14 */
   2738 			d0 |= AR_BANK4_BMODE_LF_SYNTH_FREQ;
   2739 			chansel = 10 + (c->ic_freq - 2274) / 5;
   2740 		} else
   2741 			chansel = 16 + (c->ic_freq - 2272) / 5;
   2742 		chansel <<= 2;
   2743 	}
   2744 	d0 |= AR_BANK4_ADDR(1) | AR_BANK4_CHUP;
   2745 	d1 = otus_reverse_bits(chansel);
   2746 
   2747 	/* Write bits 0-4 of d0 and d1. */
   2748 	data = (d1 & 0x1f) << 5 | (d0 & 0x1f);
   2749 	otus_write(sc, AR_PHY(44), data);
   2750 	/* Write bits 5-7 of d0 and d1. */
   2751 	data = (d1 >> 5) << 5 | (d0 >> 5);
   2752 	otus_write(sc, AR_PHY(58), data);
   2753 
   2754 	if ((error = otus_write_barrier(sc)) == 0)
   2755 		usbd_delay_ms(sc->sc_udev, 10);
   2756 
   2757 	return error;
   2758 }
   2759 
   2760 Static void
   2761 otus_get_delta_slope(uint32_t coeff, uint32_t *exponent, uint32_t *mantissa)
   2762 {
   2763 #define COEFF_SCALE_SHIFT	24
   2764 	uint32_t exp, man;
   2765 
   2766 	DPRINTFN(DBG_FN, DBG_NO_SC, "\n");
   2767 
   2768 	/* exponent = 14 - floor(log2(coeff)) */
   2769 	for (exp = 31; exp > 0; exp--)
   2770 		if (coeff & (1 << exp))
   2771 			break;
   2772 	KASSERT(exp != 0);
   2773 	exp = 14 - (exp - COEFF_SCALE_SHIFT);
   2774 
   2775 	/* mantissa = floor(coeff * 2^exponent + 0.5) */
   2776 	man = coeff + (1 << (COEFF_SCALE_SHIFT - exp - 1));
   2777 
   2778 	*mantissa = man >> (COEFF_SCALE_SHIFT - exp);
   2779 	*exponent = exp - 16;
   2780 #undef COEFF_SCALE_SHIFT
   2781 }
   2782 
   2783 Static int
   2784 otus_set_chan(struct otus_softc *sc, struct ieee80211_channel *c, int assoc)
   2785 {
   2786 	struct ar_cmd_frequency cmd;
   2787 	struct ar_rsp_frequency rsp;
   2788 	const uint32_t *vals;
   2789 	uint32_t coeff, exp, man, tmp;
   2790 	uint8_t code;
   2791 	int error, i;
   2792 
   2793 	DPRINTFN(DBG_FN, sc, "\n");
   2794 
   2795 
   2796 #ifdef OTUS_DEBUG
   2797 	struct ieee80211com *ic = &sc->sc_ic;
   2798 	int chan = ieee80211_chan2ieee(ic, c);
   2799 
   2800 	DPRINTFN(DBG_CHAN, sc, "setting channel %d (%dMHz)\n",
   2801 	    chan, c->ic_freq);
   2802 #endif
   2803 
   2804 	tmp = IEEE80211_IS_CHAN_2GHZ(c) ? 0x105 : 0x104;
   2805 	otus_write(sc, AR_MAC_REG_DYNAMIC_SIFS_ACK, tmp);
   2806 	if ((error = otus_write_barrier(sc)) != 0)
   2807 		return error;
   2808 
   2809 	/* Disable BB Heavy Clip. */
   2810 	otus_write(sc, AR_PHY_HEAVY_CLIP_ENABLE, 0x200);
   2811 	if ((error = otus_write_barrier(sc)) != 0)
   2812 		return error;
   2813 
   2814 	/* XXX Is that FREQ_START ? */
   2815 	error = otus_cmd(sc, AR_CMD_FREQ_STRAT, NULL, 0, NULL);
   2816 	if (error != 0)
   2817 		return error;
   2818 
   2819 	/* Reprogram PHY and RF on channel band or bandwidth changes. */
   2820 	if (sc->sc_bb_reset || c->ic_flags != sc->sc_curchan->ic_flags) {
   2821 		DPRINTFN(DBG_CHAN, sc, "band switch\n");
   2822 
   2823 		/* Cold/Warm reset BB/ADDA. */
   2824 		otus_write(sc, 0x1d4004, sc->sc_bb_reset ? 0x800 : 0x400);
   2825 		if ((error = otus_write_barrier(sc)) != 0)
   2826 			return error;
   2827 
   2828 		otus_write(sc, 0x1d4004, 0);
   2829 		if ((error = otus_write_barrier(sc)) != 0)
   2830 			return error;
   2831 		sc->sc_bb_reset = 0;
   2832 
   2833 		if ((error = otus_program_phy(sc, c)) != 0) {
   2834 			aprint_error_dev(sc->sc_dev,
   2835 			    "could not program PHY\n");
   2836 			return error;
   2837 		}
   2838 
   2839 		/* Select RF programming based on band. */
   2840 		if (IEEE80211_IS_CHAN_5GHZ(c))
   2841 			vals = ar5416_banks_vals_5ghz;
   2842 		else
   2843 			vals = ar5416_banks_vals_2ghz;
   2844 		for (i = 0; i < __arraycount(ar5416_banks_regs); i++)
   2845 			otus_write(sc, AR_PHY(ar5416_banks_regs[i]), vals[i]);
   2846 		if ((error = otus_write_barrier(sc)) != 0) {
   2847 			aprint_error_dev(sc->sc_dev, "could not program RF\n");
   2848 			return error;
   2849 		}
   2850 		code = AR_CMD_RF_INIT;
   2851 	} else {
   2852 		code = AR_CMD_FREQUENCY;
   2853 	}
   2854 
   2855 	if ((error = otus_set_rf_bank4(sc, c)) != 0)
   2856 		return error;
   2857 
   2858 	tmp = (sc->sc_txmask == 0x5) ? 0x340 : 0x240;
   2859 	otus_write(sc, AR_PHY_TURBO, tmp);
   2860 	if ((error = otus_write_barrier(sc)) != 0)
   2861 		return error;
   2862 
   2863 	/* Send firmware command to set channel. */
   2864 	cmd.freq = htole32((uint32_t)c->ic_freq * 1000);
   2865 	cmd.dynht2040 = htole32(0);
   2866 	cmd.htena = htole32(1);
   2867 
   2868 	/* Set Delta Slope (exponent and mantissa). */
   2869 	coeff = (100 << 24) / c->ic_freq;
   2870 	otus_get_delta_slope(coeff, &exp, &man);
   2871 	cmd.dsc_exp = htole32(exp);
   2872 	cmd.dsc_man = htole32(man);
   2873 	DPRINTFN(DBG_CHAN, sc, "ds coeff=%u exp=%u man=%u\n",
   2874 	    coeff, exp, man);
   2875 
   2876 	/* For Short GI, coeff is 9/10 that of normal coeff. */
   2877 	coeff = (9 * coeff) / 10;
   2878 	otus_get_delta_slope(coeff, &exp, &man);
   2879 	cmd.dsc_shgi_exp = htole32(exp);
   2880 	cmd.dsc_shgi_man = htole32(man);
   2881 	DPRINTFN(DBG_CHAN, sc, "ds shgi coeff=%u exp=%u man=%u\n",
   2882 	    coeff, exp, man);
   2883 
   2884 	/* Set wait time for AGC and noise calibration (100 or 200ms). */
   2885 	cmd.check_loop_count = assoc ? htole32(2000) : htole32(1000);
   2886 	DPRINTFN(DBG_CHAN, sc, "%s\n",
   2887 	    code == AR_CMD_RF_INIT ? "RF_INIT" : "FREQUENCY");
   2888 	error = otus_cmd(sc, code, &cmd, sizeof(cmd), &rsp);
   2889 	if (error != 0)
   2890 		return error;
   2891 
   2892 	if ((rsp.status & htole32(AR_CAL_ERR_AGC | AR_CAL_ERR_NF_VAL)) != 0) {
   2893 		DPRINTFN(DBG_CHAN, sc, "status=%#x\n", le32toh(rsp.status));
   2894 		/* Force cold reset on next channel. */
   2895 		sc->sc_bb_reset = 1;
   2896 	}
   2897 
   2898 #ifdef OTUS_DEBUG
   2899 	if (otus_debug & DBG_CHAN) {
   2900 		DPRINTFN(DBG_CHAN, sc, "calibration status=%#x\n",
   2901 		    le32toh(rsp.status));
   2902 		for (i = 0; i < 2; i++) {	/* 2 Rx chains */
   2903 			/* Sign-extend 9-bit NF values. */
   2904 			DPRINTFN(DBG_CHAN, sc, "noisefloor chain %d=%d\n",
   2905 			    i, (((int32_t)le32toh(rsp.nf[i])) << 4) >> 23);
   2906 			DPRINTFN(DBG_CHAN, sc, "noisefloor ext chain %d=%d\n",
   2907 			    i, ((int32_t)le32toh(rsp.nf_ext[i])) >> 23);
   2908 		}
   2909 	}
   2910 #endif
   2911 	sc->sc_curchan = c;
   2912 	return 0;
   2913 }
   2914 
   2915 #ifdef notyet
   2916 Static int
   2917 otus_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
   2918     struct ieee80211_key *k)
   2919 {
   2920 	struct otus_softc *sc;
   2921 	struct otus_cmd_key cmd;
   2922 
   2923 	sc = ic->ic_ifp->if_softc;
   2924 
   2925 	DPRINTFN(DBG_FN, sc, "\n");
   2926 
   2927 	/* Defer setting of WEP keys until interface is brought up. */
   2928 	if ((ic->ic_ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
   2929 	    (IFF_UP | IFF_RUNNING))
   2930 		return 0;
   2931 
   2932 	/* Do it in a process context. */
   2933 	cmd.key = *k;
   2934 	cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
   2935 	otus_do_async(sc, otus_set_key_cb, &cmd, sizeof(cmd));
   2936 	return 0;
   2937 }
   2938 
   2939 Static void
   2940 otus_set_key_cb(struct otus_softc *sc, void *arg)
   2941 {
   2942 	struct otus_cmd_key *cmd;
   2943 	struct ieee80211_key *k;
   2944 	struct ar_cmd_ekey key;
   2945 	uint16_t cipher;
   2946 	int error;
   2947 
   2948 	DPRINTFN(DBG_FN, sc, "\n");
   2949 
   2950 	cmd = arg;
   2951 	k = &cmd->key;
   2952 
   2953 	memset(&key, 0, sizeof(key));
   2954 	if (k->k_flags & IEEE80211_KEY_GROUP) {
   2955 		key.uid = htole16(k->k_id);
   2956 		IEEE80211_ADDR_COPY(key.macaddr, sc->sc_ic.ic_myaddr);
   2957 		key.macaddr[0] |= 0x80;
   2958 	} else {
   2959 		key.uid = htole16(OTUS_UID(cmd->associd));
   2960 		IEEE80211_ADDR_COPY(key.macaddr, ni->ni_macaddr);
   2961 	}
   2962 	key.kix = htole16(0);
   2963 	/* Map net80211 cipher to hardware. */
   2964 	switch (k->k_cipher) {
   2965 	case IEEE80211_CIPHER_WEP40:
   2966 		cipher = AR_CIPHER_WEP64;
   2967 		break;
   2968 	case IEEE80211_CIPHER_WEP104:
   2969 		cipher = AR_CIPHER_WEP128;
   2970 		break;
   2971 	case IEEE80211_CIPHER_TKIP:
   2972 		cipher = AR_CIPHER_TKIP;
   2973 		break;
   2974 	case IEEE80211_CIPHER_CCMP:
   2975 		cipher = AR_CIPHER_AES;
   2976 		break;
   2977 	default:
   2978 		return;
   2979 	}
   2980 	key.cipher = htole16(cipher);
   2981 	memcpy(key.key, k->k_key, MIN(k->k_len, 16));
   2982 	error = otus_cmd(sc, AR_CMD_EKEY, &key, sizeof(key), NULL);
   2983 	if (error != 0 || k->k_cipher != IEEE80211_CIPHER_TKIP)
   2984 		return;
   2985 
   2986 	/* TKIP: set Tx/Rx MIC Key. */
   2987 	key.kix = htole16(1);
   2988 	memcpy(key.key, k->k_key + 16, 16);
   2989 	(void)otus_cmd(sc, AR_CMD_EKEY, &key, sizeof(key), NULL);
   2990 }
   2991 
   2992 Static void
   2993 otus_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
   2994     struct ieee80211_key *k)
   2995 {
   2996 	struct otus_softc *sc;
   2997 	struct otus_cmd_key cmd;
   2998 
   2999 	sc = ic->ic_ifp->if_softc;
   3000 
   3001 	DPRINTFN(DBG_FN, sc, "\n");
   3002 
   3003 	if (!(ic->ic_ifp->if_flags & IFF_RUNNING) ||
   3004 	    ic->ic_state != IEEE80211_S_RUN)
   3005 		return;	/* Nothing to do. */
   3006 
   3007 	/* Do it in a process context. */
   3008 	cmd.key = *k;
   3009 	cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
   3010 	otus_do_async(sc, otus_delete_key_cb, &cmd, sizeof(cmd));
   3011 }
   3012 
   3013 Static void
   3014 otus_delete_key_cb(struct otus_softc *sc, void *arg)
   3015 {
   3016 	struct otus_cmd_key *cmd;
   3017 	struct ieee80211_key *k;
   3018 	uint32_t uid;
   3019 
   3020 	DPRINTFN(DBG_FN, sc, "\n");
   3021 
   3022 	cmd = arg;
   3023 	k = &cmd->key;
   3024 	if (k->k_flags & IEEE80211_KEY_GROUP)
   3025 		uid = htole32(k->k_id);
   3026 	else
   3027 		uid = htole32(OTUS_UID(cmd->associd));
   3028 	(void)otus_cmd(sc, AR_CMD_DKEY, &uid, sizeof(uid), NULL);
   3029 }
   3030 #endif /* notyet */
   3031 
   3032 Static void
   3033 otus_calib_to(void *arg)
   3034 {
   3035 	struct otus_softc *sc;
   3036 	struct ieee80211com *ic;
   3037 	struct ieee80211_node *ni;
   3038 	struct otus_node *on;
   3039 	int s;
   3040 
   3041 	sc = arg;
   3042 
   3043 	DPRINTFN(DBG_FN, sc, "\n");
   3044 
   3045 	if (sc->sc_dying)
   3046 		return;
   3047 
   3048 	s = splnet();
   3049 	ic = &sc->sc_ic;
   3050 	ni = ic->ic_bss;
   3051 	on = (void *)ni;
   3052 	ieee80211_amrr_choose(&sc->sc_amrr, ni, &on->amn);
   3053 	splx(s);
   3054 
   3055 	if (!sc->sc_dying)
   3056 		callout_schedule(&sc->sc_calib_to, hz);
   3057 }
   3058 
   3059 Static int
   3060 otus_set_bssid(struct otus_softc *sc, const uint8_t *bssid)
   3061 {
   3062 
   3063 	DPRINTFN(DBG_FN, sc, "\n");
   3064 
   3065 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   3066 
   3067 	otus_write(sc, AR_MAC_REG_BSSID_L,
   3068 	    bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24);
   3069 	otus_write(sc, AR_MAC_REG_BSSID_H,
   3070 	    bssid[4] | bssid[5] << 8);
   3071 	return otus_write_barrier(sc);
   3072 }
   3073 
   3074 Static int
   3075 otus_set_macaddr(struct otus_softc *sc, const uint8_t *addr)
   3076 {
   3077 
   3078 	DPRINTFN(DBG_FN, sc, "\n");
   3079 
   3080 	KASSERT(mutex_owned(&sc->sc_write_mtx));
   3081 
   3082 	otus_write(sc, AR_MAC_REG_MAC_ADDR_L,
   3083 	    addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
   3084 	otus_write(sc, AR_MAC_REG_MAC_ADDR_H,
   3085 	    addr[4] | addr[5] << 8);
   3086 	return otus_write_barrier(sc);
   3087 }
   3088 
   3089 #ifdef notyet
   3090 /* Default single-LED. */
   3091 Static void
   3092 otus_led_newstate_type1(struct otus_softc *sc)
   3093 {
   3094 
   3095 	DPRINTFN(DBG_FN, sc, "\n");
   3096 
   3097 	/* TBD */
   3098 }
   3099 
   3100 /* NETGEAR, dual-LED. */
   3101 Static void
   3102 otus_led_newstate_type2(struct otus_softc *sc)
   3103 {
   3104 
   3105 	DPRINTFN(DBG_FN, sc, "\n");
   3106 
   3107 	/* TBD */
   3108 }
   3109 #endif /* notyet */
   3110 
   3111 /*
   3112  * NETGEAR, single-LED/3 colors (blue, red, purple.)
   3113  */
   3114 Static void
   3115 otus_led_newstate_type3(struct otus_softc *sc)
   3116 {
   3117 	struct ieee80211com *ic;
   3118 	uint32_t led_state;
   3119 
   3120 	DPRINTFN(DBG_FN, sc, "\n");
   3121 
   3122 	ic = &sc->sc_ic;
   3123 	led_state = sc->sc_led_state;
   3124 	switch (ic->ic_state) {
   3125 	case IEEE80211_S_INIT:
   3126 		led_state = 0;
   3127 		break;
   3128 	case IEEE80211_S_SCAN:
   3129 		led_state ^= AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON;
   3130 		led_state &= ~(IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) ?
   3131 		    AR_GPIO_REG_DATA_LED1_ON : AR_GPIO_REG_DATA_LED0_ON);
   3132 		break;
   3133 	case IEEE80211_S_AUTH:
   3134 	case IEEE80211_S_ASSOC:
   3135 		/* XXX: Turn both LEDs on for AUTH and ASSOC? */
   3136 		led_state = AR_GPIO_REG_DATA_LED0_ON | AR_GPIO_REG_DATA_LED1_ON;
   3137 		break;
   3138 	case IEEE80211_S_RUN:
   3139 		led_state = IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) ?
   3140 		    AR_GPIO_REG_DATA_LED0_ON : AR_GPIO_REG_DATA_LED1_ON;
   3141 		break;
   3142 	}
   3143 	if (led_state != sc->sc_led_state) {
   3144 		otus_write(sc, AR_GPIO_REG_DATA, led_state);
   3145 		if (otus_write_barrier(sc) == 0)
   3146 			sc->sc_led_state = led_state;
   3147 	}
   3148 }
   3149 
   3150 Static int
   3151 otus_init(struct ifnet *ifp)
   3152 {
   3153 	struct otus_softc *sc;
   3154 	struct ieee80211com *ic;
   3155 	uint32_t filter, pm_mode, sniffer;
   3156 	int error;
   3157 
   3158 	sc = ifp->if_softc;
   3159 
   3160 	DPRINTFN(DBG_FN | DBG_INIT, sc, "\n");
   3161 
   3162 	ic = &sc->sc_ic;
   3163 
   3164 	mutex_enter(&sc->sc_write_mtx);
   3165 
   3166 	/* Init host command ring. */
   3167 	mutex_spin_enter(&sc->sc_task_mtx);
   3168 	sc->sc_cmdq.cur = sc->sc_cmdq.next = sc->sc_cmdq.queued = 0;
   3169 	mutex_spin_exit(&sc->sc_task_mtx);
   3170 
   3171 	if ((error = otus_init_mac(sc)) != 0) {
   3172 		mutex_exit(&sc->sc_write_mtx);
   3173 		aprint_error_dev(sc->sc_dev, "could not initialize MAC\n");
   3174 		return error;
   3175 	}
   3176 
   3177 	IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
   3178 	(void)otus_set_macaddr(sc, ic->ic_myaddr);
   3179 
   3180 	pm_mode = AR_MAC_REG_POWERMGT_DEFAULTS;
   3181 	sniffer = AR_MAC_REG_SNIFFER_DEFAULTS;
   3182 	filter = AR_MAC_REG_FTF_DEFAULTS;
   3183 	sc->sc_rx_error_msk = ~0;
   3184 
   3185 	switch (ic->ic_opmode) {
   3186 #ifdef notyet
   3187 #ifndef IEEE80211_STA_ONLY
   3188 	case IEEE80211_M_HOSTAP:
   3189 		pm_mode |= AR_MAC_REG_POWERMGT_AP;
   3190 		break;
   3191 	case IEEE80211_M_IBSS:
   3192 		pm_mode |= AR_MAC_REG_POWERMGT_IBSS;	/* XXX: was 0x0 */
   3193 		break;
   3194 #endif
   3195 #endif
   3196 	case IEEE80211_M_STA:
   3197 		pm_mode |= AR_MAC_REG_POWERMGT_STA;
   3198 		break;
   3199 	case IEEE80211_M_MONITOR:
   3200 		sc->sc_rx_error_msk = ~AR_RX_ERROR_BAD_RA;
   3201 		filter = AR_MAC_REG_FTF_MONITOR;
   3202 		sniffer |= AR_MAC_REG_SNIFFER_ENABLE_PROMISC;
   3203 		break;
   3204 	default:
   3205 		aprint_error_dev(sc->sc_dev, "bad opmode: %d", ic->ic_opmode);
   3206 		return EOPNOTSUPP;	/* XXX: ??? */
   3207 	}
   3208 	otus_write(sc, AR_MAC_REG_POWERMANAGEMENT, pm_mode);
   3209 	otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, filter);
   3210 	otus_write(sc, AR_MAC_REG_SNIFFER, sniffer);
   3211 	(void)otus_write_barrier(sc);
   3212 
   3213 	sc->sc_bb_reset = 1;	/* Force cold reset. */
   3214 	if ((error = otus_set_chan(sc, ic->ic_curchan, 0)) != 0) {
   3215 		mutex_exit(&sc->sc_write_mtx);
   3216 		aprint_error_dev(sc->sc_dev, "could not set channel\n");
   3217 		return error;
   3218 	}
   3219 
   3220 	/* Start Rx. */
   3221 	otus_write(sc, AR_MAC_REG_DMA, AR_MAC_REG_DMA_ENABLE);
   3222 	(void)otus_write_barrier(sc);
   3223 	mutex_exit(&sc->sc_write_mtx);
   3224 
   3225 	ifp->if_flags &= ~IFF_OACTIVE;
   3226 	ifp->if_flags |= IFF_RUNNING;
   3227 
   3228 	if (ic->ic_opmode == IEEE80211_M_MONITOR)
   3229 		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
   3230 	else
   3231 		ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
   3232 
   3233 	return 0;
   3234 }
   3235 
   3236 Static void
   3237 otus_stop(struct ifnet *ifp)
   3238 {
   3239 	struct otus_softc *sc;
   3240 	struct ieee80211com *ic;
   3241 	int s;
   3242 
   3243 	sc = ifp->if_softc;
   3244 
   3245 	DPRINTFN(DBG_FN, sc, "\n");
   3246 
   3247 	ic = &sc->sc_ic;
   3248 
   3249 	sc->sc_tx_timer = 0;
   3250 	ifp->if_timer = 0;
   3251 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   3252 
   3253 	callout_halt(&sc->sc_scan_to, NULL);
   3254 	callout_halt(&sc->sc_calib_to, NULL);
   3255 
   3256 	s = splusb();
   3257 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
   3258 	otus_wait_async(sc);
   3259 	splx(s);
   3260 
   3261 	/* Stop Rx. */
   3262 	mutex_enter(&sc->sc_write_mtx);
   3263 	otus_write(sc, AR_MAC_REG_DMA, AR_MAC_REG_DMA_OFF);
   3264 	(void)otus_write_barrier(sc);
   3265 	mutex_exit(&sc->sc_write_mtx);
   3266 }
   3267