1*232edc8cSjdolecek /* $NetBSD: if_run.c,v 1.42 2020/06/24 21:06:39 jdolecek Exp $ */
29cdb1c70Snonaka /* $OpenBSD: if_run.c,v 1.90 2012/03/24 15:11:04 jsg Exp $ */
39cdb1c70Snonaka
49cdb1c70Snonaka /*-
59cdb1c70Snonaka * Copyright (c) 2008-2010 Damien Bergamini <damien.bergamini@free.fr>
69cdb1c70Snonaka *
79cdb1c70Snonaka * Permission to use, copy, modify, and distribute this software for any
89cdb1c70Snonaka * purpose with or without fee is hereby granted, provided that the above
99cdb1c70Snonaka * copyright notice and this permission notice appear in all copies.
109cdb1c70Snonaka *
119cdb1c70Snonaka * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
129cdb1c70Snonaka * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
139cdb1c70Snonaka * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
149cdb1c70Snonaka * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
159cdb1c70Snonaka * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
169cdb1c70Snonaka * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
179cdb1c70Snonaka * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
189cdb1c70Snonaka */
199cdb1c70Snonaka
209cdb1c70Snonaka /*-
21d164e220Smlelstv * Ralink Technology RT2700U/RT2800U/RT3000U/RT3900E chipset driver.
229cdb1c70Snonaka * http://www.ralinktech.com/
239cdb1c70Snonaka */
249cdb1c70Snonaka
259cdb1c70Snonaka #include <sys/cdefs.h>
26*232edc8cSjdolecek __KERNEL_RCSID(0, "$NetBSD: if_run.c,v 1.42 2020/06/24 21:06:39 jdolecek Exp $");
27a7c71d30Sskrll
28a7c71d30Sskrll #ifdef _KERNEL_OPT
29a7c71d30Sskrll #include "opt_usb.h"
30a7c71d30Sskrll #endif
319cdb1c70Snonaka
329cdb1c70Snonaka #include <sys/param.h>
339cdb1c70Snonaka #include <sys/sockio.h>
349cdb1c70Snonaka #include <sys/sysctl.h>
359cdb1c70Snonaka #include <sys/mbuf.h>
369cdb1c70Snonaka #include <sys/kernel.h>
379cdb1c70Snonaka #include <sys/socket.h>
389cdb1c70Snonaka #include <sys/systm.h>
399cdb1c70Snonaka #include <sys/malloc.h>
409cdb1c70Snonaka #include <sys/callout.h>
419cdb1c70Snonaka #include <sys/module.h>
429cdb1c70Snonaka #include <sys/conf.h>
439cdb1c70Snonaka #include <sys/device.h>
4490e85cecSmlelstv #include <sys/atomic.h>
459cdb1c70Snonaka
469cdb1c70Snonaka #include <sys/bus.h>
479cdb1c70Snonaka #include <machine/endian.h>
489cdb1c70Snonaka #include <sys/intr.h>
499cdb1c70Snonaka
509cdb1c70Snonaka #include <net/bpf.h>
519cdb1c70Snonaka #include <net/if.h>
529cdb1c70Snonaka #include <net/if_arp.h>
539cdb1c70Snonaka #include <net/if_dl.h>
549cdb1c70Snonaka #include <net/if_ether.h>
559cdb1c70Snonaka #include <net/if_media.h>
569cdb1c70Snonaka #include <net/if_types.h>
579cdb1c70Snonaka
589cdb1c70Snonaka #include <net80211/ieee80211_var.h>
599cdb1c70Snonaka #include <net80211/ieee80211_amrr.h>
609cdb1c70Snonaka #include <net80211/ieee80211_radiotap.h>
619cdb1c70Snonaka
629cdb1c70Snonaka #include <dev/firmload.h>
639cdb1c70Snonaka
649cdb1c70Snonaka #include <dev/usb/usb.h>
659cdb1c70Snonaka #include <dev/usb/usbdi.h>
669cdb1c70Snonaka #include <dev/usb/usbdivar.h>
679cdb1c70Snonaka #include <dev/usb/usbdi_util.h>
689cdb1c70Snonaka #include <dev/usb/usbdevs.h>
699cdb1c70Snonaka
709cdb1c70Snonaka #include <dev/ic/rt2860reg.h> /* shared with ral(4) */
719cdb1c70Snonaka #include <dev/usb/if_runvar.h>
729cdb1c70Snonaka
739cdb1c70Snonaka #ifdef RUN_DEBUG
749cdb1c70Snonaka #define DPRINTF(x) do { if (run_debug) printf x; } while (0)
759cdb1c70Snonaka #define DPRINTFN(n, x) do { if (run_debug >= (n)) printf x; } while (0)
769cdb1c70Snonaka int run_debug = 0;
779cdb1c70Snonaka #else
789cdb1c70Snonaka #define DPRINTF(x)
799cdb1c70Snonaka #define DPRINTFN(n, x)
809cdb1c70Snonaka #endif
819cdb1c70Snonaka
82faca41fbSmlelstv #define IEEE80211_HAS_ADDR4(wh) IEEE80211_IS_DSTODS(wh)
83faca41fbSmlelstv
849cdb1c70Snonaka #define USB_ID(v, p) { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }
859cdb1c70Snonaka static const struct usb_devno run_devs[] = {
869cdb1c70Snonaka USB_ID(ABOCOM, RT2770),
879cdb1c70Snonaka USB_ID(ABOCOM, RT2870),
889cdb1c70Snonaka USB_ID(ABOCOM, RT3070),
899cdb1c70Snonaka USB_ID(ABOCOM, RT3071),
909cdb1c70Snonaka USB_ID(ABOCOM, RT3072),
919cdb1c70Snonaka USB_ID(ABOCOM2, RT2870_1),
929cdb1c70Snonaka USB_ID(ACCTON, RT2770),
939cdb1c70Snonaka USB_ID(ACCTON, RT2870_1),
949cdb1c70Snonaka USB_ID(ACCTON, RT2870_2),
959cdb1c70Snonaka USB_ID(ACCTON, RT2870_3),
969cdb1c70Snonaka USB_ID(ACCTON, RT2870_4),
979cdb1c70Snonaka USB_ID(ACCTON, RT2870_5),
989cdb1c70Snonaka USB_ID(ACCTON, RT3070),
999cdb1c70Snonaka USB_ID(ACCTON, RT3070_1),
1009cdb1c70Snonaka USB_ID(ACCTON, RT3070_2),
1019cdb1c70Snonaka USB_ID(ACCTON, RT3070_3),
1029cdb1c70Snonaka USB_ID(ACCTON, RT3070_4),
1039cdb1c70Snonaka USB_ID(ACCTON, RT3070_5),
1049cdb1c70Snonaka USB_ID(ACCTON, RT3070_6),
1059cdb1c70Snonaka USB_ID(AIRTIES, RT3070),
1069cdb1c70Snonaka USB_ID(AIRTIES, RT3070_2),
1079cdb1c70Snonaka USB_ID(ALLWIN, RT2070),
1089cdb1c70Snonaka USB_ID(ALLWIN, RT2770),
1099cdb1c70Snonaka USB_ID(ALLWIN, RT2870),
1109cdb1c70Snonaka USB_ID(ALLWIN, RT3070),
1119cdb1c70Snonaka USB_ID(ALLWIN, RT3071),
1129cdb1c70Snonaka USB_ID(ALLWIN, RT3072),
1139cdb1c70Snonaka USB_ID(ALLWIN, RT3572),
1149cdb1c70Snonaka USB_ID(AMIGO, RT2870_1),
1159cdb1c70Snonaka USB_ID(AMIGO, RT2870_2),
1169cdb1c70Snonaka USB_ID(AMIT, CGWLUSB2GNR),
1179cdb1c70Snonaka USB_ID(AMIT, RT2870_1),
1189cdb1c70Snonaka USB_ID(AMIT2, RT2870),
1199cdb1c70Snonaka USB_ID(ASUSTEK, RT2870_1),
1209cdb1c70Snonaka USB_ID(ASUSTEK, RT2870_2),
1219cdb1c70Snonaka USB_ID(ASUSTEK, RT2870_3),
1229cdb1c70Snonaka USB_ID(ASUSTEK, RT2870_4),
1239cdb1c70Snonaka USB_ID(ASUSTEK, RT2870_5),
1249cdb1c70Snonaka USB_ID(ASUSTEK, RT3070),
1259cdb1c70Snonaka USB_ID(ASUSTEK, RT3070_1),
126d164e220Smlelstv USB_ID(ASUSTEK, USBN53),
127d164e220Smlelstv USB_ID(ASUSTEK, USBN66),
1289cdb1c70Snonaka USB_ID(ASUSTEK2, USBN11),
1299cdb1c70Snonaka USB_ID(AZUREWAVE, RT2870_1),
1309cdb1c70Snonaka USB_ID(AZUREWAVE, RT2870_2),
1319cdb1c70Snonaka USB_ID(AZUREWAVE, RT3070),
1329cdb1c70Snonaka USB_ID(AZUREWAVE, RT3070_2),
1339cdb1c70Snonaka USB_ID(AZUREWAVE, RT3070_3),
1349cdb1c70Snonaka USB_ID(AZUREWAVE, RT3070_4),
1359cdb1c70Snonaka USB_ID(AZUREWAVE, RT3070_5),
1369cdb1c70Snonaka USB_ID(BELKIN, F5D8053V3),
1379cdb1c70Snonaka USB_ID(BELKIN, F5D8055),
1389cdb1c70Snonaka USB_ID(BELKIN, F5D8055V2),
1399cdb1c70Snonaka USB_ID(BELKIN, F6D4050V1),
1409cdb1c70Snonaka USB_ID(BELKIN, F6D4050V2),
1419cdb1c70Snonaka USB_ID(BELKIN, F7D1101V2),
1429cdb1c70Snonaka USB_ID(BELKIN, RT2870_1),
1439cdb1c70Snonaka USB_ID(BELKIN, RT2870_2),
144d164e220Smlelstv USB_ID(BELKIN, RTL8192CU_2),
1459cdb1c70Snonaka USB_ID(BEWAN, RT3070),
1469cdb1c70Snonaka USB_ID(CISCOLINKSYS, AE1000),
1479cdb1c70Snonaka USB_ID(CISCOLINKSYS, AM10),
1489cdb1c70Snonaka USB_ID(CISCOLINKSYS2, RT3070),
1499cdb1c70Snonaka USB_ID(CISCOLINKSYS3, RT3070),
1509cdb1c70Snonaka USB_ID(CONCEPTRONIC, RT2870_1),
1519cdb1c70Snonaka USB_ID(CONCEPTRONIC, RT2870_2),
1529cdb1c70Snonaka USB_ID(CONCEPTRONIC, RT2870_3),
1539cdb1c70Snonaka USB_ID(CONCEPTRONIC, RT2870_4),
1549cdb1c70Snonaka USB_ID(CONCEPTRONIC, RT2870_5),
1559cdb1c70Snonaka USB_ID(CONCEPTRONIC, RT2870_6),
1569cdb1c70Snonaka USB_ID(CONCEPTRONIC, RT2870_7),
1579cdb1c70Snonaka USB_ID(CONCEPTRONIC, RT2870_8),
1589cdb1c70Snonaka USB_ID(CONCEPTRONIC, RT3070_1),
1599cdb1c70Snonaka USB_ID(CONCEPTRONIC, RT3070_2),
1609cdb1c70Snonaka USB_ID(CONCEPTRONIC, RT3070_3),
1619cdb1c70Snonaka USB_ID(COREGA, CGWLUSB300GNM),
1629cdb1c70Snonaka USB_ID(COREGA, RT2870_1),
1639cdb1c70Snonaka USB_ID(COREGA, RT2870_2),
1649cdb1c70Snonaka USB_ID(COREGA, RT2870_3),
1659cdb1c70Snonaka USB_ID(COREGA, RT3070),
1669cdb1c70Snonaka USB_ID(CYBERTAN, RT2870),
1679cdb1c70Snonaka USB_ID(DLINK, RT2870),
1689cdb1c70Snonaka USB_ID(DLINK, RT3072),
169d164e220Smlelstv USB_ID(DLINK, DWA127),
170d164e220Smlelstv USB_ID(DLINK, DWA140B3),
171d164e220Smlelstv USB_ID(DLINK, DWA160B2),
172d164e220Smlelstv USB_ID(DLINK, DWA162),
1739cdb1c70Snonaka USB_ID(DLINK2, DWA130),
1749cdb1c70Snonaka USB_ID(DLINK2, RT2870_1),
1759cdb1c70Snonaka USB_ID(DLINK2, RT2870_2),
1769cdb1c70Snonaka USB_ID(DLINK2, RT3070_1),
1779cdb1c70Snonaka USB_ID(DLINK2, RT3070_2),
1789cdb1c70Snonaka USB_ID(DLINK2, RT3070_3),
1799cdb1c70Snonaka USB_ID(DLINK2, RT3070_4),
1809cdb1c70Snonaka USB_ID(DLINK2, RT3070_5),
1819cdb1c70Snonaka USB_ID(DLINK2, RT3072),
1829cdb1c70Snonaka USB_ID(DLINK2, RT3072_1),
1839cdb1c70Snonaka USB_ID(DVICO, RT3070),
1849cdb1c70Snonaka USB_ID(EDIMAX, EW7717),
1859cdb1c70Snonaka USB_ID(EDIMAX, EW7718),
1869cdb1c70Snonaka USB_ID(EDIMAX, EW7722UTN),
1879cdb1c70Snonaka USB_ID(EDIMAX, RT2870_1),
1889cdb1c70Snonaka USB_ID(ENCORE, RT3070),
1899cdb1c70Snonaka USB_ID(ENCORE, RT3070_2),
1909cdb1c70Snonaka USB_ID(ENCORE, RT3070_3),
1919cdb1c70Snonaka USB_ID(GIGABYTE, GNWB31N),
1929cdb1c70Snonaka USB_ID(GIGABYTE, GNWB32L),
1939cdb1c70Snonaka USB_ID(GIGABYTE, RT2870_1),
1949cdb1c70Snonaka USB_ID(GIGASET, RT3070_1),
1959cdb1c70Snonaka USB_ID(GIGASET, RT3070_2),
1969cdb1c70Snonaka USB_ID(GUILLEMOT, HWNU300),
1979cdb1c70Snonaka USB_ID(HAWKING, HWUN2),
1989cdb1c70Snonaka USB_ID(HAWKING, RT2870_1),
1999cdb1c70Snonaka USB_ID(HAWKING, RT2870_2),
2009cdb1c70Snonaka USB_ID(HAWKING, RT2870_3),
2019cdb1c70Snonaka USB_ID(HAWKING, RT2870_4),
2029cdb1c70Snonaka USB_ID(HAWKING, RT2870_5),
2039cdb1c70Snonaka USB_ID(HAWKING, RT3070),
2049cdb1c70Snonaka USB_ID(IODATA, RT3072_1),
2059cdb1c70Snonaka USB_ID(IODATA, RT3072_2),
2069cdb1c70Snonaka USB_ID(IODATA, RT3072_3),
2079cdb1c70Snonaka USB_ID(IODATA, RT3072_4),
2089cdb1c70Snonaka USB_ID(LINKSYS4, RT3070),
2099cdb1c70Snonaka USB_ID(LINKSYS4, WUSB100),
2109cdb1c70Snonaka USB_ID(LINKSYS4, WUSB54GC_3),
2119cdb1c70Snonaka USB_ID(LINKSYS4, WUSB600N),
2129cdb1c70Snonaka USB_ID(LINKSYS4, WUSB600NV2),
2139cdb1c70Snonaka USB_ID(LOGITEC, LANW300NU2),
214d164e220Smlelstv USB_ID(LOGITEC, LANW300NU2S),
215d164e220Smlelstv USB_ID(LOGITEC, LAN_W300ANU2),
216d164e220Smlelstv USB_ID(LOGITEC, LAN_W450ANU2E),
2179cdb1c70Snonaka USB_ID(LOGITEC, RT2870_1),
2189cdb1c70Snonaka USB_ID(LOGITEC, RT2870_2),
2199cdb1c70Snonaka USB_ID(LOGITEC, RT2870_3),
2209cdb1c70Snonaka USB_ID(LOGITEC, RT3020),
2219cdb1c70Snonaka USB_ID(MELCO, RT2870_1),
2229cdb1c70Snonaka USB_ID(MELCO, RT2870_2),
2239cdb1c70Snonaka USB_ID(MELCO, WLIUCAG300N),
2249cdb1c70Snonaka USB_ID(MELCO, WLIUCG300N),
2259cdb1c70Snonaka USB_ID(MELCO, WLIUCG301N),
2269cdb1c70Snonaka USB_ID(MELCO, WLIUCGN),
2279cdb1c70Snonaka USB_ID(MELCO, WLIUCGNHP),
2289cdb1c70Snonaka USB_ID(MELCO, WLIUCGNM),
2299cdb1c70Snonaka USB_ID(MELCO, WLIUCGNM2T),
2309cdb1c70Snonaka USB_ID(MOTOROLA4, RT2770),
2319cdb1c70Snonaka USB_ID(MOTOROLA4, RT3070),
2329cdb1c70Snonaka USB_ID(MSI, RT3070),
2339cdb1c70Snonaka USB_ID(MSI, RT3070_2),
2349cdb1c70Snonaka USB_ID(MSI, RT3070_3),
2359cdb1c70Snonaka USB_ID(MSI, RT3070_4),
2369cdb1c70Snonaka USB_ID(MSI, RT3070_5),
2379cdb1c70Snonaka USB_ID(MSI, RT3070_6),
2389cdb1c70Snonaka USB_ID(MSI, RT3070_7),
2399cdb1c70Snonaka USB_ID(MSI, RT3070_8),
2409cdb1c70Snonaka USB_ID(MSI, RT3070_9),
2419cdb1c70Snonaka USB_ID(MSI, RT3070_10),
2429cdb1c70Snonaka USB_ID(MSI, RT3070_11),
2439cdb1c70Snonaka USB_ID(MSI, RT3070_12),
2449cdb1c70Snonaka USB_ID(MSI, RT3070_13),
2459cdb1c70Snonaka USB_ID(MSI, RT3070_14),
2469cdb1c70Snonaka USB_ID(MSI, RT3070_15),
2479cdb1c70Snonaka USB_ID(OVISLINK, RT3071),
2489cdb1c70Snonaka USB_ID(OVISLINK, RT3072),
2499cdb1c70Snonaka USB_ID(PARA, RT3070),
2509cdb1c70Snonaka USB_ID(PEGATRON, RT2870),
2519cdb1c70Snonaka USB_ID(PEGATRON, RT3070),
2529cdb1c70Snonaka USB_ID(PEGATRON, RT3070_2),
2539cdb1c70Snonaka USB_ID(PEGATRON, RT3070_3),
2549cdb1c70Snonaka USB_ID(PEGATRON, RT3072),
2559cdb1c70Snonaka USB_ID(PHILIPS, RT2870),
2569cdb1c70Snonaka USB_ID(PLANEX2, GWUS300MINIS),
2579cdb1c70Snonaka USB_ID(PLANEX2, GWUSMICRO300),
2589cdb1c70Snonaka USB_ID(PLANEX2, GWUSMICRON),
2599cdb1c70Snonaka USB_ID(PLANEX2, GWUS300MINIX),
2609cdb1c70Snonaka USB_ID(PLANEX2, RT3070),
2619cdb1c70Snonaka USB_ID(QCOM, RT2870),
2629cdb1c70Snonaka USB_ID(QUANTA, RT3070),
2639cdb1c70Snonaka USB_ID(RALINK, RT2070),
2649cdb1c70Snonaka USB_ID(RALINK, RT2770),
2659cdb1c70Snonaka USB_ID(RALINK, RT2870),
2669cdb1c70Snonaka USB_ID(RALINK, RT3070),
2679cdb1c70Snonaka USB_ID(RALINK, RT3071),
2689cdb1c70Snonaka USB_ID(RALINK, RT3072),
2699cdb1c70Snonaka USB_ID(RALINK, RT3370),
2709cdb1c70Snonaka USB_ID(RALINK, RT3572),
271d164e220Smlelstv USB_ID(RALINK, RT3573),
2722c1adfbeShauke USB_ID(RALINK, RT5370),
273faca41fbSmlelstv USB_ID(RALINK, RT5572),
2749cdb1c70Snonaka USB_ID(RALINK, RT8070),
2759cdb1c70Snonaka USB_ID(SAMSUNG, RT2870_1),
2769cdb1c70Snonaka USB_ID(SENAO, RT2870_1),
2779cdb1c70Snonaka USB_ID(SENAO, RT2870_2),
2789cdb1c70Snonaka USB_ID(SENAO, RT2870_3),
2799cdb1c70Snonaka USB_ID(SENAO, RT2870_4),
2809cdb1c70Snonaka USB_ID(SENAO, RT3070),
2819cdb1c70Snonaka USB_ID(SENAO, RT3071),
2829cdb1c70Snonaka USB_ID(SENAO, RT3072),
2839cdb1c70Snonaka USB_ID(SENAO, RT3072_2),
2849cdb1c70Snonaka USB_ID(SENAO, RT3072_3),
2859cdb1c70Snonaka USB_ID(SENAO, RT3072_4),
2869cdb1c70Snonaka USB_ID(SENAO, RT3072_5),
2879cdb1c70Snonaka USB_ID(SITECOMEU, RT2870_1),
2889cdb1c70Snonaka USB_ID(SITECOMEU, RT2870_2),
2899cdb1c70Snonaka USB_ID(SITECOMEU, RT2870_3),
2909cdb1c70Snonaka USB_ID(SITECOMEU, RT3070_1),
291d164e220Smlelstv USB_ID(SITECOMEU, RT3070_3),
2929cdb1c70Snonaka USB_ID(SITECOMEU, RT3072_3),
2939cdb1c70Snonaka USB_ID(SITECOMEU, RT3072_4),
2949cdb1c70Snonaka USB_ID(SITECOMEU, RT3072_5),
295d164e220Smlelstv USB_ID(SITECOMEU, RT3072_6),
2969cdb1c70Snonaka USB_ID(SITECOMEU, WL302),
2979cdb1c70Snonaka USB_ID(SITECOMEU, WL315),
2989cdb1c70Snonaka USB_ID(SITECOMEU, WL321),
2999cdb1c70Snonaka USB_ID(SITECOMEU, WL324),
3009cdb1c70Snonaka USB_ID(SITECOMEU, WL329),
3019cdb1c70Snonaka USB_ID(SITECOMEU, WL343),
3029cdb1c70Snonaka USB_ID(SITECOMEU, WL344),
3039cdb1c70Snonaka USB_ID(SITECOMEU, WL345),
3049cdb1c70Snonaka USB_ID(SITECOMEU, WL349V4),
3059cdb1c70Snonaka USB_ID(SITECOMEU, WL608),
3069cdb1c70Snonaka USB_ID(SITECOMEU, WLA4000),
3079cdb1c70Snonaka USB_ID(SITECOMEU, WLA5000),
3089cdb1c70Snonaka USB_ID(SPARKLAN, RT2870_1),
3099cdb1c70Snonaka USB_ID(SPARKLAN, RT2870_2),
3109cdb1c70Snonaka USB_ID(SPARKLAN, RT3070),
3119cdb1c70Snonaka USB_ID(SWEEX2, LW153),
3129cdb1c70Snonaka USB_ID(SWEEX2, LW303),
3139cdb1c70Snonaka USB_ID(SWEEX2, LW313),
3149cdb1c70Snonaka USB_ID(TOSHIBA, RT3070),
3159cdb1c70Snonaka USB_ID(UMEDIA, RT2870_1),
3169cdb1c70Snonaka USB_ID(UMEDIA, TEW645UB),
3179cdb1c70Snonaka USB_ID(ZCOM, RT2870_1),
3189cdb1c70Snonaka USB_ID(ZCOM, RT2870_2),
3199cdb1c70Snonaka USB_ID(ZINWELL, RT2870_1),
3209cdb1c70Snonaka USB_ID(ZINWELL, RT2870_2),
3219cdb1c70Snonaka USB_ID(ZINWELL, RT3070),
3229cdb1c70Snonaka USB_ID(ZINWELL, RT3072),
3239cdb1c70Snonaka USB_ID(ZINWELL, RT3072_2),
3249cdb1c70Snonaka USB_ID(ZYXEL, NWD2105),
3259cdb1c70Snonaka USB_ID(ZYXEL, NWD211AN),
3269cdb1c70Snonaka USB_ID(ZYXEL, RT2870_1),
3279cdb1c70Snonaka USB_ID(ZYXEL, RT2870_2),
3289cdb1c70Snonaka USB_ID(ZYXEL, RT3070),
3299cdb1c70Snonaka };
3309cdb1c70Snonaka
3319cdb1c70Snonaka static int run_match(device_t, cfdata_t, void *);
3329cdb1c70Snonaka static void run_attach(device_t, device_t, void *);
3339cdb1c70Snonaka static int run_detach(device_t, int);
3349cdb1c70Snonaka static int run_activate(device_t, enum devact);
3359cdb1c70Snonaka
3369cdb1c70Snonaka CFATTACH_DECL_NEW(run, sizeof(struct run_softc),
3379cdb1c70Snonaka run_match, run_attach, run_detach, run_activate);
3389cdb1c70Snonaka
3399cdb1c70Snonaka static int run_alloc_rx_ring(struct run_softc *);
3409cdb1c70Snonaka static void run_free_rx_ring(struct run_softc *);
3419cdb1c70Snonaka static int run_alloc_tx_ring(struct run_softc *, int);
3429cdb1c70Snonaka static void run_free_tx_ring(struct run_softc *, int);
3439cdb1c70Snonaka static int run_load_microcode(struct run_softc *);
3449cdb1c70Snonaka static int run_reset(struct run_softc *);
3459cdb1c70Snonaka static int run_read(struct run_softc *, uint16_t, uint32_t *);
3469cdb1c70Snonaka static int run_read_region_1(struct run_softc *, uint16_t,
3479cdb1c70Snonaka uint8_t *, int);
3489cdb1c70Snonaka static int run_write_2(struct run_softc *, uint16_t, uint16_t);
3499cdb1c70Snonaka static int run_write(struct run_softc *, uint16_t, uint32_t);
3509cdb1c70Snonaka static int run_write_region_1(struct run_softc *, uint16_t,
3519cdb1c70Snonaka const uint8_t *, int);
3529cdb1c70Snonaka static int run_set_region_4(struct run_softc *, uint16_t,
3539cdb1c70Snonaka uint32_t, int);
354faca41fbSmlelstv static int run_efuse_read(struct run_softc *, uint16_t,
355faca41fbSmlelstv uint16_t *, int);
3569cdb1c70Snonaka static int run_efuse_read_2(struct run_softc *, uint16_t,
3579cdb1c70Snonaka uint16_t *);
3589cdb1c70Snonaka static int run_eeprom_read_2(struct run_softc *, uint16_t,
3599cdb1c70Snonaka uint16_t *);
3609cdb1c70Snonaka static int run_rt2870_rf_write(struct run_softc *, uint8_t,
3619cdb1c70Snonaka uint32_t);
3629cdb1c70Snonaka static int run_rt3070_rf_read(struct run_softc *, uint8_t,
3639cdb1c70Snonaka uint8_t *);
3649cdb1c70Snonaka static int run_rt3070_rf_write(struct run_softc *, uint8_t,
3659cdb1c70Snonaka uint8_t);
3669cdb1c70Snonaka static int run_bbp_read(struct run_softc *, uint8_t, uint8_t *);
3679cdb1c70Snonaka static int run_bbp_write(struct run_softc *, uint8_t, uint8_t);
3689cdb1c70Snonaka static int run_mcu_cmd(struct run_softc *, uint8_t, uint16_t);
369d164e220Smlelstv static const char * run_get_rf(uint16_t);
370faca41fbSmlelstv static void run_rt3593_get_txpower(struct run_softc *);
371faca41fbSmlelstv static void run_get_txpower(struct run_softc *);
3729cdb1c70Snonaka static int run_read_eeprom(struct run_softc *);
3739cdb1c70Snonaka static struct ieee80211_node *
3749cdb1c70Snonaka run_node_alloc(struct ieee80211_node_table *);
3759cdb1c70Snonaka static int run_media_change(struct ifnet *);
3769cdb1c70Snonaka static void run_next_scan(void *);
3779cdb1c70Snonaka static void run_task(void *);
3789cdb1c70Snonaka static void run_do_async(struct run_softc *,
3799cdb1c70Snonaka void (*)(struct run_softc *, void *), void *, int);
3809cdb1c70Snonaka static int run_newstate(struct ieee80211com *,
3819cdb1c70Snonaka enum ieee80211_state, int);
3829cdb1c70Snonaka static void run_newstate_cb(struct run_softc *, void *);
3839cdb1c70Snonaka static int run_updateedca(struct ieee80211com *);
3849cdb1c70Snonaka static void run_updateedca_cb(struct run_softc *, void *);
3859cdb1c70Snonaka #ifdef RUN_HWCRYPTO
3869cdb1c70Snonaka static int run_set_key(struct ieee80211com *,
3879cdb1c70Snonaka const struct ieee80211_key *, const uint8_t *);
3889cdb1c70Snonaka static void run_set_key_cb(struct run_softc *, void *);
3899cdb1c70Snonaka static int run_delete_key(struct ieee80211com *,
3909cdb1c70Snonaka const struct ieee80211_key *);
3919cdb1c70Snonaka static void run_delete_key_cb(struct run_softc *, void *);
3929cdb1c70Snonaka #endif
3939cdb1c70Snonaka static void run_calibrate_to(void *);
3949cdb1c70Snonaka static void run_calibrate_cb(struct run_softc *, void *);
3959cdb1c70Snonaka static void run_newassoc(struct ieee80211_node *, int);
3969cdb1c70Snonaka static void run_rx_frame(struct run_softc *, uint8_t *, int);
3974e8e6643Sskrll static void run_rxeof(struct usbd_xfer *, void *,
3989cdb1c70Snonaka usbd_status);
3994e8e6643Sskrll static void run_txeof(struct usbd_xfer *, void *,
4009cdb1c70Snonaka usbd_status);
4019cdb1c70Snonaka static int run_tx(struct run_softc *, struct mbuf *,
4029cdb1c70Snonaka struct ieee80211_node *);
4039cdb1c70Snonaka static void run_start(struct ifnet *);
4049cdb1c70Snonaka static void run_watchdog(struct ifnet *);
4059cdb1c70Snonaka static int run_ioctl(struct ifnet *, u_long, void *);
4069cdb1c70Snonaka static void run_select_chan_group(struct run_softc *, int);
407faca41fbSmlelstv static void run_iq_calib(struct run_softc *, u_int);
4089cdb1c70Snonaka static void run_set_agc(struct run_softc *, uint8_t);
4099cdb1c70Snonaka static void run_set_rx_antenna(struct run_softc *, int);
4109cdb1c70Snonaka static void run_rt2870_set_chan(struct run_softc *, u_int);
4119cdb1c70Snonaka static void run_rt3070_set_chan(struct run_softc *, u_int);
4129cdb1c70Snonaka static void run_rt3572_set_chan(struct run_softc *, u_int);
413faca41fbSmlelstv static void run_rt3593_set_chan(struct run_softc *, u_int);
414faca41fbSmlelstv static void run_rt5390_set_chan(struct run_softc *, u_int);
415faca41fbSmlelstv static void run_rt5592_set_chan(struct run_softc *, u_int);
4169cdb1c70Snonaka static int run_set_chan(struct run_softc *,
4179cdb1c70Snonaka struct ieee80211_channel *);
418faca41fbSmlelstv static void run_updateprot(struct run_softc *);
4199cdb1c70Snonaka static void run_enable_tsf_sync(struct run_softc *);
4209cdb1c70Snonaka static void run_enable_mrr(struct run_softc *);
4219cdb1c70Snonaka static void run_set_txpreamble(struct run_softc *);
4229cdb1c70Snonaka static void run_set_basicrates(struct run_softc *);
4239cdb1c70Snonaka static void run_set_leds(struct run_softc *, uint16_t);
4249cdb1c70Snonaka static void run_set_bssid(struct run_softc *, const uint8_t *);
4259cdb1c70Snonaka static void run_set_macaddr(struct run_softc *, const uint8_t *);
4269cdb1c70Snonaka static void run_updateslot(struct ifnet *);
4279cdb1c70Snonaka static void run_updateslot_cb(struct run_softc *, void *);
4289cdb1c70Snonaka static int8_t run_rssi2dbm(struct run_softc *, uint8_t, uint8_t);
429faca41fbSmlelstv static void run_rt5390_bbp_init(struct run_softc *);
4309cdb1c70Snonaka static int run_bbp_init(struct run_softc *);
4319cdb1c70Snonaka static int run_rt3070_rf_init(struct run_softc *);
432faca41fbSmlelstv static int run_rt3593_rf_init(struct run_softc *);
433faca41fbSmlelstv static int run_rt5390_rf_init(struct run_softc *);
4349cdb1c70Snonaka static int run_rt3070_filter_calib(struct run_softc *, uint8_t,
4359cdb1c70Snonaka uint8_t, uint8_t *);
4369cdb1c70Snonaka static void run_rt3070_rf_setup(struct run_softc *);
437faca41fbSmlelstv static void run_rt3593_rf_setup(struct run_softc *);
438faca41fbSmlelstv static void run_rt5390_rf_setup(struct run_softc *);
4399cdb1c70Snonaka static int run_txrx_enable(struct run_softc *);
440faca41fbSmlelstv static int run_adjust_freq_offset(struct run_softc *);
4419cdb1c70Snonaka static int run_init(struct ifnet *);
4429cdb1c70Snonaka static void run_stop(struct ifnet *, int);
4439cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY
4449cdb1c70Snonaka static int run_setup_beacon(struct run_softc *);
4459cdb1c70Snonaka #endif
4469cdb1c70Snonaka
4479cdb1c70Snonaka static const struct {
4489cdb1c70Snonaka uint32_t reg;
4499cdb1c70Snonaka uint32_t val;
4509cdb1c70Snonaka } rt2870_def_mac[] = {
4519cdb1c70Snonaka RT2870_DEF_MAC
4529cdb1c70Snonaka };
4539cdb1c70Snonaka
4549cdb1c70Snonaka static const struct {
4559cdb1c70Snonaka uint8_t reg;
4569cdb1c70Snonaka uint8_t val;
4579cdb1c70Snonaka } rt2860_def_bbp[] = {
4589cdb1c70Snonaka RT2860_DEF_BBP
459faca41fbSmlelstv }, rt5390_def_bbp[] = {
460faca41fbSmlelstv RT5390_DEF_BBP
461faca41fbSmlelstv }, rt5592_def_bbp[] = {
462faca41fbSmlelstv RT5592_DEF_BBP
463faca41fbSmlelstv };
464faca41fbSmlelstv
465faca41fbSmlelstv /*
466faca41fbSmlelstv * Default values for BBP register R196 for RT5592.
467faca41fbSmlelstv */
468faca41fbSmlelstv static const uint8_t rt5592_bbp_r196[] = {
469faca41fbSmlelstv 0xe0, 0x1f, 0x38, 0x32, 0x08, 0x28, 0x19, 0x0a, 0xff, 0x00,
470faca41fbSmlelstv 0x16, 0x10, 0x10, 0x0b, 0x36, 0x2c, 0x26, 0x24, 0x42, 0x36,
471faca41fbSmlelstv 0x30, 0x2d, 0x4c, 0x46, 0x3d, 0x40, 0x3e, 0x42, 0x3d, 0x40,
472faca41fbSmlelstv 0x3c, 0x34, 0x2c, 0x2f, 0x3c, 0x35, 0x2e, 0x2a, 0x49, 0x41,
473faca41fbSmlelstv 0x36, 0x31, 0x30, 0x30, 0x0e, 0x0d, 0x28, 0x21, 0x1c, 0x16,
474faca41fbSmlelstv 0x50, 0x4a, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
475faca41fbSmlelstv 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
476faca41fbSmlelstv 0x00, 0x00, 0x7d, 0x14, 0x32, 0x2c, 0x36, 0x4c, 0x43, 0x2c,
477faca41fbSmlelstv 0x2e, 0x36, 0x30, 0x6e
4789cdb1c70Snonaka };
4799cdb1c70Snonaka
4809cdb1c70Snonaka static const struct rfprog {
4819cdb1c70Snonaka uint8_t chan;
4829cdb1c70Snonaka uint32_t r1, r2, r3, r4;
4839cdb1c70Snonaka } rt2860_rf2850[] = {
4849cdb1c70Snonaka RT2860_RF2850
4859cdb1c70Snonaka };
4869cdb1c70Snonaka
4879cdb1c70Snonaka static const struct {
4889cdb1c70Snonaka uint8_t n, r, k;
4899cdb1c70Snonaka } rt3070_freqs[] = {
4909cdb1c70Snonaka RT3070_RF3052
4919cdb1c70Snonaka };
4929cdb1c70Snonaka
493faca41fbSmlelstv static const struct rt5592_freqs {
494faca41fbSmlelstv uint16_t n;
495faca41fbSmlelstv uint8_t k, m, r;
496faca41fbSmlelstv } rt5592_freqs_20mhz[] = {
497faca41fbSmlelstv RT5592_RF5592_20MHZ
498faca41fbSmlelstv },rt5592_freqs_40mhz[] = {
499faca41fbSmlelstv RT5592_RF5592_40MHZ
500faca41fbSmlelstv };
501faca41fbSmlelstv
5029cdb1c70Snonaka static const struct {
5039cdb1c70Snonaka uint8_t reg;
5049cdb1c70Snonaka uint8_t val;
5059cdb1c70Snonaka } rt3070_def_rf[] = {
5069cdb1c70Snonaka RT3070_DEF_RF
5079cdb1c70Snonaka }, rt3572_def_rf[] = {
5089cdb1c70Snonaka RT3572_DEF_RF
509faca41fbSmlelstv },rt3593_def_rf[] = {
510faca41fbSmlelstv RT3593_DEF_RF
511faca41fbSmlelstv },rt5390_def_rf[] = {
512faca41fbSmlelstv RT5390_DEF_RF
513faca41fbSmlelstv },rt5392_def_rf[] = {
514faca41fbSmlelstv RT5392_DEF_RF
515faca41fbSmlelstv },rt5592_def_rf[] = {
516faca41fbSmlelstv RT5592_DEF_RF
517faca41fbSmlelstv },rt5592_2ghz_def_rf[] = {
518faca41fbSmlelstv RT5592_2GHZ_DEF_RF
519faca41fbSmlelstv },rt5592_5ghz_def_rf[] = {
520faca41fbSmlelstv RT5592_5GHZ_DEF_RF
521faca41fbSmlelstv };
522faca41fbSmlelstv
523faca41fbSmlelstv static const struct {
524faca41fbSmlelstv u_int firstchan;
525faca41fbSmlelstv u_int lastchan;
526faca41fbSmlelstv uint8_t reg;
527faca41fbSmlelstv uint8_t val;
528faca41fbSmlelstv } rt5592_chan_5ghz[] = {
529faca41fbSmlelstv RT5592_CHAN_5GHZ
5309cdb1c70Snonaka };
5319cdb1c70Snonaka
5329cdb1c70Snonaka static int
firmware_load(const char * dname,const char * iname,uint8_t ** ucodep,size_t * sizep)5339cdb1c70Snonaka firmware_load(const char *dname, const char *iname, uint8_t **ucodep,
5349cdb1c70Snonaka size_t *sizep)
5359cdb1c70Snonaka {
5369cdb1c70Snonaka firmware_handle_t fh;
5379cdb1c70Snonaka int error;
5389cdb1c70Snonaka
5399cdb1c70Snonaka if ((error = firmware_open(dname, iname, &fh)) != 0)
5404e8e6643Sskrll return error;
5419cdb1c70Snonaka *sizep = firmware_get_size(fh);
5429cdb1c70Snonaka if ((*ucodep = firmware_malloc(*sizep)) == NULL) {
5439cdb1c70Snonaka firmware_close(fh);
5444e8e6643Sskrll return ENOMEM;
5459cdb1c70Snonaka }
5469cdb1c70Snonaka if ((error = firmware_read(fh, 0, *ucodep, *sizep)) != 0)
5479cdb1c70Snonaka firmware_free(*ucodep, *sizep);
5489cdb1c70Snonaka firmware_close(fh);
5499cdb1c70Snonaka
5504e8e6643Sskrll return error;
5519cdb1c70Snonaka }
5529cdb1c70Snonaka
5539cdb1c70Snonaka static int
run_match(device_t parent,cfdata_t match,void * aux)5549cdb1c70Snonaka run_match(device_t parent, cfdata_t match, void *aux)
5559cdb1c70Snonaka {
5569cdb1c70Snonaka struct usb_attach_arg *uaa = aux;
5579cdb1c70Snonaka
5584e8e6643Sskrll return (usb_lookup(run_devs, uaa->uaa_vendor, uaa->uaa_product) != NULL) ?
5599cdb1c70Snonaka UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
5609cdb1c70Snonaka }
5619cdb1c70Snonaka
5629cdb1c70Snonaka static void
run_attach(device_t parent,device_t self,void * aux)5639cdb1c70Snonaka run_attach(device_t parent, device_t self, void *aux)
5649cdb1c70Snonaka {
5659cdb1c70Snonaka struct run_softc *sc = device_private(self);
5669cdb1c70Snonaka struct usb_attach_arg *uaa = aux;
5679cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
5689cdb1c70Snonaka struct ifnet *ifp = &sc->sc_if;
5699cdb1c70Snonaka usb_interface_descriptor_t *id;
5709cdb1c70Snonaka usb_endpoint_descriptor_t *ed;
5719cdb1c70Snonaka char *devinfop;
5729cdb1c70Snonaka int i, nrx, ntx, ntries, error;
5739cdb1c70Snonaka uint32_t ver;
5749cdb1c70Snonaka
5759cdb1c70Snonaka aprint_naive("\n");
5769cdb1c70Snonaka aprint_normal("\n");
5779cdb1c70Snonaka
5789cdb1c70Snonaka sc->sc_dev = self;
5794e8e6643Sskrll sc->sc_udev = uaa->uaa_device;
5809cdb1c70Snonaka
5819cdb1c70Snonaka devinfop = usbd_devinfo_alloc(sc->sc_udev, 0);
5829cdb1c70Snonaka aprint_normal_dev(sc->sc_dev, "%s\n", devinfop);
5839cdb1c70Snonaka usbd_devinfo_free(devinfop);
5849cdb1c70Snonaka
585897388eaSskrll error = usbd_set_config_no(sc->sc_udev, 1, 0);
586897388eaSskrll if (error != 0) {
587897388eaSskrll aprint_error_dev(sc->sc_dev, "failed to set configuration"
588897388eaSskrll ", err=%s\n", usbd_errstr(error));
5899cdb1c70Snonaka return;
5909cdb1c70Snonaka }
5919cdb1c70Snonaka
5929cdb1c70Snonaka /* get the first interface handle */
5939cdb1c70Snonaka error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
5949cdb1c70Snonaka if (error != 0) {
5959cdb1c70Snonaka aprint_error_dev(sc->sc_dev,
5969cdb1c70Snonaka "could not get interface handle\n");
5979cdb1c70Snonaka return;
5989cdb1c70Snonaka }
5999cdb1c70Snonaka
6009cdb1c70Snonaka /*
6019cdb1c70Snonaka * Find all bulk endpoints. There are 7 bulk endpoints: 1 for RX
6029cdb1c70Snonaka * and 6 for TX (4 EDCAs + HCCA + Prio).
6039cdb1c70Snonaka * Update 03-14-2009: some devices like the Planex GW-US300MiniS
6049cdb1c70Snonaka * seem to have only 4 TX bulk endpoints (Fukaumi Naoki).
6059cdb1c70Snonaka */
6069cdb1c70Snonaka nrx = ntx = 0;
6079cdb1c70Snonaka id = usbd_get_interface_descriptor(sc->sc_iface);
6089cdb1c70Snonaka for (i = 0; i < id->bNumEndpoints; i++) {
6099cdb1c70Snonaka ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
6109cdb1c70Snonaka if (ed == NULL || UE_GET_XFERTYPE(ed->bmAttributes) != UE_BULK)
6119cdb1c70Snonaka continue;
6129cdb1c70Snonaka
6139cdb1c70Snonaka if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
6149cdb1c70Snonaka sc->rxq.pipe_no = ed->bEndpointAddress;
6159cdb1c70Snonaka nrx++;
616d42627d4Sskrll } else if (ntx < RUN_MAXEPOUT) {
6179cdb1c70Snonaka sc->txq[ntx].pipe_no = ed->bEndpointAddress;
6189cdb1c70Snonaka ntx++;
6199cdb1c70Snonaka }
6209cdb1c70Snonaka }
6219cdb1c70Snonaka /* make sure we've got them all */
622d42627d4Sskrll if (nrx < 1 || ntx < RUN_MAXEPOUT) {
6239cdb1c70Snonaka aprint_error_dev(sc->sc_dev, "missing endpoint\n");
6249cdb1c70Snonaka return;
6259cdb1c70Snonaka }
6269cdb1c70Snonaka
6277c64a30eSjmcneill usb_init_task(&sc->sc_task, run_task, sc, 0);
6289cdb1c70Snonaka callout_init(&sc->scan_to, 0);
6299cdb1c70Snonaka callout_setfunc(&sc->scan_to, run_next_scan, sc);
6309cdb1c70Snonaka callout_init(&sc->calib_to, 0);
6319cdb1c70Snonaka callout_setfunc(&sc->calib_to, run_calibrate_to, sc);
6329cdb1c70Snonaka
6339cdb1c70Snonaka sc->amrr.amrr_min_success_threshold = 1;
6349cdb1c70Snonaka sc->amrr.amrr_max_success_threshold = 10;
6359cdb1c70Snonaka
6369cdb1c70Snonaka /* wait for the chip to settle */
6379cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) {
6389cdb1c70Snonaka if (run_read(sc, RT2860_ASIC_VER_ID, &ver) != 0)
6399cdb1c70Snonaka return;
6409cdb1c70Snonaka if (ver != 0 && ver != 0xffffffff)
6419cdb1c70Snonaka break;
6429cdb1c70Snonaka DELAY(10);
6439cdb1c70Snonaka }
6449cdb1c70Snonaka if (ntries == 100) {
6459cdb1c70Snonaka aprint_error_dev(sc->sc_dev,
6469cdb1c70Snonaka "timeout waiting for NIC to initialize\n");
6479cdb1c70Snonaka return;
6489cdb1c70Snonaka }
6499cdb1c70Snonaka sc->mac_ver = ver >> 16;
6509cdb1c70Snonaka sc->mac_rev = ver & 0xffff;
6519cdb1c70Snonaka
652c2d905cbSgson /*
653c2d905cbSgson * Per the comment in run_write_region_1(), "the WRITE_REGION_1
654c2d905cbSgson * command is not stable on RT2860", but WRITE_REGION_1 calls
655c2d905cbSgson * of up to 64 bytes have been tested and found to work with
656c2d905cbSgson * mac_ver 0x5390, and they reduce the run time of "ifconfig
657c2d905cbSgson * run0 up" from 30 seconds to a couple of seconds on OHCI.
658c2d905cbSgson * Enable WRITE_REGION_1 for the tested version only. As other
659c2d905cbSgson * versions are tested and found to work, they can be added
660c2d905cbSgson * here.
661c2d905cbSgson */
662c2d905cbSgson if (sc->mac_ver == 0x5390)
663c2d905cbSgson sc->sc_flags |= RUN_USE_BLOCK_WRITE;
664c2d905cbSgson
6659cdb1c70Snonaka /* retrieve RF rev. no and various other things from EEPROM */
6669cdb1c70Snonaka run_read_eeprom(sc);
6679cdb1c70Snonaka
6681d5cb2a3Sjakllsch aprint_verbose_dev(sc->sc_dev,
669aa3d6ec1Schristos "MAC/BBP RT%04X (rev 0x%04X), RF %s (MIMO %dT%dR), address %s\n",
6709cdb1c70Snonaka sc->mac_ver, sc->mac_rev, run_get_rf(sc->rf_rev), sc->ntxchains,
6719cdb1c70Snonaka sc->nrxchains, ether_sprintf(ic->ic_myaddr));
6729cdb1c70Snonaka
6739cdb1c70Snonaka ic->ic_ifp = ifp;
6749cdb1c70Snonaka ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
6759cdb1c70Snonaka ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
6769cdb1c70Snonaka ic->ic_state = IEEE80211_S_INIT;
6779cdb1c70Snonaka
6789cdb1c70Snonaka /* set device capabilities */
6799cdb1c70Snonaka ic->ic_caps =
6809cdb1c70Snonaka IEEE80211_C_MONITOR | /* monitor mode supported */
6819cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY
6829cdb1c70Snonaka IEEE80211_C_IBSS | /* IBSS mode supported */
6839cdb1c70Snonaka IEEE80211_C_HOSTAP | /* HostAP mode supported */
6849cdb1c70Snonaka #endif
6859cdb1c70Snonaka IEEE80211_C_SHPREAMBLE | /* short preamble supported */
6869cdb1c70Snonaka IEEE80211_C_SHSLOT | /* short slot time supported */
6879cdb1c70Snonaka #ifdef RUN_HWCRYPTO
6889cdb1c70Snonaka IEEE80211_C_WEP | /* WEP */
6899cdb1c70Snonaka IEEE80211_C_TKIP | /* TKIP */
6909cdb1c70Snonaka IEEE80211_C_AES_CCM | /* AES CCMP */
6919cdb1c70Snonaka IEEE80211_C_TKIPMIC | /* TKIPMIC */
6929cdb1c70Snonaka #endif
6939cdb1c70Snonaka IEEE80211_C_WME | /* WME */
6949cdb1c70Snonaka IEEE80211_C_WPA; /* WPA/RSN */
6959cdb1c70Snonaka
6969cdb1c70Snonaka if (sc->rf_rev == RT2860_RF_2750 ||
6979cdb1c70Snonaka sc->rf_rev == RT2860_RF_2850 ||
698faca41fbSmlelstv sc->rf_rev == RT3070_RF_3052 ||
699faca41fbSmlelstv sc->rf_rev == RT3070_RF_3053 ||
700faca41fbSmlelstv sc->rf_rev == RT5592_RF_5592) {
7019cdb1c70Snonaka /* set supported .11a rates */
7029cdb1c70Snonaka ic->ic_sup_rates[IEEE80211_MODE_11A] =
7039cdb1c70Snonaka ieee80211_std_rateset_11a;
7049cdb1c70Snonaka
7059cdb1c70Snonaka /* set supported .11a channels */
7069cdb1c70Snonaka for (i = 14; i < (int)__arraycount(rt2860_rf2850); i++) {
7079cdb1c70Snonaka uint8_t chan = rt2860_rf2850[i].chan;
7089cdb1c70Snonaka ic->ic_channels[chan].ic_freq =
7099cdb1c70Snonaka ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);
7109cdb1c70Snonaka ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;
7119cdb1c70Snonaka }
7129cdb1c70Snonaka }
7139cdb1c70Snonaka
7149cdb1c70Snonaka /* set supported .11b and .11g rates */
7159cdb1c70Snonaka ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
7169cdb1c70Snonaka ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
7179cdb1c70Snonaka
7189cdb1c70Snonaka /* set supported .11b and .11g channels (1 through 14) */
7199cdb1c70Snonaka for (i = 1; i <= 14; i++) {
7209cdb1c70Snonaka ic->ic_channels[i].ic_freq =
7219cdb1c70Snonaka ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
7229cdb1c70Snonaka ic->ic_channels[i].ic_flags =
7239cdb1c70Snonaka IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
7249cdb1c70Snonaka IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
7259cdb1c70Snonaka }
7269cdb1c70Snonaka
7279cdb1c70Snonaka ifp->if_softc = sc;
7289cdb1c70Snonaka ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
7299cdb1c70Snonaka ifp->if_init = run_init;
7309cdb1c70Snonaka ifp->if_ioctl = run_ioctl;
7319cdb1c70Snonaka ifp->if_start = run_start;
7329cdb1c70Snonaka ifp->if_watchdog = run_watchdog;
7339cdb1c70Snonaka IFQ_SET_READY(&ifp->if_snd);
7349cdb1c70Snonaka memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
7359cdb1c70Snonaka
7369cdb1c70Snonaka if_attach(ifp);
7379cdb1c70Snonaka ieee80211_ifattach(ic);
7389cdb1c70Snonaka ic->ic_node_alloc = run_node_alloc;
7399cdb1c70Snonaka ic->ic_newassoc = run_newassoc;
7409cdb1c70Snonaka ic->ic_updateslot = run_updateslot;
7419cdb1c70Snonaka ic->ic_wme.wme_update = run_updateedca;
7429cdb1c70Snonaka #ifdef RUN_HWCRYPTO
7439cdb1c70Snonaka ic->ic_crypto.cs_key_set = run_set_key;
7449cdb1c70Snonaka ic->ic_crypto.cs_key_delete = run_delete_key;
7459cdb1c70Snonaka #endif
7469cdb1c70Snonaka /* override state transition machine */
7479cdb1c70Snonaka sc->sc_newstate = ic->ic_newstate;
7489cdb1c70Snonaka ic->ic_newstate = run_newstate;
7497a9a30c5Sthorpej
7507a9a30c5Sthorpej /* XXX media locking needs revisiting */
7517a9a30c5Sthorpej mutex_init(&sc->sc_media_mtx, MUTEX_DEFAULT, IPL_SOFTUSB);
7527a9a30c5Sthorpej ieee80211_media_init_with_lock(ic,
7537a9a30c5Sthorpej run_media_change, ieee80211_media_status, &sc->sc_media_mtx);
7549cdb1c70Snonaka
7559cdb1c70Snonaka bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
7569cdb1c70Snonaka sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
7579cdb1c70Snonaka &sc->sc_drvbpf);
7589cdb1c70Snonaka
7599cdb1c70Snonaka sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
7609cdb1c70Snonaka sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
7619cdb1c70Snonaka sc->sc_rxtap.wr_ihdr.it_present = htole32(RUN_RX_RADIOTAP_PRESENT);
7629cdb1c70Snonaka
7639cdb1c70Snonaka sc->sc_txtap_len = sizeof(sc->sc_txtapu);
7649cdb1c70Snonaka sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
7659cdb1c70Snonaka sc->sc_txtap.wt_ihdr.it_present = htole32(RUN_TX_RADIOTAP_PRESENT);
7669cdb1c70Snonaka
7679cdb1c70Snonaka ieee80211_announce(ic);
7689cdb1c70Snonaka
7699cdb1c70Snonaka usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
770b2901b1bSnonaka
771b2901b1bSnonaka if (!pmf_device_register(self, NULL, NULL))
772b2901b1bSnonaka aprint_error_dev(self, "couldn't establish power handler\n");
7739cdb1c70Snonaka }
7749cdb1c70Snonaka
7759cdb1c70Snonaka static int
run_detach(device_t self,int flags)7769cdb1c70Snonaka run_detach(device_t self, int flags)
7779cdb1c70Snonaka {
7789cdb1c70Snonaka struct run_softc *sc = device_private(self);
7799cdb1c70Snonaka struct ifnet *ifp = &sc->sc_if;
7809cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
7819cdb1c70Snonaka int s;
7829cdb1c70Snonaka
7839cdb1c70Snonaka if (ifp->if_softc == NULL)
7844e8e6643Sskrll return 0;
7859cdb1c70Snonaka
786b2901b1bSnonaka pmf_device_deregister(self);
787b2901b1bSnonaka
788da8283baSmlelstv s = splusb();
7899cdb1c70Snonaka
7909cdb1c70Snonaka sc->sc_flags |= RUN_DETACHING;
7919cdb1c70Snonaka
7929cdb1c70Snonaka if (ifp->if_flags & IFF_RUNNING) {
7939cdb1c70Snonaka run_stop(ifp, 0);
794080b2b0bSriastradh callout_halt(&sc->scan_to, NULL);
795080b2b0bSriastradh callout_halt(&sc->calib_to, NULL);
796a1de0147Sriastradh usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER,
797a1de0147Sriastradh NULL);
7989cdb1c70Snonaka }
7999cdb1c70Snonaka
8009cdb1c70Snonaka ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
8019cdb1c70Snonaka bpf_detach(ifp);
8029cdb1c70Snonaka ieee80211_ifdetach(ic);
8039cdb1c70Snonaka if_detach(ifp);
8049cdb1c70Snonaka
8059cdb1c70Snonaka splx(s);
8069cdb1c70Snonaka
8079cdb1c70Snonaka usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
8089cdb1c70Snonaka
809faca41fbSmlelstv callout_stop(&sc->scan_to);
810faca41fbSmlelstv callout_stop(&sc->calib_to);
811faca41fbSmlelstv
8129cdb1c70Snonaka callout_destroy(&sc->scan_to);
8139cdb1c70Snonaka callout_destroy(&sc->calib_to);
8149cdb1c70Snonaka
8154e8e6643Sskrll return 0;
8169cdb1c70Snonaka }
8179cdb1c70Snonaka
8189cdb1c70Snonaka static int
run_activate(device_t self,enum devact act)8199cdb1c70Snonaka run_activate(device_t self, enum devact act)
8209cdb1c70Snonaka {
8219cdb1c70Snonaka struct run_softc *sc = device_private(self);
8229cdb1c70Snonaka
8239cdb1c70Snonaka switch (act) {
8249cdb1c70Snonaka case DVACT_DEACTIVATE:
8259cdb1c70Snonaka if_deactivate(sc->sc_ic.ic_ifp);
8264e8e6643Sskrll return 0;
8279cdb1c70Snonaka default:
8284e8e6643Sskrll return EOPNOTSUPP;
8299cdb1c70Snonaka }
8309cdb1c70Snonaka }
8319cdb1c70Snonaka
8329cdb1c70Snonaka static int
run_alloc_rx_ring(struct run_softc * sc)8339cdb1c70Snonaka run_alloc_rx_ring(struct run_softc *sc)
8349cdb1c70Snonaka {
8359cdb1c70Snonaka struct run_rx_ring *rxq = &sc->rxq;
8369cdb1c70Snonaka int i, error;
8379cdb1c70Snonaka
8389cdb1c70Snonaka error = usbd_open_pipe(sc->sc_iface, rxq->pipe_no, 0, &rxq->pipeh);
8399cdb1c70Snonaka if (error != 0)
8409cdb1c70Snonaka goto fail;
8419cdb1c70Snonaka
8429cdb1c70Snonaka for (i = 0; i < RUN_RX_RING_COUNT; i++) {
8439cdb1c70Snonaka struct run_rx_data *data = &rxq->data[i];
8449cdb1c70Snonaka
8459cdb1c70Snonaka data->sc = sc; /* backpointer for callbacks */
8469cdb1c70Snonaka
8474e8e6643Sskrll error = usbd_create_xfer(sc->rxq.pipeh, RUN_MAX_RXSZ,
848b8421611Sskrll 0, 0, &data->xfer);
8494e8e6643Sskrll if (error)
8509cdb1c70Snonaka goto fail;
8514e8e6643Sskrll
8524e8e6643Sskrll data->buf = usbd_get_buffer(data->xfer);
8539cdb1c70Snonaka }
8549cdb1c70Snonaka if (error != 0)
8559cdb1c70Snonaka fail: run_free_rx_ring(sc);
8564e8e6643Sskrll return error;
8579cdb1c70Snonaka }
8589cdb1c70Snonaka
8599cdb1c70Snonaka static void
run_free_rx_ring(struct run_softc * sc)8609cdb1c70Snonaka run_free_rx_ring(struct run_softc *sc)
8619cdb1c70Snonaka {
8629cdb1c70Snonaka struct run_rx_ring *rxq = &sc->rxq;
8639cdb1c70Snonaka int i;
8649cdb1c70Snonaka
8659cdb1c70Snonaka if (rxq->pipeh != NULL) {
8669cdb1c70Snonaka usbd_abort_pipe(rxq->pipeh);
8679cdb1c70Snonaka }
8689cdb1c70Snonaka for (i = 0; i < RUN_RX_RING_COUNT; i++) {
8699cdb1c70Snonaka if (rxq->data[i].xfer != NULL)
8704e8e6643Sskrll usbd_destroy_xfer(rxq->data[i].xfer);
8719cdb1c70Snonaka rxq->data[i].xfer = NULL;
8729cdb1c70Snonaka }
8734e8e6643Sskrll if (rxq->pipeh != NULL) {
8744e8e6643Sskrll usbd_close_pipe(rxq->pipeh);
8754e8e6643Sskrll rxq->pipeh = NULL;
8764e8e6643Sskrll }
8779cdb1c70Snonaka }
8789cdb1c70Snonaka
8799cdb1c70Snonaka static int
run_alloc_tx_ring(struct run_softc * sc,int qid)8809cdb1c70Snonaka run_alloc_tx_ring(struct run_softc *sc, int qid)
8819cdb1c70Snonaka {
8829cdb1c70Snonaka struct run_tx_ring *txq = &sc->txq[qid];
8839cdb1c70Snonaka int i, error;
884d164e220Smlelstv uint16_t txwisize;
885d164e220Smlelstv
886d164e220Smlelstv txwisize = sizeof(struct rt2860_txwi);
887d164e220Smlelstv if (sc->mac_ver == 0x5592)
888d164e220Smlelstv txwisize += sizeof(uint32_t);
8899cdb1c70Snonaka
8909cdb1c70Snonaka txq->cur = txq->queued = 0;
8919cdb1c70Snonaka
8929cdb1c70Snonaka error = usbd_open_pipe(sc->sc_iface, txq->pipe_no, 0, &txq->pipeh);
8939cdb1c70Snonaka if (error != 0)
8949cdb1c70Snonaka goto fail;
8959cdb1c70Snonaka
8969cdb1c70Snonaka for (i = 0; i < RUN_TX_RING_COUNT; i++) {
8979cdb1c70Snonaka struct run_tx_data *data = &txq->data[i];
8989cdb1c70Snonaka
8999cdb1c70Snonaka data->sc = sc; /* backpointer for callbacks */
9009cdb1c70Snonaka data->qid = qid;
9019cdb1c70Snonaka
9024e8e6643Sskrll error = usbd_create_xfer(txq->pipeh, RUN_MAX_TXSZ,
9034e8e6643Sskrll USBD_FORCE_SHORT_XFER, 0, &data->xfer);
9044e8e6643Sskrll if (error)
9059cdb1c70Snonaka goto fail;
9064e8e6643Sskrll
9074e8e6643Sskrll data->buf = usbd_get_buffer(data->xfer);
9089cdb1c70Snonaka /* zeroize the TXD + TXWI part */
909d164e220Smlelstv memset(data->buf, 0, sizeof(struct rt2870_txd) + txwisize);
9109cdb1c70Snonaka }
9119cdb1c70Snonaka if (error != 0)
9129cdb1c70Snonaka fail: run_free_tx_ring(sc, qid);
9134e8e6643Sskrll return error;
9149cdb1c70Snonaka }
9159cdb1c70Snonaka
9169cdb1c70Snonaka static void
run_free_tx_ring(struct run_softc * sc,int qid)9179cdb1c70Snonaka run_free_tx_ring(struct run_softc *sc, int qid)
9189cdb1c70Snonaka {
9199cdb1c70Snonaka struct run_tx_ring *txq = &sc->txq[qid];
9209cdb1c70Snonaka int i;
9219cdb1c70Snonaka
9229cdb1c70Snonaka if (txq->pipeh != NULL) {
9239cdb1c70Snonaka usbd_abort_pipe(txq->pipeh);
9249cdb1c70Snonaka usbd_close_pipe(txq->pipeh);
9259cdb1c70Snonaka txq->pipeh = NULL;
9269cdb1c70Snonaka }
9279cdb1c70Snonaka for (i = 0; i < RUN_TX_RING_COUNT; i++) {
9289cdb1c70Snonaka if (txq->data[i].xfer != NULL)
9294e8e6643Sskrll usbd_destroy_xfer(txq->data[i].xfer);
9309cdb1c70Snonaka txq->data[i].xfer = NULL;
9319cdb1c70Snonaka }
9329cdb1c70Snonaka }
9339cdb1c70Snonaka
934*232edc8cSjdolecek static int __noinline
run_load_microcode(struct run_softc * sc)9359cdb1c70Snonaka run_load_microcode(struct run_softc *sc)
9369cdb1c70Snonaka {
9379cdb1c70Snonaka usb_device_request_t req;
9389cdb1c70Snonaka const char *fwname;
9398317b16eSmartin u_char *ucode = NULL; /* XXX gcc 4.8.3: maybe-uninitialized */
9408317b16eSmartin size_t size = 0; /* XXX gcc 4.8.3: maybe-uninitialized */
9419cdb1c70Snonaka uint32_t tmp;
9429cdb1c70Snonaka int ntries, error;
9439cdb1c70Snonaka
9449cdb1c70Snonaka /* RT3071/RT3072 use a different firmware */
9459cdb1c70Snonaka if (sc->mac_ver != 0x2860 &&
9469cdb1c70Snonaka sc->mac_ver != 0x2872 &&
9479cdb1c70Snonaka sc->mac_ver != 0x3070)
9489cdb1c70Snonaka fwname = "run-rt3071";
9499cdb1c70Snonaka else
9509cdb1c70Snonaka fwname = "run-rt2870";
9519cdb1c70Snonaka
952c9051a9fSnonaka if ((error = firmware_load("run", fwname, &ucode, &size)) != 0) {
9531d5cb2a3Sjakllsch device_printf(sc->sc_dev,
9549cdb1c70Snonaka "error %d, could not read firmware %s\n", error, fwname);
9554e8e6643Sskrll return error;
9569cdb1c70Snonaka }
9579cdb1c70Snonaka if (size != 4096) {
9581d5cb2a3Sjakllsch device_printf(sc->sc_dev,
9599cdb1c70Snonaka "invalid firmware size (should be 4KB)\n");
9609cdb1c70Snonaka firmware_free(ucode, size);
9614e8e6643Sskrll return EINVAL;
9629cdb1c70Snonaka }
9639cdb1c70Snonaka
9649cdb1c70Snonaka run_read(sc, RT2860_ASIC_VER_ID, &tmp);
9659cdb1c70Snonaka /* write microcode image */
9669cdb1c70Snonaka run_write_region_1(sc, RT2870_FW_BASE, ucode, size);
9679cdb1c70Snonaka firmware_free(ucode, size);
9689cdb1c70Snonaka run_write(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff);
9699cdb1c70Snonaka run_write(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff);
9709cdb1c70Snonaka
9719cdb1c70Snonaka req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
9729cdb1c70Snonaka req.bRequest = RT2870_RESET;
9739cdb1c70Snonaka USETW(req.wValue, 8);
9749cdb1c70Snonaka USETW(req.wIndex, 0);
9759cdb1c70Snonaka USETW(req.wLength, 0);
9769cdb1c70Snonaka if ((error = usbd_do_request(sc->sc_udev, &req, NULL)) != 0)
9774e8e6643Sskrll return error;
9789cdb1c70Snonaka
9799cdb1c70Snonaka usbd_delay_ms(sc->sc_udev, 10);
980d164e220Smlelstv run_write(sc, RT2860_H2M_BBPAGENT, 0);
9819cdb1c70Snonaka run_write(sc, RT2860_H2M_MAILBOX, 0);
982d164e220Smlelstv run_write(sc, RT2860_H2M_INTSRC, 0);
9839cdb1c70Snonaka if ((error = run_mcu_cmd(sc, RT2860_MCU_CMD_RFRESET, 0)) != 0)
9844e8e6643Sskrll return error;
9859cdb1c70Snonaka
9869cdb1c70Snonaka /* wait until microcontroller is ready */
9879cdb1c70Snonaka for (ntries = 0; ntries < 1000; ntries++) {
9889cdb1c70Snonaka if ((error = run_read(sc, RT2860_SYS_CTRL, &tmp)) != 0)
9894e8e6643Sskrll return error;
9909cdb1c70Snonaka if (tmp & RT2860_MCU_READY)
9919cdb1c70Snonaka break;
992faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
9939cdb1c70Snonaka }
9949cdb1c70Snonaka if (ntries == 1000) {
9951d5cb2a3Sjakllsch device_printf(sc->sc_dev,
9969cdb1c70Snonaka "timeout waiting for MCU to initialize\n");
9974e8e6643Sskrll return ETIMEDOUT;
9989cdb1c70Snonaka }
9999cdb1c70Snonaka
10009cdb1c70Snonaka sc->sc_flags |= RUN_FWLOADED;
10019cdb1c70Snonaka
10029cdb1c70Snonaka DPRINTF(("microcode successfully loaded after %d tries\n", ntries));
10034e8e6643Sskrll return 0;
10049cdb1c70Snonaka }
10059cdb1c70Snonaka
1006*232edc8cSjdolecek static int __noinline
run_reset(struct run_softc * sc)10079cdb1c70Snonaka run_reset(struct run_softc *sc)
10089cdb1c70Snonaka {
10099cdb1c70Snonaka usb_device_request_t req;
10109cdb1c70Snonaka
10119cdb1c70Snonaka req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
10129cdb1c70Snonaka req.bRequest = RT2870_RESET;
10139cdb1c70Snonaka USETW(req.wValue, 1);
10149cdb1c70Snonaka USETW(req.wIndex, 0);
10159cdb1c70Snonaka USETW(req.wLength, 0);
10169cdb1c70Snonaka return usbd_do_request(sc->sc_udev, &req, NULL);
10179cdb1c70Snonaka }
10189cdb1c70Snonaka
1019*232edc8cSjdolecek static int __noinline
run_read(struct run_softc * sc,uint16_t reg,uint32_t * val)10209cdb1c70Snonaka run_read(struct run_softc *sc, uint16_t reg, uint32_t *val)
10219cdb1c70Snonaka {
10229cdb1c70Snonaka uint32_t tmp;
10239cdb1c70Snonaka int error;
10249cdb1c70Snonaka
10254e8e6643Sskrll error = run_read_region_1(sc, reg, (uint8_t *)&tmp, sizeof(tmp));
10269cdb1c70Snonaka if (error == 0)
10279cdb1c70Snonaka *val = le32toh(tmp);
10289cdb1c70Snonaka else
10299cdb1c70Snonaka *val = 0xffffffff;
10304e8e6643Sskrll return error;
10319cdb1c70Snonaka }
10329cdb1c70Snonaka
10339cdb1c70Snonaka static int
run_read_region_1(struct run_softc * sc,uint16_t reg,uint8_t * buf,int len)10349cdb1c70Snonaka run_read_region_1(struct run_softc *sc, uint16_t reg, uint8_t *buf, int len)
10359cdb1c70Snonaka {
10369cdb1c70Snonaka usb_device_request_t req;
10379cdb1c70Snonaka
10389cdb1c70Snonaka req.bmRequestType = UT_READ_VENDOR_DEVICE;
10399cdb1c70Snonaka req.bRequest = RT2870_READ_REGION_1;
10409cdb1c70Snonaka USETW(req.wValue, 0);
10419cdb1c70Snonaka USETW(req.wIndex, reg);
10429cdb1c70Snonaka USETW(req.wLength, len);
10439cdb1c70Snonaka return usbd_do_request(sc->sc_udev, &req, buf);
10449cdb1c70Snonaka }
10459cdb1c70Snonaka
10469cdb1c70Snonaka static int
run_write_2(struct run_softc * sc,uint16_t reg,uint16_t val)10479cdb1c70Snonaka run_write_2(struct run_softc *sc, uint16_t reg, uint16_t val)
10489cdb1c70Snonaka {
10499cdb1c70Snonaka usb_device_request_t req;
10509cdb1c70Snonaka
10519cdb1c70Snonaka req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
10529cdb1c70Snonaka req.bRequest = RT2870_WRITE_2;
10539cdb1c70Snonaka USETW(req.wValue, val);
10549cdb1c70Snonaka USETW(req.wIndex, reg);
10559cdb1c70Snonaka USETW(req.wLength, 0);
10569cdb1c70Snonaka return usbd_do_request(sc->sc_udev, &req, NULL);
10579cdb1c70Snonaka }
10589cdb1c70Snonaka
1059*232edc8cSjdolecek static int __noinline
run_write(struct run_softc * sc,uint16_t reg,uint32_t val)10609cdb1c70Snonaka run_write(struct run_softc *sc, uint16_t reg, uint32_t val)
10619cdb1c70Snonaka {
1062c2d905cbSgson uint32_t tmp = htole32(val);
1063c2d905cbSgson return run_write_region_1(sc, reg, (uint8_t *)&tmp, sizeof(tmp));
10649cdb1c70Snonaka }
10659cdb1c70Snonaka
10669cdb1c70Snonaka static int
run_write_region_1(struct run_softc * sc,uint16_t reg,const uint8_t * buf,int len)10679cdb1c70Snonaka run_write_region_1(struct run_softc *sc, uint16_t reg, const uint8_t *buf,
10689cdb1c70Snonaka int len)
10699cdb1c70Snonaka {
1070c2d905cbSgson int error = 0;
1071c2d905cbSgson if (sc->sc_flags & RUN_USE_BLOCK_WRITE) {
10729cdb1c70Snonaka usb_device_request_t req;
1073c2d905cbSgson /*
1074c2d905cbSgson * NOTE: It appears the WRITE_REGION_1 command cannot be
1075c2d905cbSgson * passed a huge amount of data, which will crash the
1076c2d905cbSgson * firmware. Limit amount of data passed to 64 bytes at a
1077c2d905cbSgson * time.
1078c2d905cbSgson */
1079c2d905cbSgson while (len > 0) {
1080c2d905cbSgson int delta = MIN(len, 64);
10819cdb1c70Snonaka req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
10829cdb1c70Snonaka req.bRequest = RT2870_WRITE_REGION_1;
10839cdb1c70Snonaka USETW(req.wValue, 0);
10849cdb1c70Snonaka USETW(req.wIndex, reg);
1085c2d905cbSgson USETW(req.wLength, delta);
1086c2d905cbSgson error = usbd_do_request(sc->sc_udev, &req,
1087c2d905cbSgson __UNCONST(buf));
1088c2d905cbSgson if (error != 0)
1089c2d905cbSgson break;
1090c2d905cbSgson reg += delta;
1091c2d905cbSgson buf += delta;
1092c2d905cbSgson len -= delta;
1093c2d905cbSgson }
1094c2d905cbSgson } else {
1095c2d905cbSgson /*
1096c2d905cbSgson * NB: the WRITE_REGION_1 command is not stable on RT2860.
1097c2d905cbSgson * We thus issue multiple WRITE_2 commands instead.
1098c2d905cbSgson */
1099c2d905cbSgson int i;
1100c2d905cbSgson KASSERT((len & 1) == 0);
1101c2d905cbSgson for (i = 0; i < len && error == 0; i += 2)
1102c2d905cbSgson error = run_write_2(sc, reg + i, buf[i] | buf[i + 1] << 8);
1103c2d905cbSgson }
1104c2d905cbSgson return error;
11059cdb1c70Snonaka }
11069cdb1c70Snonaka
11079cdb1c70Snonaka static int
run_set_region_4(struct run_softc * sc,uint16_t reg,uint32_t val,int count)11089cdb1c70Snonaka run_set_region_4(struct run_softc *sc, uint16_t reg, uint32_t val, int count)
11099cdb1c70Snonaka {
11109cdb1c70Snonaka int error = 0;
11119cdb1c70Snonaka
1112c2d905cbSgson if (sc->sc_flags & RUN_USE_BLOCK_WRITE) {
1113c2d905cbSgson while (count > 0) {
1114c2d905cbSgson int i, delta;
1115c2d905cbSgson uint32_t tmp[16];
1116c2d905cbSgson
1117c2d905cbSgson delta = MIN(count, __arraycount(tmp));
1118c2d905cbSgson for (i = 0; i < delta; i++)
1119c2d905cbSgson tmp[i] = htole32(val);
1120c2d905cbSgson error = run_write_region_1(sc, reg, (uint8_t *)tmp,
1121c2d905cbSgson delta * sizeof(uint32_t));
1122c2d905cbSgson if (error != 0)
1123c2d905cbSgson break;
1124c2d905cbSgson reg += delta * sizeof(uint32_t);
1125c2d905cbSgson count -= delta;
1126c2d905cbSgson }
1127c2d905cbSgson } else {
11289cdb1c70Snonaka for (; count > 0 && error == 0; count--, reg += 4)
11299cdb1c70Snonaka error = run_write(sc, reg, val);
1130c2d905cbSgson }
11314e8e6643Sskrll return error;
11329cdb1c70Snonaka }
11339cdb1c70Snonaka
11349cdb1c70Snonaka static int
run_efuse_read(struct run_softc * sc,uint16_t addr,uint16_t * val,int count)1135faca41fbSmlelstv run_efuse_read(struct run_softc *sc, uint16_t addr, uint16_t *val, int count)
11369cdb1c70Snonaka {
11379cdb1c70Snonaka uint32_t tmp;
11389cdb1c70Snonaka uint16_t reg;
11399cdb1c70Snonaka int error, ntries;
11409cdb1c70Snonaka
11419cdb1c70Snonaka if ((error = run_read(sc, RT3070_EFUSE_CTRL, &tmp)) != 0)
11424e8e6643Sskrll return error;
11439cdb1c70Snonaka
1144faca41fbSmlelstv if (count == 2)
11459cdb1c70Snonaka addr *= 2;
11469cdb1c70Snonaka /*-
11479cdb1c70Snonaka * Read one 16-byte block into registers EFUSE_DATA[0-3]:
11489cdb1c70Snonaka * DATA0: F E D C
11499cdb1c70Snonaka * DATA1: B A 9 8
11509cdb1c70Snonaka * DATA2: 7 6 5 4
11519cdb1c70Snonaka * DATA3: 3 2 1 0
11529cdb1c70Snonaka */
11539cdb1c70Snonaka tmp &= ~(RT3070_EFSROM_MODE_MASK | RT3070_EFSROM_AIN_MASK);
11549cdb1c70Snonaka tmp |= (addr & ~0xf) << RT3070_EFSROM_AIN_SHIFT | RT3070_EFSROM_KICK;
11559cdb1c70Snonaka run_write(sc, RT3070_EFUSE_CTRL, tmp);
11569cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) {
11579cdb1c70Snonaka if ((error = run_read(sc, RT3070_EFUSE_CTRL, &tmp)) != 0)
11584e8e6643Sskrll return error;
11599cdb1c70Snonaka if (!(tmp & RT3070_EFSROM_KICK))
11609cdb1c70Snonaka break;
1161faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 2);
11629cdb1c70Snonaka }
11639cdb1c70Snonaka if (ntries == 100)
11644e8e6643Sskrll return ETIMEDOUT;
11659cdb1c70Snonaka
11669cdb1c70Snonaka if ((tmp & RT3070_EFUSE_AOUT_MASK) == RT3070_EFUSE_AOUT_MASK) {
11679cdb1c70Snonaka *val = 0xffff; /* address not found */
11684e8e6643Sskrll return 0;
11699cdb1c70Snonaka }
11709cdb1c70Snonaka /* determine to which 32-bit register our 16-bit word belongs */
11719cdb1c70Snonaka reg = RT3070_EFUSE_DATA3 - (addr & 0xc);
11729cdb1c70Snonaka if ((error = run_read(sc, reg, &tmp)) != 0)
11734e8e6643Sskrll return error;
11749cdb1c70Snonaka
1175d164e220Smlelstv tmp >>= (8 * (addr & 0x3));
1176faca41fbSmlelstv *val = (addr & 1) ? tmp >> 16 : tmp & 0xffff;
11774e8e6643Sskrll return 0;
11789cdb1c70Snonaka }
11799cdb1c70Snonaka
1180faca41fbSmlelstv /* Read 16-bit from eFUSE ROM for RT3xxxx. */
1181faca41fbSmlelstv static int
run_efuse_read_2(struct run_softc * sc,uint16_t addr,uint16_t * val)1182faca41fbSmlelstv run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val)
1183faca41fbSmlelstv {
118426ee7ba1Sskrll return run_efuse_read(sc, addr, val, 2);
1185faca41fbSmlelstv }
1186faca41fbSmlelstv
11879cdb1c70Snonaka static int
run_eeprom_read_2(struct run_softc * sc,uint16_t addr,uint16_t * val)11889cdb1c70Snonaka run_eeprom_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val)
11899cdb1c70Snonaka {
11909cdb1c70Snonaka usb_device_request_t req;
11919cdb1c70Snonaka uint16_t tmp;
11929cdb1c70Snonaka int error;
11939cdb1c70Snonaka
11949cdb1c70Snonaka addr *= 2;
11959cdb1c70Snonaka req.bmRequestType = UT_READ_VENDOR_DEVICE;
11969cdb1c70Snonaka req.bRequest = RT2870_EEPROM_READ;
11979cdb1c70Snonaka USETW(req.wValue, 0);
11989cdb1c70Snonaka USETW(req.wIndex, addr);
11994e8e6643Sskrll USETW(req.wLength, sizeof(tmp));
12009cdb1c70Snonaka error = usbd_do_request(sc->sc_udev, &req, &tmp);
12019cdb1c70Snonaka if (error == 0)
12029cdb1c70Snonaka *val = le16toh(tmp);
12039cdb1c70Snonaka else
12049cdb1c70Snonaka *val = 0xffff;
12054e8e6643Sskrll return error;
12069cdb1c70Snonaka }
12079cdb1c70Snonaka
12089cdb1c70Snonaka static __inline int
run_srom_read(struct run_softc * sc,uint16_t addr,uint16_t * val)12099cdb1c70Snonaka run_srom_read(struct run_softc *sc, uint16_t addr, uint16_t *val)
12109cdb1c70Snonaka {
12119cdb1c70Snonaka
12129cdb1c70Snonaka /* either eFUSE ROM or EEPROM */
12139cdb1c70Snonaka return sc->sc_srom_read(sc, addr, val);
12149cdb1c70Snonaka }
12159cdb1c70Snonaka
12169cdb1c70Snonaka static int
run_rt2870_rf_write(struct run_softc * sc,uint8_t reg,uint32_t val)12179cdb1c70Snonaka run_rt2870_rf_write(struct run_softc *sc, uint8_t reg, uint32_t val)
12189cdb1c70Snonaka {
12199cdb1c70Snonaka uint32_t tmp;
12209cdb1c70Snonaka int error, ntries;
12219cdb1c70Snonaka
12229cdb1c70Snonaka for (ntries = 0; ntries < 10; ntries++) {
12239cdb1c70Snonaka if ((error = run_read(sc, RT2860_RF_CSR_CFG0, &tmp)) != 0)
12244e8e6643Sskrll return error;
12259cdb1c70Snonaka if (!(tmp & RT2860_RF_REG_CTRL))
12269cdb1c70Snonaka break;
12279cdb1c70Snonaka }
12289cdb1c70Snonaka if (ntries == 10)
12294e8e6643Sskrll return ETIMEDOUT;
12309cdb1c70Snonaka
12319cdb1c70Snonaka /* RF registers are 24-bit on the RT2860 */
12329cdb1c70Snonaka tmp = RT2860_RF_REG_CTRL | 24 << RT2860_RF_REG_WIDTH_SHIFT |
12339cdb1c70Snonaka (val & 0x3fffff) << 2 | (reg & 3);
12349cdb1c70Snonaka return run_write(sc, RT2860_RF_CSR_CFG0, tmp);
12359cdb1c70Snonaka }
12369cdb1c70Snonaka
12379cdb1c70Snonaka static int
run_rt3070_rf_read(struct run_softc * sc,uint8_t reg,uint8_t * val)12389cdb1c70Snonaka run_rt3070_rf_read(struct run_softc *sc, uint8_t reg, uint8_t *val)
12399cdb1c70Snonaka {
12409cdb1c70Snonaka uint32_t tmp;
12419cdb1c70Snonaka int error, ntries;
12429cdb1c70Snonaka
12439cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) {
12449cdb1c70Snonaka if ((error = run_read(sc, RT3070_RF_CSR_CFG, &tmp)) != 0)
12454e8e6643Sskrll return error;
12469cdb1c70Snonaka if (!(tmp & RT3070_RF_KICK))
12479cdb1c70Snonaka break;
12489cdb1c70Snonaka }
12499cdb1c70Snonaka if (ntries == 100)
12504e8e6643Sskrll return ETIMEDOUT;
12519cdb1c70Snonaka
12529cdb1c70Snonaka tmp = RT3070_RF_KICK | reg << 8;
12539cdb1c70Snonaka if ((error = run_write(sc, RT3070_RF_CSR_CFG, tmp)) != 0)
12544e8e6643Sskrll return error;
12559cdb1c70Snonaka
12569cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) {
12579cdb1c70Snonaka if ((error = run_read(sc, RT3070_RF_CSR_CFG, &tmp)) != 0)
12584e8e6643Sskrll return error;
12599cdb1c70Snonaka if (!(tmp & RT3070_RF_KICK))
12609cdb1c70Snonaka break;
12619cdb1c70Snonaka }
12629cdb1c70Snonaka if (ntries == 100)
12634e8e6643Sskrll return ETIMEDOUT;
12649cdb1c70Snonaka
12659cdb1c70Snonaka *val = tmp & 0xff;
12664e8e6643Sskrll return 0;
12679cdb1c70Snonaka }
12689cdb1c70Snonaka
12699cdb1c70Snonaka static int
run_rt3070_rf_write(struct run_softc * sc,uint8_t reg,uint8_t val)12709cdb1c70Snonaka run_rt3070_rf_write(struct run_softc *sc, uint8_t reg, uint8_t val)
12719cdb1c70Snonaka {
12729cdb1c70Snonaka uint32_t tmp;
12739cdb1c70Snonaka int error, ntries;
12749cdb1c70Snonaka
12759cdb1c70Snonaka for (ntries = 0; ntries < 10; ntries++) {
12769cdb1c70Snonaka if ((error = run_read(sc, RT3070_RF_CSR_CFG, &tmp)) != 0)
12774e8e6643Sskrll return error;
12789cdb1c70Snonaka if (!(tmp & RT3070_RF_KICK))
12799cdb1c70Snonaka break;
12809cdb1c70Snonaka }
12819cdb1c70Snonaka if (ntries == 10)
12824e8e6643Sskrll return ETIMEDOUT;
12839cdb1c70Snonaka
12849cdb1c70Snonaka tmp = RT3070_RF_WRITE | RT3070_RF_KICK | reg << 8 | val;
12859cdb1c70Snonaka return run_write(sc, RT3070_RF_CSR_CFG, tmp);
12869cdb1c70Snonaka }
12879cdb1c70Snonaka
12889cdb1c70Snonaka static int
run_bbp_read(struct run_softc * sc,uint8_t reg,uint8_t * val)12899cdb1c70Snonaka run_bbp_read(struct run_softc *sc, uint8_t reg, uint8_t *val)
12909cdb1c70Snonaka {
12919cdb1c70Snonaka uint32_t tmp;
12929cdb1c70Snonaka int ntries, error;
12939cdb1c70Snonaka
12949cdb1c70Snonaka for (ntries = 0; ntries < 10; ntries++) {
12959cdb1c70Snonaka if ((error = run_read(sc, RT2860_BBP_CSR_CFG, &tmp)) != 0)
12964e8e6643Sskrll return error;
12979cdb1c70Snonaka if (!(tmp & RT2860_BBP_CSR_KICK))
12989cdb1c70Snonaka break;
12999cdb1c70Snonaka }
13009cdb1c70Snonaka if (ntries == 10)
13014e8e6643Sskrll return ETIMEDOUT;
13029cdb1c70Snonaka
13039cdb1c70Snonaka tmp = RT2860_BBP_CSR_READ | RT2860_BBP_CSR_KICK | reg << 8;
13049cdb1c70Snonaka if ((error = run_write(sc, RT2860_BBP_CSR_CFG, tmp)) != 0)
13054e8e6643Sskrll return error;
13069cdb1c70Snonaka
13079cdb1c70Snonaka for (ntries = 0; ntries < 10; ntries++) {
13089cdb1c70Snonaka if ((error = run_read(sc, RT2860_BBP_CSR_CFG, &tmp)) != 0)
13094e8e6643Sskrll return error;
13109cdb1c70Snonaka if (!(tmp & RT2860_BBP_CSR_KICK))
13119cdb1c70Snonaka break;
13129cdb1c70Snonaka }
13139cdb1c70Snonaka if (ntries == 10)
13144e8e6643Sskrll return ETIMEDOUT;
13159cdb1c70Snonaka
13169cdb1c70Snonaka *val = tmp & 0xff;
13174e8e6643Sskrll return 0;
13189cdb1c70Snonaka }
13199cdb1c70Snonaka
13209cdb1c70Snonaka static int
run_bbp_write(struct run_softc * sc,uint8_t reg,uint8_t val)13219cdb1c70Snonaka run_bbp_write(struct run_softc *sc, uint8_t reg, uint8_t val)
13229cdb1c70Snonaka {
13239cdb1c70Snonaka uint32_t tmp;
13249cdb1c70Snonaka int ntries, error;
13259cdb1c70Snonaka
13269cdb1c70Snonaka for (ntries = 0; ntries < 10; ntries++) {
13279cdb1c70Snonaka if ((error = run_read(sc, RT2860_BBP_CSR_CFG, &tmp)) != 0)
13284e8e6643Sskrll return error;
13299cdb1c70Snonaka if (!(tmp & RT2860_BBP_CSR_KICK))
13309cdb1c70Snonaka break;
13319cdb1c70Snonaka }
13329cdb1c70Snonaka if (ntries == 10)
13334e8e6643Sskrll return ETIMEDOUT;
13349cdb1c70Snonaka
13359cdb1c70Snonaka tmp = RT2860_BBP_CSR_KICK | reg << 8 | val;
13369cdb1c70Snonaka return run_write(sc, RT2860_BBP_CSR_CFG, tmp);
13379cdb1c70Snonaka }
13389cdb1c70Snonaka
13399cdb1c70Snonaka /*
13409cdb1c70Snonaka * Send a command to the 8051 microcontroller unit.
13419cdb1c70Snonaka */
13429cdb1c70Snonaka static int
run_mcu_cmd(struct run_softc * sc,uint8_t cmd,uint16_t arg)13439cdb1c70Snonaka run_mcu_cmd(struct run_softc *sc, uint8_t cmd, uint16_t arg)
13449cdb1c70Snonaka {
13459cdb1c70Snonaka uint32_t tmp;
13469cdb1c70Snonaka int error, ntries;
13479cdb1c70Snonaka
13489cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) {
13499cdb1c70Snonaka if ((error = run_read(sc, RT2860_H2M_MAILBOX, &tmp)) != 0)
13504e8e6643Sskrll return error;
13519cdb1c70Snonaka if (!(tmp & RT2860_H2M_BUSY))
13529cdb1c70Snonaka break;
13539cdb1c70Snonaka }
13549cdb1c70Snonaka if (ntries == 100)
13554e8e6643Sskrll return ETIMEDOUT;
13569cdb1c70Snonaka
13579cdb1c70Snonaka tmp = RT2860_H2M_BUSY | RT2860_TOKEN_NO_INTR << 16 | arg;
13589cdb1c70Snonaka if ((error = run_write(sc, RT2860_H2M_MAILBOX, tmp)) == 0)
13599cdb1c70Snonaka error = run_write(sc, RT2860_HOST_CMD, cmd);
13604e8e6643Sskrll return error;
13619cdb1c70Snonaka }
13629cdb1c70Snonaka
13639cdb1c70Snonaka /*
13649cdb1c70Snonaka * Add `delta' (signed) to each 4-bit sub-word of a 32-bit word.
13659cdb1c70Snonaka * Used to adjust per-rate Tx power registers.
13669cdb1c70Snonaka */
13679cdb1c70Snonaka static __inline uint32_t
b4inc(uint32_t b32,int8_t delta)13689cdb1c70Snonaka b4inc(uint32_t b32, int8_t delta)
13699cdb1c70Snonaka {
13709cdb1c70Snonaka int8_t i, b4;
13719cdb1c70Snonaka
13729cdb1c70Snonaka for (i = 0; i < 8; i++) {
13739cdb1c70Snonaka b4 = b32 & 0xf;
13749cdb1c70Snonaka b4 += delta;
13759cdb1c70Snonaka if (b4 < 0)
13769cdb1c70Snonaka b4 = 0;
13779cdb1c70Snonaka else if (b4 > 0xf)
13789cdb1c70Snonaka b4 = 0xf;
13799cdb1c70Snonaka b32 = b32 >> 4 | b4 << 28;
13809cdb1c70Snonaka }
13814e8e6643Sskrll return b32;
13829cdb1c70Snonaka }
13839cdb1c70Snonaka
13849cdb1c70Snonaka static const char *
run_get_rf(uint16_t rev)1385d164e220Smlelstv run_get_rf(uint16_t rev)
13869cdb1c70Snonaka {
13879cdb1c70Snonaka switch (rev) {
13889cdb1c70Snonaka case RT2860_RF_2820: return "RT2820";
13899cdb1c70Snonaka case RT2860_RF_2850: return "RT2850";
13909cdb1c70Snonaka case RT2860_RF_2720: return "RT2720";
13919cdb1c70Snonaka case RT2860_RF_2750: return "RT2750";
13929cdb1c70Snonaka case RT3070_RF_3020: return "RT3020";
13939cdb1c70Snonaka case RT3070_RF_2020: return "RT2020";
13949cdb1c70Snonaka case RT3070_RF_3021: return "RT3021";
13959cdb1c70Snonaka case RT3070_RF_3022: return "RT3022";
13969cdb1c70Snonaka case RT3070_RF_3052: return "RT3052";
1397faca41fbSmlelstv case RT3070_RF_3053: return "RT3053";
1398faca41fbSmlelstv case RT5592_RF_5592: return "RT5592";
1399faca41fbSmlelstv case RT5390_RF_5370: return "RT5370";
1400faca41fbSmlelstv case RT5390_RF_5372: return "RT5372";
14019cdb1c70Snonaka }
14029cdb1c70Snonaka return "unknown";
14039cdb1c70Snonaka }
14049cdb1c70Snonaka
1405faca41fbSmlelstv static void
run_rt3593_get_txpower(struct run_softc * sc)1406faca41fbSmlelstv run_rt3593_get_txpower(struct run_softc *sc)
1407faca41fbSmlelstv {
1408faca41fbSmlelstv uint16_t addr, val;
1409faca41fbSmlelstv int i;
1410faca41fbSmlelstv
1411faca41fbSmlelstv /* Read power settings for 2GHz channels. */
1412faca41fbSmlelstv for (i = 0; i < 14; i += 2) {
1413faca41fbSmlelstv addr = (sc->ntxchains == 3) ? RT3593_EEPROM_PWR2GHZ_BASE1 :
1414faca41fbSmlelstv RT2860_EEPROM_PWR2GHZ_BASE1;
1415faca41fbSmlelstv run_srom_read(sc, addr + i / 2, &val);
1416faca41fbSmlelstv sc->txpow1[i + 0] = (int8_t)(val & 0xff);
1417faca41fbSmlelstv sc->txpow1[i + 1] = (int8_t)(val >> 8);
1418faca41fbSmlelstv
1419faca41fbSmlelstv addr = (sc->ntxchains == 3) ? RT3593_EEPROM_PWR2GHZ_BASE2 :
1420faca41fbSmlelstv RT2860_EEPROM_PWR2GHZ_BASE2;
1421faca41fbSmlelstv run_srom_read(sc, addr + i / 2, &val);
1422faca41fbSmlelstv sc->txpow2[i + 0] = (int8_t)(val & 0xff);
1423faca41fbSmlelstv sc->txpow2[i + 1] = (int8_t)(val >> 8);
1424faca41fbSmlelstv
1425faca41fbSmlelstv if (sc->ntxchains == 3) {
1426faca41fbSmlelstv run_srom_read(sc, RT3593_EEPROM_PWR2GHZ_BASE3 + i / 2,
1427faca41fbSmlelstv &val);
1428faca41fbSmlelstv sc->txpow3[i + 0] = (int8_t)(val & 0xff);
1429faca41fbSmlelstv sc->txpow3[i + 1] = (int8_t)(val >> 8);
1430faca41fbSmlelstv }
1431faca41fbSmlelstv }
1432faca41fbSmlelstv /* Fix broken Tx power entries. */
1433faca41fbSmlelstv for (i = 0; i < 14; i++) {
1434faca41fbSmlelstv if (sc->txpow1[i] > 31)
1435faca41fbSmlelstv sc->txpow1[i] = 5;
1436faca41fbSmlelstv if (sc->txpow2[i] > 31)
1437faca41fbSmlelstv sc->txpow2[i] = 5;
1438faca41fbSmlelstv if (sc->ntxchains == 3) {
1439faca41fbSmlelstv if (sc->txpow3[i] > 31)
1440faca41fbSmlelstv sc->txpow3[i] = 5;
1441faca41fbSmlelstv }
1442faca41fbSmlelstv }
1443faca41fbSmlelstv /* Read power settings for 5GHz channels. */
1444faca41fbSmlelstv for (i = 0; i < 40; i += 2) {
1445faca41fbSmlelstv run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE1 + i / 2, &val);
1446faca41fbSmlelstv sc->txpow1[i + 14] = (int8_t)(val & 0xff);
1447faca41fbSmlelstv sc->txpow1[i + 15] = (int8_t)(val >> 8);
1448faca41fbSmlelstv
1449faca41fbSmlelstv run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE2 + i / 2, &val);
1450faca41fbSmlelstv sc->txpow2[i + 14] = (int8_t)(val & 0xff);
1451faca41fbSmlelstv sc->txpow2[i + 15] = (int8_t)(val >> 8);
1452faca41fbSmlelstv
1453faca41fbSmlelstv if (sc->ntxchains == 3) {
1454faca41fbSmlelstv run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE3 + i / 2,
1455faca41fbSmlelstv &val);
1456faca41fbSmlelstv sc->txpow3[i + 14] = (int8_t)(val & 0xff);
1457faca41fbSmlelstv sc->txpow3[i + 15] = (int8_t)(val >> 8);
1458faca41fbSmlelstv }
1459faca41fbSmlelstv }
1460faca41fbSmlelstv }
1461faca41fbSmlelstv
1462faca41fbSmlelstv static void
run_get_txpower(struct run_softc * sc)1463faca41fbSmlelstv run_get_txpower(struct run_softc *sc)
1464faca41fbSmlelstv {
1465faca41fbSmlelstv uint16_t val;
1466faca41fbSmlelstv int i;
1467faca41fbSmlelstv
1468faca41fbSmlelstv /* Read power settings for 2GHz channels. */
1469faca41fbSmlelstv for (i = 0; i < 14; i += 2) {
1470faca41fbSmlelstv run_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2, &val);
1471faca41fbSmlelstv sc->txpow1[i + 0] = (int8_t)(val & 0xff);
1472faca41fbSmlelstv sc->txpow1[i + 1] = (int8_t)(val >> 8);
1473faca41fbSmlelstv
1474faca41fbSmlelstv if (sc->mac_ver != 0x5390) {
1475faca41fbSmlelstv run_srom_read(sc,
1476faca41fbSmlelstv RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2, &val);
1477faca41fbSmlelstv sc->txpow2[i + 0] = (int8_t)(val & 0xff);
1478faca41fbSmlelstv sc->txpow2[i + 1] = (int8_t)(val >> 8);
1479faca41fbSmlelstv }
1480faca41fbSmlelstv }
1481faca41fbSmlelstv /* Fix broken Tx power entries. */
1482faca41fbSmlelstv for (i = 0; i < 14; i++) {
1483faca41fbSmlelstv if (sc->mac_ver >= 0x5390) {
1484faca41fbSmlelstv if (sc->txpow1[i] < 0 || sc->txpow1[i] > 39)
1485faca41fbSmlelstv sc->txpow1[i] = 5;
1486faca41fbSmlelstv } else {
1487faca41fbSmlelstv if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31)
1488faca41fbSmlelstv sc->txpow1[i] = 5;
1489faca41fbSmlelstv }
1490faca41fbSmlelstv if (sc->mac_ver > 0x5390) {
1491faca41fbSmlelstv if (sc->txpow2[i] < 0 || sc->txpow2[i] > 39)
1492faca41fbSmlelstv sc->txpow2[i] = 5;
1493faca41fbSmlelstv } else if (sc->mac_ver < 0x5390) {
1494faca41fbSmlelstv if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31)
1495faca41fbSmlelstv sc->txpow2[i] = 5;
1496faca41fbSmlelstv }
1497faca41fbSmlelstv DPRINTF(("chan %d: power1=%d, power2=%d\n",
1498faca41fbSmlelstv rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]));
1499faca41fbSmlelstv }
1500faca41fbSmlelstv /* Read power settings for 5GHz channels. */
1501faca41fbSmlelstv for (i = 0; i < 40; i += 2) {
1502faca41fbSmlelstv run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2, &val);
1503faca41fbSmlelstv sc->txpow1[i + 14] = (int8_t)(val & 0xff);
1504faca41fbSmlelstv sc->txpow1[i + 15] = (int8_t)(val >> 8);
1505faca41fbSmlelstv
1506faca41fbSmlelstv run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2, &val);
1507faca41fbSmlelstv sc->txpow2[i + 14] = (int8_t)(val & 0xff);
1508faca41fbSmlelstv sc->txpow2[i + 15] = (int8_t)(val >> 8);
1509faca41fbSmlelstv }
1510faca41fbSmlelstv /* Fix broken Tx power entries. */
1511faca41fbSmlelstv for (i = 0; i < 40; i++ ) {
1512faca41fbSmlelstv if (sc->mac_ver != 0x5592) {
1513faca41fbSmlelstv if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15)
1514faca41fbSmlelstv sc->txpow1[14 + i] = 5;
1515faca41fbSmlelstv if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15)
1516faca41fbSmlelstv sc->txpow2[14 + i] = 5;
1517faca41fbSmlelstv }
1518faca41fbSmlelstv DPRINTF(("chan %d: power1=%d, power2=%d\n",
1519faca41fbSmlelstv rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i],
1520faca41fbSmlelstv sc->txpow2[14 + i]));
1521faca41fbSmlelstv }
1522faca41fbSmlelstv }
1523faca41fbSmlelstv
15249cdb1c70Snonaka static int
run_read_eeprom(struct run_softc * sc)15259cdb1c70Snonaka run_read_eeprom(struct run_softc *sc)
15269cdb1c70Snonaka {
15279cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
15289cdb1c70Snonaka int8_t delta_2ghz, delta_5ghz;
15299cdb1c70Snonaka uint32_t tmp;
15309cdb1c70Snonaka uint16_t val;
15319cdb1c70Snonaka int ridx, ant, i;
15329cdb1c70Snonaka
15339cdb1c70Snonaka /* check whether the ROM is eFUSE ROM or EEPROM */
15349cdb1c70Snonaka sc->sc_srom_read = run_eeprom_read_2;
15359cdb1c70Snonaka if (sc->mac_ver >= 0x3070) {
15369cdb1c70Snonaka run_read(sc, RT3070_EFUSE_CTRL, &tmp);
1537aa3d6ec1Schristos DPRINTF(("EFUSE_CTRL=0x%08x\n", tmp));
15389cdb1c70Snonaka if (tmp & RT3070_SEL_EFUSE)
15399cdb1c70Snonaka sc->sc_srom_read = run_efuse_read_2;
15409cdb1c70Snonaka }
15419cdb1c70Snonaka
15429cdb1c70Snonaka /* read ROM version */
15439cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_VERSION, &val);
15449cdb1c70Snonaka DPRINTF(("EEPROM rev=%d, FAE=%d\n", val & 0xff, val >> 8));
15459cdb1c70Snonaka
15469cdb1c70Snonaka /* read MAC address */
15479cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_MAC01, &val);
15489cdb1c70Snonaka ic->ic_myaddr[0] = val & 0xff;
15499cdb1c70Snonaka ic->ic_myaddr[1] = val >> 8;
15509cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_MAC23, &val);
15519cdb1c70Snonaka ic->ic_myaddr[2] = val & 0xff;
15529cdb1c70Snonaka ic->ic_myaddr[3] = val >> 8;
15539cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_MAC45, &val);
15549cdb1c70Snonaka ic->ic_myaddr[4] = val & 0xff;
15559cdb1c70Snonaka ic->ic_myaddr[5] = val >> 8;
15569cdb1c70Snonaka
1557d164e220Smlelstv if (sc->mac_ver < 0x3593) {
15589cdb1c70Snonaka /* read vendor BBP settings */
15599cdb1c70Snonaka for (i = 0; i < 10; i++) {
15609cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val);
15619cdb1c70Snonaka sc->bbp[i].val = val & 0xff;
15629cdb1c70Snonaka sc->bbp[i].reg = val >> 8;
1563aa3d6ec1Schristos DPRINTF(("BBP%d=0x%02x\n", sc->bbp[i].reg,
1564d164e220Smlelstv sc->bbp[i].val));
15659cdb1c70Snonaka }
1566faca41fbSmlelstv
1567d164e220Smlelstv if (sc->mac_ver >= 0x3071) {
15689cdb1c70Snonaka /* read vendor RF settings */
1569faca41fbSmlelstv for (i = 0; i < 8; i++) {
1570d164e220Smlelstv run_srom_read(sc, RT3071_EEPROM_RF_BASE + i,
1571d164e220Smlelstv &val);
15729cdb1c70Snonaka sc->rf[i].val = val & 0xff;
15739cdb1c70Snonaka sc->rf[i].reg = val >> 8;
1574aa3d6ec1Schristos DPRINTF(("RF%d=0x%02x\n", sc->rf[i].reg,
15759cdb1c70Snonaka sc->rf[i].val));
15769cdb1c70Snonaka }
1577d164e220Smlelstv }
1578d164e220Smlelstv }
15799cdb1c70Snonaka
15809cdb1c70Snonaka /* read RF frequency offset from EEPROM */
1581d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS :
1582d164e220Smlelstv RT3593_EEPROM_FREQ, &val);
15839cdb1c70Snonaka sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0;
15849cdb1c70Snonaka DPRINTF(("EEPROM freq offset %d\n", sc->freq & 0xff));
1585d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS :
1586d164e220Smlelstv RT3593_EEPROM_FREQ, &val);
15879cdb1c70Snonaka if ((val >> 8) != 0xff) {
15889cdb1c70Snonaka /* read LEDs operating mode */
15899cdb1c70Snonaka sc->leds = val >> 8;
1590d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED1 :
1591d164e220Smlelstv RT3593_EEPROM_LED1, &sc->led[0]);
1592d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED2 :
1593d164e220Smlelstv RT3593_EEPROM_LED2, &sc->led[1]);
1594d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED3 :
1595d164e220Smlelstv RT3593_EEPROM_LED3, &sc->led[2]);
15969cdb1c70Snonaka } else {
15979cdb1c70Snonaka /* broken EEPROM, use default settings */
15989cdb1c70Snonaka sc->leds = 0x01;
15999cdb1c70Snonaka sc->led[0] = 0x5555;
16009cdb1c70Snonaka sc->led[1] = 0x2221;
16019cdb1c70Snonaka sc->led[2] = 0x5627; /* differs from RT2860 */
16029cdb1c70Snonaka }
1603aa3d6ec1Schristos DPRINTF(("EEPROM LED mode=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n",
16049cdb1c70Snonaka sc->leds, sc->led[0], sc->led[1], sc->led[2]));
16059cdb1c70Snonaka
16069cdb1c70Snonaka /* read RF information */
1607d164e220Smlelstv if (sc->mac_ver == 0x5390 || sc->mac_ver == 0x5392)
1608d164e220Smlelstv run_srom_read(sc, 0x00, &val);
1609d164e220Smlelstv else
16109cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val);
16119cdb1c70Snonaka if (val == 0xffff) {
16129cdb1c70Snonaka DPRINTF(("invalid EEPROM antenna info, using default\n"));
16139cdb1c70Snonaka if (sc->mac_ver == 0x3572) {
16149cdb1c70Snonaka /* default to RF3052 2T2R */
16159cdb1c70Snonaka sc->rf_rev = RT3070_RF_3052;
16169cdb1c70Snonaka sc->ntxchains = 2;
16179cdb1c70Snonaka sc->nrxchains = 2;
16189cdb1c70Snonaka } else if (sc->mac_ver >= 0x3070) {
16199cdb1c70Snonaka /* default to RF3020 1T1R */
16209cdb1c70Snonaka sc->rf_rev = RT3070_RF_3020;
16219cdb1c70Snonaka sc->ntxchains = 1;
16229cdb1c70Snonaka sc->nrxchains = 1;
16239cdb1c70Snonaka } else {
16249cdb1c70Snonaka /* default to RF2820 1T2R */
16259cdb1c70Snonaka sc->rf_rev = RT2860_RF_2820;
16269cdb1c70Snonaka sc->ntxchains = 1;
16279cdb1c70Snonaka sc->nrxchains = 2;
16289cdb1c70Snonaka }
16299cdb1c70Snonaka } else {
1630d164e220Smlelstv if (sc->mac_ver == 0x5390 || sc->mac_ver == 0x5392) {
1631d164e220Smlelstv sc->rf_rev = val;
1632d164e220Smlelstv run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val);
1633d164e220Smlelstv } else
16349cdb1c70Snonaka sc->rf_rev = (val >> 8) & 0xf;
16359cdb1c70Snonaka sc->ntxchains = (val >> 4) & 0xf;
16369cdb1c70Snonaka sc->nrxchains = val & 0xf;
16379cdb1c70Snonaka }
1638aa3d6ec1Schristos DPRINTF(("EEPROM RF rev=0x%04x chains=%dT%dR\n",
16399cdb1c70Snonaka sc->rf_rev, sc->ntxchains, sc->nrxchains));
16409cdb1c70Snonaka
16419cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_CONFIG, &val);
1642aa3d6ec1Schristos DPRINTF(("EEPROM CFG 0x%04x\n", val));
16439cdb1c70Snonaka /* check if driver should patch the DAC issue */
16449cdb1c70Snonaka if ((val >> 8) != 0xff)
16459cdb1c70Snonaka sc->patch_dac = (val >> 15) & 1;
16469cdb1c70Snonaka if ((val & 0xff) != 0xff) {
16479cdb1c70Snonaka sc->ext_5ghz_lna = (val >> 3) & 1;
16489cdb1c70Snonaka sc->ext_2ghz_lna = (val >> 2) & 1;
16499cdb1c70Snonaka /* check if RF supports automatic Tx access gain control */
16509cdb1c70Snonaka sc->calib_2ghz = sc->calib_5ghz = (val >> 1) & 1;
16519cdb1c70Snonaka /* check if we have a hardware radio switch */
16529cdb1c70Snonaka sc->rfswitch = val & 1;
16539cdb1c70Snonaka }
16549cdb1c70Snonaka
1655faca41fbSmlelstv /* Read Tx power settings. */
1656faca41fbSmlelstv if (sc->mac_ver == 0x3593)
1657faca41fbSmlelstv run_rt3593_get_txpower(sc);
1658faca41fbSmlelstv else
1659faca41fbSmlelstv run_get_txpower(sc);
16609cdb1c70Snonaka
16619cdb1c70Snonaka /* read Tx power compensation for each Tx rate */
16629cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_DELTAPWR, &val);
16639cdb1c70Snonaka delta_2ghz = delta_5ghz = 0;
16649cdb1c70Snonaka if ((val & 0xff) != 0xff && (val & 0x80)) {
16659cdb1c70Snonaka delta_2ghz = val & 0xf;
16669cdb1c70Snonaka if (!(val & 0x40)) /* negative number */
16679cdb1c70Snonaka delta_2ghz = -delta_2ghz;
16689cdb1c70Snonaka }
16699cdb1c70Snonaka val >>= 8;
16709cdb1c70Snonaka if ((val & 0xff) != 0xff && (val & 0x80)) {
16719cdb1c70Snonaka delta_5ghz = val & 0xf;
16729cdb1c70Snonaka if (!(val & 0x40)) /* negative number */
16739cdb1c70Snonaka delta_5ghz = -delta_5ghz;
16749cdb1c70Snonaka }
16759cdb1c70Snonaka DPRINTF(("power compensation=%d (2GHz), %d (5GHz)\n",
16769cdb1c70Snonaka delta_2ghz, delta_5ghz));
16779cdb1c70Snonaka
16789cdb1c70Snonaka for (ridx = 0; ridx < 5; ridx++) {
16799cdb1c70Snonaka uint32_t reg;
16809cdb1c70Snonaka
16819cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2, &val);
16829cdb1c70Snonaka reg = val;
16839cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2 + 1, &val);
16849cdb1c70Snonaka reg |= (uint32_t)val << 16;
16859cdb1c70Snonaka
16869cdb1c70Snonaka sc->txpow20mhz[ridx] = reg;
16879cdb1c70Snonaka sc->txpow40mhz_2ghz[ridx] = b4inc(reg, delta_2ghz);
16889cdb1c70Snonaka sc->txpow40mhz_5ghz[ridx] = b4inc(reg, delta_5ghz);
16899cdb1c70Snonaka
1690aa3d6ec1Schristos DPRINTF(("ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, "
1691aa3d6ec1Schristos "40MHz/5GHz=0x%08x\n", ridx, sc->txpow20mhz[ridx],
16929cdb1c70Snonaka sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx]));
16939cdb1c70Snonaka }
16949cdb1c70Snonaka
1695d164e220Smlelstv DPRINTF(("mac_ver %hx\n", sc->mac_ver));
16969cdb1c70Snonaka /* read RSSI offsets and LNA gains from EEPROM */
1697d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_2GHZ :
1698d164e220Smlelstv RT3593_EEPROM_RSSI1_2GHZ, &val);
16999cdb1c70Snonaka sc->rssi_2ghz[0] = val & 0xff; /* Ant A */
17009cdb1c70Snonaka sc->rssi_2ghz[1] = val >> 8; /* Ant B */
1701d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_2GHZ :
1702d164e220Smlelstv RT3593_EEPROM_RSSI2_2GHZ, &val);
17039cdb1c70Snonaka if (sc->mac_ver >= 0x3070) {
1704faca41fbSmlelstv if (sc->mac_ver == 0x3593) {
1705faca41fbSmlelstv sc->txmixgain_2ghz = 0;
1706faca41fbSmlelstv sc->rssi_2ghz[2] = val & 0xff; /* Ant C */
1707faca41fbSmlelstv } else {
17089cdb1c70Snonaka /*
17099cdb1c70Snonaka * On RT3070 chips (limited to 2 Rx chains), this ROM
17109cdb1c70Snonaka * field contains the Tx mixer gain for the 2GHz band.
17119cdb1c70Snonaka */
17129cdb1c70Snonaka if ((val & 0xff) != 0xff)
17139cdb1c70Snonaka sc->txmixgain_2ghz = val & 0x7;
1714faca41fbSmlelstv }
17159cdb1c70Snonaka DPRINTF(("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz));
17169cdb1c70Snonaka } else {
17179cdb1c70Snonaka sc->rssi_2ghz[2] = val & 0xff; /* Ant C */
17189cdb1c70Snonaka }
1719faca41fbSmlelstv if (sc->mac_ver == 0x3593)
1720faca41fbSmlelstv run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val);
17219cdb1c70Snonaka sc->lna[2] = val >> 8; /* channel group 2 */
17229cdb1c70Snonaka
1723faca41fbSmlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_5GHZ :
1724d164e220Smlelstv RT3593_EEPROM_RSSI1_5GHZ, &val);
17259cdb1c70Snonaka sc->rssi_5ghz[0] = val & 0xff; /* Ant A */
17269cdb1c70Snonaka sc->rssi_5ghz[1] = val >> 8; /* Ant B */
1727faca41fbSmlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_5GHZ :
1728faca41fbSmlelstv RT3593_EEPROM_RSSI2_5GHZ, &val);
17299cdb1c70Snonaka if (sc->mac_ver == 0x3572) {
17309cdb1c70Snonaka /*
17319cdb1c70Snonaka * On RT3572 chips (limited to 2 Rx chains), this ROM
17329cdb1c70Snonaka * field contains the Tx mixer gain for the 5GHz band.
17339cdb1c70Snonaka */
17349cdb1c70Snonaka if ((val & 0xff) != 0xff)
17359cdb1c70Snonaka sc->txmixgain_5ghz = val & 0x7;
17369cdb1c70Snonaka DPRINTF(("tx mixer gain=%u (5GHz)\n", sc->txmixgain_5ghz));
17379cdb1c70Snonaka } else {
17389cdb1c70Snonaka sc->rssi_5ghz[2] = val & 0xff; /* Ant C */
17399cdb1c70Snonaka }
1740faca41fbSmlelstv if (sc->mac_ver == 0x3593) {
1741faca41fbSmlelstv sc->txmixgain_5ghz = 0;
1742faca41fbSmlelstv run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val);
1743faca41fbSmlelstv }
17449cdb1c70Snonaka sc->lna[3] = val >> 8; /* channel group 3 */
17459cdb1c70Snonaka
1746faca41fbSmlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LNA :
1747faca41fbSmlelstv RT3593_EEPROM_LNA, &val);
17489cdb1c70Snonaka sc->lna[0] = val & 0xff; /* channel group 0 */
17499cdb1c70Snonaka sc->lna[1] = val >> 8; /* channel group 1 */
17509cdb1c70Snonaka
17519cdb1c70Snonaka /* fix broken 5GHz LNA entries */
17529cdb1c70Snonaka if (sc->lna[2] == 0 || sc->lna[2] == 0xff) {
17539cdb1c70Snonaka DPRINTF(("invalid LNA for channel group %d\n", 2));
17549cdb1c70Snonaka sc->lna[2] = sc->lna[1];
17559cdb1c70Snonaka }
17569cdb1c70Snonaka if (sc->lna[3] == 0 || sc->lna[3] == 0xff) {
17579cdb1c70Snonaka DPRINTF(("invalid LNA for channel group %d\n", 3));
17589cdb1c70Snonaka sc->lna[3] = sc->lna[1];
17599cdb1c70Snonaka }
17609cdb1c70Snonaka
17619cdb1c70Snonaka /* fix broken RSSI offset entries */
17629cdb1c70Snonaka for (ant = 0; ant < 3; ant++) {
17639cdb1c70Snonaka if (sc->rssi_2ghz[ant] < -10 || sc->rssi_2ghz[ant] > 10) {
17649cdb1c70Snonaka DPRINTF(("invalid RSSI%d offset: %d (2GHz)\n",
17659cdb1c70Snonaka ant + 1, sc->rssi_2ghz[ant]));
17669cdb1c70Snonaka sc->rssi_2ghz[ant] = 0;
17679cdb1c70Snonaka }
17689cdb1c70Snonaka if (sc->rssi_5ghz[ant] < -10 || sc->rssi_5ghz[ant] > 10) {
17699cdb1c70Snonaka DPRINTF(("invalid RSSI%d offset: %d (5GHz)\n",
17709cdb1c70Snonaka ant + 1, sc->rssi_5ghz[ant]));
17719cdb1c70Snonaka sc->rssi_5ghz[ant] = 0;
17729cdb1c70Snonaka }
17739cdb1c70Snonaka }
17744e8e6643Sskrll return 0;
17759cdb1c70Snonaka }
17769cdb1c70Snonaka
17779cdb1c70Snonaka static struct ieee80211_node *
run_node_alloc(struct ieee80211_node_table * nt)17789cdb1c70Snonaka run_node_alloc(struct ieee80211_node_table *nt)
17799cdb1c70Snonaka {
17809cdb1c70Snonaka struct run_node *rn =
17819cdb1c70Snonaka malloc(sizeof(struct run_node), M_DEVBUF, M_NOWAIT | M_ZERO);
17824e8e6643Sskrll return rn ? &rn->ni : NULL;
17839cdb1c70Snonaka }
17849cdb1c70Snonaka
17859cdb1c70Snonaka static int
run_media_change(struct ifnet * ifp)17869cdb1c70Snonaka run_media_change(struct ifnet *ifp)
17879cdb1c70Snonaka {
17889cdb1c70Snonaka struct run_softc *sc = ifp->if_softc;
17899cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
17909cdb1c70Snonaka uint8_t rate, ridx;
17919cdb1c70Snonaka int error;
17929cdb1c70Snonaka
17939cdb1c70Snonaka error = ieee80211_media_change(ifp);
17949cdb1c70Snonaka if (error != ENETRESET)
17954e8e6643Sskrll return error;
17969cdb1c70Snonaka
17979cdb1c70Snonaka if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
17989cdb1c70Snonaka rate = ic->ic_sup_rates[ic->ic_curmode].
17999cdb1c70Snonaka rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
18009cdb1c70Snonaka for (ridx = 0; ridx <= RT2860_RIDX_MAX; ridx++)
18019cdb1c70Snonaka if (rt2860_rates[ridx].rate == rate)
18029cdb1c70Snonaka break;
18039cdb1c70Snonaka sc->fixed_ridx = ridx;
18049cdb1c70Snonaka }
18059cdb1c70Snonaka
18069cdb1c70Snonaka if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
18079cdb1c70Snonaka run_init(ifp);
18089cdb1c70Snonaka
18094e8e6643Sskrll return 0;
18109cdb1c70Snonaka }
18119cdb1c70Snonaka
18129cdb1c70Snonaka static void
run_next_scan(void * arg)18139cdb1c70Snonaka run_next_scan(void *arg)
18149cdb1c70Snonaka {
18159cdb1c70Snonaka struct run_softc *sc = arg;
18169cdb1c70Snonaka
18179cdb1c70Snonaka if (sc->sc_ic.ic_state == IEEE80211_S_SCAN)
18189cdb1c70Snonaka ieee80211_next_scan(&sc->sc_ic);
18199cdb1c70Snonaka }
18209cdb1c70Snonaka
18219cdb1c70Snonaka static void
run_task(void * arg)18229cdb1c70Snonaka run_task(void *arg)
18239cdb1c70Snonaka {
18249cdb1c70Snonaka struct run_softc *sc = arg;
18259cdb1c70Snonaka struct run_host_cmd_ring *ring = &sc->cmdq;
18269cdb1c70Snonaka struct run_host_cmd *cmd;
18279cdb1c70Snonaka int s;
18289cdb1c70Snonaka
18299cdb1c70Snonaka /* process host commands */
18309cdb1c70Snonaka s = splusb();
18319cdb1c70Snonaka while (ring->next != ring->cur) {
18329cdb1c70Snonaka cmd = &ring->cmd[ring->next];
18339cdb1c70Snonaka splx(s);
183490e85cecSmlelstv membar_consumer();
18359cdb1c70Snonaka /* callback */
18369cdb1c70Snonaka cmd->cb(sc, cmd->data);
18379cdb1c70Snonaka s = splusb();
183890e85cecSmlelstv atomic_dec_uint(&ring->queued);
18399cdb1c70Snonaka ring->next = (ring->next + 1) % RUN_HOST_CMD_RING_COUNT;
18409cdb1c70Snonaka }
18419cdb1c70Snonaka wakeup(ring);
18429cdb1c70Snonaka splx(s);
18439cdb1c70Snonaka }
18449cdb1c70Snonaka
18459cdb1c70Snonaka static void
run_do_async(struct run_softc * sc,void (* cb)(struct run_softc *,void *),void * arg,int len)18469cdb1c70Snonaka run_do_async(struct run_softc *sc, void (*cb)(struct run_softc *, void *),
18479cdb1c70Snonaka void *arg, int len)
18489cdb1c70Snonaka {
18499cdb1c70Snonaka struct run_host_cmd_ring *ring = &sc->cmdq;
18509cdb1c70Snonaka struct run_host_cmd *cmd;
18519cdb1c70Snonaka int s;
18529cdb1c70Snonaka
18539cdb1c70Snonaka if (sc->sc_flags & RUN_DETACHING)
18549cdb1c70Snonaka return;
18559cdb1c70Snonaka
18569cdb1c70Snonaka s = splusb();
18579cdb1c70Snonaka cmd = &ring->cmd[ring->cur];
18589cdb1c70Snonaka cmd->cb = cb;
18599cdb1c70Snonaka KASSERT(len <= sizeof(cmd->data));
18609cdb1c70Snonaka memcpy(cmd->data, arg, len);
186190e85cecSmlelstv membar_producer();
18629cdb1c70Snonaka ring->cur = (ring->cur + 1) % RUN_HOST_CMD_RING_COUNT;
18639cdb1c70Snonaka
18649cdb1c70Snonaka /* if there is no pending command already, schedule a task */
186590e85cecSmlelstv if (atomic_inc_uint_nv(&ring->queued) == 1)
18669cdb1c70Snonaka usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
18679cdb1c70Snonaka splx(s);
18689cdb1c70Snonaka }
18699cdb1c70Snonaka
18709cdb1c70Snonaka static int
run_newstate(struct ieee80211com * ic,enum ieee80211_state nstate,int arg)18719cdb1c70Snonaka run_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
18729cdb1c70Snonaka {
18739cdb1c70Snonaka struct run_softc *sc = ic->ic_ifp->if_softc;
18749cdb1c70Snonaka struct run_cmd_newstate cmd;
18759cdb1c70Snonaka
18769cdb1c70Snonaka callout_stop(&sc->scan_to);
18779cdb1c70Snonaka callout_stop(&sc->calib_to);
18789cdb1c70Snonaka
18799cdb1c70Snonaka /* do it in a process context */
18809cdb1c70Snonaka cmd.state = nstate;
18819cdb1c70Snonaka cmd.arg = arg;
18824e8e6643Sskrll run_do_async(sc, run_newstate_cb, &cmd, sizeof(cmd));
18834e8e6643Sskrll return 0;
18849cdb1c70Snonaka }
18859cdb1c70Snonaka
18869cdb1c70Snonaka static void
run_newstate_cb(struct run_softc * sc,void * arg)18879cdb1c70Snonaka run_newstate_cb(struct run_softc *sc, void *arg)
18889cdb1c70Snonaka {
18899cdb1c70Snonaka struct run_cmd_newstate *cmd = arg;
18909cdb1c70Snonaka struct ifnet *ifp = &sc->sc_if;
18919cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
18929cdb1c70Snonaka enum ieee80211_state ostate;
18939cdb1c70Snonaka struct ieee80211_node *ni;
18949cdb1c70Snonaka uint32_t tmp, sta[3];
18959cdb1c70Snonaka uint8_t wcid;
18969cdb1c70Snonaka int s;
18979cdb1c70Snonaka
18989cdb1c70Snonaka s = splnet();
18999cdb1c70Snonaka ostate = ic->ic_state;
19009cdb1c70Snonaka
19019cdb1c70Snonaka if (ostate == IEEE80211_S_RUN) {
19029cdb1c70Snonaka /* turn link LED off */
19039cdb1c70Snonaka run_set_leds(sc, RT2860_LED_RADIO);
19049cdb1c70Snonaka }
19059cdb1c70Snonaka
19069cdb1c70Snonaka switch (cmd->state) {
19079cdb1c70Snonaka case IEEE80211_S_INIT:
19089cdb1c70Snonaka if (ostate == IEEE80211_S_RUN) {
19099cdb1c70Snonaka /* abort TSF synchronization */
19109cdb1c70Snonaka run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
19119cdb1c70Snonaka run_write(sc, RT2860_BCN_TIME_CFG,
19129cdb1c70Snonaka tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
19139cdb1c70Snonaka RT2860_TBTT_TIMER_EN));
19149cdb1c70Snonaka }
19159cdb1c70Snonaka break;
19169cdb1c70Snonaka
19179cdb1c70Snonaka case IEEE80211_S_SCAN:
19189cdb1c70Snonaka run_set_chan(sc, ic->ic_curchan);
19199cdb1c70Snonaka callout_schedule(&sc->scan_to, hz / 5);
19209cdb1c70Snonaka break;
19219cdb1c70Snonaka
19229cdb1c70Snonaka case IEEE80211_S_AUTH:
19239cdb1c70Snonaka case IEEE80211_S_ASSOC:
19249cdb1c70Snonaka run_set_chan(sc, ic->ic_curchan);
19259cdb1c70Snonaka break;
19269cdb1c70Snonaka
19279cdb1c70Snonaka case IEEE80211_S_RUN:
19289cdb1c70Snonaka run_set_chan(sc, ic->ic_curchan);
19299cdb1c70Snonaka
19309cdb1c70Snonaka ni = ic->ic_bss;
19319cdb1c70Snonaka
19329cdb1c70Snonaka if (ic->ic_opmode != IEEE80211_M_MONITOR) {
19339cdb1c70Snonaka run_updateslot(ifp);
19349cdb1c70Snonaka run_enable_mrr(sc);
19359cdb1c70Snonaka run_set_txpreamble(sc);
19369cdb1c70Snonaka run_set_basicrates(sc);
19379cdb1c70Snonaka run_set_bssid(sc, ni->ni_bssid);
19389cdb1c70Snonaka }
19399cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY
19409cdb1c70Snonaka if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
19419cdb1c70Snonaka ic->ic_opmode == IEEE80211_M_IBSS)
19429cdb1c70Snonaka (void)run_setup_beacon(sc);
19439cdb1c70Snonaka #endif
19449cdb1c70Snonaka if (ic->ic_opmode == IEEE80211_M_STA) {
19459cdb1c70Snonaka /* add BSS entry to the WCID table */
19469cdb1c70Snonaka wcid = RUN_AID2WCID(ni->ni_associd);
19479cdb1c70Snonaka run_write_region_1(sc, RT2860_WCID_ENTRY(wcid),
19489cdb1c70Snonaka ni->ni_macaddr, IEEE80211_ADDR_LEN);
19499cdb1c70Snonaka
19509cdb1c70Snonaka /* fake a join to init the tx rate */
19519cdb1c70Snonaka run_newassoc(ni, 1);
19529cdb1c70Snonaka }
19539cdb1c70Snonaka if (ic->ic_opmode != IEEE80211_M_MONITOR) {
19549cdb1c70Snonaka run_enable_tsf_sync(sc);
19559cdb1c70Snonaka
19569cdb1c70Snonaka /* clear statistic registers used by AMRR */
19579cdb1c70Snonaka run_read_region_1(sc, RT2860_TX_STA_CNT0,
19584e8e6643Sskrll (uint8_t *)sta, sizeof(sta));
19599cdb1c70Snonaka /* start calibration timer */
19609cdb1c70Snonaka callout_schedule(&sc->calib_to, hz);
19619cdb1c70Snonaka }
19629cdb1c70Snonaka
19639cdb1c70Snonaka /* turn link LED on */
19649cdb1c70Snonaka run_set_leds(sc, RT2860_LED_RADIO |
19659cdb1c70Snonaka (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ?
19669cdb1c70Snonaka RT2860_LED_LINK_2GHZ : RT2860_LED_LINK_5GHZ));
19679cdb1c70Snonaka break;
19689cdb1c70Snonaka }
19699cdb1c70Snonaka (void)sc->sc_newstate(ic, cmd->state, cmd->arg);
19709cdb1c70Snonaka splx(s);
19719cdb1c70Snonaka }
19729cdb1c70Snonaka
19739cdb1c70Snonaka static int
run_updateedca(struct ieee80211com * ic)19749cdb1c70Snonaka run_updateedca(struct ieee80211com *ic)
19759cdb1c70Snonaka {
19769cdb1c70Snonaka
19779cdb1c70Snonaka /* do it in a process context */
19789cdb1c70Snonaka run_do_async(ic->ic_ifp->if_softc, run_updateedca_cb, NULL, 0);
19794e8e6643Sskrll return 0;
19809cdb1c70Snonaka }
19819cdb1c70Snonaka
19829cdb1c70Snonaka /* ARGSUSED */
19839cdb1c70Snonaka static void
run_updateedca_cb(struct run_softc * sc,void * arg)19849cdb1c70Snonaka run_updateedca_cb(struct run_softc *sc, void *arg)
19859cdb1c70Snonaka {
19869cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
19879cdb1c70Snonaka int s, aci;
19889cdb1c70Snonaka
19899cdb1c70Snonaka s = splnet();
19909cdb1c70Snonaka /* update MAC TX configuration registers */
19919cdb1c70Snonaka for (aci = 0; aci < WME_NUM_AC; aci++) {
19929cdb1c70Snonaka run_write(sc, RT2860_EDCA_AC_CFG(aci),
19939cdb1c70Snonaka ic->ic_wme.wme_params[aci].wmep_logcwmax << 16 |
19949cdb1c70Snonaka ic->ic_wme.wme_params[aci].wmep_logcwmin << 12 |
19959cdb1c70Snonaka ic->ic_wme.wme_params[aci].wmep_aifsn << 8 |
19969cdb1c70Snonaka ic->ic_wme.wme_params[aci].wmep_txopLimit);
19979cdb1c70Snonaka }
19989cdb1c70Snonaka
19999cdb1c70Snonaka /* update SCH/DMA registers too */
20009cdb1c70Snonaka run_write(sc, RT2860_WMM_AIFSN_CFG,
20019cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VO].wmep_aifsn << 12 |
20029cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VI].wmep_aifsn << 8 |
20039cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BK].wmep_aifsn << 4 |
20049cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BE].wmep_aifsn);
20059cdb1c70Snonaka run_write(sc, RT2860_WMM_CWMIN_CFG,
20069cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VO].wmep_logcwmin << 12 |
20079cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VI].wmep_logcwmin << 8 |
20089cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BK].wmep_logcwmin << 4 |
20099cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BE].wmep_logcwmin);
20109cdb1c70Snonaka run_write(sc, RT2860_WMM_CWMAX_CFG,
20119cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VO].wmep_logcwmax << 12 |
20129cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VI].wmep_logcwmax << 8 |
20139cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BK].wmep_logcwmax << 4 |
20149cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BE].wmep_logcwmax);
20159cdb1c70Snonaka run_write(sc, RT2860_WMM_TXOP0_CFG,
20169cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BK].wmep_txopLimit << 16 |
20179cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BE].wmep_txopLimit);
20189cdb1c70Snonaka run_write(sc, RT2860_WMM_TXOP1_CFG,
20199cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VO].wmep_txopLimit << 16 |
20209cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VI].wmep_txopLimit);
20219cdb1c70Snonaka splx(s);
20229cdb1c70Snonaka }
20239cdb1c70Snonaka
20249cdb1c70Snonaka #ifdef RUN_HWCRYPTO
20259cdb1c70Snonaka static int
run_set_key(struct ieee80211com * ic,const struct ieee80211_key * k,const uint8_t * mac)20269cdb1c70Snonaka run_set_key(struct ieee80211com *ic, const struct ieee80211_key *k,
20279cdb1c70Snonaka const uint8_t *mac)
20289cdb1c70Snonaka {
20299cdb1c70Snonaka struct run_softc *sc = ic->ic_ifp->if_softc;
20309cdb1c70Snonaka struct ieee80211_node *ni = ic->ic_bss;
20319cdb1c70Snonaka struct run_cmd_key cmd;
20329cdb1c70Snonaka
20339cdb1c70Snonaka /* do it in a process context */
20349cdb1c70Snonaka cmd.key = *k;
20359cdb1c70Snonaka cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
20364e8e6643Sskrll run_do_async(sc, run_set_key_cb, &cmd, sizeof(cmd));
20379cdb1c70Snonaka return 1;
20389cdb1c70Snonaka }
20399cdb1c70Snonaka
20409cdb1c70Snonaka static void
run_set_key_cb(struct run_softc * sc,void * arg)20419cdb1c70Snonaka run_set_key_cb(struct run_softc *sc, void *arg)
20429cdb1c70Snonaka {
20439cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY
20449cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
20459cdb1c70Snonaka #endif
20469cdb1c70Snonaka struct run_cmd_key *cmd = arg;
20479cdb1c70Snonaka struct ieee80211_key *k = &cmd->key;
20489cdb1c70Snonaka uint32_t attr;
20499cdb1c70Snonaka uint16_t base;
20509cdb1c70Snonaka uint8_t mode, wcid, iv[8];
20519cdb1c70Snonaka
20529cdb1c70Snonaka /* map net80211 cipher to RT2860 security mode */
20539cdb1c70Snonaka switch (k->wk_cipher->ic_cipher) {
20549cdb1c70Snonaka case IEEE80211_CIPHER_WEP:
20559cdb1c70Snonaka k->wk_flags |= IEEE80211_KEY_GROUP; /* XXX */
20569cdb1c70Snonaka if (k->wk_keylen == 5)
20579cdb1c70Snonaka mode = RT2860_MODE_WEP40;
20589cdb1c70Snonaka else
20599cdb1c70Snonaka mode = RT2860_MODE_WEP104;
20609cdb1c70Snonaka break;
20619cdb1c70Snonaka case IEEE80211_CIPHER_TKIP:
20629cdb1c70Snonaka mode = RT2860_MODE_TKIP;
20639cdb1c70Snonaka break;
20649cdb1c70Snonaka case IEEE80211_CIPHER_AES_CCM:
20659cdb1c70Snonaka mode = RT2860_MODE_AES_CCMP;
20669cdb1c70Snonaka break;
20679cdb1c70Snonaka default:
20689cdb1c70Snonaka return;
20699cdb1c70Snonaka }
20709cdb1c70Snonaka
20719cdb1c70Snonaka if (k->wk_flags & IEEE80211_KEY_GROUP) {
20729cdb1c70Snonaka wcid = 0; /* NB: update WCID0 for group keys */
20739cdb1c70Snonaka base = RT2860_SKEY(0, k->wk_keyix);
20749cdb1c70Snonaka } else {
20759cdb1c70Snonaka wcid = RUN_AID2WCID(cmd->associd);
20769cdb1c70Snonaka base = RT2860_PKEY(wcid);
20779cdb1c70Snonaka }
20789cdb1c70Snonaka
20799cdb1c70Snonaka if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) {
20809cdb1c70Snonaka run_write_region_1(sc, base, k->wk_key, 16);
20819cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY
20829cdb1c70Snonaka if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
20839cdb1c70Snonaka run_write_region_1(sc, base + 16, &k->wk_key[16], 8);
20849cdb1c70Snonaka run_write_region_1(sc, base + 24, &k->wk_key[24], 8);
20859cdb1c70Snonaka } else
20869cdb1c70Snonaka #endif
20879cdb1c70Snonaka {
20889cdb1c70Snonaka run_write_region_1(sc, base + 16, &k->wk_key[24], 8);
20899cdb1c70Snonaka run_write_region_1(sc, base + 24, &k->wk_key[16], 8);
20909cdb1c70Snonaka }
20919cdb1c70Snonaka } else {
20929cdb1c70Snonaka /* roundup len to 16-bit: XXX fix write_region_1() instead */
20939cdb1c70Snonaka run_write_region_1(sc, base, k->wk_key,
20949cdb1c70Snonaka (k->wk_keylen + 1) & ~1);
20959cdb1c70Snonaka }
20969cdb1c70Snonaka
20979cdb1c70Snonaka if (!(k->wk_flags & IEEE80211_KEY_GROUP) ||
20989cdb1c70Snonaka (k->wk_flags & IEEE80211_KEY_XMIT)) {
20999cdb1c70Snonaka /* set initial packet number in IV+EIV */
21009cdb1c70Snonaka if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_WEP) {
21014e8e6643Sskrll memset(iv, 0, sizeof(iv));
21029cdb1c70Snonaka iv[3] = sc->sc_ic.ic_crypto.cs_def_txkey << 6;
21039cdb1c70Snonaka } else {
21049cdb1c70Snonaka if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) {
21059cdb1c70Snonaka iv[0] = k->wk_keytsc >> 8;
21069cdb1c70Snonaka iv[1] = (iv[0] | 0x20) & 0x7f;
21079cdb1c70Snonaka iv[2] = k->wk_keytsc;
21089cdb1c70Snonaka } else /* CCMP */ {
21099cdb1c70Snonaka iv[0] = k->wk_keytsc;
21109cdb1c70Snonaka iv[1] = k->wk_keytsc >> 8;
21119cdb1c70Snonaka iv[2] = 0;
21129cdb1c70Snonaka }
21139cdb1c70Snonaka iv[3] = k->wk_keyix << 6 | IEEE80211_WEP_EXTIV;
21149cdb1c70Snonaka iv[4] = k->wk_keytsc >> 16;
21159cdb1c70Snonaka iv[5] = k->wk_keytsc >> 24;
21169cdb1c70Snonaka iv[6] = k->wk_keytsc >> 32;
21179cdb1c70Snonaka iv[7] = k->wk_keytsc >> 40;
21189cdb1c70Snonaka }
21199cdb1c70Snonaka run_write_region_1(sc, RT2860_IVEIV(wcid), iv, 8);
21209cdb1c70Snonaka }
21219cdb1c70Snonaka
21229cdb1c70Snonaka if (k->wk_flags & IEEE80211_KEY_GROUP) {
21239cdb1c70Snonaka /* install group key */
21249cdb1c70Snonaka run_read(sc, RT2860_SKEY_MODE_0_7, &attr);
21259cdb1c70Snonaka attr &= ~(0xf << (k->wk_keyix * 4));
21269cdb1c70Snonaka attr |= mode << (k->wk_keyix * 4);
21279cdb1c70Snonaka run_write(sc, RT2860_SKEY_MODE_0_7, attr);
21289cdb1c70Snonaka } else {
21299cdb1c70Snonaka /* install pairwise key */
21309cdb1c70Snonaka run_read(sc, RT2860_WCID_ATTR(wcid), &attr);
21319cdb1c70Snonaka attr = (attr & ~0xf) | (mode << 1) | RT2860_RX_PKEY_EN;
21329cdb1c70Snonaka run_write(sc, RT2860_WCID_ATTR(wcid), attr);
21339cdb1c70Snonaka }
21349cdb1c70Snonaka }
21359cdb1c70Snonaka
21369cdb1c70Snonaka static int
run_delete_key(struct ieee80211com * ic,const struct ieee80211_key * k)21379cdb1c70Snonaka run_delete_key(struct ieee80211com *ic, const struct ieee80211_key *k)
21389cdb1c70Snonaka {
21399cdb1c70Snonaka struct run_softc *sc = ic->ic_ifp->if_softc;
21409cdb1c70Snonaka struct ieee80211_node *ni = ic->ic_bss;
21419cdb1c70Snonaka struct run_cmd_key cmd;
21429cdb1c70Snonaka
21439cdb1c70Snonaka /* do it in a process context */
21449cdb1c70Snonaka cmd.key = *k;
21459cdb1c70Snonaka cmd.associd = (ni != NULL) ? ni->ni_associd : 0;
21464e8e6643Sskrll run_do_async(sc, run_delete_key_cb, &cmd, sizeof(cmd));
21479cdb1c70Snonaka return 1;
21489cdb1c70Snonaka }
21499cdb1c70Snonaka
21509cdb1c70Snonaka static void
run_delete_key_cb(struct run_softc * sc,void * arg)21519cdb1c70Snonaka run_delete_key_cb(struct run_softc *sc, void *arg)
21529cdb1c70Snonaka {
21539cdb1c70Snonaka struct run_cmd_key *cmd = arg;
21549cdb1c70Snonaka struct ieee80211_key *k = &cmd->key;
21559cdb1c70Snonaka uint32_t attr;
21569cdb1c70Snonaka uint8_t wcid;
21579cdb1c70Snonaka
21589cdb1c70Snonaka if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_WEP)
21599cdb1c70Snonaka k->wk_flags |= IEEE80211_KEY_GROUP; /* XXX */
21609cdb1c70Snonaka
21619cdb1c70Snonaka if (k->wk_flags & IEEE80211_KEY_GROUP) {
21629cdb1c70Snonaka /* remove group key */
21639cdb1c70Snonaka run_read(sc, RT2860_SKEY_MODE_0_7, &attr);
21649cdb1c70Snonaka attr &= ~(0xf << (k->wk_keyix * 4));
21659cdb1c70Snonaka run_write(sc, RT2860_SKEY_MODE_0_7, attr);
21669cdb1c70Snonaka
21679cdb1c70Snonaka } else {
21689cdb1c70Snonaka /* remove pairwise key */
21699cdb1c70Snonaka wcid = RUN_AID2WCID(cmd->associd);
21709cdb1c70Snonaka run_read(sc, RT2860_WCID_ATTR(wcid), &attr);
21719cdb1c70Snonaka attr &= ~0xf;
21729cdb1c70Snonaka run_write(sc, RT2860_WCID_ATTR(wcid), attr);
21739cdb1c70Snonaka }
21749cdb1c70Snonaka }
21759cdb1c70Snonaka #endif
21769cdb1c70Snonaka
21779cdb1c70Snonaka static void
run_calibrate_to(void * arg)21789cdb1c70Snonaka run_calibrate_to(void *arg)
21799cdb1c70Snonaka {
21809cdb1c70Snonaka
21819cdb1c70Snonaka /* do it in a process context */
21829cdb1c70Snonaka run_do_async(arg, run_calibrate_cb, NULL, 0);
21839cdb1c70Snonaka /* next timeout will be rescheduled in the calibration task */
21849cdb1c70Snonaka }
21859cdb1c70Snonaka
21869cdb1c70Snonaka /* ARGSUSED */
21879cdb1c70Snonaka static void
run_calibrate_cb(struct run_softc * sc,void * arg)21889cdb1c70Snonaka run_calibrate_cb(struct run_softc *sc, void *arg)
21899cdb1c70Snonaka {
21909cdb1c70Snonaka struct ifnet *ifp = &sc->sc_if;
21919cdb1c70Snonaka uint32_t sta[3];
21929cdb1c70Snonaka int s, error;
21939cdb1c70Snonaka
21949cdb1c70Snonaka /* read statistic counters (clear on read) and update AMRR state */
21959cdb1c70Snonaka error = run_read_region_1(sc, RT2860_TX_STA_CNT0, (uint8_t *)sta,
21964e8e6643Sskrll sizeof(sta));
21979cdb1c70Snonaka if (error != 0)
21989cdb1c70Snonaka goto skip;
21999cdb1c70Snonaka
22009cdb1c70Snonaka DPRINTF(("retrycnt=%d txcnt=%d failcnt=%d\n",
22019cdb1c70Snonaka le32toh(sta[1]) >> 16, le32toh(sta[1]) & 0xffff,
22029cdb1c70Snonaka le32toh(sta[0]) & 0xffff));
22039cdb1c70Snonaka
22049cdb1c70Snonaka s = splnet();
22059cdb1c70Snonaka /* count failed TX as errors */
2206cdaa0e91Sthorpej if_statadd(ifp, if_oerrors, le32toh(sta[0]) & 0xffff);
22079cdb1c70Snonaka
22089cdb1c70Snonaka sc->amn.amn_retrycnt =
22099cdb1c70Snonaka (le32toh(sta[0]) & 0xffff) + /* failed TX count */
22109cdb1c70Snonaka (le32toh(sta[1]) >> 16); /* TX retransmission count */
22119cdb1c70Snonaka
22129cdb1c70Snonaka sc->amn.amn_txcnt =
22139cdb1c70Snonaka sc->amn.amn_retrycnt +
22149cdb1c70Snonaka (le32toh(sta[1]) & 0xffff); /* successful TX count */
22159cdb1c70Snonaka
22169cdb1c70Snonaka ieee80211_amrr_choose(&sc->amrr, sc->sc_ic.ic_bss, &sc->amn);
22179cdb1c70Snonaka splx(s);
22189cdb1c70Snonaka
22199cdb1c70Snonaka skip: callout_schedule(&sc->calib_to, hz);
22209cdb1c70Snonaka }
22219cdb1c70Snonaka
22229cdb1c70Snonaka static void
run_newassoc(struct ieee80211_node * ni,int isnew)22239cdb1c70Snonaka run_newassoc(struct ieee80211_node *ni, int isnew)
22249cdb1c70Snonaka {
22259cdb1c70Snonaka struct run_softc *sc = ni->ni_ic->ic_ifp->if_softc;
22269cdb1c70Snonaka struct run_node *rn = (void *)ni;
22279cdb1c70Snonaka struct ieee80211_rateset *rs = &ni->ni_rates;
22289cdb1c70Snonaka uint8_t rate;
22299cdb1c70Snonaka int ridx, i, j;
22309cdb1c70Snonaka
22319cdb1c70Snonaka DPRINTF(("new assoc isnew=%d addr=%s\n",
22329cdb1c70Snonaka isnew, ether_sprintf(ni->ni_macaddr)));
22339cdb1c70Snonaka
22349cdb1c70Snonaka ieee80211_amrr_node_init(&sc->amrr, &sc->amn);
22359cdb1c70Snonaka /* start at lowest available bit-rate, AMRR will raise */
22369cdb1c70Snonaka ni->ni_txrate = 0;
22379cdb1c70Snonaka
22389cdb1c70Snonaka for (i = 0; i < rs->rs_nrates; i++) {
22399cdb1c70Snonaka rate = rs->rs_rates[i] & IEEE80211_RATE_VAL;
22409cdb1c70Snonaka /* convert 802.11 rate to hardware rate index */
22419cdb1c70Snonaka for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++)
22429cdb1c70Snonaka if (rt2860_rates[ridx].rate == rate)
22439cdb1c70Snonaka break;
22449cdb1c70Snonaka rn->ridx[i] = ridx;
22459cdb1c70Snonaka /* determine rate of control response frames */
22469cdb1c70Snonaka for (j = i; j >= 0; j--) {
22479cdb1c70Snonaka if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC) &&
22489cdb1c70Snonaka rt2860_rates[rn->ridx[i]].phy ==
22499cdb1c70Snonaka rt2860_rates[rn->ridx[j]].phy)
22509cdb1c70Snonaka break;
22519cdb1c70Snonaka }
22529cdb1c70Snonaka if (j >= 0) {
22539cdb1c70Snonaka rn->ctl_ridx[i] = rn->ridx[j];
22549cdb1c70Snonaka } else {
22559cdb1c70Snonaka /* no basic rate found, use mandatory one */
22569cdb1c70Snonaka rn->ctl_ridx[i] = rt2860_rates[ridx].ctl_ridx;
22579cdb1c70Snonaka }
2258aa3d6ec1Schristos DPRINTF(("rate=0x%02x ridx=%d ctl_ridx=%d\n",
22599cdb1c70Snonaka rs->rs_rates[i], rn->ridx[i], rn->ctl_ridx[i]));
22609cdb1c70Snonaka }
22619cdb1c70Snonaka }
22629cdb1c70Snonaka
22639cdb1c70Snonaka /*
22649cdb1c70Snonaka * Return the Rx chain with the highest RSSI for a given frame.
22659cdb1c70Snonaka */
22669cdb1c70Snonaka static __inline uint8_t
run_maxrssi_chain(struct run_softc * sc,const struct rt2860_rxwi * rxwi)22679cdb1c70Snonaka run_maxrssi_chain(struct run_softc *sc, const struct rt2860_rxwi *rxwi)
22689cdb1c70Snonaka {
22699cdb1c70Snonaka uint8_t rxchain = 0;
22709cdb1c70Snonaka
22719cdb1c70Snonaka if (sc->nrxchains > 1) {
22729cdb1c70Snonaka if (rxwi->rssi[1] > rxwi->rssi[rxchain])
22739cdb1c70Snonaka rxchain = 1;
22749cdb1c70Snonaka if (sc->nrxchains > 2)
22759cdb1c70Snonaka if (rxwi->rssi[2] > rxwi->rssi[rxchain])
22769cdb1c70Snonaka rxchain = 2;
22779cdb1c70Snonaka }
22784e8e6643Sskrll return rxchain;
22799cdb1c70Snonaka }
22809cdb1c70Snonaka
22819cdb1c70Snonaka static void
run_rx_frame(struct run_softc * sc,uint8_t * buf,int dmalen)22829cdb1c70Snonaka run_rx_frame(struct run_softc *sc, uint8_t *buf, int dmalen)
22839cdb1c70Snonaka {
22849cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
22859cdb1c70Snonaka struct ifnet *ifp = &sc->sc_if;
22869cdb1c70Snonaka struct ieee80211_frame *wh;
22879cdb1c70Snonaka struct ieee80211_node *ni;
22889cdb1c70Snonaka struct rt2870_rxd *rxd;
22899cdb1c70Snonaka struct rt2860_rxwi *rxwi;
22909cdb1c70Snonaka struct mbuf *m;
22919cdb1c70Snonaka uint32_t flags;
2292faca41fbSmlelstv uint16_t len, rxwisize, phy;
22939cdb1c70Snonaka uint8_t ant, rssi;
22949cdb1c70Snonaka int s;
22959cdb1c70Snonaka #ifdef RUN_HWCRYPTO
22969cdb1c70Snonaka int decrypted = 0;
22979cdb1c70Snonaka #endif
22989cdb1c70Snonaka
22999cdb1c70Snonaka rxwi = (struct rt2860_rxwi *)buf;
2300d164e220Smlelstv rxwisize = sizeof(struct rt2860_rxwi);
2301d164e220Smlelstv if (sc->mac_ver == 0x5592)
2302d164e220Smlelstv rxwisize += sizeof(uint64_t);
2303d164e220Smlelstv else if (sc->mac_ver == 0x3593)
2304d164e220Smlelstv rxwisize += sizeof(uint32_t);
23059cdb1c70Snonaka len = le16toh(rxwi->len) & 0xfff;
23069cdb1c70Snonaka if (__predict_false(len > dmalen)) {
23079cdb1c70Snonaka DPRINTF(("bad RXWI length %u > %u\n", len, dmalen));
23089cdb1c70Snonaka return;
23099cdb1c70Snonaka }
23109cdb1c70Snonaka /* Rx descriptor is located at the end */
23119cdb1c70Snonaka rxd = (struct rt2870_rxd *)(buf + dmalen);
23129cdb1c70Snonaka flags = le32toh(rxd->flags);
23139cdb1c70Snonaka
23149cdb1c70Snonaka if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) {
2315cdaa0e91Sthorpej if_statinc(ifp, if_ierrors);
23169cdb1c70Snonaka return;
23179cdb1c70Snonaka }
23189cdb1c70Snonaka
2319d164e220Smlelstv wh = (struct ieee80211_frame *)(buf + rxwisize);
23209cdb1c70Snonaka
23219cdb1c70Snonaka if (__predict_false((flags & RT2860_RX_MICERR))) {
23229cdb1c70Snonaka /* report MIC failures to net80211 for TKIP */
23239cdb1c70Snonaka ieee80211_notify_michael_failure(ic, wh, 0/* XXX */);
2324cdaa0e91Sthorpej if_statinc(ifp, if_ierrors);
23259cdb1c70Snonaka return;
23269cdb1c70Snonaka }
23279cdb1c70Snonaka
23289cdb1c70Snonaka if (flags & RT2860_RX_L2PAD) {
23299cdb1c70Snonaka u_int hdrlen = ieee80211_hdrspace(ic, wh);
2330ef294642Smaxv memmove((uint8_t *)wh + 2, wh, hdrlen);
23319cdb1c70Snonaka wh = (struct ieee80211_frame *)((uint8_t *)wh + 2);
23329cdb1c70Snonaka }
23339cdb1c70Snonaka
2334d164e220Smlelstv #ifdef RUN_HWCRYPTO
2335d164e220Smlelstv if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
2336d164e220Smlelstv wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
2337d164e220Smlelstv decrypted = 1;
2338d164e220Smlelstv }
2339d164e220Smlelstv #endif
2340d164e220Smlelstv
23419cdb1c70Snonaka /* could use m_devget but net80211 wants contig mgmt frames */
23429cdb1c70Snonaka MGETHDR(m, M_DONTWAIT, MT_DATA);
23439cdb1c70Snonaka if (__predict_false(m == NULL)) {
2344cdaa0e91Sthorpej if_statinc(ifp, if_ierrors);
23459cdb1c70Snonaka return;
23469cdb1c70Snonaka }
23479cdb1c70Snonaka if (len > MHLEN) {
234889e3596fSmartin if (__predict_true(len <= MCLBYTES))
23499cdb1c70Snonaka MCLGET(m, M_DONTWAIT);
23509cdb1c70Snonaka if (__predict_false(!(m->m_flags & M_EXT))) {
2351cdaa0e91Sthorpej if_statinc(ifp, if_ierrors);
23529cdb1c70Snonaka m_freem(m);
23539cdb1c70Snonaka return;
23549cdb1c70Snonaka }
23559cdb1c70Snonaka }
23569cdb1c70Snonaka /* finalize mbuf */
2357d938d837Sozaki-r m_set_rcvif(m, ifp);
23589cdb1c70Snonaka memcpy(mtod(m, void *), wh, len);
23599cdb1c70Snonaka m->m_pkthdr.len = m->m_len = len;
23609cdb1c70Snonaka
23619cdb1c70Snonaka ant = run_maxrssi_chain(sc, rxwi);
23629cdb1c70Snonaka rssi = rxwi->rssi[ant];
23639cdb1c70Snonaka
23649cdb1c70Snonaka if (__predict_false(sc->sc_drvbpf != NULL)) {
23659cdb1c70Snonaka struct run_rx_radiotap_header *tap = &sc->sc_rxtap;
23669cdb1c70Snonaka
23679cdb1c70Snonaka tap->wr_flags = 0;
23689cdb1c70Snonaka tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
23699cdb1c70Snonaka tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
23709cdb1c70Snonaka tap->wr_antsignal = rssi;
23719cdb1c70Snonaka tap->wr_antenna = ant;
23729cdb1c70Snonaka tap->wr_dbm_antsignal = run_rssi2dbm(sc, rssi, ant);
23739cdb1c70Snonaka tap->wr_rate = 2; /* in case it can't be found below */
23749cdb1c70Snonaka phy = le16toh(rxwi->phy);
23759cdb1c70Snonaka switch (phy & RT2860_PHY_MODE) {
23769cdb1c70Snonaka case RT2860_PHY_CCK:
23779cdb1c70Snonaka switch ((phy & RT2860_PHY_MCS) & ~RT2860_PHY_SHPRE) {
23789cdb1c70Snonaka case 0: tap->wr_rate = 2; break;
23799cdb1c70Snonaka case 1: tap->wr_rate = 4; break;
23809cdb1c70Snonaka case 2: tap->wr_rate = 11; break;
23819cdb1c70Snonaka case 3: tap->wr_rate = 22; break;
23829cdb1c70Snonaka }
23839cdb1c70Snonaka if (phy & RT2860_PHY_SHPRE)
23849cdb1c70Snonaka tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
23859cdb1c70Snonaka break;
23869cdb1c70Snonaka case RT2860_PHY_OFDM:
23879cdb1c70Snonaka switch (phy & RT2860_PHY_MCS) {
23889cdb1c70Snonaka case 0: tap->wr_rate = 12; break;
23899cdb1c70Snonaka case 1: tap->wr_rate = 18; break;
23909cdb1c70Snonaka case 2: tap->wr_rate = 24; break;
23919cdb1c70Snonaka case 3: tap->wr_rate = 36; break;
23929cdb1c70Snonaka case 4: tap->wr_rate = 48; break;
23939cdb1c70Snonaka case 5: tap->wr_rate = 72; break;
23949cdb1c70Snonaka case 6: tap->wr_rate = 96; break;
23959cdb1c70Snonaka case 7: tap->wr_rate = 108; break;
23969cdb1c70Snonaka }
23979cdb1c70Snonaka break;
23989cdb1c70Snonaka }
23993cd62456Smsaitoh bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m, BPF_D_IN);
24009cdb1c70Snonaka }
24019cdb1c70Snonaka
24029cdb1c70Snonaka s = splnet();
24039cdb1c70Snonaka ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
24049cdb1c70Snonaka #ifdef RUN_HWCRYPTO
24059cdb1c70Snonaka if (decrypted) {
24069cdb1c70Snonaka uint32_t icflags = ic->ic_flags;
24079cdb1c70Snonaka
24089cdb1c70Snonaka ic->ic_flags &= ~IEEE80211_F_DROPUNENC; /* XXX */
24099cdb1c70Snonaka ieee80211_input(ic, m, ni, rssi, 0);
24109cdb1c70Snonaka ic->ic_flags = icflags;
24119cdb1c70Snonaka } else
24129cdb1c70Snonaka #endif
24139cdb1c70Snonaka ieee80211_input(ic, m, ni, rssi, 0);
24149cdb1c70Snonaka
24159cdb1c70Snonaka /* node is no longer needed */
24169cdb1c70Snonaka ieee80211_free_node(ni);
24179cdb1c70Snonaka
24189cdb1c70Snonaka /*
24199cdb1c70Snonaka * In HostAP mode, ieee80211_input() will enqueue packets in if_snd
24209cdb1c70Snonaka * without calling if_start().
24219cdb1c70Snonaka */
24229cdb1c70Snonaka if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_flags & IFF_OACTIVE))
24239cdb1c70Snonaka run_start(ifp);
24249cdb1c70Snonaka
24259cdb1c70Snonaka splx(s);
24269cdb1c70Snonaka }
24279cdb1c70Snonaka
24289cdb1c70Snonaka static void
run_rxeof(struct usbd_xfer * xfer,void * priv,usbd_status status)24294e8e6643Sskrll run_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
24309cdb1c70Snonaka {
24319cdb1c70Snonaka struct run_rx_data *data = priv;
24329cdb1c70Snonaka struct run_softc *sc = data->sc;
24339cdb1c70Snonaka uint8_t *buf;
24349cdb1c70Snonaka uint32_t dmalen;
24359cdb1c70Snonaka int xferlen;
2436d164e220Smlelstv uint16_t rxwisize;
24379cdb1c70Snonaka
24388f96d6f5Smlelstv if (__predict_false(sc->sc_flags & RUN_DETACHING))
24398f96d6f5Smlelstv return;
24408f96d6f5Smlelstv
2441d164e220Smlelstv rxwisize = sizeof(struct rt2860_rxwi);
2442d164e220Smlelstv if (sc->mac_ver == 0x5592)
2443d164e220Smlelstv rxwisize += sizeof(uint64_t);
2444d164e220Smlelstv else if (sc->mac_ver == 0x3593)
2445d164e220Smlelstv rxwisize += sizeof(uint32_t);
2446d164e220Smlelstv
24479cdb1c70Snonaka if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
2448d164e220Smlelstv DPRINTF(("RX status=%s\n", usbd_errstr(status)));
24499cdb1c70Snonaka if (status == USBD_STALLED)
24509cdb1c70Snonaka usbd_clear_endpoint_stall_async(sc->rxq.pipeh);
24519cdb1c70Snonaka if (status != USBD_CANCELLED)
24529cdb1c70Snonaka goto skip;
24539cdb1c70Snonaka return;
24549cdb1c70Snonaka }
24559cdb1c70Snonaka usbd_get_xfer_status(xfer, NULL, NULL, &xferlen, NULL);
24569cdb1c70Snonaka
24579cdb1c70Snonaka if (__predict_false(xferlen < (int)(sizeof(uint32_t) +
2458d164e220Smlelstv rxwisize + sizeof(struct rt2870_rxd)))) {
24599cdb1c70Snonaka DPRINTF(("xfer too short %d\n", xferlen));
24609cdb1c70Snonaka goto skip;
24619cdb1c70Snonaka }
24629cdb1c70Snonaka
24639cdb1c70Snonaka /* HW can aggregate multiple 802.11 frames in a single USB xfer */
24649cdb1c70Snonaka buf = data->buf;
24659cdb1c70Snonaka while (xferlen > 8) {
24669cdb1c70Snonaka dmalen = le32toh(*(uint32_t *)buf) & 0xffff;
24679cdb1c70Snonaka
2468faca41fbSmlelstv if (__predict_false((dmalen >= (uint32_t)-8) || dmalen == 0 ||
2469faca41fbSmlelstv (dmalen & 3) != 0)) {
24709cdb1c70Snonaka DPRINTF(("bad DMA length %u (%x)\n", dmalen, dmalen));
24719cdb1c70Snonaka break;
24729cdb1c70Snonaka }
24739cdb1c70Snonaka if (__predict_false(dmalen + 8 > (uint32_t)xferlen)) {
24749cdb1c70Snonaka DPRINTF(("bad DMA length %u > %d\n",
24759cdb1c70Snonaka dmalen + 8, xferlen));
24769cdb1c70Snonaka break;
24779cdb1c70Snonaka }
24789cdb1c70Snonaka run_rx_frame(sc, buf + sizeof(uint32_t), dmalen);
24799cdb1c70Snonaka buf += dmalen + 8;
24809cdb1c70Snonaka xferlen -= dmalen + 8;
24819cdb1c70Snonaka }
24829cdb1c70Snonaka
24839cdb1c70Snonaka skip: /* setup a new transfer */
24844e8e6643Sskrll usbd_setup_xfer(xfer, data, data->buf, RUN_MAX_RXSZ,
24854e8e6643Sskrll USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, run_rxeof);
2486d164e220Smlelstv status = usbd_transfer(xfer);
2487d164e220Smlelstv if (status != USBD_NORMAL_COMPLETION &&
2488d164e220Smlelstv status != USBD_IN_PROGRESS)
2489d164e220Smlelstv device_printf(sc->sc_dev, "requeuing rx failed: %s\n",
2490d164e220Smlelstv usbd_errstr(status));
24919cdb1c70Snonaka }
24929cdb1c70Snonaka
24939cdb1c70Snonaka static void
run_txeof(struct usbd_xfer * xfer,void * priv,usbd_status status)24944e8e6643Sskrll run_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
24959cdb1c70Snonaka {
24969cdb1c70Snonaka struct run_tx_data *data = priv;
24979cdb1c70Snonaka struct run_softc *sc = data->sc;
24989cdb1c70Snonaka struct run_tx_ring *txq = &sc->txq[data->qid];
24999cdb1c70Snonaka struct ifnet *ifp = &sc->sc_if;
25009cdb1c70Snonaka int s;
25019cdb1c70Snonaka
2502d164e220Smlelstv s = splnet();
2503d164e220Smlelstv txq->queued--;
2504d164e220Smlelstv sc->qfullmsk &= ~(1 << data->qid);
2505d164e220Smlelstv
25069cdb1c70Snonaka if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
2507d164e220Smlelstv if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
2508d164e220Smlelstv return;
2509d164e220Smlelstv
2510d164e220Smlelstv DPRINTF(("%s: usb error on tx: %s\n",
2511d164e220Smlelstv device_xname(sc->sc_dev), usbd_errstr(status)));
25129cdb1c70Snonaka if (status == USBD_STALLED)
25139cdb1c70Snonaka usbd_clear_endpoint_stall_async(txq->pipeh);
2514cdaa0e91Sthorpej if_statinc(ifp, if_oerrors);
2515d164e220Smlelstv splx(s);
25169cdb1c70Snonaka return;
25179cdb1c70Snonaka }
25189cdb1c70Snonaka
25199cdb1c70Snonaka sc->sc_tx_timer = 0;
2520cdaa0e91Sthorpej if_statinc(ifp, if_opackets);
25219cdb1c70Snonaka ifp->if_flags &= ~IFF_OACTIVE;
25229cdb1c70Snonaka run_start(ifp);
25239cdb1c70Snonaka splx(s);
25249cdb1c70Snonaka }
25259cdb1c70Snonaka
25269cdb1c70Snonaka static int
run_tx(struct run_softc * sc,struct mbuf * m,struct ieee80211_node * ni)25279cdb1c70Snonaka run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
25289cdb1c70Snonaka {
25299cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
25309cdb1c70Snonaka struct run_node *rn = (void *)ni;
25319cdb1c70Snonaka struct ieee80211_frame *wh;
25329cdb1c70Snonaka #ifndef RUN_HWCRYPTO
25339cdb1c70Snonaka struct ieee80211_key *k;
25349cdb1c70Snonaka #endif
25359cdb1c70Snonaka struct run_tx_ring *ring;
25369cdb1c70Snonaka struct run_tx_data *data;
25379cdb1c70Snonaka struct rt2870_txd *txd;
25389cdb1c70Snonaka struct rt2860_txwi *txwi;
2539d164e220Smlelstv uint16_t qos, dur, mcs;
2540d164e220Smlelstv uint16_t txwisize;
2541d164e220Smlelstv uint8_t type, tid, qid;
2542d164e220Smlelstv int hasqos, ridx, ctl_ridx, xferlen;
2543faca41fbSmlelstv uint8_t pad;
2544d164e220Smlelstv usbd_status status;
25459cdb1c70Snonaka
25469cdb1c70Snonaka wh = mtod(m, struct ieee80211_frame *);
25479cdb1c70Snonaka
25489cdb1c70Snonaka #ifndef RUN_HWCRYPTO
25499cdb1c70Snonaka if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
25509cdb1c70Snonaka k = ieee80211_crypto_encap(ic, ni, m);
25519cdb1c70Snonaka if (k == NULL) {
25529cdb1c70Snonaka m_freem(m);
25534e8e6643Sskrll return ENOBUFS;
25549cdb1c70Snonaka }
25559cdb1c70Snonaka
25569cdb1c70Snonaka /* packet header may have moved, reset our local pointer */
25579cdb1c70Snonaka wh = mtod(m, struct ieee80211_frame *);
25589cdb1c70Snonaka }
25599cdb1c70Snonaka #endif
25609cdb1c70Snonaka type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
25619cdb1c70Snonaka
256289f5489aSchristos if ((hasqos = ieee80211_has_qos(wh))) {
25639cdb1c70Snonaka qos = ((struct ieee80211_qosframe *)wh)->i_qos[0];
25649cdb1c70Snonaka tid = qos & IEEE80211_QOS_TID;
25659cdb1c70Snonaka qid = TID_TO_WME_AC(tid);
25669cdb1c70Snonaka } else {
2567d164e220Smlelstv qos = 0;
25689cdb1c70Snonaka tid = 0;
25699cdb1c70Snonaka qid = WME_AC_BE;
25709cdb1c70Snonaka }
25719cdb1c70Snonaka ring = &sc->txq[qid];
25729cdb1c70Snonaka data = &ring->data[ring->cur];
25739cdb1c70Snonaka
25749cdb1c70Snonaka /* pickup a rate index */
25759cdb1c70Snonaka if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
25769cdb1c70Snonaka type != IEEE80211_FC0_TYPE_DATA) {
25779cdb1c70Snonaka ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
25789cdb1c70Snonaka RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1;
25799cdb1c70Snonaka ctl_ridx = rt2860_rates[ridx].ctl_ridx;
25809cdb1c70Snonaka } else if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
25819cdb1c70Snonaka ridx = sc->fixed_ridx;
25829cdb1c70Snonaka ctl_ridx = rt2860_rates[ridx].ctl_ridx;
25839cdb1c70Snonaka } else {
25849cdb1c70Snonaka ridx = rn->ridx[ni->ni_txrate];
25859cdb1c70Snonaka ctl_ridx = rn->ctl_ridx[ni->ni_txrate];
25869cdb1c70Snonaka }
25879cdb1c70Snonaka
25889cdb1c70Snonaka /* get MCS code from rate index */
25899cdb1c70Snonaka mcs = rt2860_rates[ridx].mcs;
25909cdb1c70Snonaka
2591d164e220Smlelstv txwisize = sizeof(struct rt2860_txwi);
2592d164e220Smlelstv if (sc->mac_ver == 0x5592)
2593d164e220Smlelstv txwisize += sizeof(uint32_t);
2594faca41fbSmlelstv xferlen = txwisize + m->m_pkthdr.len;
2595d164e220Smlelstv
25969cdb1c70Snonaka /* roundup to 32-bit alignment */
25979cdb1c70Snonaka xferlen = (xferlen + 3) & ~3;
25989cdb1c70Snonaka
25999cdb1c70Snonaka txd = (struct rt2870_txd *)data->buf;
26009cdb1c70Snonaka txd->flags = RT2860_TX_QSEL_EDCA;
26019cdb1c70Snonaka txd->len = htole16(xferlen);
26029cdb1c70Snonaka
2603faca41fbSmlelstv /*
2604faca41fbSmlelstv * Ether both are true or both are false, the header
2605faca41fbSmlelstv * are nicely aligned to 32-bit. So, no L2 padding.
2606faca41fbSmlelstv */
2607faca41fbSmlelstv if (IEEE80211_HAS_ADDR4(wh) == IEEE80211_QOS_HAS_SEQ(wh))
2608faca41fbSmlelstv pad = 0;
2609faca41fbSmlelstv else
2610faca41fbSmlelstv pad = 2;
2611faca41fbSmlelstv
26129cdb1c70Snonaka /* setup TX Wireless Information */
26139cdb1c70Snonaka txwi = (struct rt2860_txwi *)(txd + 1);
26149cdb1c70Snonaka txwi->flags = 0;
26159cdb1c70Snonaka txwi->xflags = hasqos ? 0 : RT2860_TX_NSEQ;
26169cdb1c70Snonaka txwi->wcid = (type == IEEE80211_FC0_TYPE_DATA) ?
26179cdb1c70Snonaka RUN_AID2WCID(ni->ni_associd) : 0xff;
2618faca41fbSmlelstv txwi->len = htole16(m->m_pkthdr.len - pad);
26199cdb1c70Snonaka if (rt2860_rates[ridx].phy == IEEE80211_T_DS) {
26209cdb1c70Snonaka txwi->phy = htole16(RT2860_PHY_CCK);
26219cdb1c70Snonaka if (ridx != RT2860_RIDX_CCK1 &&
26229cdb1c70Snonaka (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
26239cdb1c70Snonaka mcs |= RT2860_PHY_SHPRE;
26249cdb1c70Snonaka } else
2625faca41fbSmlelstv mcs |= RT2860_PHY_OFDM;
2626d164e220Smlelstv txwi->phy = htole16(mcs);
26279cdb1c70Snonaka
26289cdb1c70Snonaka txwi->txop = RT2860_TX_TXOP_BACKOFF;
26299cdb1c70Snonaka
26309cdb1c70Snonaka if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
26319cdb1c70Snonaka (!hasqos || (qos & IEEE80211_QOS_ACKPOLICY) !=
26329cdb1c70Snonaka IEEE80211_QOS_ACKPOLICY_NOACK)) {
26339cdb1c70Snonaka txwi->xflags |= RT2860_TX_ACK;
26349cdb1c70Snonaka if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
26359cdb1c70Snonaka dur = rt2860_rates[ctl_ridx].sp_ack_dur;
26369cdb1c70Snonaka else
26379cdb1c70Snonaka dur = rt2860_rates[ctl_ridx].lp_ack_dur;
26389cdb1c70Snonaka *(uint16_t *)wh->i_dur = htole16(dur);
26399cdb1c70Snonaka }
26409cdb1c70Snonaka
26419cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY
26429cdb1c70Snonaka /* ask MAC to insert timestamp into probe responses */
26439cdb1c70Snonaka if ((wh->i_fc[0] &
26449cdb1c70Snonaka (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
26459cdb1c70Snonaka (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP))
26469cdb1c70Snonaka /* NOTE: beacons do not pass through tx_data() */
26479cdb1c70Snonaka txwi->flags |= RT2860_TX_TS;
26489cdb1c70Snonaka #endif
26499cdb1c70Snonaka
26509cdb1c70Snonaka if (__predict_false(sc->sc_drvbpf != NULL)) {
26519cdb1c70Snonaka struct run_tx_radiotap_header *tap = &sc->sc_txtap;
26529cdb1c70Snonaka
26539cdb1c70Snonaka tap->wt_flags = 0;
26549cdb1c70Snonaka tap->wt_rate = rt2860_rates[ridx].rate;
26559cdb1c70Snonaka tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
26569cdb1c70Snonaka tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
26579cdb1c70Snonaka tap->wt_hwqueue = qid;
26589cdb1c70Snonaka if (mcs & RT2860_PHY_SHPRE)
26599cdb1c70Snonaka tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
26609cdb1c70Snonaka
26613cd62456Smsaitoh bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m, BPF_D_OUT);
26629cdb1c70Snonaka }
26639cdb1c70Snonaka
2664faca41fbSmlelstv m_copydata(m, 0, m->m_pkthdr.len, ((uint8_t *)txwi) + txwisize);
26659cdb1c70Snonaka m_freem(m);
26669cdb1c70Snonaka
26679cdb1c70Snonaka xferlen += sizeof(*txd) + 4;
26689cdb1c70Snonaka
26694e8e6643Sskrll usbd_setup_xfer(data->xfer, data, data->buf, xferlen,
26704e8e6643Sskrll USBD_FORCE_SHORT_XFER, RUN_TX_TIMEOUT, run_txeof);
2671d164e220Smlelstv status = usbd_transfer(data->xfer);
2672d164e220Smlelstv if (__predict_false(status != USBD_IN_PROGRESS &&
2673d164e220Smlelstv status != USBD_NORMAL_COMPLETION)) {
2674d164e220Smlelstv device_printf(sc->sc_dev, "queuing tx failed: %s\n",
2675d164e220Smlelstv usbd_errstr(status));
2676d164e220Smlelstv return EIO;
2677d164e220Smlelstv }
26789cdb1c70Snonaka
26799cdb1c70Snonaka ieee80211_free_node(ni);
26809cdb1c70Snonaka
26819cdb1c70Snonaka ring->cur = (ring->cur + 1) % RUN_TX_RING_COUNT;
26829cdb1c70Snonaka if (++ring->queued >= RUN_TX_RING_COUNT)
26839cdb1c70Snonaka sc->qfullmsk |= 1 << qid;
26849cdb1c70Snonaka
26854e8e6643Sskrll return 0;
26869cdb1c70Snonaka }
26879cdb1c70Snonaka
26889cdb1c70Snonaka static void
run_start(struct ifnet * ifp)26899cdb1c70Snonaka run_start(struct ifnet *ifp)
26909cdb1c70Snonaka {
26919cdb1c70Snonaka struct run_softc *sc = ifp->if_softc;
26929cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
26939cdb1c70Snonaka struct ether_header *eh;
26949cdb1c70Snonaka struct ieee80211_node *ni;
26959cdb1c70Snonaka struct mbuf *m;
26969cdb1c70Snonaka
26979cdb1c70Snonaka if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
26989cdb1c70Snonaka return;
26999cdb1c70Snonaka
27009cdb1c70Snonaka for (;;) {
27019cdb1c70Snonaka if (sc->qfullmsk != 0) {
27029cdb1c70Snonaka ifp->if_flags |= IFF_OACTIVE;
27039cdb1c70Snonaka break;
27049cdb1c70Snonaka }
27059cdb1c70Snonaka /* send pending management frames first */
27069cdb1c70Snonaka IF_DEQUEUE(&ic->ic_mgtq, m);
27079cdb1c70Snonaka if (m != NULL) {
2708ea0349e7Sozaki-r ni = M_GETCTX(m, struct ieee80211_node *);
27096bbd2477Sozaki-r M_CLEARCTX(m);
27109cdb1c70Snonaka goto sendit;
27119cdb1c70Snonaka }
27129cdb1c70Snonaka if (ic->ic_state != IEEE80211_S_RUN)
27139cdb1c70Snonaka break;
27149cdb1c70Snonaka
27159cdb1c70Snonaka /* encapsulate and send data frames */
27169cdb1c70Snonaka IFQ_DEQUEUE(&ifp->if_snd, m);
27179cdb1c70Snonaka if (m == NULL)
27189cdb1c70Snonaka break;
27199cdb1c70Snonaka if (m->m_len < (int)sizeof(*eh) &&
27209cdb1c70Snonaka (m = m_pullup(m, sizeof(*eh))) == NULL) {
2721cdaa0e91Sthorpej if_statinc(ifp, if_oerrors);
27229cdb1c70Snonaka continue;
27239cdb1c70Snonaka }
27249cdb1c70Snonaka
27259cdb1c70Snonaka eh = mtod(m, struct ether_header *);
27269cdb1c70Snonaka ni = ieee80211_find_txnode(ic, eh->ether_dhost);
27279cdb1c70Snonaka if (ni == NULL) {
27289cdb1c70Snonaka m_freem(m);
2729cdaa0e91Sthorpej if_statinc(ifp, if_oerrors);
27309cdb1c70Snonaka continue;
27319cdb1c70Snonaka }
27329cdb1c70Snonaka
27333cd62456Smsaitoh bpf_mtap(ifp, m, BPF_D_OUT);
27349cdb1c70Snonaka
27359cdb1c70Snonaka if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
27369cdb1c70Snonaka ieee80211_free_node(ni);
2737cdaa0e91Sthorpej if_statinc(ifp, if_oerrors);
27389cdb1c70Snonaka continue;
27399cdb1c70Snonaka }
27409cdb1c70Snonaka sendit:
27413cd62456Smsaitoh bpf_mtap3(ic->ic_rawbpf, m, BPF_D_OUT);
27429cdb1c70Snonaka
27439cdb1c70Snonaka if (run_tx(sc, m, ni) != 0) {
27449cdb1c70Snonaka ieee80211_free_node(ni);
2745cdaa0e91Sthorpej if_statinc(ifp, if_oerrors);
27469cdb1c70Snonaka continue;
27479cdb1c70Snonaka }
27489cdb1c70Snonaka
27499cdb1c70Snonaka sc->sc_tx_timer = 5;
27509cdb1c70Snonaka ifp->if_timer = 1;
27519cdb1c70Snonaka }
27529cdb1c70Snonaka }
27539cdb1c70Snonaka
27549cdb1c70Snonaka static void
run_watchdog(struct ifnet * ifp)27559cdb1c70Snonaka run_watchdog(struct ifnet *ifp)
27569cdb1c70Snonaka {
27579cdb1c70Snonaka struct run_softc *sc = ifp->if_softc;
27589cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
27599cdb1c70Snonaka
27609cdb1c70Snonaka ifp->if_timer = 0;
27619cdb1c70Snonaka
27629cdb1c70Snonaka if (sc->sc_tx_timer > 0) {
27639cdb1c70Snonaka if (--sc->sc_tx_timer == 0) {
27641d5cb2a3Sjakllsch device_printf(sc->sc_dev, "device timeout\n");
27659cdb1c70Snonaka /* run_init(ifp); XXX needs a process context! */
2766cdaa0e91Sthorpej if_statinc(ifp, if_oerrors);
27679cdb1c70Snonaka return;
27689cdb1c70Snonaka }
27699cdb1c70Snonaka ifp->if_timer = 1;
27709cdb1c70Snonaka }
27719cdb1c70Snonaka
27729cdb1c70Snonaka ieee80211_watchdog(ic);
27739cdb1c70Snonaka }
27749cdb1c70Snonaka
27759cdb1c70Snonaka static int
run_ioctl(struct ifnet * ifp,u_long cmd,void * data)27769cdb1c70Snonaka run_ioctl(struct ifnet *ifp, u_long cmd, void *data)
27779cdb1c70Snonaka {
27789cdb1c70Snonaka struct run_softc *sc = ifp->if_softc;
27799cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
27809cdb1c70Snonaka int s, error = 0;
27819cdb1c70Snonaka
27829cdb1c70Snonaka s = splnet();
27839cdb1c70Snonaka
27849cdb1c70Snonaka switch (cmd) {
27859cdb1c70Snonaka case SIOCSIFFLAGS:
27869cdb1c70Snonaka if ((error = ifioctl_common(ifp, cmd, data)) != 0)
27879cdb1c70Snonaka break;
27889cdb1c70Snonaka switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
27899cdb1c70Snonaka case IFF_UP|IFF_RUNNING:
27909cdb1c70Snonaka break;
27919cdb1c70Snonaka case IFF_UP:
27929cdb1c70Snonaka run_init(ifp);
27939cdb1c70Snonaka break;
27949cdb1c70Snonaka case IFF_RUNNING:
27959cdb1c70Snonaka run_stop(ifp, 1);
27969cdb1c70Snonaka break;
27979cdb1c70Snonaka case 0:
27989cdb1c70Snonaka break;
27999cdb1c70Snonaka }
28009cdb1c70Snonaka break;
28019cdb1c70Snonaka
28029cdb1c70Snonaka case SIOCADDMULTI:
28039cdb1c70Snonaka case SIOCDELMULTI:
28049cdb1c70Snonaka if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
28059cdb1c70Snonaka /* setup multicast filter, etc */
28069cdb1c70Snonaka error = 0;
28079cdb1c70Snonaka }
28089cdb1c70Snonaka break;
28099cdb1c70Snonaka
28109cdb1c70Snonaka default:
28119cdb1c70Snonaka error = ieee80211_ioctl(ic, cmd, data);
28129cdb1c70Snonaka break;
28139cdb1c70Snonaka }
28149cdb1c70Snonaka
28159cdb1c70Snonaka if (error == ENETRESET) {
28169cdb1c70Snonaka if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
28179cdb1c70Snonaka (IFF_UP | IFF_RUNNING)) {
28189cdb1c70Snonaka run_init(ifp);
28199cdb1c70Snonaka }
28209cdb1c70Snonaka error = 0;
28219cdb1c70Snonaka }
28229cdb1c70Snonaka
28239cdb1c70Snonaka splx(s);
28249cdb1c70Snonaka
28254e8e6643Sskrll return error;
28269cdb1c70Snonaka }
28279cdb1c70Snonaka
28289cdb1c70Snonaka static void
run_select_chan_group(struct run_softc * sc,int group)28299cdb1c70Snonaka run_select_chan_group(struct run_softc *sc, int group)
28309cdb1c70Snonaka {
28319cdb1c70Snonaka uint32_t tmp;
28329cdb1c70Snonaka uint8_t agc;
28339cdb1c70Snonaka
28349cdb1c70Snonaka run_bbp_write(sc, 62, 0x37 - sc->lna[group]);
28359cdb1c70Snonaka run_bbp_write(sc, 63, 0x37 - sc->lna[group]);
28369cdb1c70Snonaka run_bbp_write(sc, 64, 0x37 - sc->lna[group]);
2837d164e220Smlelstv if (sc->mac_ver < 0x3572)
28389cdb1c70Snonaka run_bbp_write(sc, 86, 0x00);
28399cdb1c70Snonaka
2840d164e220Smlelstv if (sc->mac_ver == 0x3593) {
2841d164e220Smlelstv run_bbp_write(sc, 77, 0x98);
2842d164e220Smlelstv run_bbp_write(sc, 83, (group == 0) ? 0x8a : 0x9a);
2843d164e220Smlelstv }
2844d164e220Smlelstv
28459cdb1c70Snonaka if (group == 0) {
28469cdb1c70Snonaka if (sc->ext_2ghz_lna) {
2847d164e220Smlelstv if (sc->mac_ver >= 0x5390)
2848d164e220Smlelstv run_bbp_write(sc, 75, 0x52);
2849d164e220Smlelstv else {
28509cdb1c70Snonaka run_bbp_write(sc, 82, 0x62);
28519cdb1c70Snonaka run_bbp_write(sc, 75, 0x46);
28529cdb1c70Snonaka }
28539cdb1c70Snonaka } else {
2854d164e220Smlelstv if (sc->mac_ver == 0x5592) {
2855d164e220Smlelstv run_bbp_write(sc, 79, 0x1c);
2856d164e220Smlelstv run_bbp_write(sc, 80, 0x0e);
2857d164e220Smlelstv run_bbp_write(sc, 81, 0x3a);
2858d164e220Smlelstv run_bbp_write(sc, 82, 0x62);
2859d164e220Smlelstv
2860d164e220Smlelstv run_bbp_write(sc, 195, 0x80);
2861d164e220Smlelstv run_bbp_write(sc, 196, 0xe0);
2862d164e220Smlelstv run_bbp_write(sc, 195, 0x81);
2863d164e220Smlelstv run_bbp_write(sc, 196, 0x1f);
2864d164e220Smlelstv run_bbp_write(sc, 195, 0x82);
2865d164e220Smlelstv run_bbp_write(sc, 196, 0x38);
2866d164e220Smlelstv run_bbp_write(sc, 195, 0x83);
2867d164e220Smlelstv run_bbp_write(sc, 196, 0x32);
2868d164e220Smlelstv run_bbp_write(sc, 195, 0x85);
2869d164e220Smlelstv run_bbp_write(sc, 196, 0x28);
2870d164e220Smlelstv run_bbp_write(sc, 195, 0x86);
2871d164e220Smlelstv run_bbp_write(sc, 196, 0x19);
2872d164e220Smlelstv } else if (sc->mac_ver >= 0x5390) {
2873d164e220Smlelstv run_bbp_write(sc, 75, 0x50);
2874d164e220Smlelstv } else {
2875d164e220Smlelstv run_bbp_write(sc, 82,
2876d164e220Smlelstv (sc->mac_ver == 0x3593) ? 0x62 : 0x84);
2877d164e220Smlelstv run_bbp_write(sc, 75, 0x50);
2878d164e220Smlelstv }
2879d164e220Smlelstv }
2880d164e220Smlelstv } else {
2881d164e220Smlelstv if (sc->mac_ver == 0x5592) {
2882d164e220Smlelstv run_bbp_write(sc, 79, 0x18);
2883d164e220Smlelstv run_bbp_write(sc, 80, 0x08);
2884d164e220Smlelstv run_bbp_write(sc, 81, 0x38);
2885d164e220Smlelstv run_bbp_write(sc, 82, 0x92);
2886d164e220Smlelstv
2887d164e220Smlelstv run_bbp_write(sc, 195, 0x80);
2888d164e220Smlelstv run_bbp_write(sc, 196, 0xf0);
2889d164e220Smlelstv run_bbp_write(sc, 195, 0x81);
2890d164e220Smlelstv run_bbp_write(sc, 196, 0x1e);
2891d164e220Smlelstv run_bbp_write(sc, 195, 0x82);
2892d164e220Smlelstv run_bbp_write(sc, 196, 0x28);
2893d164e220Smlelstv run_bbp_write(sc, 195, 0x83);
2894d164e220Smlelstv run_bbp_write(sc, 196, 0x20);
2895d164e220Smlelstv run_bbp_write(sc, 195, 0x85);
2896d164e220Smlelstv run_bbp_write(sc, 196, 0x7f);
2897d164e220Smlelstv run_bbp_write(sc, 195, 0x86);
2898d164e220Smlelstv run_bbp_write(sc, 196, 0x7f);
2899d164e220Smlelstv } else if (sc->mac_ver == 0x3572)
29009cdb1c70Snonaka run_bbp_write(sc, 82, 0x94);
29019cdb1c70Snonaka else
2902d164e220Smlelstv run_bbp_write(sc, 82,
2903d164e220Smlelstv (sc->mac_ver == 0x3593) ? 0x82 : 0xf2);
29049cdb1c70Snonaka if (sc->ext_5ghz_lna)
29059cdb1c70Snonaka run_bbp_write(sc, 75, 0x46);
29069cdb1c70Snonaka else
29079cdb1c70Snonaka run_bbp_write(sc, 75, 0x50);
29089cdb1c70Snonaka }
29099cdb1c70Snonaka
29109cdb1c70Snonaka run_read(sc, RT2860_TX_BAND_CFG, &tmp);
29119cdb1c70Snonaka tmp &= ~(RT2860_5G_BAND_SEL_N | RT2860_5G_BAND_SEL_P);
29129cdb1c70Snonaka tmp |= (group == 0) ? RT2860_5G_BAND_SEL_N : RT2860_5G_BAND_SEL_P;
29139cdb1c70Snonaka run_write(sc, RT2860_TX_BAND_CFG, tmp);
29149cdb1c70Snonaka
29159cdb1c70Snonaka /* enable appropriate Power Amplifiers and Low Noise Amplifiers */
29169cdb1c70Snonaka tmp = RT2860_RFTR_EN | RT2860_TRSW_EN | RT2860_LNA_PE0_EN;
2917d164e220Smlelstv if (sc->mac_ver == 0x3593)
2918d164e220Smlelstv tmp |= RT3593_LNA_PE_G2_EN | RT3593_LNA_PE_A2_EN;
29199cdb1c70Snonaka if (sc->nrxchains > 1)
29209cdb1c70Snonaka tmp |= RT2860_LNA_PE1_EN;
29219cdb1c70Snonaka if (group == 0) { /* 2GHz */
29229cdb1c70Snonaka tmp |= RT2860_PA_PE_G0_EN;
29239cdb1c70Snonaka if (sc->ntxchains > 1)
29249cdb1c70Snonaka tmp |= RT2860_PA_PE_G1_EN;
29259cdb1c70Snonaka } else { /* 5GHz */
29269cdb1c70Snonaka tmp |= RT2860_PA_PE_A0_EN;
29279cdb1c70Snonaka if (sc->ntxchains > 1)
29289cdb1c70Snonaka tmp |= RT2860_PA_PE_A1_EN;
2929d164e220Smlelstv if (sc->mac_ver == 0x3593) {
2930d164e220Smlelstv if (sc->ntxchains > 2)
2931d164e220Smlelstv tmp |= RT3593_PA_PE_G2_EN;
2932d164e220Smlelstv }
29339cdb1c70Snonaka }
29349cdb1c70Snonaka if (sc->mac_ver == 0x3572) {
29359cdb1c70Snonaka run_rt3070_rf_write(sc, 8, 0x00);
29369cdb1c70Snonaka run_write(sc, RT2860_TX_PIN_CFG, tmp);
29379cdb1c70Snonaka run_rt3070_rf_write(sc, 8, 0x80);
29389cdb1c70Snonaka } else
29399cdb1c70Snonaka run_write(sc, RT2860_TX_PIN_CFG, tmp);
29409cdb1c70Snonaka
2941d164e220Smlelstv if (sc->mac_ver == 0x5592) {
2942d164e220Smlelstv run_bbp_write(sc, 195, 0x8d);
2943d164e220Smlelstv run_bbp_write(sc, 196, 0x1a);
2944d164e220Smlelstv }
2945d164e220Smlelstv
2946d164e220Smlelstv if (sc->mac_ver == 0x3593) {
2947d164e220Smlelstv run_read(sc, RT2860_GPIO_CTRL, &tmp);
2948d164e220Smlelstv tmp &= ~0x01010000;
2949d164e220Smlelstv if (group == 0)
2950d164e220Smlelstv tmp |= 0x00010000;
2951d164e220Smlelstv tmp = (tmp & ~0x00009090) | 0x00000090;
2952d164e220Smlelstv run_write(sc, RT2860_GPIO_CTRL, tmp);
2953d164e220Smlelstv }
2954d164e220Smlelstv
29559cdb1c70Snonaka /* set initial AGC value */
29569cdb1c70Snonaka if (group == 0) { /* 2GHz band */
29579cdb1c70Snonaka if (sc->mac_ver >= 0x3070)
29589cdb1c70Snonaka agc = 0x1c + sc->lna[0] * 2;
29599cdb1c70Snonaka else
29609cdb1c70Snonaka agc = 0x2e + sc->lna[0];
29619cdb1c70Snonaka } else { /* 5GHz band */
29629cdb1c70Snonaka if (sc->mac_ver == 0x3572)
29639cdb1c70Snonaka agc = 0x22 + (sc->lna[group] * 5) / 3;
29649cdb1c70Snonaka else
29659cdb1c70Snonaka agc = 0x32 + (sc->lna[group] * 5) / 3;
29669cdb1c70Snonaka }
29679cdb1c70Snonaka run_set_agc(sc, agc);
29689cdb1c70Snonaka }
29699cdb1c70Snonaka
29709cdb1c70Snonaka static void
run_rt2870_set_chan(struct run_softc * sc,u_int chan)29719cdb1c70Snonaka run_rt2870_set_chan(struct run_softc *sc, u_int chan)
29729cdb1c70Snonaka {
29739cdb1c70Snonaka const struct rfprog *rfprog = rt2860_rf2850;
29749cdb1c70Snonaka uint32_t r2, r3, r4;
29759cdb1c70Snonaka int8_t txpow1, txpow2;
29769cdb1c70Snonaka int i;
29779cdb1c70Snonaka
29789cdb1c70Snonaka /* find the settings for this channel (we know it exists) */
29799cdb1c70Snonaka for (i = 0; rfprog[i].chan != chan; i++);
29809cdb1c70Snonaka
29819cdb1c70Snonaka r2 = rfprog[i].r2;
29829cdb1c70Snonaka if (sc->ntxchains == 1)
29839cdb1c70Snonaka r2 |= 1 << 12; /* 1T: disable Tx chain 2 */
29849cdb1c70Snonaka if (sc->nrxchains == 1)
29859cdb1c70Snonaka r2 |= 1 << 15 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */
29869cdb1c70Snonaka else if (sc->nrxchains == 2)
29879cdb1c70Snonaka r2 |= 1 << 4; /* 2R: disable Rx chain 3 */
29889cdb1c70Snonaka
29899cdb1c70Snonaka /* use Tx power values from EEPROM */
29909cdb1c70Snonaka txpow1 = sc->txpow1[i];
29919cdb1c70Snonaka txpow2 = sc->txpow2[i];
29929cdb1c70Snonaka if (chan > 14) {
29939cdb1c70Snonaka if (txpow1 >= 0)
29949cdb1c70Snonaka txpow1 = txpow1 << 1 | 1;
29959cdb1c70Snonaka else
29969cdb1c70Snonaka txpow1 = (7 + txpow1) << 1;
29979cdb1c70Snonaka if (txpow2 >= 0)
29989cdb1c70Snonaka txpow2 = txpow2 << 1 | 1;
29999cdb1c70Snonaka else
30009cdb1c70Snonaka txpow2 = (7 + txpow2) << 1;
30019cdb1c70Snonaka }
30029cdb1c70Snonaka r3 = rfprog[i].r3 | txpow1 << 7;
30039cdb1c70Snonaka r4 = rfprog[i].r4 | sc->freq << 13 | txpow2 << 4;
30049cdb1c70Snonaka
30059cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1);
30069cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF2, r2);
30079cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF3, r3);
30089cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF4, r4);
30099cdb1c70Snonaka
3010faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
30119cdb1c70Snonaka
30129cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1);
30139cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF2, r2);
30149cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF3, r3 | 1);
30159cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF4, r4);
30169cdb1c70Snonaka
3017faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
30189cdb1c70Snonaka
30199cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1);
30209cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF2, r2);
30219cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF3, r3);
30229cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF4, r4);
30239cdb1c70Snonaka }
30249cdb1c70Snonaka
30259cdb1c70Snonaka static void
run_rt3070_set_chan(struct run_softc * sc,u_int chan)30269cdb1c70Snonaka run_rt3070_set_chan(struct run_softc *sc, u_int chan)
30279cdb1c70Snonaka {
30289cdb1c70Snonaka int8_t txpow1, txpow2;
30299cdb1c70Snonaka uint8_t rf;
30309cdb1c70Snonaka int i;
30319cdb1c70Snonaka
30329cdb1c70Snonaka KASSERT(chan >= 1 && chan <= 14); /* RT3070 is 2GHz only */
30339cdb1c70Snonaka
30349cdb1c70Snonaka /* find the settings for this channel (we know it exists) */
30359cdb1c70Snonaka for (i = 0; rt2860_rf2850[i].chan != chan; i++)
30369cdb1c70Snonaka continue;
30379cdb1c70Snonaka
30389cdb1c70Snonaka /* use Tx power values from EEPROM */
30399cdb1c70Snonaka txpow1 = sc->txpow1[i];
30409cdb1c70Snonaka txpow2 = sc->txpow2[i];
30419cdb1c70Snonaka
30429cdb1c70Snonaka run_rt3070_rf_write(sc, 2, rt3070_freqs[i].n);
30439cdb1c70Snonaka run_rt3070_rf_write(sc, 3, rt3070_freqs[i].k);
30449cdb1c70Snonaka run_rt3070_rf_read(sc, 6, &rf);
30459cdb1c70Snonaka rf = (rf & ~0x03) | rt3070_freqs[i].r;
30469cdb1c70Snonaka run_rt3070_rf_write(sc, 6, rf);
30479cdb1c70Snonaka
30489cdb1c70Snonaka /* set Tx0 power */
30499cdb1c70Snonaka run_rt3070_rf_read(sc, 12, &rf);
30509cdb1c70Snonaka rf = (rf & ~0x1f) | txpow1;
30519cdb1c70Snonaka run_rt3070_rf_write(sc, 12, rf);
30529cdb1c70Snonaka
30539cdb1c70Snonaka /* set Tx1 power */
30549cdb1c70Snonaka run_rt3070_rf_read(sc, 13, &rf);
30559cdb1c70Snonaka rf = (rf & ~0x1f) | txpow2;
30569cdb1c70Snonaka run_rt3070_rf_write(sc, 13, rf);
30579cdb1c70Snonaka
30589cdb1c70Snonaka run_rt3070_rf_read(sc, 1, &rf);
30599cdb1c70Snonaka rf &= ~0xfc;
30609cdb1c70Snonaka if (sc->ntxchains == 1)
30619cdb1c70Snonaka rf |= 1 << 7 | 1 << 5; /* 1T: disable Tx chains 2 & 3 */
30629cdb1c70Snonaka else if (sc->ntxchains == 2)
30639cdb1c70Snonaka rf |= 1 << 7; /* 2T: disable Tx chain 3 */
30649cdb1c70Snonaka if (sc->nrxchains == 1)
30659cdb1c70Snonaka rf |= 1 << 6 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */
30669cdb1c70Snonaka else if (sc->nrxchains == 2)
30679cdb1c70Snonaka rf |= 1 << 6; /* 2R: disable Rx chain 3 */
30689cdb1c70Snonaka run_rt3070_rf_write(sc, 1, rf);
30699cdb1c70Snonaka
30709cdb1c70Snonaka /* set RF offset */
30719cdb1c70Snonaka run_rt3070_rf_read(sc, 23, &rf);
30729cdb1c70Snonaka rf = (rf & ~0x7f) | sc->freq;
30739cdb1c70Snonaka run_rt3070_rf_write(sc, 23, rf);
30749cdb1c70Snonaka
30759cdb1c70Snonaka /* program RF filter */
30769cdb1c70Snonaka run_rt3070_rf_read(sc, 24, &rf); /* Tx */
30779cdb1c70Snonaka rf = (rf & ~0x3f) | sc->rf24_20mhz;
30789cdb1c70Snonaka run_rt3070_rf_write(sc, 24, rf);
30799cdb1c70Snonaka run_rt3070_rf_read(sc, 31, &rf); /* Rx */
30809cdb1c70Snonaka rf = (rf & ~0x3f) | sc->rf24_20mhz;
30819cdb1c70Snonaka run_rt3070_rf_write(sc, 31, rf);
30829cdb1c70Snonaka
30839cdb1c70Snonaka /* enable RF tuning */
30849cdb1c70Snonaka run_rt3070_rf_read(sc, 7, &rf);
30859cdb1c70Snonaka run_rt3070_rf_write(sc, 7, rf | 0x01);
30869cdb1c70Snonaka }
30879cdb1c70Snonaka
30889cdb1c70Snonaka static void
run_rt3572_set_chan(struct run_softc * sc,u_int chan)30899cdb1c70Snonaka run_rt3572_set_chan(struct run_softc *sc, u_int chan)
30909cdb1c70Snonaka {
30919cdb1c70Snonaka int8_t txpow1, txpow2;
30929cdb1c70Snonaka uint32_t tmp;
30939cdb1c70Snonaka uint8_t rf;
30949cdb1c70Snonaka int i;
30959cdb1c70Snonaka
30969cdb1c70Snonaka /* find the settings for this channel (we know it exists) */
30979cdb1c70Snonaka for (i = 0; rt2860_rf2850[i].chan != chan; i++);
30989cdb1c70Snonaka
30999cdb1c70Snonaka /* use Tx power values from EEPROM */
31009cdb1c70Snonaka txpow1 = sc->txpow1[i];
31019cdb1c70Snonaka txpow2 = sc->txpow2[i];
31029cdb1c70Snonaka
31039cdb1c70Snonaka if (chan <= 14) {
31049cdb1c70Snonaka run_bbp_write(sc, 25, sc->bbp25);
31059cdb1c70Snonaka run_bbp_write(sc, 26, sc->bbp26);
31069cdb1c70Snonaka } else {
31079cdb1c70Snonaka /* enable IQ phase correction */
31089cdb1c70Snonaka run_bbp_write(sc, 25, 0x09);
31099cdb1c70Snonaka run_bbp_write(sc, 26, 0xff);
31109cdb1c70Snonaka }
31119cdb1c70Snonaka
31129cdb1c70Snonaka run_rt3070_rf_write(sc, 2, rt3070_freqs[i].n);
31139cdb1c70Snonaka run_rt3070_rf_write(sc, 3, rt3070_freqs[i].k);
31149cdb1c70Snonaka run_rt3070_rf_read(sc, 6, &rf);
31159cdb1c70Snonaka rf = (rf & ~0x0f) | rt3070_freqs[i].r;
31169cdb1c70Snonaka rf |= (chan <= 14) ? 0x08 : 0x04;
31179cdb1c70Snonaka run_rt3070_rf_write(sc, 6, rf);
31189cdb1c70Snonaka
31199cdb1c70Snonaka /* set PLL mode */
31209cdb1c70Snonaka run_rt3070_rf_read(sc, 5, &rf);
31219cdb1c70Snonaka rf &= ~(0x08 | 0x04);
31229cdb1c70Snonaka rf |= (chan <= 14) ? 0x04 : 0x08;
31239cdb1c70Snonaka run_rt3070_rf_write(sc, 5, rf);
31249cdb1c70Snonaka
31259cdb1c70Snonaka /* set Tx power for chain 0 */
31269cdb1c70Snonaka if (chan <= 14)
31279cdb1c70Snonaka rf = 0x60 | txpow1;
31289cdb1c70Snonaka else
31299cdb1c70Snonaka rf = 0xe0 | (txpow1 & 0xc) << 1 | (txpow1 & 0x3);
31309cdb1c70Snonaka run_rt3070_rf_write(sc, 12, rf);
31319cdb1c70Snonaka
31329cdb1c70Snonaka /* set Tx power for chain 1 */
31339cdb1c70Snonaka if (chan <= 14)
31349cdb1c70Snonaka rf = 0x60 | txpow2;
31359cdb1c70Snonaka else
31369cdb1c70Snonaka rf = 0xe0 | (txpow2 & 0xc) << 1 | (txpow2 & 0x3);
31379cdb1c70Snonaka run_rt3070_rf_write(sc, 13, rf);
31389cdb1c70Snonaka
31399cdb1c70Snonaka /* set Tx/Rx streams */
31409cdb1c70Snonaka run_rt3070_rf_read(sc, 1, &rf);
31419cdb1c70Snonaka rf &= ~0xfc;
31429cdb1c70Snonaka if (sc->ntxchains == 1)
31439cdb1c70Snonaka rf |= 1 << 7 | 1 << 5; /* 1T: disable Tx chains 2 & 3 */
31449cdb1c70Snonaka else if (sc->ntxchains == 2)
31459cdb1c70Snonaka rf |= 1 << 7; /* 2T: disable Tx chain 3 */
31469cdb1c70Snonaka if (sc->nrxchains == 1)
31479cdb1c70Snonaka rf |= 1 << 6 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */
31489cdb1c70Snonaka else if (sc->nrxchains == 2)
31499cdb1c70Snonaka rf |= 1 << 6; /* 2R: disable Rx chain 3 */
31509cdb1c70Snonaka run_rt3070_rf_write(sc, 1, rf);
31519cdb1c70Snonaka
31529cdb1c70Snonaka /* set RF offset */
31539cdb1c70Snonaka run_rt3070_rf_read(sc, 23, &rf);
31549cdb1c70Snonaka rf = (rf & ~0x7f) | sc->freq;
31559cdb1c70Snonaka run_rt3070_rf_write(sc, 23, rf);
31569cdb1c70Snonaka
31579cdb1c70Snonaka /* program RF filter */
31589cdb1c70Snonaka rf = sc->rf24_20mhz;
31599cdb1c70Snonaka run_rt3070_rf_write(sc, 24, rf); /* Tx */
31609cdb1c70Snonaka run_rt3070_rf_write(sc, 31, rf); /* Rx */
31619cdb1c70Snonaka
31629cdb1c70Snonaka /* enable RF tuning */
31639cdb1c70Snonaka run_rt3070_rf_read(sc, 7, &rf);
31649cdb1c70Snonaka rf = (chan <= 14) ? 0xd8 : ((rf & ~0xc8) | 0x14);
31659cdb1c70Snonaka run_rt3070_rf_write(sc, 7, rf);
31669cdb1c70Snonaka
31679cdb1c70Snonaka /* TSSI */
31689cdb1c70Snonaka rf = (chan <= 14) ? 0xc3 : 0xc0;
31699cdb1c70Snonaka run_rt3070_rf_write(sc, 9, rf);
31709cdb1c70Snonaka
31719cdb1c70Snonaka /* set loop filter 1 */
31729cdb1c70Snonaka run_rt3070_rf_write(sc, 10, 0xf1);
31739cdb1c70Snonaka /* set loop filter 2 */
31749cdb1c70Snonaka run_rt3070_rf_write(sc, 11, (chan <= 14) ? 0xb9 : 0x00);
31759cdb1c70Snonaka
31769cdb1c70Snonaka /* set tx_mx2_ic */
31779cdb1c70Snonaka run_rt3070_rf_write(sc, 15, (chan <= 14) ? 0x53 : 0x43);
31789cdb1c70Snonaka /* set tx_mx1_ic */
31799cdb1c70Snonaka if (chan <= 14)
31809cdb1c70Snonaka rf = 0x48 | sc->txmixgain_2ghz;
31819cdb1c70Snonaka else
31829cdb1c70Snonaka rf = 0x78 | sc->txmixgain_5ghz;
31839cdb1c70Snonaka run_rt3070_rf_write(sc, 16, rf);
31849cdb1c70Snonaka
31859cdb1c70Snonaka /* set tx_lo1 */
31869cdb1c70Snonaka run_rt3070_rf_write(sc, 17, 0x23);
31879cdb1c70Snonaka /* set tx_lo2 */
31889cdb1c70Snonaka if (chan <= 14)
31899cdb1c70Snonaka rf = 0x93;
31909cdb1c70Snonaka else if (chan <= 64)
31919cdb1c70Snonaka rf = 0xb7;
31929cdb1c70Snonaka else if (chan <= 128)
31939cdb1c70Snonaka rf = 0x74;
31949cdb1c70Snonaka else
31959cdb1c70Snonaka rf = 0x72;
31969cdb1c70Snonaka run_rt3070_rf_write(sc, 19, rf);
31979cdb1c70Snonaka
31989cdb1c70Snonaka /* set rx_lo1 */
31999cdb1c70Snonaka if (chan <= 14)
32009cdb1c70Snonaka rf = 0xb3;
32019cdb1c70Snonaka else if (chan <= 64)
32029cdb1c70Snonaka rf = 0xf6;
32039cdb1c70Snonaka else if (chan <= 128)
32049cdb1c70Snonaka rf = 0xf4;
32059cdb1c70Snonaka else
32069cdb1c70Snonaka rf = 0xf3;
32079cdb1c70Snonaka run_rt3070_rf_write(sc, 20, rf);
32089cdb1c70Snonaka
32099cdb1c70Snonaka /* set pfd_delay */
32109cdb1c70Snonaka if (chan <= 14)
32119cdb1c70Snonaka rf = 0x15;
32129cdb1c70Snonaka else if (chan <= 64)
32139cdb1c70Snonaka rf = 0x3d;
32149cdb1c70Snonaka else
32159cdb1c70Snonaka rf = 0x01;
32169cdb1c70Snonaka run_rt3070_rf_write(sc, 25, rf);
32179cdb1c70Snonaka
32189cdb1c70Snonaka /* set rx_lo2 */
32199cdb1c70Snonaka run_rt3070_rf_write(sc, 26, (chan <= 14) ? 0x85 : 0x87);
32209cdb1c70Snonaka /* set ldo_rf_vc */
32219cdb1c70Snonaka run_rt3070_rf_write(sc, 27, (chan <= 14) ? 0x00 : 0x01);
32229cdb1c70Snonaka /* set drv_cc */
32239cdb1c70Snonaka run_rt3070_rf_write(sc, 29, (chan <= 14) ? 0x9b : 0x9f);
32249cdb1c70Snonaka
32259cdb1c70Snonaka run_read(sc, RT2860_GPIO_CTRL, &tmp);
32269cdb1c70Snonaka tmp &= ~0x8080;
32279cdb1c70Snonaka if (chan <= 14)
32289cdb1c70Snonaka tmp |= 0x80;
32299cdb1c70Snonaka run_write(sc, RT2860_GPIO_CTRL, tmp);
32309cdb1c70Snonaka
32319cdb1c70Snonaka /* enable RF tuning */
32329cdb1c70Snonaka run_rt3070_rf_read(sc, 7, &rf);
32339cdb1c70Snonaka run_rt3070_rf_write(sc, 7, rf | 0x01);
32349cdb1c70Snonaka
3235faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 2);
3236faca41fbSmlelstv }
3237faca41fbSmlelstv
3238faca41fbSmlelstv static void
run_rt3593_set_chan(struct run_softc * sc,u_int chan)3239faca41fbSmlelstv run_rt3593_set_chan(struct run_softc *sc, u_int chan)
3240faca41fbSmlelstv {
3241faca41fbSmlelstv int8_t txpow1, txpow2, txpow3;
3242faca41fbSmlelstv uint8_t h20mhz, rf;
3243faca41fbSmlelstv int i;
3244faca41fbSmlelstv
3245faca41fbSmlelstv /* find the settings for this channel (we know it exists) */
3246faca41fbSmlelstv for (i = 0; rt2860_rf2850[i].chan != chan; i++);
3247faca41fbSmlelstv
3248faca41fbSmlelstv /* use Tx power values from EEPROM */
3249faca41fbSmlelstv txpow1 = sc->txpow1[i];
3250faca41fbSmlelstv txpow2 = sc->txpow2[i];
3251faca41fbSmlelstv txpow3 = (sc->ntxchains == 3) ? sc->txpow3[i] : 0;
3252faca41fbSmlelstv
3253faca41fbSmlelstv if (chan <= 14) {
3254faca41fbSmlelstv run_bbp_write(sc, 25, sc->bbp25);
3255faca41fbSmlelstv run_bbp_write(sc, 26, sc->bbp26);
3256faca41fbSmlelstv } else {
3257faca41fbSmlelstv /* Enable IQ phase correction. */
3258faca41fbSmlelstv run_bbp_write(sc, 25, 0x09);
3259faca41fbSmlelstv run_bbp_write(sc, 26, 0xff);
3260faca41fbSmlelstv }
3261faca41fbSmlelstv
3262faca41fbSmlelstv run_rt3070_rf_write(sc, 8, rt3070_freqs[i].n);
3263faca41fbSmlelstv run_rt3070_rf_write(sc, 9, rt3070_freqs[i].k & 0x0f);
3264faca41fbSmlelstv run_rt3070_rf_read(sc, 11, &rf);
3265faca41fbSmlelstv rf = (rf & ~0x03) | (rt3070_freqs[i].r & 0x03);
3266faca41fbSmlelstv run_rt3070_rf_write(sc, 11, rf);
3267faca41fbSmlelstv
3268faca41fbSmlelstv /* Set pll_idoh. */
3269faca41fbSmlelstv run_rt3070_rf_read(sc, 11, &rf);
3270faca41fbSmlelstv rf &= ~0x4c;
3271faca41fbSmlelstv rf |= (chan <= 14) ? 0x44 : 0x48;
3272faca41fbSmlelstv run_rt3070_rf_write(sc, 11, rf);
3273faca41fbSmlelstv
3274faca41fbSmlelstv if (chan <= 14)
3275faca41fbSmlelstv rf = txpow1 & 0x1f;
3276faca41fbSmlelstv else
3277faca41fbSmlelstv rf = 0x40 | ((txpow1 & 0x18) << 1) | (txpow1 & 0x07);
3278faca41fbSmlelstv run_rt3070_rf_write(sc, 53, rf);
3279faca41fbSmlelstv
3280faca41fbSmlelstv if (chan <= 14)
3281faca41fbSmlelstv rf = txpow2 & 0x1f;
3282faca41fbSmlelstv else
3283faca41fbSmlelstv rf = 0x40 | ((txpow2 & 0x18) << 1) | (txpow2 & 0x07);
3284faca41fbSmlelstv run_rt3070_rf_write(sc, 55, rf);
3285faca41fbSmlelstv
3286faca41fbSmlelstv if (chan <= 14)
3287faca41fbSmlelstv rf = txpow3 & 0x1f;
3288faca41fbSmlelstv else
3289faca41fbSmlelstv rf = 0x40 | ((txpow3 & 0x18) << 1) | (txpow3 & 0x07);
3290faca41fbSmlelstv run_rt3070_rf_write(sc, 54, rf);
3291faca41fbSmlelstv
3292faca41fbSmlelstv rf = RT3070_RF_BLOCK | RT3070_PLL_PD;
3293faca41fbSmlelstv if (sc->ntxchains == 3)
3294faca41fbSmlelstv rf |= RT3070_TX0_PD | RT3070_TX1_PD | RT3070_TX2_PD;
3295faca41fbSmlelstv else
3296faca41fbSmlelstv rf |= RT3070_TX0_PD | RT3070_TX1_PD;
3297faca41fbSmlelstv rf |= RT3070_RX0_PD | RT3070_RX1_PD | RT3070_RX2_PD;
3298faca41fbSmlelstv run_rt3070_rf_write(sc, 1, rf);
3299faca41fbSmlelstv
3300faca41fbSmlelstv run_adjust_freq_offset(sc);
3301faca41fbSmlelstv
3302faca41fbSmlelstv run_rt3070_rf_write(sc, 31, (chan <= 14) ? 0xa0 : 0x80);
3303faca41fbSmlelstv
3304faca41fbSmlelstv h20mhz = (sc->rf24_20mhz & 0x20) >> 5;
3305faca41fbSmlelstv run_rt3070_rf_read(sc, 30, &rf);
3306faca41fbSmlelstv rf = (rf & ~0x06) | (h20mhz << 1) | (h20mhz << 2);
3307faca41fbSmlelstv run_rt3070_rf_write(sc, 30, rf);
3308faca41fbSmlelstv
3309faca41fbSmlelstv run_rt3070_rf_read(sc, 36, &rf);
3310faca41fbSmlelstv if (chan <= 14)
3311faca41fbSmlelstv rf |= 0x80;
3312faca41fbSmlelstv else
3313faca41fbSmlelstv rf &= ~0x80;
3314faca41fbSmlelstv run_rt3070_rf_write(sc, 36, rf);
3315faca41fbSmlelstv
3316faca41fbSmlelstv /* Set vcolo_bs. */
3317faca41fbSmlelstv run_rt3070_rf_write(sc, 34, (chan <= 14) ? 0x3c : 0x20);
3318faca41fbSmlelstv /* Set pfd_delay. */
3319faca41fbSmlelstv run_rt3070_rf_write(sc, 12, (chan <= 14) ? 0x1a : 0x12);
3320faca41fbSmlelstv
3321faca41fbSmlelstv /* Set vco bias current control. */
3322faca41fbSmlelstv run_rt3070_rf_read(sc, 6, &rf);
3323faca41fbSmlelstv rf &= ~0xc0;
3324faca41fbSmlelstv if (chan <= 14)
3325faca41fbSmlelstv rf |= 0x40;
3326faca41fbSmlelstv else if (chan <= 128)
3327faca41fbSmlelstv rf |= 0x80;
3328faca41fbSmlelstv else
3329faca41fbSmlelstv rf |= 0x40;
3330faca41fbSmlelstv run_rt3070_rf_write(sc, 6, rf);
3331faca41fbSmlelstv
3332faca41fbSmlelstv run_rt3070_rf_read(sc, 30, &rf);
3333faca41fbSmlelstv rf = (rf & ~0x18) | 0x10;
3334faca41fbSmlelstv run_rt3070_rf_write(sc, 30, rf);
3335faca41fbSmlelstv
3336faca41fbSmlelstv run_rt3070_rf_write(sc, 10, (chan <= 14) ? 0xd3 : 0xd8);
3337faca41fbSmlelstv run_rt3070_rf_write(sc, 13, (chan <= 14) ? 0x12 : 0x23);
3338faca41fbSmlelstv
3339faca41fbSmlelstv run_rt3070_rf_read(sc, 51, &rf);
3340faca41fbSmlelstv rf = (rf & ~0x03) | 0x01;
3341faca41fbSmlelstv run_rt3070_rf_write(sc, 51, rf);
3342faca41fbSmlelstv /* Set tx_mx1_cc. */
3343faca41fbSmlelstv run_rt3070_rf_read(sc, 51, &rf);
3344faca41fbSmlelstv rf &= ~0x1c;
3345faca41fbSmlelstv rf |= (chan <= 14) ? 0x14 : 0x10;
3346faca41fbSmlelstv run_rt3070_rf_write(sc, 51, rf);
3347faca41fbSmlelstv /* Set tx_mx1_ic. */
3348faca41fbSmlelstv run_rt3070_rf_read(sc, 51, &rf);
3349faca41fbSmlelstv rf &= ~0xe0;
3350faca41fbSmlelstv rf |= (chan <= 14) ? 0x60 : 0x40;
3351faca41fbSmlelstv run_rt3070_rf_write(sc, 51, rf);
3352faca41fbSmlelstv /* Set tx_lo1_ic. */
3353faca41fbSmlelstv run_rt3070_rf_read(sc, 49, &rf);
3354faca41fbSmlelstv rf &= ~0x1c;
3355faca41fbSmlelstv rf |= (chan <= 14) ? 0x0c : 0x08;
3356faca41fbSmlelstv run_rt3070_rf_write(sc, 49, rf);
3357faca41fbSmlelstv /* Set tx_lo1_en. */
3358faca41fbSmlelstv run_rt3070_rf_read(sc, 50, &rf);
3359faca41fbSmlelstv run_rt3070_rf_write(sc, 50, rf & ~0x20);
3360faca41fbSmlelstv /* Set drv_cc. */
3361faca41fbSmlelstv run_rt3070_rf_read(sc, 57, &rf);
3362faca41fbSmlelstv rf &= ~0xfc;
3363faca41fbSmlelstv rf |= (chan <= 14) ? 0x6c : 0x3c;
3364faca41fbSmlelstv run_rt3070_rf_write(sc, 57, rf);
3365faca41fbSmlelstv /* Set rx_mix1_ic, rxa_lnactr, lna_vc, lna_inbias_en and lna_en. */
3366faca41fbSmlelstv run_rt3070_rf_write(sc, 44, (chan <= 14) ? 0x93 : 0x9b);
3367faca41fbSmlelstv /* Set drv_gnd_a, tx_vga_cc_a and tx_mx2_gain. */
3368faca41fbSmlelstv run_rt3070_rf_write(sc, 52, (chan <= 14) ? 0x45 : 0x05);
3369faca41fbSmlelstv /* Enable VCO calibration. */
3370faca41fbSmlelstv run_rt3070_rf_read(sc, 3, &rf);
3371faca41fbSmlelstv rf &= ~RT5390_VCOCAL;
3372faca41fbSmlelstv rf |= (chan <= 14) ? RT5390_VCOCAL : 0xbe;
3373faca41fbSmlelstv run_rt3070_rf_write(sc, 3, rf);
3374faca41fbSmlelstv
3375faca41fbSmlelstv if (chan <= 14)
3376faca41fbSmlelstv rf = 0x23;
3377faca41fbSmlelstv else if (chan <= 64)
3378faca41fbSmlelstv rf = 0x36;
3379faca41fbSmlelstv else if (chan <= 128)
3380faca41fbSmlelstv rf = 0x32;
3381faca41fbSmlelstv else
3382faca41fbSmlelstv rf = 0x30;
3383faca41fbSmlelstv run_rt3070_rf_write(sc, 39, rf);
3384faca41fbSmlelstv if (chan <= 14)
3385faca41fbSmlelstv rf = 0xbb;
3386faca41fbSmlelstv else if (chan <= 64)
3387faca41fbSmlelstv rf = 0xeb;
3388faca41fbSmlelstv else if (chan <= 128)
3389faca41fbSmlelstv rf = 0xb3;
3390faca41fbSmlelstv else
3391faca41fbSmlelstv rf = 0x9b;
3392faca41fbSmlelstv run_rt3070_rf_write(sc, 45, rf);
3393faca41fbSmlelstv
3394faca41fbSmlelstv /* Set FEQ/AEQ control. */
3395faca41fbSmlelstv run_bbp_write(sc, 105, 0x34);
3396faca41fbSmlelstv }
3397faca41fbSmlelstv
3398faca41fbSmlelstv static void
run_rt5390_set_chan(struct run_softc * sc,u_int chan)3399faca41fbSmlelstv run_rt5390_set_chan(struct run_softc *sc, u_int chan)
3400faca41fbSmlelstv {
3401faca41fbSmlelstv int8_t txpow1, txpow2;
3402faca41fbSmlelstv uint8_t rf;
3403faca41fbSmlelstv int i;
3404faca41fbSmlelstv
3405faca41fbSmlelstv /* find the settings for this channel (we know it exists) */
3406faca41fbSmlelstv for (i = 0; rt2860_rf2850[i].chan != chan; i++);
3407faca41fbSmlelstv
3408faca41fbSmlelstv /* use Tx power values from EEPROM */
3409faca41fbSmlelstv txpow1 = sc->txpow1[i];
3410faca41fbSmlelstv txpow2 = sc->txpow2[i];
3411faca41fbSmlelstv
3412faca41fbSmlelstv run_rt3070_rf_write(sc, 8, rt3070_freqs[i].n);
3413faca41fbSmlelstv run_rt3070_rf_write(sc, 9, rt3070_freqs[i].k & 0x0f);
3414faca41fbSmlelstv run_rt3070_rf_read(sc, 11, &rf);
3415faca41fbSmlelstv rf = (rf & ~0x03) | (rt3070_freqs[i].r & 0x03);
3416faca41fbSmlelstv run_rt3070_rf_write(sc, 11, rf);
3417faca41fbSmlelstv
3418faca41fbSmlelstv run_rt3070_rf_read(sc, 49, &rf);
3419faca41fbSmlelstv rf = (rf & ~0x3f) | (txpow1 & 0x3f);
3420faca41fbSmlelstv /* The valid range of the RF R49 is 0x00 to 0x27. */
3421faca41fbSmlelstv if ((rf & 0x3f) > 0x27)
3422faca41fbSmlelstv rf = (rf & ~0x3f) | 0x27;
3423faca41fbSmlelstv run_rt3070_rf_write(sc, 49, rf);
3424faca41fbSmlelstv
3425faca41fbSmlelstv if (sc->mac_ver == 0x5392) {
3426faca41fbSmlelstv run_rt3070_rf_read(sc, 50, &rf);
3427faca41fbSmlelstv rf = (rf & ~0x3f) | (txpow2 & 0x3f);
3428faca41fbSmlelstv /* The valid range of the RF R50 is 0x00 to 0x27. */
3429faca41fbSmlelstv if ((rf & 0x3f) > 0x27)
3430faca41fbSmlelstv rf = (rf & ~0x3f) | 0x27;
3431faca41fbSmlelstv run_rt3070_rf_write(sc, 50, rf);
3432faca41fbSmlelstv }
3433faca41fbSmlelstv
3434faca41fbSmlelstv run_rt3070_rf_read(sc, 1, &rf);
3435faca41fbSmlelstv rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD;
3436faca41fbSmlelstv if (sc->mac_ver == 0x5392)
3437faca41fbSmlelstv rf |= RT3070_RX1_PD | RT3070_TX1_PD;
3438faca41fbSmlelstv run_rt3070_rf_write(sc, 1, rf);
3439faca41fbSmlelstv
3440faca41fbSmlelstv if (sc->mac_ver != 0x5392) {
3441faca41fbSmlelstv run_rt3070_rf_read(sc, 2, &rf);
3442faca41fbSmlelstv rf |= 0x80;
3443faca41fbSmlelstv run_rt3070_rf_write(sc, 2, rf);
3444faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
3445faca41fbSmlelstv rf &= 0x7f;
3446faca41fbSmlelstv run_rt3070_rf_write(sc, 2, rf);
3447faca41fbSmlelstv }
3448faca41fbSmlelstv
3449faca41fbSmlelstv run_adjust_freq_offset(sc);
3450faca41fbSmlelstv
3451faca41fbSmlelstv if (sc->mac_ver == 0x5392) {
3452faca41fbSmlelstv /* Fix for RT5392C. */
3453faca41fbSmlelstv if (sc->mac_rev >= 0x0223) {
3454faca41fbSmlelstv if (chan <= 4)
3455faca41fbSmlelstv rf = 0x0f;
3456faca41fbSmlelstv else if (chan >= 5 && chan <= 7)
3457faca41fbSmlelstv rf = 0x0e;
3458faca41fbSmlelstv else
3459faca41fbSmlelstv rf = 0x0d;
3460faca41fbSmlelstv run_rt3070_rf_write(sc, 23, rf);
3461faca41fbSmlelstv
3462faca41fbSmlelstv if (chan <= 4)
3463faca41fbSmlelstv rf = 0x0c;
3464faca41fbSmlelstv else if (chan == 5)
3465faca41fbSmlelstv rf = 0x0b;
3466faca41fbSmlelstv else if (chan >= 6 && chan <= 7)
3467faca41fbSmlelstv rf = 0x0a;
3468faca41fbSmlelstv else if (chan >= 8 && chan <= 10)
3469faca41fbSmlelstv rf = 0x09;
3470faca41fbSmlelstv else
3471faca41fbSmlelstv rf = 0x08;
3472faca41fbSmlelstv run_rt3070_rf_write(sc, 59, rf);
3473faca41fbSmlelstv } else {
3474faca41fbSmlelstv if (chan <= 11)
3475faca41fbSmlelstv rf = 0x0f;
3476faca41fbSmlelstv else
3477faca41fbSmlelstv rf = 0x0b;
3478faca41fbSmlelstv run_rt3070_rf_write(sc, 59, rf);
3479faca41fbSmlelstv }
3480faca41fbSmlelstv } else {
3481faca41fbSmlelstv /* Fix for RT5390F. */
3482faca41fbSmlelstv if (sc->mac_rev >= 0x0502) {
3483faca41fbSmlelstv if (chan <= 11)
3484faca41fbSmlelstv rf = 0x43;
3485faca41fbSmlelstv else
3486faca41fbSmlelstv rf = 0x23;
3487faca41fbSmlelstv run_rt3070_rf_write(sc, 55, rf);
3488faca41fbSmlelstv
3489faca41fbSmlelstv if (chan <= 11)
3490faca41fbSmlelstv rf = 0x0f;
3491faca41fbSmlelstv else if (chan == 12)
3492faca41fbSmlelstv rf = 0x0d;
3493faca41fbSmlelstv else
3494faca41fbSmlelstv rf = 0x0b;
3495faca41fbSmlelstv run_rt3070_rf_write(sc, 59, rf);
3496faca41fbSmlelstv } else {
3497faca41fbSmlelstv run_rt3070_rf_write(sc, 55, 0x44);
3498faca41fbSmlelstv run_rt3070_rf_write(sc, 59, 0x8f);
3499faca41fbSmlelstv }
3500faca41fbSmlelstv }
3501faca41fbSmlelstv
3502faca41fbSmlelstv /* Enable VCO calibration. */
3503faca41fbSmlelstv run_rt3070_rf_read(sc, 3, &rf);
3504faca41fbSmlelstv rf |= RT5390_VCOCAL;
3505faca41fbSmlelstv run_rt3070_rf_write(sc, 3, rf);
3506faca41fbSmlelstv }
3507faca41fbSmlelstv
3508faca41fbSmlelstv static void
run_rt5592_set_chan(struct run_softc * sc,u_int chan)3509faca41fbSmlelstv run_rt5592_set_chan(struct run_softc *sc, u_int chan)
3510faca41fbSmlelstv {
3511faca41fbSmlelstv const struct rt5592_freqs *freqs;
3512faca41fbSmlelstv uint32_t tmp;
3513faca41fbSmlelstv uint8_t reg, rf, txpow_bound;
3514faca41fbSmlelstv int8_t txpow1, txpow2;
3515faca41fbSmlelstv int i;
3516faca41fbSmlelstv
3517faca41fbSmlelstv run_read(sc, RT5592_DEBUG_INDEX, &tmp);
3518faca41fbSmlelstv freqs = (tmp & RT5592_SEL_XTAL) ?
3519faca41fbSmlelstv rt5592_freqs_40mhz : rt5592_freqs_20mhz;
3520faca41fbSmlelstv
3521faca41fbSmlelstv /* find the settings for this channel (we know it exists) */
3522faca41fbSmlelstv for (i = 0; rt2860_rf2850[i].chan != chan; i++, freqs++);
3523faca41fbSmlelstv
3524faca41fbSmlelstv /* use Tx power values from EEPROM */
3525faca41fbSmlelstv txpow1 = sc->txpow1[i];
3526faca41fbSmlelstv txpow2 = sc->txpow2[i];
3527faca41fbSmlelstv
3528faca41fbSmlelstv run_read(sc, RT3070_LDO_CFG0, &tmp);
3529faca41fbSmlelstv tmp &= ~0x1c000000;
3530faca41fbSmlelstv if (chan > 14)
3531faca41fbSmlelstv tmp |= 0x14000000;
3532faca41fbSmlelstv run_write(sc, RT3070_LDO_CFG0, tmp);
3533faca41fbSmlelstv
3534faca41fbSmlelstv /* N setting. */
3535faca41fbSmlelstv run_rt3070_rf_write(sc, 8, freqs->n & 0xff);
3536faca41fbSmlelstv run_rt3070_rf_read(sc, 9, &rf);
3537faca41fbSmlelstv rf &= ~(1 << 4);
3538faca41fbSmlelstv rf |= ((freqs->n & 0x0100) >> 8) << 4;
3539faca41fbSmlelstv run_rt3070_rf_write(sc, 9, rf);
3540faca41fbSmlelstv
3541faca41fbSmlelstv /* K setting. */
3542faca41fbSmlelstv run_rt3070_rf_read(sc, 9, &rf);
3543faca41fbSmlelstv rf &= ~0x0f;
3544faca41fbSmlelstv rf |= (freqs->k & 0x0f);
3545faca41fbSmlelstv run_rt3070_rf_write(sc, 9, rf);
3546faca41fbSmlelstv
3547faca41fbSmlelstv /* Mode setting. */
3548faca41fbSmlelstv run_rt3070_rf_read(sc, 11, &rf);
3549faca41fbSmlelstv rf &= ~0x0c;
3550faca41fbSmlelstv rf |= ((freqs->m - 0x8) & 0x3) << 2;
3551faca41fbSmlelstv run_rt3070_rf_write(sc, 11, rf);
3552faca41fbSmlelstv run_rt3070_rf_read(sc, 9, &rf);
3553faca41fbSmlelstv rf &= ~(1 << 7);
3554faca41fbSmlelstv rf |= (((freqs->m - 0x8) & 0x4) >> 2) << 7;
3555faca41fbSmlelstv run_rt3070_rf_write(sc, 9, rf);
3556faca41fbSmlelstv
3557faca41fbSmlelstv /* R setting. */
3558faca41fbSmlelstv run_rt3070_rf_read(sc, 11, &rf);
3559faca41fbSmlelstv rf &= ~0x03;
3560faca41fbSmlelstv rf |= (freqs->r - 0x1);
3561faca41fbSmlelstv run_rt3070_rf_write(sc, 11, rf);
3562faca41fbSmlelstv
3563faca41fbSmlelstv if (chan <= 14) {
3564faca41fbSmlelstv /* Initialize RF registers for 2GHZ. */
3565faca41fbSmlelstv for (i = 0; i < (int)__arraycount(rt5592_2ghz_def_rf); i++) {
3566faca41fbSmlelstv run_rt3070_rf_write(sc, rt5592_2ghz_def_rf[i].reg,
3567faca41fbSmlelstv rt5592_2ghz_def_rf[i].val);
3568faca41fbSmlelstv }
3569faca41fbSmlelstv
3570faca41fbSmlelstv rf = (chan <= 10) ? 0x07 : 0x06;
3571faca41fbSmlelstv run_rt3070_rf_write(sc, 23, rf);
3572faca41fbSmlelstv run_rt3070_rf_write(sc, 59, rf);
3573faca41fbSmlelstv
3574faca41fbSmlelstv run_rt3070_rf_write(sc, 55, 0x43);
3575faca41fbSmlelstv
3576faca41fbSmlelstv /*
3577faca41fbSmlelstv * RF R49/R50 Tx power ALC code.
3578faca41fbSmlelstv * G-band bit<7:6>=1:0, bit<5:0> range from 0x0 ~ 0x27.
3579faca41fbSmlelstv */
3580faca41fbSmlelstv reg = 2;
3581faca41fbSmlelstv txpow_bound = 0x27;
3582faca41fbSmlelstv } else {
3583faca41fbSmlelstv /* Initialize RF registers for 5GHZ. */
3584faca41fbSmlelstv for (i = 0; i < (int)__arraycount(rt5592_5ghz_def_rf); i++) {
3585faca41fbSmlelstv run_rt3070_rf_write(sc, rt5592_5ghz_def_rf[i].reg,
3586faca41fbSmlelstv rt5592_5ghz_def_rf[i].val);
3587faca41fbSmlelstv }
3588faca41fbSmlelstv for (i = 0; i < (int)__arraycount(rt5592_chan_5ghz); i++) {
3589faca41fbSmlelstv if (chan >= rt5592_chan_5ghz[i].firstchan &&
3590faca41fbSmlelstv chan <= rt5592_chan_5ghz[i].lastchan) {
3591faca41fbSmlelstv run_rt3070_rf_write(sc, rt5592_chan_5ghz[i].reg,
3592faca41fbSmlelstv rt5592_chan_5ghz[i].val);
3593faca41fbSmlelstv }
3594faca41fbSmlelstv }
3595faca41fbSmlelstv
3596faca41fbSmlelstv /*
3597faca41fbSmlelstv * RF R49/R50 Tx power ALC code.
3598faca41fbSmlelstv * A-band bit<7:6>=1:1, bit<5:0> range from 0x0 ~ 0x2b.
3599faca41fbSmlelstv */
3600faca41fbSmlelstv reg = 3;
3601faca41fbSmlelstv txpow_bound = 0x2b;
3602faca41fbSmlelstv }
3603faca41fbSmlelstv
3604faca41fbSmlelstv /* RF R49 ch0 Tx power ALC code. */
3605faca41fbSmlelstv run_rt3070_rf_read(sc, 49, &rf);
3606faca41fbSmlelstv rf &= ~0xc0;
3607faca41fbSmlelstv rf |= (reg << 6);
3608faca41fbSmlelstv rf = (rf & ~0x3f) | (txpow1 & 0x3f);
3609faca41fbSmlelstv if ((rf & 0x3f) > txpow_bound)
3610faca41fbSmlelstv rf = (rf & ~0x3f) | txpow_bound;
3611faca41fbSmlelstv run_rt3070_rf_write(sc, 49, rf);
3612faca41fbSmlelstv
3613faca41fbSmlelstv /* RF R50 ch1 Tx power ALC code. */
3614faca41fbSmlelstv run_rt3070_rf_read(sc, 50, &rf);
3615faca41fbSmlelstv rf &= ~(1 << 7 | 1 << 6);
3616faca41fbSmlelstv rf |= (reg << 6);
3617faca41fbSmlelstv rf = (rf & ~0x3f) | (txpow2 & 0x3f);
3618faca41fbSmlelstv if ((rf & 0x3f) > txpow_bound)
3619faca41fbSmlelstv rf = (rf & ~0x3f) | txpow_bound;
3620faca41fbSmlelstv run_rt3070_rf_write(sc, 50, rf);
3621faca41fbSmlelstv
3622faca41fbSmlelstv /* Enable RF_BLOCK, PLL_PD, RX0_PD, and TX0_PD. */
3623faca41fbSmlelstv run_rt3070_rf_read(sc, 1, &rf);
3624faca41fbSmlelstv rf |= (RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD);
3625faca41fbSmlelstv if (sc->ntxchains > 1)
3626faca41fbSmlelstv rf |= RT3070_TX1_PD;
3627faca41fbSmlelstv if (sc->nrxchains > 1)
3628faca41fbSmlelstv rf |= RT3070_RX1_PD;
3629faca41fbSmlelstv run_rt3070_rf_write(sc, 1, rf);
3630faca41fbSmlelstv
3631faca41fbSmlelstv run_rt3070_rf_write(sc, 6, 0xe4);
3632faca41fbSmlelstv
3633faca41fbSmlelstv run_rt3070_rf_write(sc, 30, 0x10);
3634faca41fbSmlelstv run_rt3070_rf_write(sc, 31, 0x80);
3635faca41fbSmlelstv run_rt3070_rf_write(sc, 32, 0x80);
3636faca41fbSmlelstv
3637faca41fbSmlelstv run_adjust_freq_offset(sc);
3638faca41fbSmlelstv
3639faca41fbSmlelstv /* Enable VCO calibration. */
3640faca41fbSmlelstv run_rt3070_rf_read(sc, 3, &rf);
3641faca41fbSmlelstv rf |= RT5390_VCOCAL;
3642faca41fbSmlelstv run_rt3070_rf_write(sc, 3, rf);
3643faca41fbSmlelstv }
3644faca41fbSmlelstv
3645faca41fbSmlelstv static void
run_iq_calib(struct run_softc * sc,u_int chan)3646faca41fbSmlelstv run_iq_calib(struct run_softc *sc, u_int chan)
3647faca41fbSmlelstv {
3648faca41fbSmlelstv uint16_t val;
3649faca41fbSmlelstv
3650faca41fbSmlelstv /* Tx0 IQ gain. */
3651faca41fbSmlelstv run_bbp_write(sc, 158, 0x2c);
3652faca41fbSmlelstv if (chan <= 14)
3653faca41fbSmlelstv run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX0_2GHZ, &val, 1);
3654faca41fbSmlelstv else if (chan <= 64) {
3655faca41fbSmlelstv run_efuse_read(sc,
3656faca41fbSmlelstv RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ,
3657faca41fbSmlelstv &val, 1);
3658faca41fbSmlelstv } else if (chan <= 138) {
3659faca41fbSmlelstv run_efuse_read(sc,
3660faca41fbSmlelstv RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ,
3661faca41fbSmlelstv &val, 1);
3662faca41fbSmlelstv } else if (chan <= 165) {
3663faca41fbSmlelstv run_efuse_read(sc,
3664faca41fbSmlelstv RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ,
3665faca41fbSmlelstv &val, 1);
3666faca41fbSmlelstv } else
3667faca41fbSmlelstv val = 0;
3668faca41fbSmlelstv run_bbp_write(sc, 159, val);
3669faca41fbSmlelstv
3670faca41fbSmlelstv /* Tx0 IQ phase. */
3671faca41fbSmlelstv run_bbp_write(sc, 158, 0x2d);
3672faca41fbSmlelstv if (chan <= 14) {
3673faca41fbSmlelstv run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX0_2GHZ,
3674faca41fbSmlelstv &val, 1);
3675faca41fbSmlelstv } else if (chan <= 64) {
3676faca41fbSmlelstv run_efuse_read(sc,
3677faca41fbSmlelstv RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ,
3678faca41fbSmlelstv &val, 1);
3679faca41fbSmlelstv } else if (chan <= 138) {
3680faca41fbSmlelstv run_efuse_read(sc,
3681faca41fbSmlelstv RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ,
3682faca41fbSmlelstv &val, 1);
3683faca41fbSmlelstv } else if (chan <= 165) {
3684faca41fbSmlelstv run_efuse_read(sc,
3685faca41fbSmlelstv RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ,
3686faca41fbSmlelstv &val, 1);
3687faca41fbSmlelstv } else
3688faca41fbSmlelstv val = 0;
3689faca41fbSmlelstv run_bbp_write(sc, 159, val);
3690faca41fbSmlelstv
3691faca41fbSmlelstv /* Tx1 IQ gain. */
3692faca41fbSmlelstv run_bbp_write(sc, 158, 0x4a);
3693faca41fbSmlelstv if (chan <= 14) {
3694faca41fbSmlelstv run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX1_2GHZ,
3695faca41fbSmlelstv &val, 1);
3696faca41fbSmlelstv } else if (chan <= 64) {
3697faca41fbSmlelstv run_efuse_read(sc,
3698faca41fbSmlelstv RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ,
3699faca41fbSmlelstv &val, 1);
3700faca41fbSmlelstv } else if (chan <= 138) {
3701faca41fbSmlelstv run_efuse_read(sc,
3702faca41fbSmlelstv RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ,
3703faca41fbSmlelstv &val, 1);
3704faca41fbSmlelstv } else if (chan <= 165) {
3705faca41fbSmlelstv run_efuse_read(sc,
3706faca41fbSmlelstv RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ,
3707faca41fbSmlelstv &val, 1);
3708faca41fbSmlelstv } else
3709faca41fbSmlelstv val = 0;
3710faca41fbSmlelstv run_bbp_write(sc, 159, val);
3711faca41fbSmlelstv
3712faca41fbSmlelstv /* Tx1 IQ phase. */
3713faca41fbSmlelstv run_bbp_write(sc, 158, 0x4b);
3714faca41fbSmlelstv if (chan <= 14) {
3715faca41fbSmlelstv run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX1_2GHZ,
3716faca41fbSmlelstv &val, 1);
3717faca41fbSmlelstv } else if (chan <= 64) {
3718faca41fbSmlelstv run_efuse_read(sc,
3719faca41fbSmlelstv RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ,
3720faca41fbSmlelstv &val, 1);
3721faca41fbSmlelstv } else if (chan <= 138) {
3722faca41fbSmlelstv run_efuse_read(sc,
3723faca41fbSmlelstv RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ,
3724faca41fbSmlelstv &val, 1);
3725faca41fbSmlelstv } else if (chan <= 165) {
3726faca41fbSmlelstv run_efuse_read(sc,
3727faca41fbSmlelstv RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ,
3728faca41fbSmlelstv &val, 1);
3729faca41fbSmlelstv } else
3730faca41fbSmlelstv val = 0;
3731faca41fbSmlelstv run_bbp_write(sc, 159, val);
3732faca41fbSmlelstv
3733faca41fbSmlelstv /* RF IQ compensation control. */
3734faca41fbSmlelstv run_bbp_write(sc, 158, 0x04);
3735faca41fbSmlelstv run_efuse_read(sc, RT5390_EEPROM_RF_IQ_COMPENSATION_CTL,
3736faca41fbSmlelstv &val, 1);
3737faca41fbSmlelstv run_bbp_write(sc, 159, val);
3738faca41fbSmlelstv
3739faca41fbSmlelstv /* RF IQ imbalance compensation control. */
3740faca41fbSmlelstv run_bbp_write(sc, 158, 0x03);
3741faca41fbSmlelstv run_efuse_read(sc,
3742faca41fbSmlelstv RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL, &val, 1);
3743faca41fbSmlelstv run_bbp_write(sc, 159, val);
37449cdb1c70Snonaka }
37459cdb1c70Snonaka
37469cdb1c70Snonaka static void
run_set_agc(struct run_softc * sc,uint8_t agc)37479cdb1c70Snonaka run_set_agc(struct run_softc *sc, uint8_t agc)
37489cdb1c70Snonaka {
37499cdb1c70Snonaka uint8_t bbp;
37509cdb1c70Snonaka
37519cdb1c70Snonaka if (sc->mac_ver == 0x3572) {
37529cdb1c70Snonaka run_bbp_read(sc, 27, &bbp);
37539cdb1c70Snonaka bbp &= ~(0x3 << 5);
37549cdb1c70Snonaka run_bbp_write(sc, 27, bbp | 0 << 5); /* select Rx0 */
37559cdb1c70Snonaka run_bbp_write(sc, 66, agc);
37569cdb1c70Snonaka run_bbp_write(sc, 27, bbp | 1 << 5); /* select Rx1 */
37579cdb1c70Snonaka run_bbp_write(sc, 66, agc);
37589cdb1c70Snonaka } else
37599cdb1c70Snonaka run_bbp_write(sc, 66, agc);
37609cdb1c70Snonaka }
37619cdb1c70Snonaka
37629cdb1c70Snonaka static void
run_set_rx_antenna(struct run_softc * sc,int aux)37639cdb1c70Snonaka run_set_rx_antenna(struct run_softc *sc, int aux)
37649cdb1c70Snonaka {
37659cdb1c70Snonaka uint32_t tmp;
3766faca41fbSmlelstv uint8_t bbp152;
37679cdb1c70Snonaka
3768d164e220Smlelstv if (aux) {
3769faca41fbSmlelstv if (sc->rf_rev == RT5390_RF_5370) {
3770faca41fbSmlelstv run_bbp_read(sc, 152, &bbp152);
3771faca41fbSmlelstv bbp152 &= ~0x80;
3772d164e220Smlelstv run_bbp_write(sc, 152, bbp152);
3773d164e220Smlelstv } else {
3774d164e220Smlelstv run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, 0);
3775d164e220Smlelstv run_read(sc, RT2860_GPIO_CTRL, &tmp);
3776d164e220Smlelstv tmp &= ~0x0808;
3777d164e220Smlelstv tmp |= 0x08;
3778d164e220Smlelstv run_write(sc, RT2860_GPIO_CTRL, tmp);
3779d164e220Smlelstv }
3780d164e220Smlelstv } else {
3781d164e220Smlelstv if (sc->rf_rev == RT5390_RF_5370) {
3782d164e220Smlelstv run_bbp_read(sc, 152, &bbp152);
3783faca41fbSmlelstv bbp152 |= 0x80;
3784faca41fbSmlelstv run_bbp_write(sc, 152, bbp152);
3785faca41fbSmlelstv } else {
37869cdb1c70Snonaka run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, !aux);
37879cdb1c70Snonaka run_read(sc, RT2860_GPIO_CTRL, &tmp);
37889cdb1c70Snonaka tmp &= ~0x0808;
37899cdb1c70Snonaka run_write(sc, RT2860_GPIO_CTRL, tmp);
37909cdb1c70Snonaka }
3791faca41fbSmlelstv }
3792d164e220Smlelstv }
37939cdb1c70Snonaka
37949cdb1c70Snonaka static int
run_set_chan(struct run_softc * sc,struct ieee80211_channel * c)37959cdb1c70Snonaka run_set_chan(struct run_softc *sc, struct ieee80211_channel *c)
37969cdb1c70Snonaka {
37979cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
37989cdb1c70Snonaka u_int chan, group;
37999cdb1c70Snonaka
38009cdb1c70Snonaka chan = ieee80211_chan2ieee(ic, c);
38019cdb1c70Snonaka if (chan == 0 || chan == IEEE80211_CHAN_ANY)
38024e8e6643Sskrll return EINVAL;
38039cdb1c70Snonaka
3804faca41fbSmlelstv if (sc->mac_ver == 0x5592)
3805faca41fbSmlelstv run_rt5592_set_chan(sc, chan);
3806faca41fbSmlelstv else if (sc->mac_ver >= 0x5390)
3807faca41fbSmlelstv run_rt5390_set_chan(sc, chan);
3808faca41fbSmlelstv else if (sc->mac_ver == 0x3593)
3809faca41fbSmlelstv run_rt3593_set_chan(sc, chan);
3810faca41fbSmlelstv else if (sc->mac_ver == 0x3572)
38119cdb1c70Snonaka run_rt3572_set_chan(sc, chan);
38129cdb1c70Snonaka else if (sc->mac_ver >= 0x3070)
38139cdb1c70Snonaka run_rt3070_set_chan(sc, chan);
38149cdb1c70Snonaka else
38159cdb1c70Snonaka run_rt2870_set_chan(sc, chan);
38169cdb1c70Snonaka
38179cdb1c70Snonaka /* determine channel group */
38189cdb1c70Snonaka if (chan <= 14)
38199cdb1c70Snonaka group = 0;
38209cdb1c70Snonaka else if (chan <= 64)
38219cdb1c70Snonaka group = 1;
38229cdb1c70Snonaka else if (chan <= 128)
38239cdb1c70Snonaka group = 2;
38249cdb1c70Snonaka else
38259cdb1c70Snonaka group = 3;
38269cdb1c70Snonaka
38279cdb1c70Snonaka /* XXX necessary only when group has changed! */
38289cdb1c70Snonaka run_select_chan_group(sc, group);
38299cdb1c70Snonaka
3830faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
3831faca41fbSmlelstv
3832faca41fbSmlelstv /* Perform IQ calibration. */
3833faca41fbSmlelstv if (sc->mac_ver >= 0x5392)
3834faca41fbSmlelstv run_iq_calib(sc, chan);
3835faca41fbSmlelstv
38364e8e6643Sskrll return 0;
38379cdb1c70Snonaka }
38389cdb1c70Snonaka
38399cdb1c70Snonaka static void
run_updateprot(struct run_softc * sc)3840faca41fbSmlelstv run_updateprot(struct run_softc *sc)
3841faca41fbSmlelstv {
3842faca41fbSmlelstv struct ieee80211com *ic = &sc->sc_ic;
3843faca41fbSmlelstv uint32_t tmp;
3844faca41fbSmlelstv
3845faca41fbSmlelstv tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL;
3846faca41fbSmlelstv /* setup protection frame rate (MCS code) */
3847faca41fbSmlelstv tmp |= (ic->ic_curmode == IEEE80211_MODE_11A) ?
3848faca41fbSmlelstv rt2860_rates[RT2860_RIDX_OFDM6].mcs | RT2860_PHY_OFDM :
3849faca41fbSmlelstv rt2860_rates[RT2860_RIDX_CCK11].mcs;
3850faca41fbSmlelstv
3851faca41fbSmlelstv /* CCK frames don't require protection */
3852faca41fbSmlelstv run_write(sc, RT2860_CCK_PROT_CFG, tmp);
3853faca41fbSmlelstv if (ic->ic_flags & IEEE80211_F_USEPROT) {
3854faca41fbSmlelstv if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
3855faca41fbSmlelstv tmp |= RT2860_PROT_CTRL_RTS_CTS;
3856faca41fbSmlelstv else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
3857faca41fbSmlelstv tmp |= RT2860_PROT_CTRL_CTS;
3858faca41fbSmlelstv }
3859faca41fbSmlelstv run_write(sc, RT2860_OFDM_PROT_CFG, tmp);
3860faca41fbSmlelstv }
3861faca41fbSmlelstv
3862faca41fbSmlelstv static void
run_enable_tsf_sync(struct run_softc * sc)38639cdb1c70Snonaka run_enable_tsf_sync(struct run_softc *sc)
38649cdb1c70Snonaka {
38659cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
38669cdb1c70Snonaka uint32_t tmp;
38679cdb1c70Snonaka
38689cdb1c70Snonaka run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
38699cdb1c70Snonaka tmp &= ~0x1fffff;
38709cdb1c70Snonaka tmp |= ic->ic_bss->ni_intval * 16;
38719cdb1c70Snonaka tmp |= RT2860_TSF_TIMER_EN | RT2860_TBTT_TIMER_EN;
38729cdb1c70Snonaka if (ic->ic_opmode == IEEE80211_M_STA) {
38739cdb1c70Snonaka /*
38749cdb1c70Snonaka * Local TSF is always updated with remote TSF on beacon
38759cdb1c70Snonaka * reception.
38769cdb1c70Snonaka */
38779cdb1c70Snonaka tmp |= 1 << RT2860_TSF_SYNC_MODE_SHIFT;
38789cdb1c70Snonaka }
38799cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY
38809cdb1c70Snonaka else if (ic->ic_opmode == IEEE80211_M_IBSS) {
38819cdb1c70Snonaka tmp |= RT2860_BCN_TX_EN;
38829cdb1c70Snonaka /*
38839cdb1c70Snonaka * Local TSF is updated with remote TSF on beacon reception
38849cdb1c70Snonaka * only if the remote TSF is greater than local TSF.
38859cdb1c70Snonaka */
38869cdb1c70Snonaka tmp |= 2 << RT2860_TSF_SYNC_MODE_SHIFT;
38879cdb1c70Snonaka } else if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
38889cdb1c70Snonaka tmp |= RT2860_BCN_TX_EN;
38899cdb1c70Snonaka /* SYNC with nobody */
38909cdb1c70Snonaka tmp |= 3 << RT2860_TSF_SYNC_MODE_SHIFT;
38919cdb1c70Snonaka }
38929cdb1c70Snonaka #endif
38939cdb1c70Snonaka run_write(sc, RT2860_BCN_TIME_CFG, tmp);
38949cdb1c70Snonaka }
38959cdb1c70Snonaka
38969cdb1c70Snonaka static void
run_enable_mrr(struct run_softc * sc)38979cdb1c70Snonaka run_enable_mrr(struct run_softc *sc)
38989cdb1c70Snonaka {
38999cdb1c70Snonaka #define CCK(mcs) (mcs)
39009cdb1c70Snonaka #define OFDM(mcs) (1 << 3 | (mcs))
39019cdb1c70Snonaka run_write(sc, RT2860_LG_FBK_CFG0,
39029cdb1c70Snonaka OFDM(6) << 28 | /* 54->48 */
39039cdb1c70Snonaka OFDM(5) << 24 | /* 48->36 */
39049cdb1c70Snonaka OFDM(4) << 20 | /* 36->24 */
39059cdb1c70Snonaka OFDM(3) << 16 | /* 24->18 */
39069cdb1c70Snonaka OFDM(2) << 12 | /* 18->12 */
39079cdb1c70Snonaka OFDM(1) << 8 | /* 12-> 9 */
39089cdb1c70Snonaka OFDM(0) << 4 | /* 9-> 6 */
39099cdb1c70Snonaka OFDM(0)); /* 6-> 6 */
39109cdb1c70Snonaka
39119cdb1c70Snonaka run_write(sc, RT2860_LG_FBK_CFG1,
39129cdb1c70Snonaka CCK(2) << 12 | /* 11->5.5 */
39139cdb1c70Snonaka CCK(1) << 8 | /* 5.5-> 2 */
39149cdb1c70Snonaka CCK(0) << 4 | /* 2-> 1 */
39159cdb1c70Snonaka CCK(0)); /* 1-> 1 */
39169cdb1c70Snonaka #undef OFDM
39179cdb1c70Snonaka #undef CCK
39189cdb1c70Snonaka }
39199cdb1c70Snonaka
39209cdb1c70Snonaka static void
run_set_txpreamble(struct run_softc * sc)39219cdb1c70Snonaka run_set_txpreamble(struct run_softc *sc)
39229cdb1c70Snonaka {
39239cdb1c70Snonaka uint32_t tmp;
39249cdb1c70Snonaka
39259cdb1c70Snonaka run_read(sc, RT2860_AUTO_RSP_CFG, &tmp);
39269cdb1c70Snonaka if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
39279cdb1c70Snonaka tmp |= RT2860_CCK_SHORT_EN;
39289cdb1c70Snonaka else
39299cdb1c70Snonaka tmp &= ~RT2860_CCK_SHORT_EN;
39309cdb1c70Snonaka run_write(sc, RT2860_AUTO_RSP_CFG, tmp);
39319cdb1c70Snonaka }
39329cdb1c70Snonaka
39339cdb1c70Snonaka static void
run_set_basicrates(struct run_softc * sc)39349cdb1c70Snonaka run_set_basicrates(struct run_softc *sc)
39359cdb1c70Snonaka {
39369cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
39379cdb1c70Snonaka
39389cdb1c70Snonaka /* set basic rates mask */
39399cdb1c70Snonaka if (ic->ic_curmode == IEEE80211_MODE_11B)
39409cdb1c70Snonaka run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x003);
39419cdb1c70Snonaka else if (ic->ic_curmode == IEEE80211_MODE_11A)
39429cdb1c70Snonaka run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x150);
39439cdb1c70Snonaka else /* 11g */
39449cdb1c70Snonaka run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x15f);
39459cdb1c70Snonaka }
39469cdb1c70Snonaka
39479cdb1c70Snonaka static void
run_set_leds(struct run_softc * sc,uint16_t which)39489cdb1c70Snonaka run_set_leds(struct run_softc *sc, uint16_t which)
39499cdb1c70Snonaka {
39509cdb1c70Snonaka
39519cdb1c70Snonaka (void)run_mcu_cmd(sc, RT2860_MCU_CMD_LEDS,
39529cdb1c70Snonaka which | (sc->leds & 0x7f));
39539cdb1c70Snonaka }
39549cdb1c70Snonaka
39559cdb1c70Snonaka static void
run_set_bssid(struct run_softc * sc,const uint8_t * bssid)39569cdb1c70Snonaka run_set_bssid(struct run_softc *sc, const uint8_t *bssid)
39579cdb1c70Snonaka {
39589cdb1c70Snonaka
39599cdb1c70Snonaka run_write(sc, RT2860_MAC_BSSID_DW0,
39609cdb1c70Snonaka bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24);
39619cdb1c70Snonaka run_write(sc, RT2860_MAC_BSSID_DW1,
39629cdb1c70Snonaka bssid[4] | bssid[5] << 8);
39639cdb1c70Snonaka }
39649cdb1c70Snonaka
39659cdb1c70Snonaka static void
run_set_macaddr(struct run_softc * sc,const uint8_t * addr)39669cdb1c70Snonaka run_set_macaddr(struct run_softc *sc, const uint8_t *addr)
39679cdb1c70Snonaka {
39689cdb1c70Snonaka
39699cdb1c70Snonaka run_write(sc, RT2860_MAC_ADDR_DW0,
39709cdb1c70Snonaka addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
39719cdb1c70Snonaka run_write(sc, RT2860_MAC_ADDR_DW1,
39729cdb1c70Snonaka addr[4] | addr[5] << 8 | 0xff << 16);
39739cdb1c70Snonaka }
39749cdb1c70Snonaka
39759cdb1c70Snonaka static void
run_updateslot(struct ifnet * ifp)39769cdb1c70Snonaka run_updateslot(struct ifnet *ifp)
39779cdb1c70Snonaka {
39789cdb1c70Snonaka
39799cdb1c70Snonaka /* do it in a process context */
39809cdb1c70Snonaka run_do_async(ifp->if_softc, run_updateslot_cb, NULL, 0);
39819cdb1c70Snonaka }
39829cdb1c70Snonaka
39839cdb1c70Snonaka /* ARGSUSED */
39849cdb1c70Snonaka static void
run_updateslot_cb(struct run_softc * sc,void * arg)39859cdb1c70Snonaka run_updateslot_cb(struct run_softc *sc, void *arg)
39869cdb1c70Snonaka {
39879cdb1c70Snonaka uint32_t tmp;
39889cdb1c70Snonaka
39899cdb1c70Snonaka run_read(sc, RT2860_BKOFF_SLOT_CFG, &tmp);
39909cdb1c70Snonaka tmp &= ~0xff;
39919cdb1c70Snonaka tmp |= (sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
39929cdb1c70Snonaka run_write(sc, RT2860_BKOFF_SLOT_CFG, tmp);
39939cdb1c70Snonaka }
39949cdb1c70Snonaka
39959cdb1c70Snonaka static int8_t
run_rssi2dbm(struct run_softc * sc,uint8_t rssi,uint8_t rxchain)39969cdb1c70Snonaka run_rssi2dbm(struct run_softc *sc, uint8_t rssi, uint8_t rxchain)
39979cdb1c70Snonaka {
39989cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
39999cdb1c70Snonaka struct ieee80211_channel *c = ic->ic_curchan;
40009cdb1c70Snonaka int delta;
40019cdb1c70Snonaka
40029cdb1c70Snonaka if (IEEE80211_IS_CHAN_5GHZ(c)) {
40039cdb1c70Snonaka u_int chan = ieee80211_chan2ieee(ic, c);
40049cdb1c70Snonaka delta = sc->rssi_5ghz[rxchain];
40059cdb1c70Snonaka
40069cdb1c70Snonaka /* determine channel group */
40079cdb1c70Snonaka if (chan <= 64)
40089cdb1c70Snonaka delta -= sc->lna[1];
40099cdb1c70Snonaka else if (chan <= 128)
40109cdb1c70Snonaka delta -= sc->lna[2];
40119cdb1c70Snonaka else
40129cdb1c70Snonaka delta -= sc->lna[3];
40139cdb1c70Snonaka } else
40149cdb1c70Snonaka delta = sc->rssi_2ghz[rxchain] - sc->lna[0];
40159cdb1c70Snonaka
40164e8e6643Sskrll return -12 - delta - rssi;
40179cdb1c70Snonaka }
40189cdb1c70Snonaka
4019faca41fbSmlelstv static void
run_rt5390_bbp_init(struct run_softc * sc)4020faca41fbSmlelstv run_rt5390_bbp_init(struct run_softc *sc)
4021faca41fbSmlelstv {
4022faca41fbSmlelstv u_int i;
4023faca41fbSmlelstv uint8_t bbp;
4024faca41fbSmlelstv
4025faca41fbSmlelstv /* Apply maximum likelihood detection for 2 stream case. */
4026faca41fbSmlelstv run_bbp_read(sc, 105, &bbp);
4027faca41fbSmlelstv if (sc->nrxchains > 1)
4028faca41fbSmlelstv run_bbp_write(sc, 105, bbp | RT5390_MLD);
4029faca41fbSmlelstv
4030faca41fbSmlelstv /* Avoid data lost and CRC error. */
4031faca41fbSmlelstv run_bbp_read(sc, 4, &bbp);
4032faca41fbSmlelstv run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
4033faca41fbSmlelstv
4034faca41fbSmlelstv if (sc->mac_ver == 0x5592) {
4035faca41fbSmlelstv for (i = 0; i < (int)__arraycount(rt5592_def_bbp); i++) {
4036faca41fbSmlelstv run_bbp_write(sc, rt5592_def_bbp[i].reg,
4037faca41fbSmlelstv rt5592_def_bbp[i].val);
4038faca41fbSmlelstv }
4039faca41fbSmlelstv for (i = 0; i < (int)__arraycount(rt5592_bbp_r196); i++) {
4040faca41fbSmlelstv run_bbp_write(sc, 195, i + 0x80);
4041faca41fbSmlelstv run_bbp_write(sc, 196, rt5592_bbp_r196[i]);
4042faca41fbSmlelstv }
4043faca41fbSmlelstv } else {
4044faca41fbSmlelstv for (i = 0; i < (int)__arraycount(rt5390_def_bbp); i++) {
4045faca41fbSmlelstv run_bbp_write(sc, rt5390_def_bbp[i].reg,
4046faca41fbSmlelstv rt5390_def_bbp[i].val);
4047faca41fbSmlelstv }
4048faca41fbSmlelstv }
4049faca41fbSmlelstv if (sc->mac_ver == 0x5392) {
4050faca41fbSmlelstv run_bbp_write(sc, 88, 0x90);
4051faca41fbSmlelstv run_bbp_write(sc, 95, 0x9a);
4052faca41fbSmlelstv run_bbp_write(sc, 98, 0x12);
4053faca41fbSmlelstv run_bbp_write(sc, 106, 0x12);
4054faca41fbSmlelstv run_bbp_write(sc, 134, 0xd0);
4055faca41fbSmlelstv run_bbp_write(sc, 135, 0xf6);
4056faca41fbSmlelstv run_bbp_write(sc, 148, 0x84);
4057faca41fbSmlelstv }
4058faca41fbSmlelstv
4059faca41fbSmlelstv run_bbp_read(sc, 152, &bbp);
4060faca41fbSmlelstv run_bbp_write(sc, 152, bbp | 0x80);
4061faca41fbSmlelstv
4062faca41fbSmlelstv /* Fix BBP254 for RT5592C. */
4063faca41fbSmlelstv if (sc->mac_ver == 0x5592 && sc->mac_rev >= 0x0221) {
4064faca41fbSmlelstv run_bbp_read(sc, 254, &bbp);
4065faca41fbSmlelstv run_bbp_write(sc, 254, bbp | 0x80);
4066faca41fbSmlelstv }
4067faca41fbSmlelstv
4068faca41fbSmlelstv /* Disable hardware antenna diversity. */
4069faca41fbSmlelstv if (sc->mac_ver == 0x5390)
4070faca41fbSmlelstv run_bbp_write(sc, 154, 0);
4071faca41fbSmlelstv
4072faca41fbSmlelstv /* Initialize Rx CCK/OFDM frequency offset report. */
4073faca41fbSmlelstv run_bbp_write(sc, 142, 1);
4074faca41fbSmlelstv run_bbp_write(sc, 143, 57);
4075faca41fbSmlelstv }
4076faca41fbSmlelstv
40779cdb1c70Snonaka static int
run_bbp_init(struct run_softc * sc)40789cdb1c70Snonaka run_bbp_init(struct run_softc *sc)
40799cdb1c70Snonaka {
40809cdb1c70Snonaka int i, error, ntries;
40819cdb1c70Snonaka uint8_t bbp0;
40829cdb1c70Snonaka
40839cdb1c70Snonaka /* wait for BBP to wake up */
40849cdb1c70Snonaka for (ntries = 0; ntries < 20; ntries++) {
40859cdb1c70Snonaka if ((error = run_bbp_read(sc, 0, &bbp0)) != 0)
40864e8e6643Sskrll return error;
40879cdb1c70Snonaka if (bbp0 != 0 && bbp0 != 0xff)
40889cdb1c70Snonaka break;
40899cdb1c70Snonaka }
40909cdb1c70Snonaka if (ntries == 20)
40914e8e6643Sskrll return ETIMEDOUT;
40929cdb1c70Snonaka
40939cdb1c70Snonaka /* initialize BBP registers to default values */
4094faca41fbSmlelstv if (sc->mac_ver >= 0x5390)
4095faca41fbSmlelstv run_rt5390_bbp_init(sc);
4096faca41fbSmlelstv else {
40979cdb1c70Snonaka for (i = 0; i < (int)__arraycount(rt2860_def_bbp); i++) {
40989cdb1c70Snonaka run_bbp_write(sc, rt2860_def_bbp[i].reg,
40999cdb1c70Snonaka rt2860_def_bbp[i].val);
41009cdb1c70Snonaka }
4101faca41fbSmlelstv }
4102faca41fbSmlelstv
4103faca41fbSmlelstv if (sc->mac_ver == 0x3593) {
4104faca41fbSmlelstv run_bbp_write(sc, 79, 0x13);
4105faca41fbSmlelstv run_bbp_write(sc, 80, 0x05);
4106faca41fbSmlelstv run_bbp_write(sc, 81, 0x33);
4107faca41fbSmlelstv run_bbp_write(sc, 86, 0x46);
4108faca41fbSmlelstv run_bbp_write(sc, 137, 0x0f);
4109faca41fbSmlelstv }
41109cdb1c70Snonaka
41119cdb1c70Snonaka /* fix BBP84 for RT2860E */
41129cdb1c70Snonaka if (sc->mac_ver == 0x2860 && sc->mac_rev != 0x0101)
41139cdb1c70Snonaka run_bbp_write(sc, 84, 0x19);
41149cdb1c70Snonaka
4115d164e220Smlelstv if (sc->mac_ver >= 0x3070 && (sc->mac_ver != 0x3593 &&
4116d164e220Smlelstv sc->mac_ver != 0x5592)) {
41179cdb1c70Snonaka run_bbp_write(sc, 79, 0x13);
41189cdb1c70Snonaka run_bbp_write(sc, 80, 0x05);
41199cdb1c70Snonaka run_bbp_write(sc, 81, 0x33);
41209cdb1c70Snonaka } else if (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) {
41219cdb1c70Snonaka run_bbp_write(sc, 69, 0x16);
41229cdb1c70Snonaka run_bbp_write(sc, 73, 0x12);
41239cdb1c70Snonaka }
41244e8e6643Sskrll return 0;
41259cdb1c70Snonaka }
41269cdb1c70Snonaka
41279cdb1c70Snonaka static int
run_rt3070_rf_init(struct run_softc * sc)41289cdb1c70Snonaka run_rt3070_rf_init(struct run_softc *sc)
41299cdb1c70Snonaka {
41309cdb1c70Snonaka uint32_t tmp;
41319cdb1c70Snonaka uint8_t rf, target, bbp4;
41329cdb1c70Snonaka int i;
41339cdb1c70Snonaka
41349cdb1c70Snonaka run_rt3070_rf_read(sc, 30, &rf);
41359cdb1c70Snonaka /* toggle RF R30 bit 7 */
41369cdb1c70Snonaka run_rt3070_rf_write(sc, 30, rf | 0x80);
4137faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
41389cdb1c70Snonaka run_rt3070_rf_write(sc, 30, rf & ~0x80);
41399cdb1c70Snonaka
41409cdb1c70Snonaka /* initialize RF registers to default value */
41419cdb1c70Snonaka if (sc->mac_ver == 0x3572) {
41429cdb1c70Snonaka for (i = 0; i < (int)__arraycount(rt3572_def_rf); i++) {
41439cdb1c70Snonaka run_rt3070_rf_write(sc, rt3572_def_rf[i].reg,
41449cdb1c70Snonaka rt3572_def_rf[i].val);
41459cdb1c70Snonaka }
41469cdb1c70Snonaka } else {
41479cdb1c70Snonaka for (i = 0; i < (int)__arraycount(rt3070_def_rf); i++) {
41489cdb1c70Snonaka run_rt3070_rf_write(sc, rt3070_def_rf[i].reg,
41499cdb1c70Snonaka rt3070_def_rf[i].val);
41509cdb1c70Snonaka }
41519cdb1c70Snonaka }
41529cdb1c70Snonaka if (sc->mac_ver == 0x3572) {
41539cdb1c70Snonaka run_rt3070_rf_read(sc, 6, &rf);
41549cdb1c70Snonaka run_rt3070_rf_write(sc, 6, rf | 0x40);
4155faca41fbSmlelstv run_rt3070_rf_write(sc, 31, 0x14);
41569cdb1c70Snonaka
41579cdb1c70Snonaka run_read(sc, RT3070_LDO_CFG0, &tmp);
4158faca41fbSmlelstv tmp &= ~0x1f000000;
4159faca41fbSmlelstv if (sc->mac_rev < 0x0211 && sc->patch_dac)
4160faca41fbSmlelstv tmp |= 0x0d000000; /* 1.3V */
4161faca41fbSmlelstv else
4162faca41fbSmlelstv tmp |= 0x01000000; /* 1.2V */
41639cdb1c70Snonaka run_write(sc, RT3070_LDO_CFG0, tmp);
41649cdb1c70Snonaka } else if (sc->mac_ver == 0x3071) {
41659cdb1c70Snonaka run_rt3070_rf_read(sc, 6, &rf);
41669cdb1c70Snonaka run_rt3070_rf_write(sc, 6, rf | 0x40);
41679cdb1c70Snonaka run_rt3070_rf_write(sc, 31, 0x14);
41689cdb1c70Snonaka
41699cdb1c70Snonaka run_read(sc, RT3070_LDO_CFG0, &tmp);
41709cdb1c70Snonaka tmp &= ~0x1f000000;
41719cdb1c70Snonaka if (sc->mac_rev < 0x0211)
41729cdb1c70Snonaka tmp |= 0x0d000000; /* 1.35V */
41739cdb1c70Snonaka else
41749cdb1c70Snonaka tmp |= 0x01000000; /* 1.2V */
41759cdb1c70Snonaka run_write(sc, RT3070_LDO_CFG0, tmp);
41769cdb1c70Snonaka
41779cdb1c70Snonaka /* patch LNA_PE_G1 */
41789cdb1c70Snonaka run_read(sc, RT3070_GPIO_SWITCH, &tmp);
41799cdb1c70Snonaka run_write(sc, RT3070_GPIO_SWITCH, tmp & ~0x20);
4180d164e220Smlelstv } else if (sc->mac_ver == 0x3070 && sc->mac_rev < 0x0201) {
4181d164e220Smlelstv /*
4182d164e220Smlelstv * Change voltage from 1.2V to 1.35V for RT3070.
4183d164e220Smlelstv * The DAC issue (RT3070_LD0_CFG0) has been fixed
4184d164e220Smlelstv * in RT3070(F).
4185d164e220Smlelstv */
41869cdb1c70Snonaka run_read(sc, RT3070_LDO_CFG0, &tmp);
41879cdb1c70Snonaka tmp = (tmp & ~0x0f000000) | 0x0d000000;
41889cdb1c70Snonaka run_write(sc, RT3070_LDO_CFG0, tmp);
41899cdb1c70Snonaka }
41909cdb1c70Snonaka
41919cdb1c70Snonaka /* select 20MHz bandwidth */
41929cdb1c70Snonaka run_rt3070_rf_read(sc, 31, &rf);
41939cdb1c70Snonaka run_rt3070_rf_write(sc, 31, rf & ~0x20);
41949cdb1c70Snonaka
41959cdb1c70Snonaka /* calibrate filter for 20MHz bandwidth */
41969cdb1c70Snonaka sc->rf24_20mhz = 0x1f; /* default value */
41979cdb1c70Snonaka target = (sc->mac_ver < 0x3071) ? 0x16 : 0x13;
41989cdb1c70Snonaka run_rt3070_filter_calib(sc, 0x07, target, &sc->rf24_20mhz);
41999cdb1c70Snonaka
42009cdb1c70Snonaka /* select 40MHz bandwidth */
42019cdb1c70Snonaka run_bbp_read(sc, 4, &bbp4);
42029cdb1c70Snonaka run_bbp_write(sc, 4, (bbp4 & ~0x08) | 0x10);
42039cdb1c70Snonaka run_rt3070_rf_read(sc, 31, &rf);
42049cdb1c70Snonaka run_rt3070_rf_write(sc, 31, rf | 0x20);
42059cdb1c70Snonaka
42069cdb1c70Snonaka /* calibrate filter for 40MHz bandwidth */
42079cdb1c70Snonaka sc->rf24_40mhz = 0x2f; /* default value */
42089cdb1c70Snonaka target = (sc->mac_ver < 0x3071) ? 0x19 : 0x15;
42099cdb1c70Snonaka run_rt3070_filter_calib(sc, 0x27, target, &sc->rf24_40mhz);
42109cdb1c70Snonaka
42119cdb1c70Snonaka /* go back to 20MHz bandwidth */
42129cdb1c70Snonaka run_bbp_read(sc, 4, &bbp4);
42139cdb1c70Snonaka run_bbp_write(sc, 4, bbp4 & ~0x18);
42149cdb1c70Snonaka
42159cdb1c70Snonaka if (sc->mac_ver == 0x3572) {
42169cdb1c70Snonaka /* save default BBP registers 25 and 26 values */
42179cdb1c70Snonaka run_bbp_read(sc, 25, &sc->bbp25);
42189cdb1c70Snonaka run_bbp_read(sc, 26, &sc->bbp26);
42199cdb1c70Snonaka } else if (sc->mac_rev < 0x0211)
42209cdb1c70Snonaka run_rt3070_rf_write(sc, 27, 0x03);
42219cdb1c70Snonaka
42229cdb1c70Snonaka run_read(sc, RT3070_OPT_14, &tmp);
42239cdb1c70Snonaka run_write(sc, RT3070_OPT_14, tmp | 1);
42249cdb1c70Snonaka
42259cdb1c70Snonaka if (sc->mac_ver == 0x3070 || sc->mac_ver == 0x3071) {
42269cdb1c70Snonaka run_rt3070_rf_read(sc, 17, &rf);
42279cdb1c70Snonaka rf &= ~RT3070_TX_LO1;
42289cdb1c70Snonaka if ((sc->mac_ver == 0x3070 ||
42299cdb1c70Snonaka (sc->mac_ver == 0x3071 && sc->mac_rev >= 0x0211)) &&
42309cdb1c70Snonaka !sc->ext_2ghz_lna)
42319cdb1c70Snonaka rf |= 0x20; /* fix for long range Rx issue */
42329cdb1c70Snonaka if (sc->txmixgain_2ghz >= 1)
42339cdb1c70Snonaka rf = (rf & ~0x7) | sc->txmixgain_2ghz;
42349cdb1c70Snonaka run_rt3070_rf_write(sc, 17, rf);
42359cdb1c70Snonaka }
42369cdb1c70Snonaka if (sc->mac_ver == 0x3071) {
42379cdb1c70Snonaka run_rt3070_rf_read(sc, 1, &rf);
42389cdb1c70Snonaka rf &= ~(RT3070_RX0_PD | RT3070_TX0_PD);
42399cdb1c70Snonaka rf |= RT3070_RF_BLOCK | RT3070_RX1_PD | RT3070_TX1_PD;
42409cdb1c70Snonaka run_rt3070_rf_write(sc, 1, rf);
42419cdb1c70Snonaka
42429cdb1c70Snonaka run_rt3070_rf_read(sc, 15, &rf);
42439cdb1c70Snonaka run_rt3070_rf_write(sc, 15, rf & ~RT3070_TX_LO2);
42449cdb1c70Snonaka
42459cdb1c70Snonaka run_rt3070_rf_read(sc, 20, &rf);
42469cdb1c70Snonaka run_rt3070_rf_write(sc, 20, rf & ~RT3070_RX_LO1);
42479cdb1c70Snonaka
42489cdb1c70Snonaka run_rt3070_rf_read(sc, 21, &rf);
42499cdb1c70Snonaka run_rt3070_rf_write(sc, 21, rf & ~RT3070_RX_LO2);
42509cdb1c70Snonaka }
42519cdb1c70Snonaka if (sc->mac_ver == 0x3070 || sc->mac_ver == 0x3071) {
42529cdb1c70Snonaka /* fix Tx to Rx IQ glitch by raising RF voltage */
42539cdb1c70Snonaka run_rt3070_rf_read(sc, 27, &rf);
42549cdb1c70Snonaka rf &= ~0x77;
42559cdb1c70Snonaka if (sc->mac_rev < 0x0211)
42569cdb1c70Snonaka rf |= 0x03;
42579cdb1c70Snonaka run_rt3070_rf_write(sc, 27, rf);
42589cdb1c70Snonaka }
42594e8e6643Sskrll return 0;
42609cdb1c70Snonaka }
42619cdb1c70Snonaka
42629cdb1c70Snonaka static int
run_rt3593_rf_init(struct run_softc * sc)4263faca41fbSmlelstv run_rt3593_rf_init(struct run_softc *sc)
4264faca41fbSmlelstv {
4265faca41fbSmlelstv uint32_t tmp;
4266faca41fbSmlelstv uint8_t rf;
4267faca41fbSmlelstv int i;
4268faca41fbSmlelstv
4269faca41fbSmlelstv /* Disable the GPIO bits 4 and 7 for LNA PE control. */
4270faca41fbSmlelstv run_read(sc, RT3070_GPIO_SWITCH, &tmp);
4271faca41fbSmlelstv tmp &= ~(1 << 4 | 1 << 7);
4272faca41fbSmlelstv run_write(sc, RT3070_GPIO_SWITCH, tmp);
4273faca41fbSmlelstv
4274faca41fbSmlelstv /* Initialize RF registers to default value. */
4275faca41fbSmlelstv for (i = 0; i < __arraycount(rt3593_def_rf); i++) {
4276faca41fbSmlelstv run_rt3070_rf_write(sc, rt3593_def_rf[i].reg,
4277faca41fbSmlelstv rt3593_def_rf[i].val);
4278faca41fbSmlelstv }
4279faca41fbSmlelstv
4280faca41fbSmlelstv /* Toggle RF R2 to initiate calibration. */
4281faca41fbSmlelstv run_rt3070_rf_write(sc, 2, RT5390_RESCAL);
4282faca41fbSmlelstv
4283faca41fbSmlelstv /* Initialize RF frequency offset. */
4284faca41fbSmlelstv run_adjust_freq_offset(sc);
4285faca41fbSmlelstv
4286faca41fbSmlelstv run_rt3070_rf_read(sc, 18, &rf);
4287faca41fbSmlelstv run_rt3070_rf_write(sc, 18, rf | RT3593_AUTOTUNE_BYPASS);
4288faca41fbSmlelstv
4289faca41fbSmlelstv /*
4290faca41fbSmlelstv * Increase voltage from 1.2V to 1.35V, wait for 1 msec to
4291faca41fbSmlelstv * decrease voltage back to 1.2V.
4292faca41fbSmlelstv */
4293faca41fbSmlelstv run_read(sc, RT3070_LDO_CFG0, &tmp);
4294faca41fbSmlelstv tmp = (tmp & ~0x1f000000) | 0x0d000000;
4295faca41fbSmlelstv run_write(sc, RT3070_LDO_CFG0, tmp);
4296faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 1);
4297faca41fbSmlelstv tmp = (tmp & ~0x1f000000) | 0x01000000;
4298faca41fbSmlelstv run_write(sc, RT3070_LDO_CFG0, tmp);
4299faca41fbSmlelstv
4300faca41fbSmlelstv sc->rf24_20mhz = 0x1f;
4301faca41fbSmlelstv sc->rf24_40mhz = 0x2f;
4302faca41fbSmlelstv
4303faca41fbSmlelstv /* Save default BBP registers 25 and 26 values. */
4304faca41fbSmlelstv run_bbp_read(sc, 25, &sc->bbp25);
4305faca41fbSmlelstv run_bbp_read(sc, 26, &sc->bbp26);
4306faca41fbSmlelstv
4307faca41fbSmlelstv run_read(sc, RT3070_OPT_14, &tmp);
4308faca41fbSmlelstv run_write(sc, RT3070_OPT_14, tmp | 1);
430926ee7ba1Sskrll return 0;
4310faca41fbSmlelstv }
4311faca41fbSmlelstv
4312faca41fbSmlelstv static int
run_rt5390_rf_init(struct run_softc * sc)4313faca41fbSmlelstv run_rt5390_rf_init(struct run_softc *sc)
4314faca41fbSmlelstv {
4315faca41fbSmlelstv uint32_t tmp;
4316faca41fbSmlelstv uint8_t rf;
4317faca41fbSmlelstv int i;
4318faca41fbSmlelstv
4319faca41fbSmlelstv /* Toggle RF R2 to initiate calibration. */
4320faca41fbSmlelstv if (sc->mac_ver == 0x5390) {
4321faca41fbSmlelstv run_rt3070_rf_read(sc, 2, &rf);
4322faca41fbSmlelstv run_rt3070_rf_write(sc, 2, rf | RT5390_RESCAL);
4323faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
4324faca41fbSmlelstv run_rt3070_rf_write(sc, 2, rf & ~RT5390_RESCAL);
4325faca41fbSmlelstv } else {
4326faca41fbSmlelstv run_rt3070_rf_write(sc, 2, RT5390_RESCAL);
4327faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
4328faca41fbSmlelstv }
4329faca41fbSmlelstv
4330faca41fbSmlelstv /* Initialize RF registers to default value. */
4331faca41fbSmlelstv if (sc->mac_ver == 0x5592) {
4332faca41fbSmlelstv for (i = 0; i < __arraycount(rt5592_def_rf); i++) {
4333faca41fbSmlelstv run_rt3070_rf_write(sc, rt5592_def_rf[i].reg,
4334faca41fbSmlelstv rt5592_def_rf[i].val);
4335faca41fbSmlelstv }
4336faca41fbSmlelstv /* Initialize RF frequency offset. */
4337faca41fbSmlelstv run_adjust_freq_offset(sc);
4338faca41fbSmlelstv } else if (sc->mac_ver == 0x5392) {
4339faca41fbSmlelstv for (i = 0; i < __arraycount(rt5392_def_rf); i++) {
4340faca41fbSmlelstv run_rt3070_rf_write(sc, rt5392_def_rf[i].reg,
4341faca41fbSmlelstv rt5392_def_rf[i].val);
4342faca41fbSmlelstv }
4343faca41fbSmlelstv if (sc->mac_rev >= 0x0223) {
4344faca41fbSmlelstv run_rt3070_rf_write(sc, 23, 0x0f);
4345faca41fbSmlelstv run_rt3070_rf_write(sc, 24, 0x3e);
4346faca41fbSmlelstv run_rt3070_rf_write(sc, 51, 0x32);
4347faca41fbSmlelstv run_rt3070_rf_write(sc, 53, 0x22);
4348faca41fbSmlelstv run_rt3070_rf_write(sc, 56, 0xc1);
4349faca41fbSmlelstv run_rt3070_rf_write(sc, 59, 0x0f);
4350faca41fbSmlelstv }
4351faca41fbSmlelstv } else {
4352faca41fbSmlelstv for (i = 0; i < __arraycount(rt5390_def_rf); i++) {
4353faca41fbSmlelstv run_rt3070_rf_write(sc, rt5390_def_rf[i].reg,
4354faca41fbSmlelstv rt5390_def_rf[i].val);
4355faca41fbSmlelstv }
4356faca41fbSmlelstv if (sc->mac_rev >= 0x0502) {
4357faca41fbSmlelstv run_rt3070_rf_write(sc, 6, 0xe0);
4358faca41fbSmlelstv run_rt3070_rf_write(sc, 25, 0x80);
4359faca41fbSmlelstv run_rt3070_rf_write(sc, 46, 0x73);
4360faca41fbSmlelstv run_rt3070_rf_write(sc, 53, 0x00);
4361faca41fbSmlelstv run_rt3070_rf_write(sc, 56, 0x42);
4362faca41fbSmlelstv run_rt3070_rf_write(sc, 61, 0xd1);
4363faca41fbSmlelstv }
4364faca41fbSmlelstv }
4365faca41fbSmlelstv
4366faca41fbSmlelstv sc->rf24_20mhz = 0x1f; /* default value */
4367faca41fbSmlelstv sc->rf24_40mhz = (sc->mac_ver == 0x5592) ? 0 : 0x2f;
4368faca41fbSmlelstv
4369faca41fbSmlelstv if (sc->mac_rev < 0x0211)
4370faca41fbSmlelstv run_rt3070_rf_write(sc, 27, 0x3);
4371faca41fbSmlelstv
4372faca41fbSmlelstv run_read(sc, RT3070_OPT_14, &tmp);
4373faca41fbSmlelstv run_write(sc, RT3070_OPT_14, tmp | 1);
437426ee7ba1Sskrll return 0;
4375faca41fbSmlelstv }
4376faca41fbSmlelstv
4377faca41fbSmlelstv static int
run_rt3070_filter_calib(struct run_softc * sc,uint8_t init,uint8_t target,uint8_t * val)43789cdb1c70Snonaka run_rt3070_filter_calib(struct run_softc *sc, uint8_t init, uint8_t target,
43799cdb1c70Snonaka uint8_t *val)
43809cdb1c70Snonaka {
43819cdb1c70Snonaka uint8_t rf22, rf24;
43829cdb1c70Snonaka uint8_t bbp55_pb, bbp55_sb, delta;
43839cdb1c70Snonaka int ntries;
43849cdb1c70Snonaka
43859cdb1c70Snonaka /* program filter */
43869cdb1c70Snonaka run_rt3070_rf_read(sc, 24, &rf24);
43879cdb1c70Snonaka rf24 = (rf24 & 0xc0) | init; /* initial filter value */
43889cdb1c70Snonaka run_rt3070_rf_write(sc, 24, rf24);
43899cdb1c70Snonaka
43909cdb1c70Snonaka /* enable baseband loopback mode */
43919cdb1c70Snonaka run_rt3070_rf_read(sc, 22, &rf22);
43929cdb1c70Snonaka run_rt3070_rf_write(sc, 22, rf22 | 0x01);
43939cdb1c70Snonaka
43949cdb1c70Snonaka /* set power and frequency of passband test tone */
43959cdb1c70Snonaka run_bbp_write(sc, 24, 0x00);
43969cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) {
43979cdb1c70Snonaka /* transmit test tone */
43989cdb1c70Snonaka run_bbp_write(sc, 25, 0x90);
4399faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
44009cdb1c70Snonaka /* read received power */
44019cdb1c70Snonaka run_bbp_read(sc, 55, &bbp55_pb);
44029cdb1c70Snonaka if (bbp55_pb != 0)
44039cdb1c70Snonaka break;
44049cdb1c70Snonaka }
44059cdb1c70Snonaka if (ntries == 100)
44064e8e6643Sskrll return ETIMEDOUT;
44079cdb1c70Snonaka
44089cdb1c70Snonaka /* set power and frequency of stopband test tone */
44099cdb1c70Snonaka run_bbp_write(sc, 24, 0x06);
44109cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) {
44119cdb1c70Snonaka /* transmit test tone */
44129cdb1c70Snonaka run_bbp_write(sc, 25, 0x90);
4413faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
44149cdb1c70Snonaka /* read received power */
44159cdb1c70Snonaka run_bbp_read(sc, 55, &bbp55_sb);
44169cdb1c70Snonaka
44179cdb1c70Snonaka delta = bbp55_pb - bbp55_sb;
44189cdb1c70Snonaka if (delta > target)
44199cdb1c70Snonaka break;
44209cdb1c70Snonaka
44219cdb1c70Snonaka /* reprogram filter */
44229cdb1c70Snonaka rf24++;
44239cdb1c70Snonaka run_rt3070_rf_write(sc, 24, rf24);
44249cdb1c70Snonaka }
44259cdb1c70Snonaka if (ntries < 100) {
44269cdb1c70Snonaka if (rf24 != init)
44279cdb1c70Snonaka rf24--; /* backtrack */
44289cdb1c70Snonaka *val = rf24;
44299cdb1c70Snonaka run_rt3070_rf_write(sc, 24, rf24);
44309cdb1c70Snonaka }
44319cdb1c70Snonaka
44329cdb1c70Snonaka /* restore initial state */
44339cdb1c70Snonaka run_bbp_write(sc, 24, 0x00);
44349cdb1c70Snonaka
44359cdb1c70Snonaka /* disable baseband loopback mode */
44369cdb1c70Snonaka run_rt3070_rf_read(sc, 22, &rf22);
44379cdb1c70Snonaka run_rt3070_rf_write(sc, 22, rf22 & ~0x01);
44389cdb1c70Snonaka
44394e8e6643Sskrll return 0;
44409cdb1c70Snonaka }
44419cdb1c70Snonaka
44429cdb1c70Snonaka static void
run_rt3070_rf_setup(struct run_softc * sc)44439cdb1c70Snonaka run_rt3070_rf_setup(struct run_softc *sc)
44449cdb1c70Snonaka {
44459cdb1c70Snonaka uint8_t bbp, rf;
44469cdb1c70Snonaka int i;
44479cdb1c70Snonaka
44489cdb1c70Snonaka if (sc->mac_ver == 0x3572) {
44499cdb1c70Snonaka /* enable DC filter */
44509cdb1c70Snonaka if (sc->mac_rev >= 0x0201)
44519cdb1c70Snonaka run_bbp_write(sc, 103, 0xc0);
44529cdb1c70Snonaka
44539cdb1c70Snonaka run_bbp_read(sc, 138, &bbp);
44549cdb1c70Snonaka if (sc->ntxchains == 1)
44559cdb1c70Snonaka bbp |= 0x20; /* turn off DAC1 */
44569cdb1c70Snonaka if (sc->nrxchains == 1)
44579cdb1c70Snonaka bbp &= ~0x02; /* turn off ADC1 */
44589cdb1c70Snonaka run_bbp_write(sc, 138, bbp);
44599cdb1c70Snonaka
44609cdb1c70Snonaka if (sc->mac_rev >= 0x0211) {
44619cdb1c70Snonaka /* improve power consumption */
44629cdb1c70Snonaka run_bbp_read(sc, 31, &bbp);
44639cdb1c70Snonaka run_bbp_write(sc, 31, bbp & ~0x03);
44649cdb1c70Snonaka }
44659cdb1c70Snonaka
44669cdb1c70Snonaka run_rt3070_rf_read(sc, 16, &rf);
44679cdb1c70Snonaka rf = (rf & ~0x07) | sc->txmixgain_2ghz;
44689cdb1c70Snonaka run_rt3070_rf_write(sc, 16, rf);
44699cdb1c70Snonaka } else if (sc->mac_ver == 0x3071) {
44709cdb1c70Snonaka /* enable DC filter */
44719cdb1c70Snonaka if (sc->mac_rev >= 0x0201)
44729cdb1c70Snonaka run_bbp_write(sc, 103, 0xc0);
44739cdb1c70Snonaka
44749cdb1c70Snonaka run_bbp_read(sc, 138, &bbp);
44759cdb1c70Snonaka if (sc->ntxchains == 1)
44769cdb1c70Snonaka bbp |= 0x20; /* turn off DAC1 */
44779cdb1c70Snonaka if (sc->nrxchains == 1)
44789cdb1c70Snonaka bbp &= ~0x02; /* turn off ADC1 */
44799cdb1c70Snonaka run_bbp_write(sc, 138, bbp);
44809cdb1c70Snonaka
44819cdb1c70Snonaka if (sc->mac_rev >= 0x0211) {
44829cdb1c70Snonaka /* improve power consumption */
44839cdb1c70Snonaka run_bbp_read(sc, 31, &bbp);
44849cdb1c70Snonaka run_bbp_write(sc, 31, bbp & ~0x03);
44859cdb1c70Snonaka }
44869cdb1c70Snonaka
44879cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG1, 0);
44889cdb1c70Snonaka if (sc->mac_rev < 0x0211) {
44899cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG2,
44909cdb1c70Snonaka sc->patch_dac ? 0x2c : 0x0f);
44919cdb1c70Snonaka } else
44929cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG2, 0);
44939cdb1c70Snonaka } else if (sc->mac_ver == 0x3070) {
44949cdb1c70Snonaka if (sc->mac_rev >= 0x0201) {
44959cdb1c70Snonaka /* enable DC filter */
44969cdb1c70Snonaka run_bbp_write(sc, 103, 0xc0);
44979cdb1c70Snonaka
44989cdb1c70Snonaka /* improve power consumption */
44999cdb1c70Snonaka run_bbp_read(sc, 31, &bbp);
45009cdb1c70Snonaka run_bbp_write(sc, 31, bbp & ~0x03);
45019cdb1c70Snonaka }
45029cdb1c70Snonaka
45039cdb1c70Snonaka if (sc->mac_rev < 0x0211) {
45049cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG1, 0);
45059cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG2, 0x2c);
45069cdb1c70Snonaka } else
45079cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG2, 0);
45089cdb1c70Snonaka }
45099cdb1c70Snonaka
45109cdb1c70Snonaka /* initialize RF registers from ROM for >=RT3071*/
45119cdb1c70Snonaka if (sc->mac_ver >= 0x3071) {
45129cdb1c70Snonaka for (i = 0; i < 10; i++) {
45139cdb1c70Snonaka if (sc->rf[i].reg == 0 || sc->rf[i].reg == 0xff)
45149cdb1c70Snonaka continue;
45159cdb1c70Snonaka run_rt3070_rf_write(sc, sc->rf[i].reg, sc->rf[i].val);
45169cdb1c70Snonaka }
45179cdb1c70Snonaka }
45189cdb1c70Snonaka }
45199cdb1c70Snonaka
4520faca41fbSmlelstv static void
run_rt3593_rf_setup(struct run_softc * sc)4521faca41fbSmlelstv run_rt3593_rf_setup(struct run_softc *sc)
4522faca41fbSmlelstv {
4523faca41fbSmlelstv uint8_t bbp, rf;
4524faca41fbSmlelstv
4525faca41fbSmlelstv if (sc->mac_rev >= 0x0211) {
4526faca41fbSmlelstv /* Enable DC filter. */
4527faca41fbSmlelstv run_bbp_write(sc, 103, 0xc0);
4528faca41fbSmlelstv }
4529faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG1, 0);
4530faca41fbSmlelstv if (sc->mac_rev < 0x0211) {
4531faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG2,
4532faca41fbSmlelstv sc->patch_dac ? 0x2c : 0x0f);
4533faca41fbSmlelstv } else
4534faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG2, 0);
4535faca41fbSmlelstv
4536faca41fbSmlelstv run_rt3070_rf_read(sc, 50, &rf);
4537faca41fbSmlelstv run_rt3070_rf_write(sc, 50, rf & ~RT3593_TX_LO2);
4538faca41fbSmlelstv
4539faca41fbSmlelstv run_rt3070_rf_read(sc, 51, &rf);
4540faca41fbSmlelstv rf = (rf & ~(RT3593_TX_LO1 | 0x0c)) |
4541faca41fbSmlelstv ((sc->txmixgain_2ghz & 0x07) << 2);
4542faca41fbSmlelstv run_rt3070_rf_write(sc, 51, rf);
4543faca41fbSmlelstv
4544faca41fbSmlelstv run_rt3070_rf_read(sc, 38, &rf);
4545faca41fbSmlelstv run_rt3070_rf_write(sc, 38, rf & ~RT5390_RX_LO1);
4546faca41fbSmlelstv
4547faca41fbSmlelstv run_rt3070_rf_read(sc, 39, &rf);
4548faca41fbSmlelstv run_rt3070_rf_write(sc, 39, rf & ~RT5390_RX_LO2);
4549faca41fbSmlelstv
4550faca41fbSmlelstv run_rt3070_rf_read(sc, 1, &rf);
4551faca41fbSmlelstv run_rt3070_rf_write(sc, 1, rf & ~(RT3070_RF_BLOCK | RT3070_PLL_PD));
4552faca41fbSmlelstv
4553faca41fbSmlelstv run_rt3070_rf_read(sc, 30, &rf);
4554faca41fbSmlelstv rf = (rf & ~0x18) | 0x10;
4555faca41fbSmlelstv run_rt3070_rf_write(sc, 30, rf);
4556faca41fbSmlelstv
4557faca41fbSmlelstv /* Apply maximum likelihood detection for 2 stream case. */
4558faca41fbSmlelstv run_bbp_read(sc, 105, &bbp);
4559faca41fbSmlelstv if (sc->nrxchains > 1)
4560faca41fbSmlelstv run_bbp_write(sc, 105, bbp | RT5390_MLD);
4561faca41fbSmlelstv
4562faca41fbSmlelstv /* Avoid data lost and CRC error. */
4563faca41fbSmlelstv run_bbp_read(sc, 4, &bbp);
4564faca41fbSmlelstv run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
4565faca41fbSmlelstv
4566faca41fbSmlelstv run_bbp_write(sc, 92, 0x02);
4567faca41fbSmlelstv run_bbp_write(sc, 82, 0x82);
4568faca41fbSmlelstv run_bbp_write(sc, 106, 0x05);
4569faca41fbSmlelstv run_bbp_write(sc, 104, 0x92);
4570faca41fbSmlelstv run_bbp_write(sc, 88, 0x90);
4571faca41fbSmlelstv run_bbp_write(sc, 148, 0xc8);
4572faca41fbSmlelstv run_bbp_write(sc, 47, 0x48);
4573faca41fbSmlelstv run_bbp_write(sc, 120, 0x50);
4574faca41fbSmlelstv
4575faca41fbSmlelstv run_bbp_write(sc, 163, 0x9d);
4576faca41fbSmlelstv
4577faca41fbSmlelstv /* SNR mapping. */
4578faca41fbSmlelstv run_bbp_write(sc, 142, 0x06);
4579faca41fbSmlelstv run_bbp_write(sc, 143, 0xa0);
4580faca41fbSmlelstv run_bbp_write(sc, 142, 0x07);
4581faca41fbSmlelstv run_bbp_write(sc, 143, 0xa1);
4582faca41fbSmlelstv run_bbp_write(sc, 142, 0x08);
4583faca41fbSmlelstv run_bbp_write(sc, 143, 0xa2);
4584faca41fbSmlelstv
4585faca41fbSmlelstv run_bbp_write(sc, 31, 0x08);
4586faca41fbSmlelstv run_bbp_write(sc, 68, 0x0b);
4587faca41fbSmlelstv run_bbp_write(sc, 105, 0x04);
4588faca41fbSmlelstv }
4589faca41fbSmlelstv
4590faca41fbSmlelstv static void
run_rt5390_rf_setup(struct run_softc * sc)4591faca41fbSmlelstv run_rt5390_rf_setup(struct run_softc *sc)
4592faca41fbSmlelstv {
4593faca41fbSmlelstv uint8_t bbp, rf;
4594faca41fbSmlelstv
4595faca41fbSmlelstv if (sc->mac_rev >= 0x0211) {
4596faca41fbSmlelstv /* Enable DC filter. */
4597faca41fbSmlelstv run_bbp_write(sc, 103, 0xc0);
4598faca41fbSmlelstv
4599faca41fbSmlelstv if (sc->mac_ver != 0x5592) {
4600faca41fbSmlelstv /* Improve power consumption. */
4601faca41fbSmlelstv run_bbp_read(sc, 31, &bbp);
4602faca41fbSmlelstv run_bbp_write(sc, 31, bbp & ~0x03);
4603faca41fbSmlelstv }
4604faca41fbSmlelstv }
4605faca41fbSmlelstv
4606faca41fbSmlelstv run_bbp_read(sc, 138, &bbp);
4607faca41fbSmlelstv if (sc->ntxchains == 1)
4608faca41fbSmlelstv bbp |= 0x20; /* turn off DAC1 */
4609faca41fbSmlelstv if (sc->nrxchains == 1)
4610faca41fbSmlelstv bbp &= ~0x02; /* turn off ADC1 */
4611faca41fbSmlelstv run_bbp_write(sc, 138, bbp);
4612faca41fbSmlelstv
4613faca41fbSmlelstv run_rt3070_rf_read(sc, 38, &rf);
4614faca41fbSmlelstv run_rt3070_rf_write(sc, 38, rf & ~RT5390_RX_LO1);
4615faca41fbSmlelstv
4616faca41fbSmlelstv run_rt3070_rf_read(sc, 39, &rf);
4617faca41fbSmlelstv run_rt3070_rf_write(sc, 39, rf & ~RT5390_RX_LO2);
4618faca41fbSmlelstv
4619faca41fbSmlelstv /* Avoid data lost and CRC error. */
4620faca41fbSmlelstv run_bbp_read(sc, 4, &bbp);
4621faca41fbSmlelstv run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
4622faca41fbSmlelstv
4623faca41fbSmlelstv run_rt3070_rf_read(sc, 30, &rf);
4624faca41fbSmlelstv rf = (rf & ~0x18) | 0x10;
4625faca41fbSmlelstv run_rt3070_rf_write(sc, 30, rf);
4626faca41fbSmlelstv
4627faca41fbSmlelstv if (sc->mac_ver != 0x5592) {
4628faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG1, 0);
4629faca41fbSmlelstv if (sc->mac_rev < 0x0211) {
4630faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG2,
4631faca41fbSmlelstv sc->patch_dac ? 0x2c : 0x0f);
4632faca41fbSmlelstv } else
4633faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG2, 0);
4634faca41fbSmlelstv }
4635faca41fbSmlelstv }
4636faca41fbSmlelstv
46379cdb1c70Snonaka static int
run_txrx_enable(struct run_softc * sc)46389cdb1c70Snonaka run_txrx_enable(struct run_softc *sc)
46399cdb1c70Snonaka {
46409cdb1c70Snonaka uint32_t tmp;
46419cdb1c70Snonaka int error, ntries;
46429cdb1c70Snonaka
46439cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_TX_EN);
46449cdb1c70Snonaka for (ntries = 0; ntries < 200; ntries++) {
46459cdb1c70Snonaka if ((error = run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp)) != 0)
46464e8e6643Sskrll return error;
46479cdb1c70Snonaka if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0)
46489cdb1c70Snonaka break;
4649faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 50);
46509cdb1c70Snonaka }
46519cdb1c70Snonaka if (ntries == 200)
46524e8e6643Sskrll return ETIMEDOUT;
46539cdb1c70Snonaka
4654faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 50);
46559cdb1c70Snonaka
46569cdb1c70Snonaka tmp |= RT2860_RX_DMA_EN | RT2860_TX_DMA_EN | RT2860_TX_WB_DDONE;
46579cdb1c70Snonaka run_write(sc, RT2860_WPDMA_GLO_CFG, tmp);
46589cdb1c70Snonaka
46599cdb1c70Snonaka /* enable Rx bulk aggregation (set timeout and limit) */
46609cdb1c70Snonaka tmp = RT2860_USB_TX_EN | RT2860_USB_RX_EN | RT2860_USB_RX_AGG_EN |
46619cdb1c70Snonaka RT2860_USB_RX_AGG_TO(128) | RT2860_USB_RX_AGG_LMT(2);
46629cdb1c70Snonaka run_write(sc, RT2860_USB_DMA_CFG, tmp);
46639cdb1c70Snonaka
46649cdb1c70Snonaka /* set Rx filter */
46659cdb1c70Snonaka tmp = RT2860_DROP_CRC_ERR | RT2860_DROP_PHY_ERR;
46669cdb1c70Snonaka if (sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR) {
46679cdb1c70Snonaka tmp |= RT2860_DROP_UC_NOME | RT2860_DROP_DUPL |
46689cdb1c70Snonaka RT2860_DROP_CTS | RT2860_DROP_BA | RT2860_DROP_ACK |
46699cdb1c70Snonaka RT2860_DROP_VER_ERR | RT2860_DROP_CTRL_RSV |
46709cdb1c70Snonaka RT2860_DROP_CFACK | RT2860_DROP_CFEND;
46719cdb1c70Snonaka if (sc->sc_ic.ic_opmode == IEEE80211_M_STA)
46729cdb1c70Snonaka tmp |= RT2860_DROP_RTS | RT2860_DROP_PSPOLL;
46739cdb1c70Snonaka }
46749cdb1c70Snonaka run_write(sc, RT2860_RX_FILTR_CFG, tmp);
46759cdb1c70Snonaka
46769cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL,
46779cdb1c70Snonaka RT2860_MAC_RX_EN | RT2860_MAC_TX_EN);
46789cdb1c70Snonaka
46794e8e6643Sskrll return 0;
46809cdb1c70Snonaka }
46819cdb1c70Snonaka
46829cdb1c70Snonaka static int
run_adjust_freq_offset(struct run_softc * sc)4683faca41fbSmlelstv run_adjust_freq_offset(struct run_softc *sc)
4684faca41fbSmlelstv {
4685faca41fbSmlelstv uint8_t rf, tmp;
4686faca41fbSmlelstv
4687faca41fbSmlelstv run_rt3070_rf_read(sc, 17, &rf);
4688faca41fbSmlelstv tmp = rf;
4689faca41fbSmlelstv rf = (rf & ~0x7f) | (sc->freq & 0x7f);
4690faca41fbSmlelstv rf = MIN(rf, 0x5f);
4691faca41fbSmlelstv
4692faca41fbSmlelstv if (tmp != rf)
4693faca41fbSmlelstv run_mcu_cmd(sc, 0x74, (tmp << 8 ) | rf);
4694faca41fbSmlelstv
469526ee7ba1Sskrll return 0;
4696faca41fbSmlelstv }
4697faca41fbSmlelstv
4698faca41fbSmlelstv static int
run_init(struct ifnet * ifp)46999cdb1c70Snonaka run_init(struct ifnet *ifp)
47009cdb1c70Snonaka {
47019cdb1c70Snonaka struct run_softc *sc = ifp->if_softc;
47029cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
47039cdb1c70Snonaka uint32_t tmp;
47049cdb1c70Snonaka uint8_t bbp1, bbp3;
47059cdb1c70Snonaka int i, error, qid, ridx, ntries;
4706d164e220Smlelstv usbd_status status;
47079cdb1c70Snonaka
47089cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) {
47099cdb1c70Snonaka if ((error = run_read(sc, RT2860_ASIC_VER_ID, &tmp)) != 0)
47109cdb1c70Snonaka goto fail;
47119cdb1c70Snonaka if (tmp != 0 && tmp != 0xffffffff)
47129cdb1c70Snonaka break;
4713faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
47149cdb1c70Snonaka }
47159cdb1c70Snonaka if (ntries == 100) {
47169cdb1c70Snonaka error = ETIMEDOUT;
47179cdb1c70Snonaka goto fail;
47189cdb1c70Snonaka }
47199cdb1c70Snonaka
47209cdb1c70Snonaka if ((sc->sc_flags & RUN_FWLOADED) == 0 &&
47219cdb1c70Snonaka (error = run_load_microcode(sc)) != 0) {
47221d5cb2a3Sjakllsch device_printf(sc->sc_dev,
47239cdb1c70Snonaka "could not load 8051 microcode\n");
47249cdb1c70Snonaka goto fail;
47259cdb1c70Snonaka }
47269cdb1c70Snonaka
47279cdb1c70Snonaka if (ifp->if_flags & IFF_RUNNING)
47289cdb1c70Snonaka run_stop(ifp, 0);
47299cdb1c70Snonaka
47309cdb1c70Snonaka /* init host command ring */
47319cdb1c70Snonaka sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
47329cdb1c70Snonaka
47339cdb1c70Snonaka /* init Tx rings (4 EDCAs) */
47349cdb1c70Snonaka for (qid = 0; qid < 4; qid++) {
47359cdb1c70Snonaka if ((error = run_alloc_tx_ring(sc, qid)) != 0)
47369cdb1c70Snonaka goto fail;
47379cdb1c70Snonaka }
47389cdb1c70Snonaka /* init Rx ring */
47399cdb1c70Snonaka if ((error = run_alloc_rx_ring(sc)) != 0)
47409cdb1c70Snonaka goto fail;
47419cdb1c70Snonaka
47429cdb1c70Snonaka IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
47439cdb1c70Snonaka run_set_macaddr(sc, ic->ic_myaddr);
47449cdb1c70Snonaka
47459cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) {
47469cdb1c70Snonaka if ((error = run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp)) != 0)
47479cdb1c70Snonaka goto fail;
47489cdb1c70Snonaka if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0)
47499cdb1c70Snonaka break;
4750faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
47519cdb1c70Snonaka }
47529cdb1c70Snonaka if (ntries == 100) {
47531d5cb2a3Sjakllsch device_printf(sc->sc_dev,
47549cdb1c70Snonaka "timeout waiting for DMA engine\n");
47559cdb1c70Snonaka error = ETIMEDOUT;
47569cdb1c70Snonaka goto fail;
47579cdb1c70Snonaka }
47589cdb1c70Snonaka tmp &= 0xff0;
47599cdb1c70Snonaka tmp |= RT2860_TX_WB_DDONE;
47609cdb1c70Snonaka run_write(sc, RT2860_WPDMA_GLO_CFG, tmp);
47619cdb1c70Snonaka
47629cdb1c70Snonaka /* turn off PME_OEN to solve high-current issue */
47639cdb1c70Snonaka run_read(sc, RT2860_SYS_CTRL, &tmp);
47649cdb1c70Snonaka run_write(sc, RT2860_SYS_CTRL, tmp & ~RT2860_PME_OEN);
47659cdb1c70Snonaka
47669cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL,
47679cdb1c70Snonaka RT2860_BBP_HRST | RT2860_MAC_SRST);
47689cdb1c70Snonaka run_write(sc, RT2860_USB_DMA_CFG, 0);
47699cdb1c70Snonaka
47709cdb1c70Snonaka if ((error = run_reset(sc)) != 0) {
47711d5cb2a3Sjakllsch device_printf(sc->sc_dev, "could not reset chipset\n");
47729cdb1c70Snonaka goto fail;
47739cdb1c70Snonaka }
47749cdb1c70Snonaka
47759cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL, 0);
47769cdb1c70Snonaka
47779cdb1c70Snonaka /* init Tx power for all Tx rates (from EEPROM) */
47789cdb1c70Snonaka for (ridx = 0; ridx < 5; ridx++) {
47799cdb1c70Snonaka if (sc->txpow20mhz[ridx] == 0xffffffff)
47809cdb1c70Snonaka continue;
47819cdb1c70Snonaka run_write(sc, RT2860_TX_PWR_CFG(ridx), sc->txpow20mhz[ridx]);
47829cdb1c70Snonaka }
47839cdb1c70Snonaka
47849cdb1c70Snonaka for (i = 0; i < (int)__arraycount(rt2870_def_mac); i++)
47859cdb1c70Snonaka run_write(sc, rt2870_def_mac[i].reg, rt2870_def_mac[i].val);
47869cdb1c70Snonaka run_write(sc, RT2860_WMM_AIFSN_CFG, 0x00002273);
47879cdb1c70Snonaka run_write(sc, RT2860_WMM_CWMIN_CFG, 0x00002344);
47889cdb1c70Snonaka run_write(sc, RT2860_WMM_CWMAX_CFG, 0x000034aa);
47899cdb1c70Snonaka
4790faca41fbSmlelstv if (sc->mac_ver >= 0x5390) {
4791faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG0,
4792faca41fbSmlelstv 4 << RT2860_DLY_PAPE_EN_SHIFT | 4);
4793faca41fbSmlelstv if (sc->mac_ver >= 0x5392) {
4794faca41fbSmlelstv run_write(sc, RT2860_MAX_LEN_CFG, 0x00002fff);
4795faca41fbSmlelstv if (sc->mac_ver == 0x5592) {
4796faca41fbSmlelstv run_write(sc, RT2860_HT_FBK_CFG1, 0xedcba980);
4797faca41fbSmlelstv run_write(sc, RT2860_TXOP_HLDR_ET, 0x00000082);
4798faca41fbSmlelstv } else {
4799faca41fbSmlelstv run_write(sc, RT2860_HT_FBK_CFG1, 0xedcb4980);
4800faca41fbSmlelstv run_write(sc, RT2860_LG_FBK_CFG0, 0xedcba322);
4801faca41fbSmlelstv }
4802faca41fbSmlelstv }
4803faca41fbSmlelstv } else if (sc->mac_ver >= 0x3593) {
4804faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG0,
4805faca41fbSmlelstv 4 << RT2860_DLY_PAPE_EN_SHIFT | 2);
4806faca41fbSmlelstv } else if (sc->mac_ver >= 0x3070) {
48079cdb1c70Snonaka /* set delay of PA_PE assertion to 1us (unit of 0.25us) */
48089cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG0,
48099cdb1c70Snonaka 4 << RT2860_DLY_PAPE_EN_SHIFT);
48109cdb1c70Snonaka }
48119cdb1c70Snonaka
48129cdb1c70Snonaka /* wait while MAC is busy */
48139cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) {
48149cdb1c70Snonaka if ((error = run_read(sc, RT2860_MAC_STATUS_REG, &tmp)) != 0)
48159cdb1c70Snonaka goto fail;
48169cdb1c70Snonaka if (!(tmp & (RT2860_RX_STATUS_BUSY | RT2860_TX_STATUS_BUSY)))
48179cdb1c70Snonaka break;
48189cdb1c70Snonaka DELAY(1000);
48199cdb1c70Snonaka }
48209cdb1c70Snonaka if (ntries == 100) {
48219cdb1c70Snonaka error = ETIMEDOUT;
48229cdb1c70Snonaka goto fail;
48239cdb1c70Snonaka }
48249cdb1c70Snonaka
48259cdb1c70Snonaka /* clear Host to MCU mailbox */
48269cdb1c70Snonaka run_write(sc, RT2860_H2M_BBPAGENT, 0);
48279cdb1c70Snonaka run_write(sc, RT2860_H2M_MAILBOX, 0);
4828faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10);
48299cdb1c70Snonaka
48309cdb1c70Snonaka if ((error = run_bbp_init(sc)) != 0) {
48311d5cb2a3Sjakllsch device_printf(sc->sc_dev, "could not initialize BBP\n");
48329cdb1c70Snonaka goto fail;
48339cdb1c70Snonaka }
48349cdb1c70Snonaka
4835faca41fbSmlelstv /* abort TSF synchronization */
48369cdb1c70Snonaka run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
48379cdb1c70Snonaka tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
48389cdb1c70Snonaka RT2860_TBTT_TIMER_EN);
48399cdb1c70Snonaka run_write(sc, RT2860_BCN_TIME_CFG, tmp);
48409cdb1c70Snonaka
48419cdb1c70Snonaka /* clear RX WCID search table */
48429cdb1c70Snonaka run_set_region_4(sc, RT2860_WCID_ENTRY(0), 0, 512);
48439cdb1c70Snonaka /* clear Pair-wise key table */
48449cdb1c70Snonaka run_set_region_4(sc, RT2860_PKEY(0), 0, 2048);
48459cdb1c70Snonaka /* clear IV/EIV table */
48469cdb1c70Snonaka run_set_region_4(sc, RT2860_IVEIV(0), 0, 512);
48479cdb1c70Snonaka /* clear WCID attribute table */
48489cdb1c70Snonaka run_set_region_4(sc, RT2860_WCID_ATTR(0), 0, 8 * 32);
48499cdb1c70Snonaka /* clear shared key table */
48509cdb1c70Snonaka run_set_region_4(sc, RT2860_SKEY(0, 0), 0, 8 * 32);
48519cdb1c70Snonaka /* clear shared key mode */
48529cdb1c70Snonaka run_set_region_4(sc, RT2860_SKEY_MODE_0_7, 0, 4);
48539cdb1c70Snonaka
4854faca41fbSmlelstv /* clear RX WCID search table */
4855faca41fbSmlelstv run_set_region_4(sc, RT2860_WCID_ENTRY(0), 0, 512);
4856faca41fbSmlelstv /* clear WCID attribute table */
4857faca41fbSmlelstv run_set_region_4(sc, RT2860_WCID_ATTR(0), 0, 8 * 32);
4858faca41fbSmlelstv
48599cdb1c70Snonaka run_read(sc, RT2860_US_CYC_CNT, &tmp);
48609cdb1c70Snonaka tmp = (tmp & ~0xff) | 0x1e;
48619cdb1c70Snonaka run_write(sc, RT2860_US_CYC_CNT, tmp);
48629cdb1c70Snonaka
48639cdb1c70Snonaka if (sc->mac_rev != 0x0101)
48649cdb1c70Snonaka run_write(sc, RT2860_TXOP_CTRL_CFG, 0x0000583f);
48659cdb1c70Snonaka
48669cdb1c70Snonaka run_write(sc, RT2860_WMM_TXOP0_CFG, 0);
48679cdb1c70Snonaka run_write(sc, RT2860_WMM_TXOP1_CFG, 48 << 16 | 96);
48689cdb1c70Snonaka
48699cdb1c70Snonaka /* write vendor-specific BBP values (from EEPROM) */
4870faca41fbSmlelstv if (sc->mac_ver < 0x3593) {
4871faca41fbSmlelstv for (i = 0; i < 10; i++) {
48729cdb1c70Snonaka if (sc->bbp[i].reg == 0 || sc->bbp[i].reg == 0xff)
48739cdb1c70Snonaka continue;
48749cdb1c70Snonaka run_bbp_write(sc, sc->bbp[i].reg, sc->bbp[i].val);
48759cdb1c70Snonaka }
4876faca41fbSmlelstv }
48779cdb1c70Snonaka
48789cdb1c70Snonaka /* select Main antenna for 1T1R devices */
4879faca41fbSmlelstv if (sc->rf_rev == RT3070_RF_3020 || sc->rf_rev == RT5390_RF_5370)
48809cdb1c70Snonaka run_set_rx_antenna(sc, 0);
48819cdb1c70Snonaka
48829cdb1c70Snonaka /* send LEDs operating mode to microcontroller */
48839cdb1c70Snonaka (void)run_mcu_cmd(sc, RT2860_MCU_CMD_LED1, sc->led[0]);
48849cdb1c70Snonaka (void)run_mcu_cmd(sc, RT2860_MCU_CMD_LED2, sc->led[1]);
48859cdb1c70Snonaka (void)run_mcu_cmd(sc, RT2860_MCU_CMD_LED3, sc->led[2]);
48869cdb1c70Snonaka
4887faca41fbSmlelstv if (sc->mac_ver >= 0x5390)
4888faca41fbSmlelstv run_rt5390_rf_init(sc);
4889faca41fbSmlelstv else if (sc->mac_ver == 0x3593)
4890faca41fbSmlelstv run_rt3593_rf_init(sc);
4891faca41fbSmlelstv else if (sc->mac_ver >= 0x3070)
48929cdb1c70Snonaka run_rt3070_rf_init(sc);
48939cdb1c70Snonaka
48949cdb1c70Snonaka /* disable non-existing Rx chains */
48959cdb1c70Snonaka run_bbp_read(sc, 3, &bbp3);
48969cdb1c70Snonaka bbp3 &= ~(1 << 3 | 1 << 4);
48979cdb1c70Snonaka if (sc->nrxchains == 2)
48989cdb1c70Snonaka bbp3 |= 1 << 3;
48999cdb1c70Snonaka else if (sc->nrxchains == 3)
49009cdb1c70Snonaka bbp3 |= 1 << 4;
49019cdb1c70Snonaka run_bbp_write(sc, 3, bbp3);
49029cdb1c70Snonaka
49039cdb1c70Snonaka /* disable non-existing Tx chains */
49049cdb1c70Snonaka run_bbp_read(sc, 1, &bbp1);
49059cdb1c70Snonaka if (sc->ntxchains == 1)
49069cdb1c70Snonaka bbp1 &= ~(1 << 3 | 1 << 4);
49079cdb1c70Snonaka run_bbp_write(sc, 1, bbp1);
49089cdb1c70Snonaka
4909faca41fbSmlelstv if (sc->mac_ver >= 0x5390)
4910faca41fbSmlelstv run_rt5390_rf_setup(sc);
4911faca41fbSmlelstv else if (sc->mac_ver == 0x3593)
4912faca41fbSmlelstv run_rt3593_rf_setup(sc);
4913faca41fbSmlelstv else if (sc->mac_ver >= 0x3070)
49149cdb1c70Snonaka run_rt3070_rf_setup(sc);
49159cdb1c70Snonaka
49169cdb1c70Snonaka /* select default channel */
49179cdb1c70Snonaka run_set_chan(sc, ic->ic_curchan);
49189cdb1c70Snonaka
4919faca41fbSmlelstv /* setup initial protection mode */
4920faca41fbSmlelstv run_updateprot(sc);
4921faca41fbSmlelstv
49229cdb1c70Snonaka /* turn radio LED on */
49239cdb1c70Snonaka run_set_leds(sc, RT2860_LED_RADIO);
49249cdb1c70Snonaka
49259cdb1c70Snonaka #ifdef RUN_HWCRYPTO
49269cdb1c70Snonaka if (ic->ic_flags & IEEE80211_F_PRIVACY) {
49279cdb1c70Snonaka /* install WEP keys */
49289cdb1c70Snonaka for (i = 0; i < IEEE80211_WEP_NKID; i++)
49299cdb1c70Snonaka (void)run_set_key(ic, &ic->ic_crypto.cs_nw_keys[i],
49309cdb1c70Snonaka NULL);
49319cdb1c70Snonaka }
49329cdb1c70Snonaka #endif
49339cdb1c70Snonaka
49349cdb1c70Snonaka for (i = 0; i < RUN_RX_RING_COUNT; i++) {
49359cdb1c70Snonaka struct run_rx_data *data = &sc->rxq.data[i];
49369cdb1c70Snonaka
49374e8e6643Sskrll usbd_setup_xfer(data->xfer, data, data->buf, RUN_MAX_RXSZ,
49384e8e6643Sskrll USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, run_rxeof);
4939d164e220Smlelstv status = usbd_transfer(data->xfer);
4940d164e220Smlelstv if (status != USBD_NORMAL_COMPLETION &&
4941d164e220Smlelstv status != USBD_IN_PROGRESS) {
4942d164e220Smlelstv device_printf(sc->sc_dev, "queuing rx failed: %s\n",
4943d164e220Smlelstv usbd_errstr(status));
4944d164e220Smlelstv error = EIO;
49459cdb1c70Snonaka goto fail;
49469cdb1c70Snonaka }
4947d164e220Smlelstv }
49489cdb1c70Snonaka
49499cdb1c70Snonaka if ((error = run_txrx_enable(sc)) != 0)
49509cdb1c70Snonaka goto fail;
49519cdb1c70Snonaka
49529cdb1c70Snonaka ifp->if_flags &= ~IFF_OACTIVE;
49539cdb1c70Snonaka ifp->if_flags |= IFF_RUNNING;
49549cdb1c70Snonaka
49559cdb1c70Snonaka if (ic->ic_opmode == IEEE80211_M_MONITOR)
49569cdb1c70Snonaka ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
49579cdb1c70Snonaka else
49589cdb1c70Snonaka ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
49599cdb1c70Snonaka
49609cdb1c70Snonaka if (error != 0)
49619cdb1c70Snonaka fail: run_stop(ifp, 1);
49624e8e6643Sskrll return error;
49639cdb1c70Snonaka }
49649cdb1c70Snonaka
49659cdb1c70Snonaka static void
run_stop(struct ifnet * ifp,int disable)49669cdb1c70Snonaka run_stop(struct ifnet *ifp, int disable)
49679cdb1c70Snonaka {
49689cdb1c70Snonaka struct run_softc *sc = ifp->if_softc;
49699cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
49709cdb1c70Snonaka uint32_t tmp;
49719cdb1c70Snonaka int ntries, qid;
49729cdb1c70Snonaka
49739cdb1c70Snonaka if (ifp->if_flags & IFF_RUNNING)
49749cdb1c70Snonaka run_set_leds(sc, 0); /* turn all LEDs off */
49759cdb1c70Snonaka
49769cdb1c70Snonaka sc->sc_tx_timer = 0;
49779cdb1c70Snonaka ifp->if_timer = 0;
49789cdb1c70Snonaka ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
49799cdb1c70Snonaka
49809cdb1c70Snonaka callout_stop(&sc->scan_to);
49819cdb1c70Snonaka callout_stop(&sc->calib_to);
49829cdb1c70Snonaka
49839cdb1c70Snonaka ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
49849cdb1c70Snonaka /* wait for all queued asynchronous commands to complete */
49859cdb1c70Snonaka while (sc->cmdq.queued > 0)
49869cdb1c70Snonaka tsleep(&sc->cmdq, 0, "cmdq", 0);
49879cdb1c70Snonaka
49889cdb1c70Snonaka /* disable Tx/Rx */
49899cdb1c70Snonaka run_read(sc, RT2860_MAC_SYS_CTRL, &tmp);
49909cdb1c70Snonaka tmp &= ~(RT2860_MAC_RX_EN | RT2860_MAC_TX_EN);
49919cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL, tmp);
49929cdb1c70Snonaka
49939cdb1c70Snonaka /* wait for pending Tx to complete */
49949cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) {
49959cdb1c70Snonaka if (run_read(sc, RT2860_TXRXQ_PCNT, &tmp) != 0)
49969cdb1c70Snonaka break;
49979cdb1c70Snonaka if ((tmp & RT2860_TX2Q_PCNT_MASK) == 0)
49989cdb1c70Snonaka break;
49999cdb1c70Snonaka }
50009cdb1c70Snonaka DELAY(1000);
50019cdb1c70Snonaka run_write(sc, RT2860_USB_DMA_CFG, 0);
50029cdb1c70Snonaka
50039cdb1c70Snonaka /* reset adapter */
50049cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL, RT2860_BBP_HRST | RT2860_MAC_SRST);
50059cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL, 0);
50069cdb1c70Snonaka
50079cdb1c70Snonaka /* reset Tx and Rx rings */
50089cdb1c70Snonaka sc->qfullmsk = 0;
50099cdb1c70Snonaka for (qid = 0; qid < 4; qid++)
50109cdb1c70Snonaka run_free_tx_ring(sc, qid);
50119cdb1c70Snonaka run_free_rx_ring(sc);
50129cdb1c70Snonaka }
50139cdb1c70Snonaka
50149cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY
50159cdb1c70Snonaka static int
run_setup_beacon(struct run_softc * sc)50169cdb1c70Snonaka run_setup_beacon(struct run_softc *sc)
50179cdb1c70Snonaka {
50189cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic;
50199cdb1c70Snonaka struct rt2860_txwi txwi;
50209cdb1c70Snonaka struct mbuf *m;
5021faca41fbSmlelstv uint16_t txwisize;
50229cdb1c70Snonaka int ridx;
50239cdb1c70Snonaka
50249cdb1c70Snonaka if ((m = ieee80211_beacon_alloc(ic, ic->ic_bss, &sc->sc_bo)) == NULL)
50254e8e6643Sskrll return ENOBUFS;
50269cdb1c70Snonaka
50274e8e6643Sskrll memset(&txwi, 0, sizeof(txwi));
50289cdb1c70Snonaka txwi.wcid = 0xff;
50299cdb1c70Snonaka txwi.len = htole16(m->m_pkthdr.len);
50309cdb1c70Snonaka /* send beacons at the lowest available rate */
50319cdb1c70Snonaka ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
50329cdb1c70Snonaka RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1;
50339cdb1c70Snonaka txwi.phy = htole16(rt2860_rates[ridx].mcs);
50349cdb1c70Snonaka if (rt2860_rates[ridx].phy == IEEE80211_T_OFDM)
50359cdb1c70Snonaka txwi.phy |= htole16(RT2860_PHY_OFDM);
50369cdb1c70Snonaka txwi.txop = RT2860_TX_TXOP_HT;
50379cdb1c70Snonaka txwi.flags = RT2860_TX_TS;
50389cdb1c70Snonaka
5039faca41fbSmlelstv txwisize = (sc->mac_ver == 0x5592) ?
5040faca41fbSmlelstv sizeof(txwi) + sizeof(uint32_t) : sizeof(txwi);
50419cdb1c70Snonaka run_write_region_1(sc, RT2860_BCN_BASE(0),
5042faca41fbSmlelstv (uint8_t *)&txwi, txwisize);
5043faca41fbSmlelstv run_write_region_1(sc, RT2860_BCN_BASE(0) + txwisize,
5044faca41fbSmlelstv mtod(m, uint8_t *), (m->m_pkthdr.len + 1) & ~1);
50459cdb1c70Snonaka
50469cdb1c70Snonaka m_freem(m);
50479cdb1c70Snonaka
50484e8e6643Sskrll return 0;
50499cdb1c70Snonaka }
50509cdb1c70Snonaka #endif
50519cdb1c70Snonaka
505260d3fae6Schristos MODULE(MODULE_CLASS_DRIVER, if_run, NULL);
50539cdb1c70Snonaka
50549cdb1c70Snonaka #ifdef _MODULE
50559cdb1c70Snonaka #include "ioconf.c"
50569cdb1c70Snonaka #endif
50579cdb1c70Snonaka
50589cdb1c70Snonaka static int
if_run_modcmd(modcmd_t cmd,void * arg)50599cdb1c70Snonaka if_run_modcmd(modcmd_t cmd, void *arg)
50609cdb1c70Snonaka {
50619cdb1c70Snonaka int error = 0;
50629cdb1c70Snonaka
50639cdb1c70Snonaka switch (cmd) {
50649cdb1c70Snonaka case MODULE_CMD_INIT:
50659cdb1c70Snonaka #ifdef _MODULE
50669cdb1c70Snonaka error = config_init_component(cfdriver_ioconf_run,
50679cdb1c70Snonaka cfattach_ioconf_run, cfdata_ioconf_run);
50689cdb1c70Snonaka #endif
50694e8e6643Sskrll return error;
50709cdb1c70Snonaka case MODULE_CMD_FINI:
50719cdb1c70Snonaka #ifdef _MODULE
50729cdb1c70Snonaka error = config_fini_component(cfdriver_ioconf_run,
50739cdb1c70Snonaka cfattach_ioconf_run, cfdata_ioconf_run);
50749cdb1c70Snonaka #endif
50754e8e6643Sskrll return error;
50769cdb1c70Snonaka default:
50774e8e6643Sskrll return ENOTTY;
50789cdb1c70Snonaka }
50799cdb1c70Snonaka }
5080