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