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