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