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