xref: /netbsd-src/sys/dev/usb/if_run.c (revision 232edc8c483b130afc40922d64064aaae788d67f)
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