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