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