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