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