1*90e85cecSmlelstv /* $NetBSD: if_run.c,v 1.35 2020/01/04 22:30:06 mlelstv 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*90e85cecSmlelstv __KERNEL_RCSID(0, "$NetBSD: if_run.c,v 1.35 2020/01/04 22:30:06 mlelstv 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> 44*90e85cecSmlelstv #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 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 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 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 6529cdb1c70Snonaka /* retrieve RF rev. no and various other things from EEPROM */ 6539cdb1c70Snonaka run_read_eeprom(sc); 6549cdb1c70Snonaka 6551d5cb2a3Sjakllsch aprint_verbose_dev(sc->sc_dev, 6569cdb1c70Snonaka "MAC/BBP RT%04X (rev 0x%04X), RF %s (MIMO %dT%dR), address %s\n", 6579cdb1c70Snonaka sc->mac_ver, sc->mac_rev, run_get_rf(sc->rf_rev), sc->ntxchains, 6589cdb1c70Snonaka sc->nrxchains, ether_sprintf(ic->ic_myaddr)); 6599cdb1c70Snonaka 6609cdb1c70Snonaka ic->ic_ifp = ifp; 6619cdb1c70Snonaka ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 6629cdb1c70Snonaka ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 6639cdb1c70Snonaka ic->ic_state = IEEE80211_S_INIT; 6649cdb1c70Snonaka 6659cdb1c70Snonaka /* set device capabilities */ 6669cdb1c70Snonaka ic->ic_caps = 6679cdb1c70Snonaka IEEE80211_C_MONITOR | /* monitor mode supported */ 6689cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY 6699cdb1c70Snonaka IEEE80211_C_IBSS | /* IBSS mode supported */ 6709cdb1c70Snonaka IEEE80211_C_HOSTAP | /* HostAP mode supported */ 6719cdb1c70Snonaka #endif 6729cdb1c70Snonaka IEEE80211_C_SHPREAMBLE | /* short preamble supported */ 6739cdb1c70Snonaka IEEE80211_C_SHSLOT | /* short slot time supported */ 6749cdb1c70Snonaka #ifdef RUN_HWCRYPTO 6759cdb1c70Snonaka IEEE80211_C_WEP | /* WEP */ 6769cdb1c70Snonaka IEEE80211_C_TKIP | /* TKIP */ 6779cdb1c70Snonaka IEEE80211_C_AES_CCM | /* AES CCMP */ 6789cdb1c70Snonaka IEEE80211_C_TKIPMIC | /* TKIPMIC */ 6799cdb1c70Snonaka #endif 6809cdb1c70Snonaka IEEE80211_C_WME | /* WME */ 6819cdb1c70Snonaka IEEE80211_C_WPA; /* WPA/RSN */ 6829cdb1c70Snonaka 6839cdb1c70Snonaka if (sc->rf_rev == RT2860_RF_2750 || 6849cdb1c70Snonaka sc->rf_rev == RT2860_RF_2850 || 685faca41fbSmlelstv sc->rf_rev == RT3070_RF_3052 || 686faca41fbSmlelstv sc->rf_rev == RT3070_RF_3053 || 687faca41fbSmlelstv sc->rf_rev == RT5592_RF_5592) { 6889cdb1c70Snonaka /* set supported .11a rates */ 6899cdb1c70Snonaka ic->ic_sup_rates[IEEE80211_MODE_11A] = 6909cdb1c70Snonaka ieee80211_std_rateset_11a; 6919cdb1c70Snonaka 6929cdb1c70Snonaka /* set supported .11a channels */ 6939cdb1c70Snonaka for (i = 14; i < (int)__arraycount(rt2860_rf2850); i++) { 6949cdb1c70Snonaka uint8_t chan = rt2860_rf2850[i].chan; 6959cdb1c70Snonaka ic->ic_channels[chan].ic_freq = 6969cdb1c70Snonaka ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ); 6979cdb1c70Snonaka ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A; 6989cdb1c70Snonaka } 6999cdb1c70Snonaka } 7009cdb1c70Snonaka 7019cdb1c70Snonaka /* set supported .11b and .11g rates */ 7029cdb1c70Snonaka ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b; 7039cdb1c70Snonaka ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g; 7049cdb1c70Snonaka 7059cdb1c70Snonaka /* set supported .11b and .11g channels (1 through 14) */ 7069cdb1c70Snonaka for (i = 1; i <= 14; i++) { 7079cdb1c70Snonaka ic->ic_channels[i].ic_freq = 7089cdb1c70Snonaka ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 7099cdb1c70Snonaka ic->ic_channels[i].ic_flags = 7109cdb1c70Snonaka IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | 7119cdb1c70Snonaka IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; 7129cdb1c70Snonaka } 7139cdb1c70Snonaka 7149cdb1c70Snonaka ifp->if_softc = sc; 7159cdb1c70Snonaka ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 7169cdb1c70Snonaka ifp->if_init = run_init; 7179cdb1c70Snonaka ifp->if_ioctl = run_ioctl; 7189cdb1c70Snonaka ifp->if_start = run_start; 7199cdb1c70Snonaka ifp->if_watchdog = run_watchdog; 7209cdb1c70Snonaka IFQ_SET_READY(&ifp->if_snd); 7219cdb1c70Snonaka memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 7229cdb1c70Snonaka 7239cdb1c70Snonaka if_attach(ifp); 7249cdb1c70Snonaka ieee80211_ifattach(ic); 7259cdb1c70Snonaka ic->ic_node_alloc = run_node_alloc; 7269cdb1c70Snonaka ic->ic_newassoc = run_newassoc; 7279cdb1c70Snonaka ic->ic_updateslot = run_updateslot; 7289cdb1c70Snonaka ic->ic_wme.wme_update = run_updateedca; 7299cdb1c70Snonaka #ifdef RUN_HWCRYPTO 7309cdb1c70Snonaka ic->ic_crypto.cs_key_set = run_set_key; 7319cdb1c70Snonaka ic->ic_crypto.cs_key_delete = run_delete_key; 7329cdb1c70Snonaka #endif 7339cdb1c70Snonaka /* override state transition machine */ 7349cdb1c70Snonaka sc->sc_newstate = ic->ic_newstate; 7359cdb1c70Snonaka ic->ic_newstate = run_newstate; 7369cdb1c70Snonaka ieee80211_media_init(ic, run_media_change, ieee80211_media_status); 7379cdb1c70Snonaka 7389cdb1c70Snonaka bpf_attach2(ifp, DLT_IEEE802_11_RADIO, 7399cdb1c70Snonaka sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN, 7409cdb1c70Snonaka &sc->sc_drvbpf); 7419cdb1c70Snonaka 7429cdb1c70Snonaka sc->sc_rxtap_len = sizeof(sc->sc_rxtapu); 7439cdb1c70Snonaka sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); 7449cdb1c70Snonaka sc->sc_rxtap.wr_ihdr.it_present = htole32(RUN_RX_RADIOTAP_PRESENT); 7459cdb1c70Snonaka 7469cdb1c70Snonaka sc->sc_txtap_len = sizeof(sc->sc_txtapu); 7479cdb1c70Snonaka sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); 7489cdb1c70Snonaka sc->sc_txtap.wt_ihdr.it_present = htole32(RUN_TX_RADIOTAP_PRESENT); 7499cdb1c70Snonaka 7509cdb1c70Snonaka ieee80211_announce(ic); 7519cdb1c70Snonaka 7529cdb1c70Snonaka usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 753b2901b1bSnonaka 754b2901b1bSnonaka if (!pmf_device_register(self, NULL, NULL)) 755b2901b1bSnonaka aprint_error_dev(self, "couldn't establish power handler\n"); 7569cdb1c70Snonaka } 7579cdb1c70Snonaka 7589cdb1c70Snonaka static int 7599cdb1c70Snonaka run_detach(device_t self, int flags) 7609cdb1c70Snonaka { 7619cdb1c70Snonaka struct run_softc *sc = device_private(self); 7629cdb1c70Snonaka struct ifnet *ifp = &sc->sc_if; 7639cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 7649cdb1c70Snonaka int s; 7659cdb1c70Snonaka 7669cdb1c70Snonaka if (ifp->if_softc == NULL) 7674e8e6643Sskrll return 0; 7689cdb1c70Snonaka 769b2901b1bSnonaka pmf_device_deregister(self); 770b2901b1bSnonaka 771da8283baSmlelstv s = splusb(); 7729cdb1c70Snonaka 7739cdb1c70Snonaka sc->sc_flags |= RUN_DETACHING; 7749cdb1c70Snonaka 7759cdb1c70Snonaka if (ifp->if_flags & IFF_RUNNING) { 7769cdb1c70Snonaka run_stop(ifp, 0); 777080b2b0bSriastradh callout_halt(&sc->scan_to, NULL); 778080b2b0bSriastradh callout_halt(&sc->calib_to, NULL); 779a1de0147Sriastradh usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER, 780a1de0147Sriastradh NULL); 7819cdb1c70Snonaka } 7829cdb1c70Snonaka 7839cdb1c70Snonaka ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 7849cdb1c70Snonaka bpf_detach(ifp); 7859cdb1c70Snonaka ieee80211_ifdetach(ic); 7869cdb1c70Snonaka if_detach(ifp); 7879cdb1c70Snonaka 7889cdb1c70Snonaka splx(s); 7899cdb1c70Snonaka 7909cdb1c70Snonaka usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 7919cdb1c70Snonaka 792faca41fbSmlelstv callout_stop(&sc->scan_to); 793faca41fbSmlelstv callout_stop(&sc->calib_to); 794faca41fbSmlelstv 7959cdb1c70Snonaka callout_destroy(&sc->scan_to); 7969cdb1c70Snonaka callout_destroy(&sc->calib_to); 7979cdb1c70Snonaka 7984e8e6643Sskrll return 0; 7999cdb1c70Snonaka } 8009cdb1c70Snonaka 8019cdb1c70Snonaka static int 8029cdb1c70Snonaka run_activate(device_t self, enum devact act) 8039cdb1c70Snonaka { 8049cdb1c70Snonaka struct run_softc *sc = device_private(self); 8059cdb1c70Snonaka 8069cdb1c70Snonaka switch (act) { 8079cdb1c70Snonaka case DVACT_DEACTIVATE: 8089cdb1c70Snonaka if_deactivate(sc->sc_ic.ic_ifp); 8094e8e6643Sskrll return 0; 8109cdb1c70Snonaka default: 8114e8e6643Sskrll return EOPNOTSUPP; 8129cdb1c70Snonaka } 8139cdb1c70Snonaka } 8149cdb1c70Snonaka 8159cdb1c70Snonaka static int 8169cdb1c70Snonaka run_alloc_rx_ring(struct run_softc *sc) 8179cdb1c70Snonaka { 8189cdb1c70Snonaka struct run_rx_ring *rxq = &sc->rxq; 8199cdb1c70Snonaka int i, error; 8209cdb1c70Snonaka 8219cdb1c70Snonaka error = usbd_open_pipe(sc->sc_iface, rxq->pipe_no, 0, &rxq->pipeh); 8229cdb1c70Snonaka if (error != 0) 8239cdb1c70Snonaka goto fail; 8249cdb1c70Snonaka 8259cdb1c70Snonaka for (i = 0; i < RUN_RX_RING_COUNT; i++) { 8269cdb1c70Snonaka struct run_rx_data *data = &rxq->data[i]; 8279cdb1c70Snonaka 8289cdb1c70Snonaka data->sc = sc; /* backpointer for callbacks */ 8299cdb1c70Snonaka 8304e8e6643Sskrll error = usbd_create_xfer(sc->rxq.pipeh, RUN_MAX_RXSZ, 831b8421611Sskrll 0, 0, &data->xfer); 8324e8e6643Sskrll if (error) 8339cdb1c70Snonaka goto fail; 8344e8e6643Sskrll 8354e8e6643Sskrll data->buf = usbd_get_buffer(data->xfer); 8369cdb1c70Snonaka } 8379cdb1c70Snonaka if (error != 0) 8389cdb1c70Snonaka fail: run_free_rx_ring(sc); 8394e8e6643Sskrll return error; 8409cdb1c70Snonaka } 8419cdb1c70Snonaka 8429cdb1c70Snonaka static void 8439cdb1c70Snonaka run_free_rx_ring(struct run_softc *sc) 8449cdb1c70Snonaka { 8459cdb1c70Snonaka struct run_rx_ring *rxq = &sc->rxq; 8469cdb1c70Snonaka int i; 8479cdb1c70Snonaka 8489cdb1c70Snonaka if (rxq->pipeh != NULL) { 8499cdb1c70Snonaka usbd_abort_pipe(rxq->pipeh); 8509cdb1c70Snonaka } 8519cdb1c70Snonaka for (i = 0; i < RUN_RX_RING_COUNT; i++) { 8529cdb1c70Snonaka if (rxq->data[i].xfer != NULL) 8534e8e6643Sskrll usbd_destroy_xfer(rxq->data[i].xfer); 8549cdb1c70Snonaka rxq->data[i].xfer = NULL; 8559cdb1c70Snonaka } 8564e8e6643Sskrll if (rxq->pipeh != NULL) { 8574e8e6643Sskrll usbd_close_pipe(rxq->pipeh); 8584e8e6643Sskrll rxq->pipeh = NULL; 8594e8e6643Sskrll } 8609cdb1c70Snonaka } 8619cdb1c70Snonaka 8629cdb1c70Snonaka static int 8639cdb1c70Snonaka run_alloc_tx_ring(struct run_softc *sc, int qid) 8649cdb1c70Snonaka { 8659cdb1c70Snonaka struct run_tx_ring *txq = &sc->txq[qid]; 8669cdb1c70Snonaka int i, error; 867d164e220Smlelstv uint16_t txwisize; 868d164e220Smlelstv 869d164e220Smlelstv txwisize = sizeof(struct rt2860_txwi); 870d164e220Smlelstv if (sc->mac_ver == 0x5592) 871d164e220Smlelstv txwisize += sizeof(uint32_t); 8729cdb1c70Snonaka 8739cdb1c70Snonaka txq->cur = txq->queued = 0; 8749cdb1c70Snonaka 8759cdb1c70Snonaka error = usbd_open_pipe(sc->sc_iface, txq->pipe_no, 0, &txq->pipeh); 8769cdb1c70Snonaka if (error != 0) 8779cdb1c70Snonaka goto fail; 8789cdb1c70Snonaka 8799cdb1c70Snonaka for (i = 0; i < RUN_TX_RING_COUNT; i++) { 8809cdb1c70Snonaka struct run_tx_data *data = &txq->data[i]; 8819cdb1c70Snonaka 8829cdb1c70Snonaka data->sc = sc; /* backpointer for callbacks */ 8839cdb1c70Snonaka data->qid = qid; 8849cdb1c70Snonaka 8854e8e6643Sskrll error = usbd_create_xfer(txq->pipeh, RUN_MAX_TXSZ, 8864e8e6643Sskrll USBD_FORCE_SHORT_XFER, 0, &data->xfer); 8874e8e6643Sskrll if (error) 8889cdb1c70Snonaka goto fail; 8894e8e6643Sskrll 8904e8e6643Sskrll data->buf = usbd_get_buffer(data->xfer); 8919cdb1c70Snonaka /* zeroize the TXD + TXWI part */ 892d164e220Smlelstv memset(data->buf, 0, sizeof(struct rt2870_txd) + txwisize); 8939cdb1c70Snonaka } 8949cdb1c70Snonaka if (error != 0) 8959cdb1c70Snonaka fail: run_free_tx_ring(sc, qid); 8964e8e6643Sskrll return error; 8979cdb1c70Snonaka } 8989cdb1c70Snonaka 8999cdb1c70Snonaka static void 9009cdb1c70Snonaka run_free_tx_ring(struct run_softc *sc, int qid) 9019cdb1c70Snonaka { 9029cdb1c70Snonaka struct run_tx_ring *txq = &sc->txq[qid]; 9039cdb1c70Snonaka int i; 9049cdb1c70Snonaka 9059cdb1c70Snonaka if (txq->pipeh != NULL) { 9069cdb1c70Snonaka usbd_abort_pipe(txq->pipeh); 9079cdb1c70Snonaka usbd_close_pipe(txq->pipeh); 9089cdb1c70Snonaka txq->pipeh = NULL; 9099cdb1c70Snonaka } 9109cdb1c70Snonaka for (i = 0; i < RUN_TX_RING_COUNT; i++) { 9119cdb1c70Snonaka if (txq->data[i].xfer != NULL) 9124e8e6643Sskrll usbd_destroy_xfer(txq->data[i].xfer); 9139cdb1c70Snonaka txq->data[i].xfer = NULL; 9149cdb1c70Snonaka } 9159cdb1c70Snonaka } 9169cdb1c70Snonaka 9179cdb1c70Snonaka static int 9189cdb1c70Snonaka run_load_microcode(struct run_softc *sc) 9199cdb1c70Snonaka { 9209cdb1c70Snonaka usb_device_request_t req; 9219cdb1c70Snonaka const char *fwname; 9228317b16eSmartin u_char *ucode = NULL; /* XXX gcc 4.8.3: maybe-uninitialized */ 9238317b16eSmartin size_t size = 0; /* XXX gcc 4.8.3: maybe-uninitialized */ 9249cdb1c70Snonaka uint32_t tmp; 9259cdb1c70Snonaka int ntries, error; 9269cdb1c70Snonaka 9279cdb1c70Snonaka /* RT3071/RT3072 use a different firmware */ 9289cdb1c70Snonaka if (sc->mac_ver != 0x2860 && 9299cdb1c70Snonaka sc->mac_ver != 0x2872 && 9309cdb1c70Snonaka sc->mac_ver != 0x3070) 9319cdb1c70Snonaka fwname = "run-rt3071"; 9329cdb1c70Snonaka else 9339cdb1c70Snonaka fwname = "run-rt2870"; 9349cdb1c70Snonaka 935c9051a9fSnonaka if ((error = firmware_load("run", fwname, &ucode, &size)) != 0) { 9361d5cb2a3Sjakllsch device_printf(sc->sc_dev, 9379cdb1c70Snonaka "error %d, could not read firmware %s\n", error, fwname); 9384e8e6643Sskrll return error; 9399cdb1c70Snonaka } 9409cdb1c70Snonaka if (size != 4096) { 9411d5cb2a3Sjakllsch device_printf(sc->sc_dev, 9429cdb1c70Snonaka "invalid firmware size (should be 4KB)\n"); 9439cdb1c70Snonaka firmware_free(ucode, size); 9444e8e6643Sskrll return EINVAL; 9459cdb1c70Snonaka } 9469cdb1c70Snonaka 9479cdb1c70Snonaka run_read(sc, RT2860_ASIC_VER_ID, &tmp); 9489cdb1c70Snonaka /* write microcode image */ 9499cdb1c70Snonaka run_write_region_1(sc, RT2870_FW_BASE, ucode, size); 9509cdb1c70Snonaka firmware_free(ucode, size); 9519cdb1c70Snonaka run_write(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff); 9529cdb1c70Snonaka run_write(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff); 9539cdb1c70Snonaka 9549cdb1c70Snonaka req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 9559cdb1c70Snonaka req.bRequest = RT2870_RESET; 9569cdb1c70Snonaka USETW(req.wValue, 8); 9579cdb1c70Snonaka USETW(req.wIndex, 0); 9589cdb1c70Snonaka USETW(req.wLength, 0); 9599cdb1c70Snonaka if ((error = usbd_do_request(sc->sc_udev, &req, NULL)) != 0) 9604e8e6643Sskrll return error; 9619cdb1c70Snonaka 9629cdb1c70Snonaka usbd_delay_ms(sc->sc_udev, 10); 963d164e220Smlelstv run_write(sc, RT2860_H2M_BBPAGENT, 0); 9649cdb1c70Snonaka run_write(sc, RT2860_H2M_MAILBOX, 0); 965d164e220Smlelstv run_write(sc, RT2860_H2M_INTSRC, 0); 9669cdb1c70Snonaka if ((error = run_mcu_cmd(sc, RT2860_MCU_CMD_RFRESET, 0)) != 0) 9674e8e6643Sskrll return error; 9689cdb1c70Snonaka 9699cdb1c70Snonaka /* wait until microcontroller is ready */ 9709cdb1c70Snonaka for (ntries = 0; ntries < 1000; ntries++) { 9719cdb1c70Snonaka if ((error = run_read(sc, RT2860_SYS_CTRL, &tmp)) != 0) 9724e8e6643Sskrll return error; 9739cdb1c70Snonaka if (tmp & RT2860_MCU_READY) 9749cdb1c70Snonaka break; 975faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 9769cdb1c70Snonaka } 9779cdb1c70Snonaka if (ntries == 1000) { 9781d5cb2a3Sjakllsch device_printf(sc->sc_dev, 9799cdb1c70Snonaka "timeout waiting for MCU to initialize\n"); 9804e8e6643Sskrll return ETIMEDOUT; 9819cdb1c70Snonaka } 9829cdb1c70Snonaka 9839cdb1c70Snonaka sc->sc_flags |= RUN_FWLOADED; 9849cdb1c70Snonaka 9859cdb1c70Snonaka DPRINTF(("microcode successfully loaded after %d tries\n", ntries)); 9864e8e6643Sskrll return 0; 9879cdb1c70Snonaka } 9889cdb1c70Snonaka 9899cdb1c70Snonaka static int 9909cdb1c70Snonaka run_reset(struct run_softc *sc) 9919cdb1c70Snonaka { 9929cdb1c70Snonaka usb_device_request_t req; 9939cdb1c70Snonaka 9949cdb1c70Snonaka req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 9959cdb1c70Snonaka req.bRequest = RT2870_RESET; 9969cdb1c70Snonaka USETW(req.wValue, 1); 9979cdb1c70Snonaka USETW(req.wIndex, 0); 9989cdb1c70Snonaka USETW(req.wLength, 0); 9999cdb1c70Snonaka return usbd_do_request(sc->sc_udev, &req, NULL); 10009cdb1c70Snonaka } 10019cdb1c70Snonaka 10029cdb1c70Snonaka static int 10039cdb1c70Snonaka run_read(struct run_softc *sc, uint16_t reg, uint32_t *val) 10049cdb1c70Snonaka { 10059cdb1c70Snonaka uint32_t tmp; 10069cdb1c70Snonaka int error; 10079cdb1c70Snonaka 10084e8e6643Sskrll error = run_read_region_1(sc, reg, (uint8_t *)&tmp, sizeof(tmp)); 10099cdb1c70Snonaka if (error == 0) 10109cdb1c70Snonaka *val = le32toh(tmp); 10119cdb1c70Snonaka else 10129cdb1c70Snonaka *val = 0xffffffff; 10134e8e6643Sskrll return error; 10149cdb1c70Snonaka } 10159cdb1c70Snonaka 10169cdb1c70Snonaka static int 10179cdb1c70Snonaka run_read_region_1(struct run_softc *sc, uint16_t reg, uint8_t *buf, int len) 10189cdb1c70Snonaka { 10199cdb1c70Snonaka usb_device_request_t req; 10209cdb1c70Snonaka 10219cdb1c70Snonaka req.bmRequestType = UT_READ_VENDOR_DEVICE; 10229cdb1c70Snonaka req.bRequest = RT2870_READ_REGION_1; 10239cdb1c70Snonaka USETW(req.wValue, 0); 10249cdb1c70Snonaka USETW(req.wIndex, reg); 10259cdb1c70Snonaka USETW(req.wLength, len); 10269cdb1c70Snonaka return usbd_do_request(sc->sc_udev, &req, buf); 10279cdb1c70Snonaka } 10289cdb1c70Snonaka 10299cdb1c70Snonaka static int 10309cdb1c70Snonaka run_write_2(struct run_softc *sc, uint16_t reg, uint16_t val) 10319cdb1c70Snonaka { 10329cdb1c70Snonaka usb_device_request_t req; 10339cdb1c70Snonaka 10349cdb1c70Snonaka req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 10359cdb1c70Snonaka req.bRequest = RT2870_WRITE_2; 10369cdb1c70Snonaka USETW(req.wValue, val); 10379cdb1c70Snonaka USETW(req.wIndex, reg); 10389cdb1c70Snonaka USETW(req.wLength, 0); 10399cdb1c70Snonaka return usbd_do_request(sc->sc_udev, &req, NULL); 10409cdb1c70Snonaka } 10419cdb1c70Snonaka 10429cdb1c70Snonaka static int 10439cdb1c70Snonaka run_write(struct run_softc *sc, uint16_t reg, uint32_t val) 10449cdb1c70Snonaka { 10459cdb1c70Snonaka int error; 10469cdb1c70Snonaka 10479cdb1c70Snonaka if ((error = run_write_2(sc, reg, val & 0xffff)) == 0) 10489cdb1c70Snonaka error = run_write_2(sc, reg + 2, val >> 16); 10494e8e6643Sskrll return error; 10509cdb1c70Snonaka } 10519cdb1c70Snonaka 10529cdb1c70Snonaka static int 10539cdb1c70Snonaka run_write_region_1(struct run_softc *sc, uint16_t reg, const uint8_t *buf, 10549cdb1c70Snonaka int len) 10559cdb1c70Snonaka { 10569cdb1c70Snonaka #if 1 10579cdb1c70Snonaka int i, error = 0; 10589cdb1c70Snonaka /* 10599cdb1c70Snonaka * NB: the WRITE_REGION_1 command is not stable on RT2860. 10609cdb1c70Snonaka * We thus issue multiple WRITE_2 commands instead. 10619cdb1c70Snonaka */ 10629cdb1c70Snonaka KASSERT((len & 1) == 0); 10639cdb1c70Snonaka for (i = 0; i < len && error == 0; i += 2) 10649cdb1c70Snonaka error = run_write_2(sc, reg + i, buf[i] | buf[i + 1] << 8); 10654e8e6643Sskrll return error; 10669cdb1c70Snonaka #else 10679cdb1c70Snonaka usb_device_request_t req; 10689cdb1c70Snonaka 10699cdb1c70Snonaka req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 10709cdb1c70Snonaka req.bRequest = RT2870_WRITE_REGION_1; 10719cdb1c70Snonaka USETW(req.wValue, 0); 10729cdb1c70Snonaka USETW(req.wIndex, reg); 10739cdb1c70Snonaka USETW(req.wLength, len); 107452f0ad4eSgson return usbd_do_request(sc->sc_udev, &req, __UNCONST(buf)); 10759cdb1c70Snonaka #endif 10769cdb1c70Snonaka } 10779cdb1c70Snonaka 10789cdb1c70Snonaka static int 10799cdb1c70Snonaka run_set_region_4(struct run_softc *sc, uint16_t reg, uint32_t val, int count) 10809cdb1c70Snonaka { 10819cdb1c70Snonaka int error = 0; 10829cdb1c70Snonaka 10839cdb1c70Snonaka for (; count > 0 && error == 0; count--, reg += 4) 10849cdb1c70Snonaka error = run_write(sc, reg, val); 10854e8e6643Sskrll return error; 10869cdb1c70Snonaka } 10879cdb1c70Snonaka 10889cdb1c70Snonaka static int 1089faca41fbSmlelstv run_efuse_read(struct run_softc *sc, uint16_t addr, uint16_t *val, int count) 10909cdb1c70Snonaka { 10919cdb1c70Snonaka uint32_t tmp; 10929cdb1c70Snonaka uint16_t reg; 10939cdb1c70Snonaka int error, ntries; 10949cdb1c70Snonaka 10959cdb1c70Snonaka if ((error = run_read(sc, RT3070_EFUSE_CTRL, &tmp)) != 0) 10964e8e6643Sskrll return error; 10979cdb1c70Snonaka 1098faca41fbSmlelstv if (count == 2) 10999cdb1c70Snonaka addr *= 2; 11009cdb1c70Snonaka /*- 11019cdb1c70Snonaka * Read one 16-byte block into registers EFUSE_DATA[0-3]: 11029cdb1c70Snonaka * DATA0: F E D C 11039cdb1c70Snonaka * DATA1: B A 9 8 11049cdb1c70Snonaka * DATA2: 7 6 5 4 11059cdb1c70Snonaka * DATA3: 3 2 1 0 11069cdb1c70Snonaka */ 11079cdb1c70Snonaka tmp &= ~(RT3070_EFSROM_MODE_MASK | RT3070_EFSROM_AIN_MASK); 11089cdb1c70Snonaka tmp |= (addr & ~0xf) << RT3070_EFSROM_AIN_SHIFT | RT3070_EFSROM_KICK; 11099cdb1c70Snonaka run_write(sc, RT3070_EFUSE_CTRL, tmp); 11109cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) { 11119cdb1c70Snonaka if ((error = run_read(sc, RT3070_EFUSE_CTRL, &tmp)) != 0) 11124e8e6643Sskrll return error; 11139cdb1c70Snonaka if (!(tmp & RT3070_EFSROM_KICK)) 11149cdb1c70Snonaka break; 1115faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 2); 11169cdb1c70Snonaka } 11179cdb1c70Snonaka if (ntries == 100) 11184e8e6643Sskrll return ETIMEDOUT; 11199cdb1c70Snonaka 11209cdb1c70Snonaka if ((tmp & RT3070_EFUSE_AOUT_MASK) == RT3070_EFUSE_AOUT_MASK) { 11219cdb1c70Snonaka *val = 0xffff; /* address not found */ 11224e8e6643Sskrll return 0; 11239cdb1c70Snonaka } 11249cdb1c70Snonaka /* determine to which 32-bit register our 16-bit word belongs */ 11259cdb1c70Snonaka reg = RT3070_EFUSE_DATA3 - (addr & 0xc); 11269cdb1c70Snonaka if ((error = run_read(sc, reg, &tmp)) != 0) 11274e8e6643Sskrll return error; 11289cdb1c70Snonaka 1129d164e220Smlelstv tmp >>= (8 * (addr & 0x3)); 1130faca41fbSmlelstv *val = (addr & 1) ? tmp >> 16 : tmp & 0xffff; 11314e8e6643Sskrll return 0; 11329cdb1c70Snonaka } 11339cdb1c70Snonaka 1134faca41fbSmlelstv /* Read 16-bit from eFUSE ROM for RT3xxxx. */ 1135faca41fbSmlelstv static int 1136faca41fbSmlelstv run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val) 1137faca41fbSmlelstv { 113826ee7ba1Sskrll return run_efuse_read(sc, addr, val, 2); 1139faca41fbSmlelstv } 1140faca41fbSmlelstv 11419cdb1c70Snonaka static int 11429cdb1c70Snonaka run_eeprom_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val) 11439cdb1c70Snonaka { 11449cdb1c70Snonaka usb_device_request_t req; 11459cdb1c70Snonaka uint16_t tmp; 11469cdb1c70Snonaka int error; 11479cdb1c70Snonaka 11489cdb1c70Snonaka addr *= 2; 11499cdb1c70Snonaka req.bmRequestType = UT_READ_VENDOR_DEVICE; 11509cdb1c70Snonaka req.bRequest = RT2870_EEPROM_READ; 11519cdb1c70Snonaka USETW(req.wValue, 0); 11529cdb1c70Snonaka USETW(req.wIndex, addr); 11534e8e6643Sskrll USETW(req.wLength, sizeof(tmp)); 11549cdb1c70Snonaka error = usbd_do_request(sc->sc_udev, &req, &tmp); 11559cdb1c70Snonaka if (error == 0) 11569cdb1c70Snonaka *val = le16toh(tmp); 11579cdb1c70Snonaka else 11589cdb1c70Snonaka *val = 0xffff; 11594e8e6643Sskrll return error; 11609cdb1c70Snonaka } 11619cdb1c70Snonaka 11629cdb1c70Snonaka static __inline int 11639cdb1c70Snonaka run_srom_read(struct run_softc *sc, uint16_t addr, uint16_t *val) 11649cdb1c70Snonaka { 11659cdb1c70Snonaka 11669cdb1c70Snonaka /* either eFUSE ROM or EEPROM */ 11679cdb1c70Snonaka return sc->sc_srom_read(sc, addr, val); 11689cdb1c70Snonaka } 11699cdb1c70Snonaka 11709cdb1c70Snonaka static int 11719cdb1c70Snonaka run_rt2870_rf_write(struct run_softc *sc, uint8_t reg, uint32_t val) 11729cdb1c70Snonaka { 11739cdb1c70Snonaka uint32_t tmp; 11749cdb1c70Snonaka int error, ntries; 11759cdb1c70Snonaka 11769cdb1c70Snonaka for (ntries = 0; ntries < 10; ntries++) { 11779cdb1c70Snonaka if ((error = run_read(sc, RT2860_RF_CSR_CFG0, &tmp)) != 0) 11784e8e6643Sskrll return error; 11799cdb1c70Snonaka if (!(tmp & RT2860_RF_REG_CTRL)) 11809cdb1c70Snonaka break; 11819cdb1c70Snonaka } 11829cdb1c70Snonaka if (ntries == 10) 11834e8e6643Sskrll return ETIMEDOUT; 11849cdb1c70Snonaka 11859cdb1c70Snonaka /* RF registers are 24-bit on the RT2860 */ 11869cdb1c70Snonaka tmp = RT2860_RF_REG_CTRL | 24 << RT2860_RF_REG_WIDTH_SHIFT | 11879cdb1c70Snonaka (val & 0x3fffff) << 2 | (reg & 3); 11889cdb1c70Snonaka return run_write(sc, RT2860_RF_CSR_CFG0, tmp); 11899cdb1c70Snonaka } 11909cdb1c70Snonaka 11919cdb1c70Snonaka static int 11929cdb1c70Snonaka run_rt3070_rf_read(struct run_softc *sc, uint8_t reg, uint8_t *val) 11939cdb1c70Snonaka { 11949cdb1c70Snonaka uint32_t tmp; 11959cdb1c70Snonaka int error, ntries; 11969cdb1c70Snonaka 11979cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) { 11989cdb1c70Snonaka if ((error = run_read(sc, RT3070_RF_CSR_CFG, &tmp)) != 0) 11994e8e6643Sskrll return error; 12009cdb1c70Snonaka if (!(tmp & RT3070_RF_KICK)) 12019cdb1c70Snonaka break; 12029cdb1c70Snonaka } 12039cdb1c70Snonaka if (ntries == 100) 12044e8e6643Sskrll return ETIMEDOUT; 12059cdb1c70Snonaka 12069cdb1c70Snonaka tmp = RT3070_RF_KICK | reg << 8; 12079cdb1c70Snonaka if ((error = run_write(sc, RT3070_RF_CSR_CFG, tmp)) != 0) 12084e8e6643Sskrll return error; 12099cdb1c70Snonaka 12109cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) { 12119cdb1c70Snonaka if ((error = run_read(sc, RT3070_RF_CSR_CFG, &tmp)) != 0) 12124e8e6643Sskrll return error; 12139cdb1c70Snonaka if (!(tmp & RT3070_RF_KICK)) 12149cdb1c70Snonaka break; 12159cdb1c70Snonaka } 12169cdb1c70Snonaka if (ntries == 100) 12174e8e6643Sskrll return ETIMEDOUT; 12189cdb1c70Snonaka 12199cdb1c70Snonaka *val = tmp & 0xff; 12204e8e6643Sskrll return 0; 12219cdb1c70Snonaka } 12229cdb1c70Snonaka 12239cdb1c70Snonaka static int 12249cdb1c70Snonaka run_rt3070_rf_write(struct run_softc *sc, uint8_t reg, uint8_t val) 12259cdb1c70Snonaka { 12269cdb1c70Snonaka uint32_t tmp; 12279cdb1c70Snonaka int error, ntries; 12289cdb1c70Snonaka 12299cdb1c70Snonaka for (ntries = 0; ntries < 10; ntries++) { 12309cdb1c70Snonaka if ((error = run_read(sc, RT3070_RF_CSR_CFG, &tmp)) != 0) 12314e8e6643Sskrll return error; 12329cdb1c70Snonaka if (!(tmp & RT3070_RF_KICK)) 12339cdb1c70Snonaka break; 12349cdb1c70Snonaka } 12359cdb1c70Snonaka if (ntries == 10) 12364e8e6643Sskrll return ETIMEDOUT; 12379cdb1c70Snonaka 12389cdb1c70Snonaka tmp = RT3070_RF_WRITE | RT3070_RF_KICK | reg << 8 | val; 12399cdb1c70Snonaka return run_write(sc, RT3070_RF_CSR_CFG, tmp); 12409cdb1c70Snonaka } 12419cdb1c70Snonaka 12429cdb1c70Snonaka static int 12439cdb1c70Snonaka run_bbp_read(struct run_softc *sc, uint8_t reg, uint8_t *val) 12449cdb1c70Snonaka { 12459cdb1c70Snonaka uint32_t tmp; 12469cdb1c70Snonaka int ntries, error; 12479cdb1c70Snonaka 12489cdb1c70Snonaka for (ntries = 0; ntries < 10; ntries++) { 12499cdb1c70Snonaka if ((error = run_read(sc, RT2860_BBP_CSR_CFG, &tmp)) != 0) 12504e8e6643Sskrll return error; 12519cdb1c70Snonaka if (!(tmp & RT2860_BBP_CSR_KICK)) 12529cdb1c70Snonaka break; 12539cdb1c70Snonaka } 12549cdb1c70Snonaka if (ntries == 10) 12554e8e6643Sskrll return ETIMEDOUT; 12569cdb1c70Snonaka 12579cdb1c70Snonaka tmp = RT2860_BBP_CSR_READ | RT2860_BBP_CSR_KICK | reg << 8; 12589cdb1c70Snonaka if ((error = run_write(sc, RT2860_BBP_CSR_CFG, tmp)) != 0) 12594e8e6643Sskrll return error; 12609cdb1c70Snonaka 12619cdb1c70Snonaka for (ntries = 0; ntries < 10; ntries++) { 12629cdb1c70Snonaka if ((error = run_read(sc, RT2860_BBP_CSR_CFG, &tmp)) != 0) 12634e8e6643Sskrll return error; 12649cdb1c70Snonaka if (!(tmp & RT2860_BBP_CSR_KICK)) 12659cdb1c70Snonaka break; 12669cdb1c70Snonaka } 12679cdb1c70Snonaka if (ntries == 10) 12684e8e6643Sskrll return ETIMEDOUT; 12699cdb1c70Snonaka 12709cdb1c70Snonaka *val = tmp & 0xff; 12714e8e6643Sskrll return 0; 12729cdb1c70Snonaka } 12739cdb1c70Snonaka 12749cdb1c70Snonaka static int 12759cdb1c70Snonaka run_bbp_write(struct run_softc *sc, uint8_t reg, uint8_t val) 12769cdb1c70Snonaka { 12779cdb1c70Snonaka uint32_t tmp; 12789cdb1c70Snonaka int ntries, error; 12799cdb1c70Snonaka 12809cdb1c70Snonaka for (ntries = 0; ntries < 10; ntries++) { 12819cdb1c70Snonaka if ((error = run_read(sc, RT2860_BBP_CSR_CFG, &tmp)) != 0) 12824e8e6643Sskrll return error; 12839cdb1c70Snonaka if (!(tmp & RT2860_BBP_CSR_KICK)) 12849cdb1c70Snonaka break; 12859cdb1c70Snonaka } 12869cdb1c70Snonaka if (ntries == 10) 12874e8e6643Sskrll return ETIMEDOUT; 12889cdb1c70Snonaka 12899cdb1c70Snonaka tmp = RT2860_BBP_CSR_KICK | reg << 8 | val; 12909cdb1c70Snonaka return run_write(sc, RT2860_BBP_CSR_CFG, tmp); 12919cdb1c70Snonaka } 12929cdb1c70Snonaka 12939cdb1c70Snonaka /* 12949cdb1c70Snonaka * Send a command to the 8051 microcontroller unit. 12959cdb1c70Snonaka */ 12969cdb1c70Snonaka static int 12979cdb1c70Snonaka run_mcu_cmd(struct run_softc *sc, uint8_t cmd, uint16_t arg) 12989cdb1c70Snonaka { 12999cdb1c70Snonaka uint32_t tmp; 13009cdb1c70Snonaka int error, ntries; 13019cdb1c70Snonaka 13029cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) { 13039cdb1c70Snonaka if ((error = run_read(sc, RT2860_H2M_MAILBOX, &tmp)) != 0) 13044e8e6643Sskrll return error; 13059cdb1c70Snonaka if (!(tmp & RT2860_H2M_BUSY)) 13069cdb1c70Snonaka break; 13079cdb1c70Snonaka } 13089cdb1c70Snonaka if (ntries == 100) 13094e8e6643Sskrll return ETIMEDOUT; 13109cdb1c70Snonaka 13119cdb1c70Snonaka tmp = RT2860_H2M_BUSY | RT2860_TOKEN_NO_INTR << 16 | arg; 13129cdb1c70Snonaka if ((error = run_write(sc, RT2860_H2M_MAILBOX, tmp)) == 0) 13139cdb1c70Snonaka error = run_write(sc, RT2860_HOST_CMD, cmd); 13144e8e6643Sskrll return error; 13159cdb1c70Snonaka } 13169cdb1c70Snonaka 13179cdb1c70Snonaka /* 13189cdb1c70Snonaka * Add `delta' (signed) to each 4-bit sub-word of a 32-bit word. 13199cdb1c70Snonaka * Used to adjust per-rate Tx power registers. 13209cdb1c70Snonaka */ 13219cdb1c70Snonaka static __inline uint32_t 13229cdb1c70Snonaka b4inc(uint32_t b32, int8_t delta) 13239cdb1c70Snonaka { 13249cdb1c70Snonaka int8_t i, b4; 13259cdb1c70Snonaka 13269cdb1c70Snonaka for (i = 0; i < 8; i++) { 13279cdb1c70Snonaka b4 = b32 & 0xf; 13289cdb1c70Snonaka b4 += delta; 13299cdb1c70Snonaka if (b4 < 0) 13309cdb1c70Snonaka b4 = 0; 13319cdb1c70Snonaka else if (b4 > 0xf) 13329cdb1c70Snonaka b4 = 0xf; 13339cdb1c70Snonaka b32 = b32 >> 4 | b4 << 28; 13349cdb1c70Snonaka } 13354e8e6643Sskrll return b32; 13369cdb1c70Snonaka } 13379cdb1c70Snonaka 13389cdb1c70Snonaka static const char * 1339d164e220Smlelstv run_get_rf(uint16_t rev) 13409cdb1c70Snonaka { 13419cdb1c70Snonaka switch (rev) { 13429cdb1c70Snonaka case RT2860_RF_2820: return "RT2820"; 13439cdb1c70Snonaka case RT2860_RF_2850: return "RT2850"; 13449cdb1c70Snonaka case RT2860_RF_2720: return "RT2720"; 13459cdb1c70Snonaka case RT2860_RF_2750: return "RT2750"; 13469cdb1c70Snonaka case RT3070_RF_3020: return "RT3020"; 13479cdb1c70Snonaka case RT3070_RF_2020: return "RT2020"; 13489cdb1c70Snonaka case RT3070_RF_3021: return "RT3021"; 13499cdb1c70Snonaka case RT3070_RF_3022: return "RT3022"; 13509cdb1c70Snonaka case RT3070_RF_3052: return "RT3052"; 1351faca41fbSmlelstv case RT3070_RF_3053: return "RT3053"; 1352faca41fbSmlelstv case RT5592_RF_5592: return "RT5592"; 1353faca41fbSmlelstv case RT5390_RF_5370: return "RT5370"; 1354faca41fbSmlelstv case RT5390_RF_5372: return "RT5372"; 13559cdb1c70Snonaka } 13569cdb1c70Snonaka return "unknown"; 13579cdb1c70Snonaka } 13589cdb1c70Snonaka 1359faca41fbSmlelstv static void 1360faca41fbSmlelstv run_rt3593_get_txpower(struct run_softc *sc) 1361faca41fbSmlelstv { 1362faca41fbSmlelstv uint16_t addr, val; 1363faca41fbSmlelstv int i; 1364faca41fbSmlelstv 1365faca41fbSmlelstv /* Read power settings for 2GHz channels. */ 1366faca41fbSmlelstv for (i = 0; i < 14; i += 2) { 1367faca41fbSmlelstv addr = (sc->ntxchains == 3) ? RT3593_EEPROM_PWR2GHZ_BASE1 : 1368faca41fbSmlelstv RT2860_EEPROM_PWR2GHZ_BASE1; 1369faca41fbSmlelstv run_srom_read(sc, addr + i / 2, &val); 1370faca41fbSmlelstv sc->txpow1[i + 0] = (int8_t)(val & 0xff); 1371faca41fbSmlelstv sc->txpow1[i + 1] = (int8_t)(val >> 8); 1372faca41fbSmlelstv 1373faca41fbSmlelstv addr = (sc->ntxchains == 3) ? RT3593_EEPROM_PWR2GHZ_BASE2 : 1374faca41fbSmlelstv RT2860_EEPROM_PWR2GHZ_BASE2; 1375faca41fbSmlelstv run_srom_read(sc, addr + i / 2, &val); 1376faca41fbSmlelstv sc->txpow2[i + 0] = (int8_t)(val & 0xff); 1377faca41fbSmlelstv sc->txpow2[i + 1] = (int8_t)(val >> 8); 1378faca41fbSmlelstv 1379faca41fbSmlelstv if (sc->ntxchains == 3) { 1380faca41fbSmlelstv run_srom_read(sc, RT3593_EEPROM_PWR2GHZ_BASE3 + i / 2, 1381faca41fbSmlelstv &val); 1382faca41fbSmlelstv sc->txpow3[i + 0] = (int8_t)(val & 0xff); 1383faca41fbSmlelstv sc->txpow3[i + 1] = (int8_t)(val >> 8); 1384faca41fbSmlelstv } 1385faca41fbSmlelstv } 1386faca41fbSmlelstv /* Fix broken Tx power entries. */ 1387faca41fbSmlelstv for (i = 0; i < 14; i++) { 1388faca41fbSmlelstv if (sc->txpow1[i] > 31) 1389faca41fbSmlelstv sc->txpow1[i] = 5; 1390faca41fbSmlelstv if (sc->txpow2[i] > 31) 1391faca41fbSmlelstv sc->txpow2[i] = 5; 1392faca41fbSmlelstv if (sc->ntxchains == 3) { 1393faca41fbSmlelstv if (sc->txpow3[i] > 31) 1394faca41fbSmlelstv sc->txpow3[i] = 5; 1395faca41fbSmlelstv } 1396faca41fbSmlelstv } 1397faca41fbSmlelstv /* Read power settings for 5GHz channels. */ 1398faca41fbSmlelstv for (i = 0; i < 40; i += 2) { 1399faca41fbSmlelstv run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE1 + i / 2, &val); 1400faca41fbSmlelstv sc->txpow1[i + 14] = (int8_t)(val & 0xff); 1401faca41fbSmlelstv sc->txpow1[i + 15] = (int8_t)(val >> 8); 1402faca41fbSmlelstv 1403faca41fbSmlelstv run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE2 + i / 2, &val); 1404faca41fbSmlelstv sc->txpow2[i + 14] = (int8_t)(val & 0xff); 1405faca41fbSmlelstv sc->txpow2[i + 15] = (int8_t)(val >> 8); 1406faca41fbSmlelstv 1407faca41fbSmlelstv if (sc->ntxchains == 3) { 1408faca41fbSmlelstv run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE3 + i / 2, 1409faca41fbSmlelstv &val); 1410faca41fbSmlelstv sc->txpow3[i + 14] = (int8_t)(val & 0xff); 1411faca41fbSmlelstv sc->txpow3[i + 15] = (int8_t)(val >> 8); 1412faca41fbSmlelstv } 1413faca41fbSmlelstv } 1414faca41fbSmlelstv } 1415faca41fbSmlelstv 1416faca41fbSmlelstv static void 1417faca41fbSmlelstv run_get_txpower(struct run_softc *sc) 1418faca41fbSmlelstv { 1419faca41fbSmlelstv uint16_t val; 1420faca41fbSmlelstv int i; 1421faca41fbSmlelstv 1422faca41fbSmlelstv /* Read power settings for 2GHz channels. */ 1423faca41fbSmlelstv for (i = 0; i < 14; i += 2) { 1424faca41fbSmlelstv run_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2, &val); 1425faca41fbSmlelstv sc->txpow1[i + 0] = (int8_t)(val & 0xff); 1426faca41fbSmlelstv sc->txpow1[i + 1] = (int8_t)(val >> 8); 1427faca41fbSmlelstv 1428faca41fbSmlelstv if (sc->mac_ver != 0x5390) { 1429faca41fbSmlelstv run_srom_read(sc, 1430faca41fbSmlelstv RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2, &val); 1431faca41fbSmlelstv sc->txpow2[i + 0] = (int8_t)(val & 0xff); 1432faca41fbSmlelstv sc->txpow2[i + 1] = (int8_t)(val >> 8); 1433faca41fbSmlelstv } 1434faca41fbSmlelstv } 1435faca41fbSmlelstv /* Fix broken Tx power entries. */ 1436faca41fbSmlelstv for (i = 0; i < 14; i++) { 1437faca41fbSmlelstv if (sc->mac_ver >= 0x5390) { 1438faca41fbSmlelstv if (sc->txpow1[i] < 0 || sc->txpow1[i] > 39) 1439faca41fbSmlelstv sc->txpow1[i] = 5; 1440faca41fbSmlelstv } else { 1441faca41fbSmlelstv if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31) 1442faca41fbSmlelstv sc->txpow1[i] = 5; 1443faca41fbSmlelstv } 1444faca41fbSmlelstv if (sc->mac_ver > 0x5390) { 1445faca41fbSmlelstv if (sc->txpow2[i] < 0 || sc->txpow2[i] > 39) 1446faca41fbSmlelstv sc->txpow2[i] = 5; 1447faca41fbSmlelstv } else if (sc->mac_ver < 0x5390) { 1448faca41fbSmlelstv if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31) 1449faca41fbSmlelstv sc->txpow2[i] = 5; 1450faca41fbSmlelstv } 1451faca41fbSmlelstv DPRINTF(("chan %d: power1=%d, power2=%d\n", 1452faca41fbSmlelstv rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i])); 1453faca41fbSmlelstv } 1454faca41fbSmlelstv /* Read power settings for 5GHz channels. */ 1455faca41fbSmlelstv for (i = 0; i < 40; i += 2) { 1456faca41fbSmlelstv run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2, &val); 1457faca41fbSmlelstv sc->txpow1[i + 14] = (int8_t)(val & 0xff); 1458faca41fbSmlelstv sc->txpow1[i + 15] = (int8_t)(val >> 8); 1459faca41fbSmlelstv 1460faca41fbSmlelstv run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2, &val); 1461faca41fbSmlelstv sc->txpow2[i + 14] = (int8_t)(val & 0xff); 1462faca41fbSmlelstv sc->txpow2[i + 15] = (int8_t)(val >> 8); 1463faca41fbSmlelstv } 1464faca41fbSmlelstv /* Fix broken Tx power entries. */ 1465faca41fbSmlelstv for (i = 0; i < 40; i++ ) { 1466faca41fbSmlelstv if (sc->mac_ver != 0x5592) { 1467faca41fbSmlelstv if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15) 1468faca41fbSmlelstv sc->txpow1[14 + i] = 5; 1469faca41fbSmlelstv if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15) 1470faca41fbSmlelstv sc->txpow2[14 + i] = 5; 1471faca41fbSmlelstv } 1472faca41fbSmlelstv DPRINTF(("chan %d: power1=%d, power2=%d\n", 1473faca41fbSmlelstv rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i], 1474faca41fbSmlelstv sc->txpow2[14 + i])); 1475faca41fbSmlelstv } 1476faca41fbSmlelstv } 1477faca41fbSmlelstv 14789cdb1c70Snonaka static int 14799cdb1c70Snonaka run_read_eeprom(struct run_softc *sc) 14809cdb1c70Snonaka { 14819cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 14829cdb1c70Snonaka int8_t delta_2ghz, delta_5ghz; 14839cdb1c70Snonaka uint32_t tmp; 14849cdb1c70Snonaka uint16_t val; 14859cdb1c70Snonaka int ridx, ant, i; 14869cdb1c70Snonaka 14879cdb1c70Snonaka /* check whether the ROM is eFUSE ROM or EEPROM */ 14889cdb1c70Snonaka sc->sc_srom_read = run_eeprom_read_2; 14899cdb1c70Snonaka if (sc->mac_ver >= 0x3070) { 14909cdb1c70Snonaka run_read(sc, RT3070_EFUSE_CTRL, &tmp); 14919cdb1c70Snonaka DPRINTF(("EFUSE_CTRL=0x%08x\n", tmp)); 14929cdb1c70Snonaka if (tmp & RT3070_SEL_EFUSE) 14939cdb1c70Snonaka sc->sc_srom_read = run_efuse_read_2; 14949cdb1c70Snonaka } 14959cdb1c70Snonaka 14969cdb1c70Snonaka /* read ROM version */ 14979cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_VERSION, &val); 14989cdb1c70Snonaka DPRINTF(("EEPROM rev=%d, FAE=%d\n", val & 0xff, val >> 8)); 14999cdb1c70Snonaka 15009cdb1c70Snonaka /* read MAC address */ 15019cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_MAC01, &val); 15029cdb1c70Snonaka ic->ic_myaddr[0] = val & 0xff; 15039cdb1c70Snonaka ic->ic_myaddr[1] = val >> 8; 15049cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_MAC23, &val); 15059cdb1c70Snonaka ic->ic_myaddr[2] = val & 0xff; 15069cdb1c70Snonaka ic->ic_myaddr[3] = val >> 8; 15079cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_MAC45, &val); 15089cdb1c70Snonaka ic->ic_myaddr[4] = val & 0xff; 15099cdb1c70Snonaka ic->ic_myaddr[5] = val >> 8; 15109cdb1c70Snonaka 1511d164e220Smlelstv if (sc->mac_ver < 0x3593) { 15129cdb1c70Snonaka /* read vendor BBP settings */ 15139cdb1c70Snonaka for (i = 0; i < 10; i++) { 15149cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val); 15159cdb1c70Snonaka sc->bbp[i].val = val & 0xff; 15169cdb1c70Snonaka sc->bbp[i].reg = val >> 8; 1517d164e220Smlelstv DPRINTF(("BBP%d=0x%02x\n", sc->bbp[i].reg, 1518d164e220Smlelstv sc->bbp[i].val)); 15199cdb1c70Snonaka } 1520faca41fbSmlelstv 1521d164e220Smlelstv if (sc->mac_ver >= 0x3071) { 15229cdb1c70Snonaka /* read vendor RF settings */ 1523faca41fbSmlelstv for (i = 0; i < 8; i++) { 1524d164e220Smlelstv run_srom_read(sc, RT3071_EEPROM_RF_BASE + i, 1525d164e220Smlelstv &val); 15269cdb1c70Snonaka sc->rf[i].val = val & 0xff; 15279cdb1c70Snonaka sc->rf[i].reg = val >> 8; 15289cdb1c70Snonaka DPRINTF(("RF%d=0x%02x\n", sc->rf[i].reg, 15299cdb1c70Snonaka sc->rf[i].val)); 15309cdb1c70Snonaka } 1531d164e220Smlelstv } 1532d164e220Smlelstv } 15339cdb1c70Snonaka 15349cdb1c70Snonaka /* read RF frequency offset from EEPROM */ 1535d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS : 1536d164e220Smlelstv RT3593_EEPROM_FREQ, &val); 15379cdb1c70Snonaka sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0; 15389cdb1c70Snonaka DPRINTF(("EEPROM freq offset %d\n", sc->freq & 0xff)); 1539d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS : 1540d164e220Smlelstv RT3593_EEPROM_FREQ, &val); 15419cdb1c70Snonaka if ((val >> 8) != 0xff) { 15429cdb1c70Snonaka /* read LEDs operating mode */ 15439cdb1c70Snonaka sc->leds = val >> 8; 1544d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED1 : 1545d164e220Smlelstv RT3593_EEPROM_LED1, &sc->led[0]); 1546d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED2 : 1547d164e220Smlelstv RT3593_EEPROM_LED2, &sc->led[1]); 1548d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED3 : 1549d164e220Smlelstv RT3593_EEPROM_LED3, &sc->led[2]); 15509cdb1c70Snonaka } else { 15519cdb1c70Snonaka /* broken EEPROM, use default settings */ 15529cdb1c70Snonaka sc->leds = 0x01; 15539cdb1c70Snonaka sc->led[0] = 0x5555; 15549cdb1c70Snonaka sc->led[1] = 0x2221; 15559cdb1c70Snonaka sc->led[2] = 0x5627; /* differs from RT2860 */ 15569cdb1c70Snonaka } 15579cdb1c70Snonaka DPRINTF(("EEPROM LED mode=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n", 15589cdb1c70Snonaka sc->leds, sc->led[0], sc->led[1], sc->led[2])); 15599cdb1c70Snonaka 15609cdb1c70Snonaka /* read RF information */ 1561d164e220Smlelstv if (sc->mac_ver == 0x5390 || sc->mac_ver == 0x5392) 1562d164e220Smlelstv run_srom_read(sc, 0x00, &val); 1563d164e220Smlelstv else 15649cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val); 15659cdb1c70Snonaka if (val == 0xffff) { 15669cdb1c70Snonaka DPRINTF(("invalid EEPROM antenna info, using default\n")); 15679cdb1c70Snonaka if (sc->mac_ver == 0x3572) { 15689cdb1c70Snonaka /* default to RF3052 2T2R */ 15699cdb1c70Snonaka sc->rf_rev = RT3070_RF_3052; 15709cdb1c70Snonaka sc->ntxchains = 2; 15719cdb1c70Snonaka sc->nrxchains = 2; 15729cdb1c70Snonaka } else if (sc->mac_ver >= 0x3070) { 15739cdb1c70Snonaka /* default to RF3020 1T1R */ 15749cdb1c70Snonaka sc->rf_rev = RT3070_RF_3020; 15759cdb1c70Snonaka sc->ntxchains = 1; 15769cdb1c70Snonaka sc->nrxchains = 1; 15779cdb1c70Snonaka } else { 15789cdb1c70Snonaka /* default to RF2820 1T2R */ 15799cdb1c70Snonaka sc->rf_rev = RT2860_RF_2820; 15809cdb1c70Snonaka sc->ntxchains = 1; 15819cdb1c70Snonaka sc->nrxchains = 2; 15829cdb1c70Snonaka } 15839cdb1c70Snonaka } else { 1584d164e220Smlelstv if (sc->mac_ver == 0x5390 || sc->mac_ver == 0x5392) { 1585d164e220Smlelstv sc->rf_rev = val; 1586d164e220Smlelstv run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val); 1587d164e220Smlelstv } else 15889cdb1c70Snonaka sc->rf_rev = (val >> 8) & 0xf; 15899cdb1c70Snonaka sc->ntxchains = (val >> 4) & 0xf; 15909cdb1c70Snonaka sc->nrxchains = val & 0xf; 15919cdb1c70Snonaka } 1592d164e220Smlelstv DPRINTF(("EEPROM RF rev=0x%04x chains=%dT%dR\n", 15939cdb1c70Snonaka sc->rf_rev, sc->ntxchains, sc->nrxchains)); 15949cdb1c70Snonaka 15959cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_CONFIG, &val); 15969cdb1c70Snonaka DPRINTF(("EEPROM CFG 0x%04x\n", val)); 15979cdb1c70Snonaka /* check if driver should patch the DAC issue */ 15989cdb1c70Snonaka if ((val >> 8) != 0xff) 15999cdb1c70Snonaka sc->patch_dac = (val >> 15) & 1; 16009cdb1c70Snonaka if ((val & 0xff) != 0xff) { 16019cdb1c70Snonaka sc->ext_5ghz_lna = (val >> 3) & 1; 16029cdb1c70Snonaka sc->ext_2ghz_lna = (val >> 2) & 1; 16039cdb1c70Snonaka /* check if RF supports automatic Tx access gain control */ 16049cdb1c70Snonaka sc->calib_2ghz = sc->calib_5ghz = (val >> 1) & 1; 16059cdb1c70Snonaka /* check if we have a hardware radio switch */ 16069cdb1c70Snonaka sc->rfswitch = val & 1; 16079cdb1c70Snonaka } 16089cdb1c70Snonaka 1609faca41fbSmlelstv /* Read Tx power settings. */ 1610faca41fbSmlelstv if (sc->mac_ver == 0x3593) 1611faca41fbSmlelstv run_rt3593_get_txpower(sc); 1612faca41fbSmlelstv else 1613faca41fbSmlelstv run_get_txpower(sc); 16149cdb1c70Snonaka 16159cdb1c70Snonaka /* read Tx power compensation for each Tx rate */ 16169cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_DELTAPWR, &val); 16179cdb1c70Snonaka delta_2ghz = delta_5ghz = 0; 16189cdb1c70Snonaka if ((val & 0xff) != 0xff && (val & 0x80)) { 16199cdb1c70Snonaka delta_2ghz = val & 0xf; 16209cdb1c70Snonaka if (!(val & 0x40)) /* negative number */ 16219cdb1c70Snonaka delta_2ghz = -delta_2ghz; 16229cdb1c70Snonaka } 16239cdb1c70Snonaka val >>= 8; 16249cdb1c70Snonaka if ((val & 0xff) != 0xff && (val & 0x80)) { 16259cdb1c70Snonaka delta_5ghz = val & 0xf; 16269cdb1c70Snonaka if (!(val & 0x40)) /* negative number */ 16279cdb1c70Snonaka delta_5ghz = -delta_5ghz; 16289cdb1c70Snonaka } 16299cdb1c70Snonaka DPRINTF(("power compensation=%d (2GHz), %d (5GHz)\n", 16309cdb1c70Snonaka delta_2ghz, delta_5ghz)); 16319cdb1c70Snonaka 16329cdb1c70Snonaka for (ridx = 0; ridx < 5; ridx++) { 16339cdb1c70Snonaka uint32_t reg; 16349cdb1c70Snonaka 16359cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2, &val); 16369cdb1c70Snonaka reg = val; 16379cdb1c70Snonaka run_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2 + 1, &val); 16389cdb1c70Snonaka reg |= (uint32_t)val << 16; 16399cdb1c70Snonaka 16409cdb1c70Snonaka sc->txpow20mhz[ridx] = reg; 16419cdb1c70Snonaka sc->txpow40mhz_2ghz[ridx] = b4inc(reg, delta_2ghz); 16429cdb1c70Snonaka sc->txpow40mhz_5ghz[ridx] = b4inc(reg, delta_5ghz); 16439cdb1c70Snonaka 16449cdb1c70Snonaka DPRINTF(("ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, " 16459cdb1c70Snonaka "40MHz/5GHz=0x%08x\n", ridx, sc->txpow20mhz[ridx], 16469cdb1c70Snonaka sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx])); 16479cdb1c70Snonaka } 16489cdb1c70Snonaka 1649d164e220Smlelstv DPRINTF(("mac_ver %hx\n", sc->mac_ver)); 16509cdb1c70Snonaka /* read RSSI offsets and LNA gains from EEPROM */ 1651d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_2GHZ : 1652d164e220Smlelstv RT3593_EEPROM_RSSI1_2GHZ, &val); 16539cdb1c70Snonaka sc->rssi_2ghz[0] = val & 0xff; /* Ant A */ 16549cdb1c70Snonaka sc->rssi_2ghz[1] = val >> 8; /* Ant B */ 1655d164e220Smlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_2GHZ : 1656d164e220Smlelstv RT3593_EEPROM_RSSI2_2GHZ, &val); 16579cdb1c70Snonaka if (sc->mac_ver >= 0x3070) { 1658faca41fbSmlelstv if (sc->mac_ver == 0x3593) { 1659faca41fbSmlelstv sc->txmixgain_2ghz = 0; 1660faca41fbSmlelstv sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ 1661faca41fbSmlelstv } else { 16629cdb1c70Snonaka /* 16639cdb1c70Snonaka * On RT3070 chips (limited to 2 Rx chains), this ROM 16649cdb1c70Snonaka * field contains the Tx mixer gain for the 2GHz band. 16659cdb1c70Snonaka */ 16669cdb1c70Snonaka if ((val & 0xff) != 0xff) 16679cdb1c70Snonaka sc->txmixgain_2ghz = val & 0x7; 1668faca41fbSmlelstv } 16699cdb1c70Snonaka DPRINTF(("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz)); 16709cdb1c70Snonaka } else { 16719cdb1c70Snonaka sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ 16729cdb1c70Snonaka } 1673faca41fbSmlelstv if (sc->mac_ver == 0x3593) 1674faca41fbSmlelstv run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val); 16759cdb1c70Snonaka sc->lna[2] = val >> 8; /* channel group 2 */ 16769cdb1c70Snonaka 1677faca41fbSmlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_5GHZ : 1678d164e220Smlelstv RT3593_EEPROM_RSSI1_5GHZ, &val); 16799cdb1c70Snonaka sc->rssi_5ghz[0] = val & 0xff; /* Ant A */ 16809cdb1c70Snonaka sc->rssi_5ghz[1] = val >> 8; /* Ant B */ 1681faca41fbSmlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_5GHZ : 1682faca41fbSmlelstv RT3593_EEPROM_RSSI2_5GHZ, &val); 16839cdb1c70Snonaka if (sc->mac_ver == 0x3572) { 16849cdb1c70Snonaka /* 16859cdb1c70Snonaka * On RT3572 chips (limited to 2 Rx chains), this ROM 16869cdb1c70Snonaka * field contains the Tx mixer gain for the 5GHz band. 16879cdb1c70Snonaka */ 16889cdb1c70Snonaka if ((val & 0xff) != 0xff) 16899cdb1c70Snonaka sc->txmixgain_5ghz = val & 0x7; 16909cdb1c70Snonaka DPRINTF(("tx mixer gain=%u (5GHz)\n", sc->txmixgain_5ghz)); 16919cdb1c70Snonaka } else { 16929cdb1c70Snonaka sc->rssi_5ghz[2] = val & 0xff; /* Ant C */ 16939cdb1c70Snonaka } 1694faca41fbSmlelstv if (sc->mac_ver == 0x3593) { 1695faca41fbSmlelstv sc->txmixgain_5ghz = 0; 1696faca41fbSmlelstv run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val); 1697faca41fbSmlelstv } 16989cdb1c70Snonaka sc->lna[3] = val >> 8; /* channel group 3 */ 16999cdb1c70Snonaka 1700faca41fbSmlelstv run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LNA : 1701faca41fbSmlelstv RT3593_EEPROM_LNA, &val); 17029cdb1c70Snonaka sc->lna[0] = val & 0xff; /* channel group 0 */ 17039cdb1c70Snonaka sc->lna[1] = val >> 8; /* channel group 1 */ 17049cdb1c70Snonaka 17059cdb1c70Snonaka /* fix broken 5GHz LNA entries */ 17069cdb1c70Snonaka if (sc->lna[2] == 0 || sc->lna[2] == 0xff) { 17079cdb1c70Snonaka DPRINTF(("invalid LNA for channel group %d\n", 2)); 17089cdb1c70Snonaka sc->lna[2] = sc->lna[1]; 17099cdb1c70Snonaka } 17109cdb1c70Snonaka if (sc->lna[3] == 0 || sc->lna[3] == 0xff) { 17119cdb1c70Snonaka DPRINTF(("invalid LNA for channel group %d\n", 3)); 17129cdb1c70Snonaka sc->lna[3] = sc->lna[1]; 17139cdb1c70Snonaka } 17149cdb1c70Snonaka 17159cdb1c70Snonaka /* fix broken RSSI offset entries */ 17169cdb1c70Snonaka for (ant = 0; ant < 3; ant++) { 17179cdb1c70Snonaka if (sc->rssi_2ghz[ant] < -10 || sc->rssi_2ghz[ant] > 10) { 17189cdb1c70Snonaka DPRINTF(("invalid RSSI%d offset: %d (2GHz)\n", 17199cdb1c70Snonaka ant + 1, sc->rssi_2ghz[ant])); 17209cdb1c70Snonaka sc->rssi_2ghz[ant] = 0; 17219cdb1c70Snonaka } 17229cdb1c70Snonaka if (sc->rssi_5ghz[ant] < -10 || sc->rssi_5ghz[ant] > 10) { 17239cdb1c70Snonaka DPRINTF(("invalid RSSI%d offset: %d (5GHz)\n", 17249cdb1c70Snonaka ant + 1, sc->rssi_5ghz[ant])); 17259cdb1c70Snonaka sc->rssi_5ghz[ant] = 0; 17269cdb1c70Snonaka } 17279cdb1c70Snonaka } 17284e8e6643Sskrll return 0; 17299cdb1c70Snonaka } 17309cdb1c70Snonaka 17319cdb1c70Snonaka static struct ieee80211_node * 17329cdb1c70Snonaka run_node_alloc(struct ieee80211_node_table *nt) 17339cdb1c70Snonaka { 17349cdb1c70Snonaka struct run_node *rn = 17359cdb1c70Snonaka malloc(sizeof(struct run_node), M_DEVBUF, M_NOWAIT | M_ZERO); 17364e8e6643Sskrll return rn ? &rn->ni : NULL; 17379cdb1c70Snonaka } 17389cdb1c70Snonaka 17399cdb1c70Snonaka static int 17409cdb1c70Snonaka run_media_change(struct ifnet *ifp) 17419cdb1c70Snonaka { 17429cdb1c70Snonaka struct run_softc *sc = ifp->if_softc; 17439cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 17449cdb1c70Snonaka uint8_t rate, ridx; 17459cdb1c70Snonaka int error; 17469cdb1c70Snonaka 17479cdb1c70Snonaka error = ieee80211_media_change(ifp); 17489cdb1c70Snonaka if (error != ENETRESET) 17494e8e6643Sskrll return error; 17509cdb1c70Snonaka 17519cdb1c70Snonaka if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) { 17529cdb1c70Snonaka rate = ic->ic_sup_rates[ic->ic_curmode]. 17539cdb1c70Snonaka rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL; 17549cdb1c70Snonaka for (ridx = 0; ridx <= RT2860_RIDX_MAX; ridx++) 17559cdb1c70Snonaka if (rt2860_rates[ridx].rate == rate) 17569cdb1c70Snonaka break; 17579cdb1c70Snonaka sc->fixed_ridx = ridx; 17589cdb1c70Snonaka } 17599cdb1c70Snonaka 17609cdb1c70Snonaka if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) 17619cdb1c70Snonaka run_init(ifp); 17629cdb1c70Snonaka 17634e8e6643Sskrll return 0; 17649cdb1c70Snonaka } 17659cdb1c70Snonaka 17669cdb1c70Snonaka static void 17679cdb1c70Snonaka run_next_scan(void *arg) 17689cdb1c70Snonaka { 17699cdb1c70Snonaka struct run_softc *sc = arg; 17709cdb1c70Snonaka 17719cdb1c70Snonaka if (sc->sc_ic.ic_state == IEEE80211_S_SCAN) 17729cdb1c70Snonaka ieee80211_next_scan(&sc->sc_ic); 17739cdb1c70Snonaka } 17749cdb1c70Snonaka 17759cdb1c70Snonaka static void 17769cdb1c70Snonaka run_task(void *arg) 17779cdb1c70Snonaka { 17789cdb1c70Snonaka struct run_softc *sc = arg; 17799cdb1c70Snonaka struct run_host_cmd_ring *ring = &sc->cmdq; 17809cdb1c70Snonaka struct run_host_cmd *cmd; 17819cdb1c70Snonaka int s; 17829cdb1c70Snonaka 17839cdb1c70Snonaka /* process host commands */ 17849cdb1c70Snonaka s = splusb(); 17859cdb1c70Snonaka while (ring->next != ring->cur) { 17869cdb1c70Snonaka cmd = &ring->cmd[ring->next]; 17879cdb1c70Snonaka splx(s); 1788*90e85cecSmlelstv membar_consumer(); 17899cdb1c70Snonaka /* callback */ 17909cdb1c70Snonaka cmd->cb(sc, cmd->data); 17919cdb1c70Snonaka s = splusb(); 1792*90e85cecSmlelstv atomic_dec_uint(&ring->queued); 17939cdb1c70Snonaka ring->next = (ring->next + 1) % RUN_HOST_CMD_RING_COUNT; 17949cdb1c70Snonaka } 17959cdb1c70Snonaka wakeup(ring); 17969cdb1c70Snonaka splx(s); 17979cdb1c70Snonaka } 17989cdb1c70Snonaka 17999cdb1c70Snonaka static void 18009cdb1c70Snonaka run_do_async(struct run_softc *sc, void (*cb)(struct run_softc *, void *), 18019cdb1c70Snonaka void *arg, int len) 18029cdb1c70Snonaka { 18039cdb1c70Snonaka struct run_host_cmd_ring *ring = &sc->cmdq; 18049cdb1c70Snonaka struct run_host_cmd *cmd; 18059cdb1c70Snonaka int s; 18069cdb1c70Snonaka 18079cdb1c70Snonaka if (sc->sc_flags & RUN_DETACHING) 18089cdb1c70Snonaka return; 18099cdb1c70Snonaka 18109cdb1c70Snonaka s = splusb(); 18119cdb1c70Snonaka cmd = &ring->cmd[ring->cur]; 18129cdb1c70Snonaka cmd->cb = cb; 18139cdb1c70Snonaka KASSERT(len <= sizeof(cmd->data)); 18149cdb1c70Snonaka memcpy(cmd->data, arg, len); 1815*90e85cecSmlelstv membar_producer(); 18169cdb1c70Snonaka ring->cur = (ring->cur + 1) % RUN_HOST_CMD_RING_COUNT; 18179cdb1c70Snonaka 18189cdb1c70Snonaka /* if there is no pending command already, schedule a task */ 1819*90e85cecSmlelstv if (atomic_inc_uint_nv(&ring->queued) == 1) 18209cdb1c70Snonaka usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER); 18219cdb1c70Snonaka splx(s); 18229cdb1c70Snonaka } 18239cdb1c70Snonaka 18249cdb1c70Snonaka static int 18259cdb1c70Snonaka run_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 18269cdb1c70Snonaka { 18279cdb1c70Snonaka struct run_softc *sc = ic->ic_ifp->if_softc; 18289cdb1c70Snonaka struct run_cmd_newstate cmd; 18299cdb1c70Snonaka 18309cdb1c70Snonaka callout_stop(&sc->scan_to); 18319cdb1c70Snonaka callout_stop(&sc->calib_to); 18329cdb1c70Snonaka 18339cdb1c70Snonaka /* do it in a process context */ 18349cdb1c70Snonaka cmd.state = nstate; 18359cdb1c70Snonaka cmd.arg = arg; 18364e8e6643Sskrll run_do_async(sc, run_newstate_cb, &cmd, sizeof(cmd)); 18374e8e6643Sskrll return 0; 18389cdb1c70Snonaka } 18399cdb1c70Snonaka 18409cdb1c70Snonaka static void 18419cdb1c70Snonaka run_newstate_cb(struct run_softc *sc, void *arg) 18429cdb1c70Snonaka { 18439cdb1c70Snonaka struct run_cmd_newstate *cmd = arg; 18449cdb1c70Snonaka struct ifnet *ifp = &sc->sc_if; 18459cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 18469cdb1c70Snonaka enum ieee80211_state ostate; 18479cdb1c70Snonaka struct ieee80211_node *ni; 18489cdb1c70Snonaka uint32_t tmp, sta[3]; 18499cdb1c70Snonaka uint8_t wcid; 18509cdb1c70Snonaka int s; 18519cdb1c70Snonaka 18529cdb1c70Snonaka s = splnet(); 18539cdb1c70Snonaka ostate = ic->ic_state; 18549cdb1c70Snonaka 18559cdb1c70Snonaka if (ostate == IEEE80211_S_RUN) { 18569cdb1c70Snonaka /* turn link LED off */ 18579cdb1c70Snonaka run_set_leds(sc, RT2860_LED_RADIO); 18589cdb1c70Snonaka } 18599cdb1c70Snonaka 18609cdb1c70Snonaka switch (cmd->state) { 18619cdb1c70Snonaka case IEEE80211_S_INIT: 18629cdb1c70Snonaka if (ostate == IEEE80211_S_RUN) { 18639cdb1c70Snonaka /* abort TSF synchronization */ 18649cdb1c70Snonaka run_read(sc, RT2860_BCN_TIME_CFG, &tmp); 18659cdb1c70Snonaka run_write(sc, RT2860_BCN_TIME_CFG, 18669cdb1c70Snonaka tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | 18679cdb1c70Snonaka RT2860_TBTT_TIMER_EN)); 18689cdb1c70Snonaka } 18699cdb1c70Snonaka break; 18709cdb1c70Snonaka 18719cdb1c70Snonaka case IEEE80211_S_SCAN: 18729cdb1c70Snonaka run_set_chan(sc, ic->ic_curchan); 18739cdb1c70Snonaka callout_schedule(&sc->scan_to, hz / 5); 18749cdb1c70Snonaka break; 18759cdb1c70Snonaka 18769cdb1c70Snonaka case IEEE80211_S_AUTH: 18779cdb1c70Snonaka case IEEE80211_S_ASSOC: 18789cdb1c70Snonaka run_set_chan(sc, ic->ic_curchan); 18799cdb1c70Snonaka break; 18809cdb1c70Snonaka 18819cdb1c70Snonaka case IEEE80211_S_RUN: 18829cdb1c70Snonaka run_set_chan(sc, ic->ic_curchan); 18839cdb1c70Snonaka 18849cdb1c70Snonaka ni = ic->ic_bss; 18859cdb1c70Snonaka 18869cdb1c70Snonaka if (ic->ic_opmode != IEEE80211_M_MONITOR) { 18879cdb1c70Snonaka run_updateslot(ifp); 18889cdb1c70Snonaka run_enable_mrr(sc); 18899cdb1c70Snonaka run_set_txpreamble(sc); 18909cdb1c70Snonaka run_set_basicrates(sc); 18919cdb1c70Snonaka run_set_bssid(sc, ni->ni_bssid); 18929cdb1c70Snonaka } 18939cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY 18949cdb1c70Snonaka if (ic->ic_opmode == IEEE80211_M_HOSTAP || 18959cdb1c70Snonaka ic->ic_opmode == IEEE80211_M_IBSS) 18969cdb1c70Snonaka (void)run_setup_beacon(sc); 18979cdb1c70Snonaka #endif 18989cdb1c70Snonaka if (ic->ic_opmode == IEEE80211_M_STA) { 18999cdb1c70Snonaka /* add BSS entry to the WCID table */ 19009cdb1c70Snonaka wcid = RUN_AID2WCID(ni->ni_associd); 19019cdb1c70Snonaka run_write_region_1(sc, RT2860_WCID_ENTRY(wcid), 19029cdb1c70Snonaka ni->ni_macaddr, IEEE80211_ADDR_LEN); 19039cdb1c70Snonaka 19049cdb1c70Snonaka /* fake a join to init the tx rate */ 19059cdb1c70Snonaka run_newassoc(ni, 1); 19069cdb1c70Snonaka } 19079cdb1c70Snonaka if (ic->ic_opmode != IEEE80211_M_MONITOR) { 19089cdb1c70Snonaka run_enable_tsf_sync(sc); 19099cdb1c70Snonaka 19109cdb1c70Snonaka /* clear statistic registers used by AMRR */ 19119cdb1c70Snonaka run_read_region_1(sc, RT2860_TX_STA_CNT0, 19124e8e6643Sskrll (uint8_t *)sta, sizeof(sta)); 19139cdb1c70Snonaka /* start calibration timer */ 19149cdb1c70Snonaka callout_schedule(&sc->calib_to, hz); 19159cdb1c70Snonaka } 19169cdb1c70Snonaka 19179cdb1c70Snonaka /* turn link LED on */ 19189cdb1c70Snonaka run_set_leds(sc, RT2860_LED_RADIO | 19199cdb1c70Snonaka (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 19209cdb1c70Snonaka RT2860_LED_LINK_2GHZ : RT2860_LED_LINK_5GHZ)); 19219cdb1c70Snonaka break; 19229cdb1c70Snonaka } 19239cdb1c70Snonaka (void)sc->sc_newstate(ic, cmd->state, cmd->arg); 19249cdb1c70Snonaka splx(s); 19259cdb1c70Snonaka } 19269cdb1c70Snonaka 19279cdb1c70Snonaka static int 19289cdb1c70Snonaka run_updateedca(struct ieee80211com *ic) 19299cdb1c70Snonaka { 19309cdb1c70Snonaka 19319cdb1c70Snonaka /* do it in a process context */ 19329cdb1c70Snonaka run_do_async(ic->ic_ifp->if_softc, run_updateedca_cb, NULL, 0); 19334e8e6643Sskrll return 0; 19349cdb1c70Snonaka } 19359cdb1c70Snonaka 19369cdb1c70Snonaka /* ARGSUSED */ 19379cdb1c70Snonaka static void 19389cdb1c70Snonaka run_updateedca_cb(struct run_softc *sc, void *arg) 19399cdb1c70Snonaka { 19409cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 19419cdb1c70Snonaka int s, aci; 19429cdb1c70Snonaka 19439cdb1c70Snonaka s = splnet(); 19449cdb1c70Snonaka /* update MAC TX configuration registers */ 19459cdb1c70Snonaka for (aci = 0; aci < WME_NUM_AC; aci++) { 19469cdb1c70Snonaka run_write(sc, RT2860_EDCA_AC_CFG(aci), 19479cdb1c70Snonaka ic->ic_wme.wme_params[aci].wmep_logcwmax << 16 | 19489cdb1c70Snonaka ic->ic_wme.wme_params[aci].wmep_logcwmin << 12 | 19499cdb1c70Snonaka ic->ic_wme.wme_params[aci].wmep_aifsn << 8 | 19509cdb1c70Snonaka ic->ic_wme.wme_params[aci].wmep_txopLimit); 19519cdb1c70Snonaka } 19529cdb1c70Snonaka 19539cdb1c70Snonaka /* update SCH/DMA registers too */ 19549cdb1c70Snonaka run_write(sc, RT2860_WMM_AIFSN_CFG, 19559cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VO].wmep_aifsn << 12 | 19569cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VI].wmep_aifsn << 8 | 19579cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BK].wmep_aifsn << 4 | 19589cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BE].wmep_aifsn); 19599cdb1c70Snonaka run_write(sc, RT2860_WMM_CWMIN_CFG, 19609cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VO].wmep_logcwmin << 12 | 19619cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VI].wmep_logcwmin << 8 | 19629cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BK].wmep_logcwmin << 4 | 19639cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BE].wmep_logcwmin); 19649cdb1c70Snonaka run_write(sc, RT2860_WMM_CWMAX_CFG, 19659cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VO].wmep_logcwmax << 12 | 19669cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VI].wmep_logcwmax << 8 | 19679cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BK].wmep_logcwmax << 4 | 19689cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BE].wmep_logcwmax); 19699cdb1c70Snonaka run_write(sc, RT2860_WMM_TXOP0_CFG, 19709cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BK].wmep_txopLimit << 16 | 19719cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_BE].wmep_txopLimit); 19729cdb1c70Snonaka run_write(sc, RT2860_WMM_TXOP1_CFG, 19739cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VO].wmep_txopLimit << 16 | 19749cdb1c70Snonaka ic->ic_wme.wme_params[WME_AC_VI].wmep_txopLimit); 19759cdb1c70Snonaka splx(s); 19769cdb1c70Snonaka } 19779cdb1c70Snonaka 19789cdb1c70Snonaka #ifdef RUN_HWCRYPTO 19799cdb1c70Snonaka static int 19809cdb1c70Snonaka run_set_key(struct ieee80211com *ic, const struct ieee80211_key *k, 19819cdb1c70Snonaka const uint8_t *mac) 19829cdb1c70Snonaka { 19839cdb1c70Snonaka struct run_softc *sc = ic->ic_ifp->if_softc; 19849cdb1c70Snonaka struct ieee80211_node *ni = ic->ic_bss; 19859cdb1c70Snonaka struct run_cmd_key cmd; 19869cdb1c70Snonaka 19879cdb1c70Snonaka /* do it in a process context */ 19889cdb1c70Snonaka cmd.key = *k; 19899cdb1c70Snonaka cmd.associd = (ni != NULL) ? ni->ni_associd : 0; 19904e8e6643Sskrll run_do_async(sc, run_set_key_cb, &cmd, sizeof(cmd)); 19919cdb1c70Snonaka return 1; 19929cdb1c70Snonaka } 19939cdb1c70Snonaka 19949cdb1c70Snonaka static void 19959cdb1c70Snonaka run_set_key_cb(struct run_softc *sc, void *arg) 19969cdb1c70Snonaka { 19979cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY 19989cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 19999cdb1c70Snonaka #endif 20009cdb1c70Snonaka struct run_cmd_key *cmd = arg; 20019cdb1c70Snonaka struct ieee80211_key *k = &cmd->key; 20029cdb1c70Snonaka uint32_t attr; 20039cdb1c70Snonaka uint16_t base; 20049cdb1c70Snonaka uint8_t mode, wcid, iv[8]; 20059cdb1c70Snonaka 20069cdb1c70Snonaka /* map net80211 cipher to RT2860 security mode */ 20079cdb1c70Snonaka switch (k->wk_cipher->ic_cipher) { 20089cdb1c70Snonaka case IEEE80211_CIPHER_WEP: 20099cdb1c70Snonaka k->wk_flags |= IEEE80211_KEY_GROUP; /* XXX */ 20109cdb1c70Snonaka if (k->wk_keylen == 5) 20119cdb1c70Snonaka mode = RT2860_MODE_WEP40; 20129cdb1c70Snonaka else 20139cdb1c70Snonaka mode = RT2860_MODE_WEP104; 20149cdb1c70Snonaka break; 20159cdb1c70Snonaka case IEEE80211_CIPHER_TKIP: 20169cdb1c70Snonaka mode = RT2860_MODE_TKIP; 20179cdb1c70Snonaka break; 20189cdb1c70Snonaka case IEEE80211_CIPHER_AES_CCM: 20199cdb1c70Snonaka mode = RT2860_MODE_AES_CCMP; 20209cdb1c70Snonaka break; 20219cdb1c70Snonaka default: 20229cdb1c70Snonaka return; 20239cdb1c70Snonaka } 20249cdb1c70Snonaka 20259cdb1c70Snonaka if (k->wk_flags & IEEE80211_KEY_GROUP) { 20269cdb1c70Snonaka wcid = 0; /* NB: update WCID0 for group keys */ 20279cdb1c70Snonaka base = RT2860_SKEY(0, k->wk_keyix); 20289cdb1c70Snonaka } else { 20299cdb1c70Snonaka wcid = RUN_AID2WCID(cmd->associd); 20309cdb1c70Snonaka base = RT2860_PKEY(wcid); 20319cdb1c70Snonaka } 20329cdb1c70Snonaka 20339cdb1c70Snonaka if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) { 20349cdb1c70Snonaka run_write_region_1(sc, base, k->wk_key, 16); 20359cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY 20369cdb1c70Snonaka if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 20379cdb1c70Snonaka run_write_region_1(sc, base + 16, &k->wk_key[16], 8); 20389cdb1c70Snonaka run_write_region_1(sc, base + 24, &k->wk_key[24], 8); 20399cdb1c70Snonaka } else 20409cdb1c70Snonaka #endif 20419cdb1c70Snonaka { 20429cdb1c70Snonaka run_write_region_1(sc, base + 16, &k->wk_key[24], 8); 20439cdb1c70Snonaka run_write_region_1(sc, base + 24, &k->wk_key[16], 8); 20449cdb1c70Snonaka } 20459cdb1c70Snonaka } else { 20469cdb1c70Snonaka /* roundup len to 16-bit: XXX fix write_region_1() instead */ 20479cdb1c70Snonaka run_write_region_1(sc, base, k->wk_key, 20489cdb1c70Snonaka (k->wk_keylen + 1) & ~1); 20499cdb1c70Snonaka } 20509cdb1c70Snonaka 20519cdb1c70Snonaka if (!(k->wk_flags & IEEE80211_KEY_GROUP) || 20529cdb1c70Snonaka (k->wk_flags & IEEE80211_KEY_XMIT)) { 20539cdb1c70Snonaka /* set initial packet number in IV+EIV */ 20549cdb1c70Snonaka if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_WEP) { 20554e8e6643Sskrll memset(iv, 0, sizeof(iv)); 20569cdb1c70Snonaka iv[3] = sc->sc_ic.ic_crypto.cs_def_txkey << 6; 20579cdb1c70Snonaka } else { 20589cdb1c70Snonaka if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) { 20599cdb1c70Snonaka iv[0] = k->wk_keytsc >> 8; 20609cdb1c70Snonaka iv[1] = (iv[0] | 0x20) & 0x7f; 20619cdb1c70Snonaka iv[2] = k->wk_keytsc; 20629cdb1c70Snonaka } else /* CCMP */ { 20639cdb1c70Snonaka iv[0] = k->wk_keytsc; 20649cdb1c70Snonaka iv[1] = k->wk_keytsc >> 8; 20659cdb1c70Snonaka iv[2] = 0; 20669cdb1c70Snonaka } 20679cdb1c70Snonaka iv[3] = k->wk_keyix << 6 | IEEE80211_WEP_EXTIV; 20689cdb1c70Snonaka iv[4] = k->wk_keytsc >> 16; 20699cdb1c70Snonaka iv[5] = k->wk_keytsc >> 24; 20709cdb1c70Snonaka iv[6] = k->wk_keytsc >> 32; 20719cdb1c70Snonaka iv[7] = k->wk_keytsc >> 40; 20729cdb1c70Snonaka } 20739cdb1c70Snonaka run_write_region_1(sc, RT2860_IVEIV(wcid), iv, 8); 20749cdb1c70Snonaka } 20759cdb1c70Snonaka 20769cdb1c70Snonaka if (k->wk_flags & IEEE80211_KEY_GROUP) { 20779cdb1c70Snonaka /* install group key */ 20789cdb1c70Snonaka run_read(sc, RT2860_SKEY_MODE_0_7, &attr); 20799cdb1c70Snonaka attr &= ~(0xf << (k->wk_keyix * 4)); 20809cdb1c70Snonaka attr |= mode << (k->wk_keyix * 4); 20819cdb1c70Snonaka run_write(sc, RT2860_SKEY_MODE_0_7, attr); 20829cdb1c70Snonaka } else { 20839cdb1c70Snonaka /* install pairwise key */ 20849cdb1c70Snonaka run_read(sc, RT2860_WCID_ATTR(wcid), &attr); 20859cdb1c70Snonaka attr = (attr & ~0xf) | (mode << 1) | RT2860_RX_PKEY_EN; 20869cdb1c70Snonaka run_write(sc, RT2860_WCID_ATTR(wcid), attr); 20879cdb1c70Snonaka } 20889cdb1c70Snonaka } 20899cdb1c70Snonaka 20909cdb1c70Snonaka static int 20919cdb1c70Snonaka run_delete_key(struct ieee80211com *ic, const struct ieee80211_key *k) 20929cdb1c70Snonaka { 20939cdb1c70Snonaka struct run_softc *sc = ic->ic_ifp->if_softc; 20949cdb1c70Snonaka struct ieee80211_node *ni = ic->ic_bss; 20959cdb1c70Snonaka struct run_cmd_key cmd; 20969cdb1c70Snonaka 20979cdb1c70Snonaka /* do it in a process context */ 20989cdb1c70Snonaka cmd.key = *k; 20999cdb1c70Snonaka cmd.associd = (ni != NULL) ? ni->ni_associd : 0; 21004e8e6643Sskrll run_do_async(sc, run_delete_key_cb, &cmd, sizeof(cmd)); 21019cdb1c70Snonaka return 1; 21029cdb1c70Snonaka } 21039cdb1c70Snonaka 21049cdb1c70Snonaka static void 21059cdb1c70Snonaka run_delete_key_cb(struct run_softc *sc, void *arg) 21069cdb1c70Snonaka { 21079cdb1c70Snonaka struct run_cmd_key *cmd = arg; 21089cdb1c70Snonaka struct ieee80211_key *k = &cmd->key; 21099cdb1c70Snonaka uint32_t attr; 21109cdb1c70Snonaka uint8_t wcid; 21119cdb1c70Snonaka 21129cdb1c70Snonaka if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_WEP) 21139cdb1c70Snonaka k->wk_flags |= IEEE80211_KEY_GROUP; /* XXX */ 21149cdb1c70Snonaka 21159cdb1c70Snonaka if (k->wk_flags & IEEE80211_KEY_GROUP) { 21169cdb1c70Snonaka /* remove group key */ 21179cdb1c70Snonaka run_read(sc, RT2860_SKEY_MODE_0_7, &attr); 21189cdb1c70Snonaka attr &= ~(0xf << (k->wk_keyix * 4)); 21199cdb1c70Snonaka run_write(sc, RT2860_SKEY_MODE_0_7, attr); 21209cdb1c70Snonaka 21219cdb1c70Snonaka } else { 21229cdb1c70Snonaka /* remove pairwise key */ 21239cdb1c70Snonaka wcid = RUN_AID2WCID(cmd->associd); 21249cdb1c70Snonaka run_read(sc, RT2860_WCID_ATTR(wcid), &attr); 21259cdb1c70Snonaka attr &= ~0xf; 21269cdb1c70Snonaka run_write(sc, RT2860_WCID_ATTR(wcid), attr); 21279cdb1c70Snonaka } 21289cdb1c70Snonaka } 21299cdb1c70Snonaka #endif 21309cdb1c70Snonaka 21319cdb1c70Snonaka static void 21329cdb1c70Snonaka run_calibrate_to(void *arg) 21339cdb1c70Snonaka { 21349cdb1c70Snonaka 21359cdb1c70Snonaka /* do it in a process context */ 21369cdb1c70Snonaka run_do_async(arg, run_calibrate_cb, NULL, 0); 21379cdb1c70Snonaka /* next timeout will be rescheduled in the calibration task */ 21389cdb1c70Snonaka } 21399cdb1c70Snonaka 21409cdb1c70Snonaka /* ARGSUSED */ 21419cdb1c70Snonaka static void 21429cdb1c70Snonaka run_calibrate_cb(struct run_softc *sc, void *arg) 21439cdb1c70Snonaka { 21449cdb1c70Snonaka struct ifnet *ifp = &sc->sc_if; 21459cdb1c70Snonaka uint32_t sta[3]; 21469cdb1c70Snonaka int s, error; 21479cdb1c70Snonaka 21489cdb1c70Snonaka /* read statistic counters (clear on read) and update AMRR state */ 21499cdb1c70Snonaka error = run_read_region_1(sc, RT2860_TX_STA_CNT0, (uint8_t *)sta, 21504e8e6643Sskrll sizeof(sta)); 21519cdb1c70Snonaka if (error != 0) 21529cdb1c70Snonaka goto skip; 21539cdb1c70Snonaka 21549cdb1c70Snonaka DPRINTF(("retrycnt=%d txcnt=%d failcnt=%d\n", 21559cdb1c70Snonaka le32toh(sta[1]) >> 16, le32toh(sta[1]) & 0xffff, 21569cdb1c70Snonaka le32toh(sta[0]) & 0xffff)); 21579cdb1c70Snonaka 21589cdb1c70Snonaka s = splnet(); 21599cdb1c70Snonaka /* count failed TX as errors */ 21609cdb1c70Snonaka ifp->if_oerrors += le32toh(sta[0]) & 0xffff; 21619cdb1c70Snonaka 21629cdb1c70Snonaka sc->amn.amn_retrycnt = 21639cdb1c70Snonaka (le32toh(sta[0]) & 0xffff) + /* failed TX count */ 21649cdb1c70Snonaka (le32toh(sta[1]) >> 16); /* TX retransmission count */ 21659cdb1c70Snonaka 21669cdb1c70Snonaka sc->amn.amn_txcnt = 21679cdb1c70Snonaka sc->amn.amn_retrycnt + 21689cdb1c70Snonaka (le32toh(sta[1]) & 0xffff); /* successful TX count */ 21699cdb1c70Snonaka 21709cdb1c70Snonaka ieee80211_amrr_choose(&sc->amrr, sc->sc_ic.ic_bss, &sc->amn); 21719cdb1c70Snonaka splx(s); 21729cdb1c70Snonaka 21739cdb1c70Snonaka skip: callout_schedule(&sc->calib_to, hz); 21749cdb1c70Snonaka } 21759cdb1c70Snonaka 21769cdb1c70Snonaka static void 21779cdb1c70Snonaka run_newassoc(struct ieee80211_node *ni, int isnew) 21789cdb1c70Snonaka { 21799cdb1c70Snonaka struct run_softc *sc = ni->ni_ic->ic_ifp->if_softc; 21809cdb1c70Snonaka struct run_node *rn = (void *)ni; 21819cdb1c70Snonaka struct ieee80211_rateset *rs = &ni->ni_rates; 21829cdb1c70Snonaka uint8_t rate; 21839cdb1c70Snonaka int ridx, i, j; 21849cdb1c70Snonaka 21859cdb1c70Snonaka DPRINTF(("new assoc isnew=%d addr=%s\n", 21869cdb1c70Snonaka isnew, ether_sprintf(ni->ni_macaddr))); 21879cdb1c70Snonaka 21889cdb1c70Snonaka ieee80211_amrr_node_init(&sc->amrr, &sc->amn); 21899cdb1c70Snonaka /* start at lowest available bit-rate, AMRR will raise */ 21909cdb1c70Snonaka ni->ni_txrate = 0; 21919cdb1c70Snonaka 21929cdb1c70Snonaka for (i = 0; i < rs->rs_nrates; i++) { 21939cdb1c70Snonaka rate = rs->rs_rates[i] & IEEE80211_RATE_VAL; 21949cdb1c70Snonaka /* convert 802.11 rate to hardware rate index */ 21959cdb1c70Snonaka for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) 21969cdb1c70Snonaka if (rt2860_rates[ridx].rate == rate) 21979cdb1c70Snonaka break; 21989cdb1c70Snonaka rn->ridx[i] = ridx; 21999cdb1c70Snonaka /* determine rate of control response frames */ 22009cdb1c70Snonaka for (j = i; j >= 0; j--) { 22019cdb1c70Snonaka if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC) && 22029cdb1c70Snonaka rt2860_rates[rn->ridx[i]].phy == 22039cdb1c70Snonaka rt2860_rates[rn->ridx[j]].phy) 22049cdb1c70Snonaka break; 22059cdb1c70Snonaka } 22069cdb1c70Snonaka if (j >= 0) { 22079cdb1c70Snonaka rn->ctl_ridx[i] = rn->ridx[j]; 22089cdb1c70Snonaka } else { 22099cdb1c70Snonaka /* no basic rate found, use mandatory one */ 22109cdb1c70Snonaka rn->ctl_ridx[i] = rt2860_rates[ridx].ctl_ridx; 22119cdb1c70Snonaka } 22129cdb1c70Snonaka DPRINTF(("rate=0x%02x ridx=%d ctl_ridx=%d\n", 22139cdb1c70Snonaka rs->rs_rates[i], rn->ridx[i], rn->ctl_ridx[i])); 22149cdb1c70Snonaka } 22159cdb1c70Snonaka } 22169cdb1c70Snonaka 22179cdb1c70Snonaka /* 22189cdb1c70Snonaka * Return the Rx chain with the highest RSSI for a given frame. 22199cdb1c70Snonaka */ 22209cdb1c70Snonaka static __inline uint8_t 22219cdb1c70Snonaka run_maxrssi_chain(struct run_softc *sc, const struct rt2860_rxwi *rxwi) 22229cdb1c70Snonaka { 22239cdb1c70Snonaka uint8_t rxchain = 0; 22249cdb1c70Snonaka 22259cdb1c70Snonaka if (sc->nrxchains > 1) { 22269cdb1c70Snonaka if (rxwi->rssi[1] > rxwi->rssi[rxchain]) 22279cdb1c70Snonaka rxchain = 1; 22289cdb1c70Snonaka if (sc->nrxchains > 2) 22299cdb1c70Snonaka if (rxwi->rssi[2] > rxwi->rssi[rxchain]) 22309cdb1c70Snonaka rxchain = 2; 22319cdb1c70Snonaka } 22324e8e6643Sskrll return rxchain; 22339cdb1c70Snonaka } 22349cdb1c70Snonaka 22359cdb1c70Snonaka static void 22369cdb1c70Snonaka run_rx_frame(struct run_softc *sc, uint8_t *buf, int dmalen) 22379cdb1c70Snonaka { 22389cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 22399cdb1c70Snonaka struct ifnet *ifp = &sc->sc_if; 22409cdb1c70Snonaka struct ieee80211_frame *wh; 22419cdb1c70Snonaka struct ieee80211_node *ni; 22429cdb1c70Snonaka struct rt2870_rxd *rxd; 22439cdb1c70Snonaka struct rt2860_rxwi *rxwi; 22449cdb1c70Snonaka struct mbuf *m; 22459cdb1c70Snonaka uint32_t flags; 2246faca41fbSmlelstv uint16_t len, rxwisize, phy; 22479cdb1c70Snonaka uint8_t ant, rssi; 22489cdb1c70Snonaka int s; 22499cdb1c70Snonaka #ifdef RUN_HWCRYPTO 22509cdb1c70Snonaka int decrypted = 0; 22519cdb1c70Snonaka #endif 22529cdb1c70Snonaka 22539cdb1c70Snonaka rxwi = (struct rt2860_rxwi *)buf; 2254d164e220Smlelstv rxwisize = sizeof(struct rt2860_rxwi); 2255d164e220Smlelstv if (sc->mac_ver == 0x5592) 2256d164e220Smlelstv rxwisize += sizeof(uint64_t); 2257d164e220Smlelstv else if (sc->mac_ver == 0x3593) 2258d164e220Smlelstv rxwisize += sizeof(uint32_t); 22599cdb1c70Snonaka len = le16toh(rxwi->len) & 0xfff; 22609cdb1c70Snonaka if (__predict_false(len > dmalen)) { 22619cdb1c70Snonaka DPRINTF(("bad RXWI length %u > %u\n", len, dmalen)); 22629cdb1c70Snonaka return; 22639cdb1c70Snonaka } 22649cdb1c70Snonaka /* Rx descriptor is located at the end */ 22659cdb1c70Snonaka rxd = (struct rt2870_rxd *)(buf + dmalen); 22669cdb1c70Snonaka flags = le32toh(rxd->flags); 22679cdb1c70Snonaka 22689cdb1c70Snonaka if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { 22699cdb1c70Snonaka ifp->if_ierrors++; 22709cdb1c70Snonaka return; 22719cdb1c70Snonaka } 22729cdb1c70Snonaka 2273d164e220Smlelstv wh = (struct ieee80211_frame *)(buf + rxwisize); 22749cdb1c70Snonaka 22759cdb1c70Snonaka if (__predict_false((flags & RT2860_RX_MICERR))) { 22769cdb1c70Snonaka /* report MIC failures to net80211 for TKIP */ 22779cdb1c70Snonaka ieee80211_notify_michael_failure(ic, wh, 0/* XXX */); 22789cdb1c70Snonaka ifp->if_ierrors++; 22799cdb1c70Snonaka return; 22809cdb1c70Snonaka } 22819cdb1c70Snonaka 22829cdb1c70Snonaka if (flags & RT2860_RX_L2PAD) { 22839cdb1c70Snonaka u_int hdrlen = ieee80211_hdrspace(ic, wh); 2284ef294642Smaxv memmove((uint8_t *)wh + 2, wh, hdrlen); 22859cdb1c70Snonaka wh = (struct ieee80211_frame *)((uint8_t *)wh + 2); 22869cdb1c70Snonaka } 22879cdb1c70Snonaka 2288d164e220Smlelstv #ifdef RUN_HWCRYPTO 2289d164e220Smlelstv if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 2290d164e220Smlelstv wh->i_fc[1] &= ~IEEE80211_FC1_WEP; 2291d164e220Smlelstv decrypted = 1; 2292d164e220Smlelstv } 2293d164e220Smlelstv #endif 2294d164e220Smlelstv 22959cdb1c70Snonaka /* could use m_devget but net80211 wants contig mgmt frames */ 22969cdb1c70Snonaka MGETHDR(m, M_DONTWAIT, MT_DATA); 22979cdb1c70Snonaka if (__predict_false(m == NULL)) { 22989cdb1c70Snonaka ifp->if_ierrors++; 22999cdb1c70Snonaka return; 23009cdb1c70Snonaka } 23019cdb1c70Snonaka if (len > MHLEN) { 23029cdb1c70Snonaka MCLGET(m, M_DONTWAIT); 23039cdb1c70Snonaka if (__predict_false(!(m->m_flags & M_EXT))) { 23049cdb1c70Snonaka ifp->if_ierrors++; 23059cdb1c70Snonaka m_freem(m); 23069cdb1c70Snonaka return; 23079cdb1c70Snonaka } 23089cdb1c70Snonaka } 23099cdb1c70Snonaka /* finalize mbuf */ 2310d938d837Sozaki-r m_set_rcvif(m, ifp); 23119cdb1c70Snonaka memcpy(mtod(m, void *), wh, len); 23129cdb1c70Snonaka m->m_pkthdr.len = m->m_len = len; 23139cdb1c70Snonaka 23149cdb1c70Snonaka ant = run_maxrssi_chain(sc, rxwi); 23159cdb1c70Snonaka rssi = rxwi->rssi[ant]; 23169cdb1c70Snonaka 23179cdb1c70Snonaka if (__predict_false(sc->sc_drvbpf != NULL)) { 23189cdb1c70Snonaka struct run_rx_radiotap_header *tap = &sc->sc_rxtap; 23199cdb1c70Snonaka 23209cdb1c70Snonaka tap->wr_flags = 0; 23219cdb1c70Snonaka tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); 23229cdb1c70Snonaka tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); 23239cdb1c70Snonaka tap->wr_antsignal = rssi; 23249cdb1c70Snonaka tap->wr_antenna = ant; 23259cdb1c70Snonaka tap->wr_dbm_antsignal = run_rssi2dbm(sc, rssi, ant); 23269cdb1c70Snonaka tap->wr_rate = 2; /* in case it can't be found below */ 23279cdb1c70Snonaka phy = le16toh(rxwi->phy); 23289cdb1c70Snonaka switch (phy & RT2860_PHY_MODE) { 23299cdb1c70Snonaka case RT2860_PHY_CCK: 23309cdb1c70Snonaka switch ((phy & RT2860_PHY_MCS) & ~RT2860_PHY_SHPRE) { 23319cdb1c70Snonaka case 0: tap->wr_rate = 2; break; 23329cdb1c70Snonaka case 1: tap->wr_rate = 4; break; 23339cdb1c70Snonaka case 2: tap->wr_rate = 11; break; 23349cdb1c70Snonaka case 3: tap->wr_rate = 22; break; 23359cdb1c70Snonaka } 23369cdb1c70Snonaka if (phy & RT2860_PHY_SHPRE) 23379cdb1c70Snonaka tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; 23389cdb1c70Snonaka break; 23399cdb1c70Snonaka case RT2860_PHY_OFDM: 23409cdb1c70Snonaka switch (phy & RT2860_PHY_MCS) { 23419cdb1c70Snonaka case 0: tap->wr_rate = 12; break; 23429cdb1c70Snonaka case 1: tap->wr_rate = 18; break; 23439cdb1c70Snonaka case 2: tap->wr_rate = 24; break; 23449cdb1c70Snonaka case 3: tap->wr_rate = 36; break; 23459cdb1c70Snonaka case 4: tap->wr_rate = 48; break; 23469cdb1c70Snonaka case 5: tap->wr_rate = 72; break; 23479cdb1c70Snonaka case 6: tap->wr_rate = 96; break; 23489cdb1c70Snonaka case 7: tap->wr_rate = 108; break; 23499cdb1c70Snonaka } 23509cdb1c70Snonaka break; 23519cdb1c70Snonaka } 23523cd62456Smsaitoh bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m, BPF_D_IN); 23539cdb1c70Snonaka } 23549cdb1c70Snonaka 23559cdb1c70Snonaka s = splnet(); 23569cdb1c70Snonaka ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); 23579cdb1c70Snonaka #ifdef RUN_HWCRYPTO 23589cdb1c70Snonaka if (decrypted) { 23599cdb1c70Snonaka uint32_t icflags = ic->ic_flags; 23609cdb1c70Snonaka 23619cdb1c70Snonaka ic->ic_flags &= ~IEEE80211_F_DROPUNENC; /* XXX */ 23629cdb1c70Snonaka ieee80211_input(ic, m, ni, rssi, 0); 23639cdb1c70Snonaka ic->ic_flags = icflags; 23649cdb1c70Snonaka } else 23659cdb1c70Snonaka #endif 23669cdb1c70Snonaka ieee80211_input(ic, m, ni, rssi, 0); 23679cdb1c70Snonaka 23689cdb1c70Snonaka /* node is no longer needed */ 23699cdb1c70Snonaka ieee80211_free_node(ni); 23709cdb1c70Snonaka 23719cdb1c70Snonaka /* 23729cdb1c70Snonaka * In HostAP mode, ieee80211_input() will enqueue packets in if_snd 23739cdb1c70Snonaka * without calling if_start(). 23749cdb1c70Snonaka */ 23759cdb1c70Snonaka if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_flags & IFF_OACTIVE)) 23769cdb1c70Snonaka run_start(ifp); 23779cdb1c70Snonaka 23789cdb1c70Snonaka splx(s); 23799cdb1c70Snonaka } 23809cdb1c70Snonaka 23819cdb1c70Snonaka static void 23824e8e6643Sskrll run_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 23839cdb1c70Snonaka { 23849cdb1c70Snonaka struct run_rx_data *data = priv; 23859cdb1c70Snonaka struct run_softc *sc = data->sc; 23869cdb1c70Snonaka uint8_t *buf; 23879cdb1c70Snonaka uint32_t dmalen; 23889cdb1c70Snonaka int xferlen; 2389d164e220Smlelstv uint16_t rxwisize; 23909cdb1c70Snonaka 23918f96d6f5Smlelstv if (__predict_false(sc->sc_flags & RUN_DETACHING)) 23928f96d6f5Smlelstv return; 23938f96d6f5Smlelstv 2394d164e220Smlelstv rxwisize = sizeof(struct rt2860_rxwi); 2395d164e220Smlelstv if (sc->mac_ver == 0x5592) 2396d164e220Smlelstv rxwisize += sizeof(uint64_t); 2397d164e220Smlelstv else if (sc->mac_ver == 0x3593) 2398d164e220Smlelstv rxwisize += sizeof(uint32_t); 2399d164e220Smlelstv 24009cdb1c70Snonaka if (__predict_false(status != USBD_NORMAL_COMPLETION)) { 2401d164e220Smlelstv DPRINTF(("RX status=%s\n", usbd_errstr(status))); 24029cdb1c70Snonaka if (status == USBD_STALLED) 24039cdb1c70Snonaka usbd_clear_endpoint_stall_async(sc->rxq.pipeh); 24049cdb1c70Snonaka if (status != USBD_CANCELLED) 24059cdb1c70Snonaka goto skip; 24069cdb1c70Snonaka return; 24079cdb1c70Snonaka } 24089cdb1c70Snonaka usbd_get_xfer_status(xfer, NULL, NULL, &xferlen, NULL); 24099cdb1c70Snonaka 24109cdb1c70Snonaka if (__predict_false(xferlen < (int)(sizeof(uint32_t) + 2411d164e220Smlelstv rxwisize + sizeof(struct rt2870_rxd)))) { 24129cdb1c70Snonaka DPRINTF(("xfer too short %d\n", xferlen)); 24139cdb1c70Snonaka goto skip; 24149cdb1c70Snonaka } 24159cdb1c70Snonaka 24169cdb1c70Snonaka /* HW can aggregate multiple 802.11 frames in a single USB xfer */ 24179cdb1c70Snonaka buf = data->buf; 24189cdb1c70Snonaka while (xferlen > 8) { 24199cdb1c70Snonaka dmalen = le32toh(*(uint32_t *)buf) & 0xffff; 24209cdb1c70Snonaka 2421faca41fbSmlelstv if (__predict_false((dmalen >= (uint32_t)-8) || dmalen == 0 || 2422faca41fbSmlelstv (dmalen & 3) != 0)) { 24239cdb1c70Snonaka DPRINTF(("bad DMA length %u (%x)\n", dmalen, dmalen)); 24249cdb1c70Snonaka break; 24259cdb1c70Snonaka } 24269cdb1c70Snonaka if (__predict_false(dmalen + 8 > (uint32_t)xferlen)) { 24279cdb1c70Snonaka DPRINTF(("bad DMA length %u > %d\n", 24289cdb1c70Snonaka dmalen + 8, xferlen)); 24299cdb1c70Snonaka break; 24309cdb1c70Snonaka } 24319cdb1c70Snonaka run_rx_frame(sc, buf + sizeof(uint32_t), dmalen); 24329cdb1c70Snonaka buf += dmalen + 8; 24339cdb1c70Snonaka xferlen -= dmalen + 8; 24349cdb1c70Snonaka } 24359cdb1c70Snonaka 24369cdb1c70Snonaka skip: /* setup a new transfer */ 24374e8e6643Sskrll usbd_setup_xfer(xfer, data, data->buf, RUN_MAX_RXSZ, 24384e8e6643Sskrll USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, run_rxeof); 2439d164e220Smlelstv status = usbd_transfer(xfer); 2440d164e220Smlelstv if (status != USBD_NORMAL_COMPLETION && 2441d164e220Smlelstv status != USBD_IN_PROGRESS) 2442d164e220Smlelstv device_printf(sc->sc_dev, "requeuing rx failed: %s\n", 2443d164e220Smlelstv usbd_errstr(status)); 24449cdb1c70Snonaka } 24459cdb1c70Snonaka 24469cdb1c70Snonaka static void 24474e8e6643Sskrll run_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 24489cdb1c70Snonaka { 24499cdb1c70Snonaka struct run_tx_data *data = priv; 24509cdb1c70Snonaka struct run_softc *sc = data->sc; 24519cdb1c70Snonaka struct run_tx_ring *txq = &sc->txq[data->qid]; 24529cdb1c70Snonaka struct ifnet *ifp = &sc->sc_if; 24539cdb1c70Snonaka int s; 24549cdb1c70Snonaka 2455d164e220Smlelstv s = splnet(); 2456d164e220Smlelstv txq->queued--; 2457d164e220Smlelstv sc->qfullmsk &= ~(1 << data->qid); 2458d164e220Smlelstv 24599cdb1c70Snonaka if (__predict_false(status != USBD_NORMAL_COMPLETION)) { 2460d164e220Smlelstv if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 2461d164e220Smlelstv return; 2462d164e220Smlelstv 2463d164e220Smlelstv DPRINTF(("%s: usb error on tx: %s\n", 2464d164e220Smlelstv device_xname(sc->sc_dev), usbd_errstr(status))); 24659cdb1c70Snonaka if (status == USBD_STALLED) 24669cdb1c70Snonaka usbd_clear_endpoint_stall_async(txq->pipeh); 24679cdb1c70Snonaka ifp->if_oerrors++; 2468d164e220Smlelstv splx(s); 24699cdb1c70Snonaka return; 24709cdb1c70Snonaka } 24719cdb1c70Snonaka 24729cdb1c70Snonaka sc->sc_tx_timer = 0; 24739cdb1c70Snonaka ifp->if_opackets++; 24749cdb1c70Snonaka ifp->if_flags &= ~IFF_OACTIVE; 24759cdb1c70Snonaka run_start(ifp); 24769cdb1c70Snonaka splx(s); 24779cdb1c70Snonaka } 24789cdb1c70Snonaka 24799cdb1c70Snonaka static int 24809cdb1c70Snonaka run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) 24819cdb1c70Snonaka { 24829cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 24839cdb1c70Snonaka struct run_node *rn = (void *)ni; 24849cdb1c70Snonaka struct ieee80211_frame *wh; 24859cdb1c70Snonaka #ifndef RUN_HWCRYPTO 24869cdb1c70Snonaka struct ieee80211_key *k; 24879cdb1c70Snonaka #endif 24889cdb1c70Snonaka struct run_tx_ring *ring; 24899cdb1c70Snonaka struct run_tx_data *data; 24909cdb1c70Snonaka struct rt2870_txd *txd; 24919cdb1c70Snonaka struct rt2860_txwi *txwi; 2492d164e220Smlelstv uint16_t qos, dur, mcs; 2493d164e220Smlelstv uint16_t txwisize; 2494d164e220Smlelstv uint8_t type, tid, qid; 2495d164e220Smlelstv int hasqos, ridx, ctl_ridx, xferlen; 2496faca41fbSmlelstv uint8_t pad; 2497d164e220Smlelstv usbd_status status; 24989cdb1c70Snonaka 24999cdb1c70Snonaka wh = mtod(m, struct ieee80211_frame *); 25009cdb1c70Snonaka 25019cdb1c70Snonaka #ifndef RUN_HWCRYPTO 25029cdb1c70Snonaka if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 25039cdb1c70Snonaka k = ieee80211_crypto_encap(ic, ni, m); 25049cdb1c70Snonaka if (k == NULL) { 25059cdb1c70Snonaka m_freem(m); 25064e8e6643Sskrll return ENOBUFS; 25079cdb1c70Snonaka } 25089cdb1c70Snonaka 25099cdb1c70Snonaka /* packet header may have moved, reset our local pointer */ 25109cdb1c70Snonaka wh = mtod(m, struct ieee80211_frame *); 25119cdb1c70Snonaka } 25129cdb1c70Snonaka #endif 25139cdb1c70Snonaka type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 25149cdb1c70Snonaka 251589f5489aSchristos if ((hasqos = ieee80211_has_qos(wh))) { 25169cdb1c70Snonaka qos = ((struct ieee80211_qosframe *)wh)->i_qos[0]; 25179cdb1c70Snonaka tid = qos & IEEE80211_QOS_TID; 25189cdb1c70Snonaka qid = TID_TO_WME_AC(tid); 25199cdb1c70Snonaka } else { 2520d164e220Smlelstv qos = 0; 25219cdb1c70Snonaka tid = 0; 25229cdb1c70Snonaka qid = WME_AC_BE; 25239cdb1c70Snonaka } 25249cdb1c70Snonaka ring = &sc->txq[qid]; 25259cdb1c70Snonaka data = &ring->data[ring->cur]; 25269cdb1c70Snonaka 25279cdb1c70Snonaka /* pickup a rate index */ 25289cdb1c70Snonaka if (IEEE80211_IS_MULTICAST(wh->i_addr1) || 25299cdb1c70Snonaka type != IEEE80211_FC0_TYPE_DATA) { 25309cdb1c70Snonaka ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ? 25319cdb1c70Snonaka RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1; 25329cdb1c70Snonaka ctl_ridx = rt2860_rates[ridx].ctl_ridx; 25339cdb1c70Snonaka } else if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) { 25349cdb1c70Snonaka ridx = sc->fixed_ridx; 25359cdb1c70Snonaka ctl_ridx = rt2860_rates[ridx].ctl_ridx; 25369cdb1c70Snonaka } else { 25379cdb1c70Snonaka ridx = rn->ridx[ni->ni_txrate]; 25389cdb1c70Snonaka ctl_ridx = rn->ctl_ridx[ni->ni_txrate]; 25399cdb1c70Snonaka } 25409cdb1c70Snonaka 25419cdb1c70Snonaka /* get MCS code from rate index */ 25429cdb1c70Snonaka mcs = rt2860_rates[ridx].mcs; 25439cdb1c70Snonaka 2544d164e220Smlelstv txwisize = sizeof(struct rt2860_txwi); 2545d164e220Smlelstv if (sc->mac_ver == 0x5592) 2546d164e220Smlelstv txwisize += sizeof(uint32_t); 2547faca41fbSmlelstv xferlen = txwisize + m->m_pkthdr.len; 2548d164e220Smlelstv 25499cdb1c70Snonaka /* roundup to 32-bit alignment */ 25509cdb1c70Snonaka xferlen = (xferlen + 3) & ~3; 25519cdb1c70Snonaka 25529cdb1c70Snonaka txd = (struct rt2870_txd *)data->buf; 25539cdb1c70Snonaka txd->flags = RT2860_TX_QSEL_EDCA; 25549cdb1c70Snonaka txd->len = htole16(xferlen); 25559cdb1c70Snonaka 2556faca41fbSmlelstv /* 2557faca41fbSmlelstv * Ether both are true or both are false, the header 2558faca41fbSmlelstv * are nicely aligned to 32-bit. So, no L2 padding. 2559faca41fbSmlelstv */ 2560faca41fbSmlelstv if (IEEE80211_HAS_ADDR4(wh) == IEEE80211_QOS_HAS_SEQ(wh)) 2561faca41fbSmlelstv pad = 0; 2562faca41fbSmlelstv else 2563faca41fbSmlelstv pad = 2; 2564faca41fbSmlelstv 25659cdb1c70Snonaka /* setup TX Wireless Information */ 25669cdb1c70Snonaka txwi = (struct rt2860_txwi *)(txd + 1); 25679cdb1c70Snonaka txwi->flags = 0; 25689cdb1c70Snonaka txwi->xflags = hasqos ? 0 : RT2860_TX_NSEQ; 25699cdb1c70Snonaka txwi->wcid = (type == IEEE80211_FC0_TYPE_DATA) ? 25709cdb1c70Snonaka RUN_AID2WCID(ni->ni_associd) : 0xff; 2571faca41fbSmlelstv txwi->len = htole16(m->m_pkthdr.len - pad); 25729cdb1c70Snonaka if (rt2860_rates[ridx].phy == IEEE80211_T_DS) { 25739cdb1c70Snonaka txwi->phy = htole16(RT2860_PHY_CCK); 25749cdb1c70Snonaka if (ridx != RT2860_RIDX_CCK1 && 25759cdb1c70Snonaka (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 25769cdb1c70Snonaka mcs |= RT2860_PHY_SHPRE; 25779cdb1c70Snonaka } else 2578faca41fbSmlelstv mcs |= RT2860_PHY_OFDM; 2579d164e220Smlelstv txwi->phy = htole16(mcs); 25809cdb1c70Snonaka 25819cdb1c70Snonaka txwi->txop = RT2860_TX_TXOP_BACKOFF; 25829cdb1c70Snonaka 25839cdb1c70Snonaka if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && 25849cdb1c70Snonaka (!hasqos || (qos & IEEE80211_QOS_ACKPOLICY) != 25859cdb1c70Snonaka IEEE80211_QOS_ACKPOLICY_NOACK)) { 25869cdb1c70Snonaka txwi->xflags |= RT2860_TX_ACK; 25879cdb1c70Snonaka if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) 25889cdb1c70Snonaka dur = rt2860_rates[ctl_ridx].sp_ack_dur; 25899cdb1c70Snonaka else 25909cdb1c70Snonaka dur = rt2860_rates[ctl_ridx].lp_ack_dur; 25919cdb1c70Snonaka *(uint16_t *)wh->i_dur = htole16(dur); 25929cdb1c70Snonaka } 25939cdb1c70Snonaka 25949cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY 25959cdb1c70Snonaka /* ask MAC to insert timestamp into probe responses */ 25969cdb1c70Snonaka if ((wh->i_fc[0] & 25979cdb1c70Snonaka (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == 25989cdb1c70Snonaka (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) 25999cdb1c70Snonaka /* NOTE: beacons do not pass through tx_data() */ 26009cdb1c70Snonaka txwi->flags |= RT2860_TX_TS; 26019cdb1c70Snonaka #endif 26029cdb1c70Snonaka 26039cdb1c70Snonaka if (__predict_false(sc->sc_drvbpf != NULL)) { 26049cdb1c70Snonaka struct run_tx_radiotap_header *tap = &sc->sc_txtap; 26059cdb1c70Snonaka 26069cdb1c70Snonaka tap->wt_flags = 0; 26079cdb1c70Snonaka tap->wt_rate = rt2860_rates[ridx].rate; 26089cdb1c70Snonaka tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); 26099cdb1c70Snonaka tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); 26109cdb1c70Snonaka tap->wt_hwqueue = qid; 26119cdb1c70Snonaka if (mcs & RT2860_PHY_SHPRE) 26129cdb1c70Snonaka tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; 26139cdb1c70Snonaka 26143cd62456Smsaitoh bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m, BPF_D_OUT); 26159cdb1c70Snonaka } 26169cdb1c70Snonaka 2617faca41fbSmlelstv m_copydata(m, 0, m->m_pkthdr.len, ((uint8_t *)txwi) + txwisize); 26189cdb1c70Snonaka m_freem(m); 26199cdb1c70Snonaka 26209cdb1c70Snonaka xferlen += sizeof(*txd) + 4; 26219cdb1c70Snonaka 26224e8e6643Sskrll usbd_setup_xfer(data->xfer, data, data->buf, xferlen, 26234e8e6643Sskrll USBD_FORCE_SHORT_XFER, RUN_TX_TIMEOUT, run_txeof); 2624d164e220Smlelstv status = usbd_transfer(data->xfer); 2625d164e220Smlelstv if (__predict_false(status != USBD_IN_PROGRESS && 2626d164e220Smlelstv status != USBD_NORMAL_COMPLETION)) { 2627d164e220Smlelstv device_printf(sc->sc_dev, "queuing tx failed: %s\n", 2628d164e220Smlelstv usbd_errstr(status)); 2629d164e220Smlelstv return EIO; 2630d164e220Smlelstv } 26319cdb1c70Snonaka 26329cdb1c70Snonaka ieee80211_free_node(ni); 26339cdb1c70Snonaka 26349cdb1c70Snonaka ring->cur = (ring->cur + 1) % RUN_TX_RING_COUNT; 26359cdb1c70Snonaka if (++ring->queued >= RUN_TX_RING_COUNT) 26369cdb1c70Snonaka sc->qfullmsk |= 1 << qid; 26379cdb1c70Snonaka 26384e8e6643Sskrll return 0; 26399cdb1c70Snonaka } 26409cdb1c70Snonaka 26419cdb1c70Snonaka static void 26429cdb1c70Snonaka run_start(struct ifnet *ifp) 26439cdb1c70Snonaka { 26449cdb1c70Snonaka struct run_softc *sc = ifp->if_softc; 26459cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 26469cdb1c70Snonaka struct ether_header *eh; 26479cdb1c70Snonaka struct ieee80211_node *ni; 26489cdb1c70Snonaka struct mbuf *m; 26499cdb1c70Snonaka 26509cdb1c70Snonaka if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 26519cdb1c70Snonaka return; 26529cdb1c70Snonaka 26539cdb1c70Snonaka for (;;) { 26549cdb1c70Snonaka if (sc->qfullmsk != 0) { 26559cdb1c70Snonaka ifp->if_flags |= IFF_OACTIVE; 26569cdb1c70Snonaka break; 26579cdb1c70Snonaka } 26589cdb1c70Snonaka /* send pending management frames first */ 26599cdb1c70Snonaka IF_DEQUEUE(&ic->ic_mgtq, m); 26609cdb1c70Snonaka if (m != NULL) { 2661ea0349e7Sozaki-r ni = M_GETCTX(m, struct ieee80211_node *); 26626bbd2477Sozaki-r M_CLEARCTX(m); 26639cdb1c70Snonaka goto sendit; 26649cdb1c70Snonaka } 26659cdb1c70Snonaka if (ic->ic_state != IEEE80211_S_RUN) 26669cdb1c70Snonaka break; 26679cdb1c70Snonaka 26689cdb1c70Snonaka /* encapsulate and send data frames */ 26699cdb1c70Snonaka IFQ_DEQUEUE(&ifp->if_snd, m); 26709cdb1c70Snonaka if (m == NULL) 26719cdb1c70Snonaka break; 26729cdb1c70Snonaka if (m->m_len < (int)sizeof(*eh) && 26739cdb1c70Snonaka (m = m_pullup(m, sizeof(*eh))) == NULL) { 26749cdb1c70Snonaka ifp->if_oerrors++; 26759cdb1c70Snonaka continue; 26769cdb1c70Snonaka } 26779cdb1c70Snonaka 26789cdb1c70Snonaka eh = mtod(m, struct ether_header *); 26799cdb1c70Snonaka ni = ieee80211_find_txnode(ic, eh->ether_dhost); 26809cdb1c70Snonaka if (ni == NULL) { 26819cdb1c70Snonaka m_freem(m); 26829cdb1c70Snonaka ifp->if_oerrors++; 26839cdb1c70Snonaka continue; 26849cdb1c70Snonaka } 26859cdb1c70Snonaka 26863cd62456Smsaitoh bpf_mtap(ifp, m, BPF_D_OUT); 26879cdb1c70Snonaka 26889cdb1c70Snonaka if ((m = ieee80211_encap(ic, m, ni)) == NULL) { 26899cdb1c70Snonaka ieee80211_free_node(ni); 26909cdb1c70Snonaka ifp->if_oerrors++; 26919cdb1c70Snonaka continue; 26929cdb1c70Snonaka } 26939cdb1c70Snonaka sendit: 26943cd62456Smsaitoh bpf_mtap3(ic->ic_rawbpf, m, BPF_D_OUT); 26959cdb1c70Snonaka 26969cdb1c70Snonaka if (run_tx(sc, m, ni) != 0) { 26979cdb1c70Snonaka ieee80211_free_node(ni); 26989cdb1c70Snonaka ifp->if_oerrors++; 26999cdb1c70Snonaka continue; 27009cdb1c70Snonaka } 27019cdb1c70Snonaka 27029cdb1c70Snonaka sc->sc_tx_timer = 5; 27039cdb1c70Snonaka ifp->if_timer = 1; 27049cdb1c70Snonaka } 27059cdb1c70Snonaka } 27069cdb1c70Snonaka 27079cdb1c70Snonaka static void 27089cdb1c70Snonaka run_watchdog(struct ifnet *ifp) 27099cdb1c70Snonaka { 27109cdb1c70Snonaka struct run_softc *sc = ifp->if_softc; 27119cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 27129cdb1c70Snonaka 27139cdb1c70Snonaka ifp->if_timer = 0; 27149cdb1c70Snonaka 27159cdb1c70Snonaka if (sc->sc_tx_timer > 0) { 27169cdb1c70Snonaka if (--sc->sc_tx_timer == 0) { 27171d5cb2a3Sjakllsch device_printf(sc->sc_dev, "device timeout\n"); 27189cdb1c70Snonaka /* run_init(ifp); XXX needs a process context! */ 27199cdb1c70Snonaka ifp->if_oerrors++; 27209cdb1c70Snonaka return; 27219cdb1c70Snonaka } 27229cdb1c70Snonaka ifp->if_timer = 1; 27239cdb1c70Snonaka } 27249cdb1c70Snonaka 27259cdb1c70Snonaka ieee80211_watchdog(ic); 27269cdb1c70Snonaka } 27279cdb1c70Snonaka 27289cdb1c70Snonaka static int 27299cdb1c70Snonaka run_ioctl(struct ifnet *ifp, u_long cmd, void *data) 27309cdb1c70Snonaka { 27319cdb1c70Snonaka struct run_softc *sc = ifp->if_softc; 27329cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 27339cdb1c70Snonaka int s, error = 0; 27349cdb1c70Snonaka 27359cdb1c70Snonaka s = splnet(); 27369cdb1c70Snonaka 27379cdb1c70Snonaka switch (cmd) { 27389cdb1c70Snonaka case SIOCSIFFLAGS: 27399cdb1c70Snonaka if ((error = ifioctl_common(ifp, cmd, data)) != 0) 27409cdb1c70Snonaka break; 27419cdb1c70Snonaka switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 27429cdb1c70Snonaka case IFF_UP|IFF_RUNNING: 27439cdb1c70Snonaka break; 27449cdb1c70Snonaka case IFF_UP: 27459cdb1c70Snonaka run_init(ifp); 27469cdb1c70Snonaka break; 27479cdb1c70Snonaka case IFF_RUNNING: 27489cdb1c70Snonaka run_stop(ifp, 1); 27499cdb1c70Snonaka break; 27509cdb1c70Snonaka case 0: 27519cdb1c70Snonaka break; 27529cdb1c70Snonaka } 27539cdb1c70Snonaka break; 27549cdb1c70Snonaka 27559cdb1c70Snonaka case SIOCADDMULTI: 27569cdb1c70Snonaka case SIOCDELMULTI: 27579cdb1c70Snonaka if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 27589cdb1c70Snonaka /* setup multicast filter, etc */ 27599cdb1c70Snonaka error = 0; 27609cdb1c70Snonaka } 27619cdb1c70Snonaka break; 27629cdb1c70Snonaka 27639cdb1c70Snonaka default: 27649cdb1c70Snonaka error = ieee80211_ioctl(ic, cmd, data); 27659cdb1c70Snonaka break; 27669cdb1c70Snonaka } 27679cdb1c70Snonaka 27689cdb1c70Snonaka if (error == ENETRESET) { 27699cdb1c70Snonaka if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 27709cdb1c70Snonaka (IFF_UP | IFF_RUNNING)) { 27719cdb1c70Snonaka run_init(ifp); 27729cdb1c70Snonaka } 27739cdb1c70Snonaka error = 0; 27749cdb1c70Snonaka } 27759cdb1c70Snonaka 27769cdb1c70Snonaka splx(s); 27779cdb1c70Snonaka 27784e8e6643Sskrll return error; 27799cdb1c70Snonaka } 27809cdb1c70Snonaka 27819cdb1c70Snonaka static void 27829cdb1c70Snonaka run_select_chan_group(struct run_softc *sc, int group) 27839cdb1c70Snonaka { 27849cdb1c70Snonaka uint32_t tmp; 27859cdb1c70Snonaka uint8_t agc; 27869cdb1c70Snonaka 27879cdb1c70Snonaka run_bbp_write(sc, 62, 0x37 - sc->lna[group]); 27889cdb1c70Snonaka run_bbp_write(sc, 63, 0x37 - sc->lna[group]); 27899cdb1c70Snonaka run_bbp_write(sc, 64, 0x37 - sc->lna[group]); 2790d164e220Smlelstv if (sc->mac_ver < 0x3572) 27919cdb1c70Snonaka run_bbp_write(sc, 86, 0x00); 27929cdb1c70Snonaka 2793d164e220Smlelstv if (sc->mac_ver == 0x3593) { 2794d164e220Smlelstv run_bbp_write(sc, 77, 0x98); 2795d164e220Smlelstv run_bbp_write(sc, 83, (group == 0) ? 0x8a : 0x9a); 2796d164e220Smlelstv } 2797d164e220Smlelstv 27989cdb1c70Snonaka if (group == 0) { 27999cdb1c70Snonaka if (sc->ext_2ghz_lna) { 2800d164e220Smlelstv if (sc->mac_ver >= 0x5390) 2801d164e220Smlelstv run_bbp_write(sc, 75, 0x52); 2802d164e220Smlelstv else { 28039cdb1c70Snonaka run_bbp_write(sc, 82, 0x62); 28049cdb1c70Snonaka run_bbp_write(sc, 75, 0x46); 28059cdb1c70Snonaka } 28069cdb1c70Snonaka } else { 2807d164e220Smlelstv if (sc->mac_ver == 0x5592) { 2808d164e220Smlelstv run_bbp_write(sc, 79, 0x1c); 2809d164e220Smlelstv run_bbp_write(sc, 80, 0x0e); 2810d164e220Smlelstv run_bbp_write(sc, 81, 0x3a); 2811d164e220Smlelstv run_bbp_write(sc, 82, 0x62); 2812d164e220Smlelstv 2813d164e220Smlelstv run_bbp_write(sc, 195, 0x80); 2814d164e220Smlelstv run_bbp_write(sc, 196, 0xe0); 2815d164e220Smlelstv run_bbp_write(sc, 195, 0x81); 2816d164e220Smlelstv run_bbp_write(sc, 196, 0x1f); 2817d164e220Smlelstv run_bbp_write(sc, 195, 0x82); 2818d164e220Smlelstv run_bbp_write(sc, 196, 0x38); 2819d164e220Smlelstv run_bbp_write(sc, 195, 0x83); 2820d164e220Smlelstv run_bbp_write(sc, 196, 0x32); 2821d164e220Smlelstv run_bbp_write(sc, 195, 0x85); 2822d164e220Smlelstv run_bbp_write(sc, 196, 0x28); 2823d164e220Smlelstv run_bbp_write(sc, 195, 0x86); 2824d164e220Smlelstv run_bbp_write(sc, 196, 0x19); 2825d164e220Smlelstv } else if (sc->mac_ver >= 0x5390) { 2826d164e220Smlelstv run_bbp_write(sc, 75, 0x50); 2827d164e220Smlelstv } else { 2828d164e220Smlelstv run_bbp_write(sc, 82, 2829d164e220Smlelstv (sc->mac_ver == 0x3593) ? 0x62 : 0x84); 2830d164e220Smlelstv run_bbp_write(sc, 75, 0x50); 2831d164e220Smlelstv } 2832d164e220Smlelstv } 2833d164e220Smlelstv } else { 2834d164e220Smlelstv if (sc->mac_ver == 0x5592) { 2835d164e220Smlelstv run_bbp_write(sc, 79, 0x18); 2836d164e220Smlelstv run_bbp_write(sc, 80, 0x08); 2837d164e220Smlelstv run_bbp_write(sc, 81, 0x38); 2838d164e220Smlelstv run_bbp_write(sc, 82, 0x92); 2839d164e220Smlelstv 2840d164e220Smlelstv run_bbp_write(sc, 195, 0x80); 2841d164e220Smlelstv run_bbp_write(sc, 196, 0xf0); 2842d164e220Smlelstv run_bbp_write(sc, 195, 0x81); 2843d164e220Smlelstv run_bbp_write(sc, 196, 0x1e); 2844d164e220Smlelstv run_bbp_write(sc, 195, 0x82); 2845d164e220Smlelstv run_bbp_write(sc, 196, 0x28); 2846d164e220Smlelstv run_bbp_write(sc, 195, 0x83); 2847d164e220Smlelstv run_bbp_write(sc, 196, 0x20); 2848d164e220Smlelstv run_bbp_write(sc, 195, 0x85); 2849d164e220Smlelstv run_bbp_write(sc, 196, 0x7f); 2850d164e220Smlelstv run_bbp_write(sc, 195, 0x86); 2851d164e220Smlelstv run_bbp_write(sc, 196, 0x7f); 2852d164e220Smlelstv } else if (sc->mac_ver == 0x3572) 28539cdb1c70Snonaka run_bbp_write(sc, 82, 0x94); 28549cdb1c70Snonaka else 2855d164e220Smlelstv run_bbp_write(sc, 82, 2856d164e220Smlelstv (sc->mac_ver == 0x3593) ? 0x82 : 0xf2); 28579cdb1c70Snonaka if (sc->ext_5ghz_lna) 28589cdb1c70Snonaka run_bbp_write(sc, 75, 0x46); 28599cdb1c70Snonaka else 28609cdb1c70Snonaka run_bbp_write(sc, 75, 0x50); 28619cdb1c70Snonaka } 28629cdb1c70Snonaka 28639cdb1c70Snonaka run_read(sc, RT2860_TX_BAND_CFG, &tmp); 28649cdb1c70Snonaka tmp &= ~(RT2860_5G_BAND_SEL_N | RT2860_5G_BAND_SEL_P); 28659cdb1c70Snonaka tmp |= (group == 0) ? RT2860_5G_BAND_SEL_N : RT2860_5G_BAND_SEL_P; 28669cdb1c70Snonaka run_write(sc, RT2860_TX_BAND_CFG, tmp); 28679cdb1c70Snonaka 28689cdb1c70Snonaka /* enable appropriate Power Amplifiers and Low Noise Amplifiers */ 28699cdb1c70Snonaka tmp = RT2860_RFTR_EN | RT2860_TRSW_EN | RT2860_LNA_PE0_EN; 2870d164e220Smlelstv if (sc->mac_ver == 0x3593) 2871d164e220Smlelstv tmp |= RT3593_LNA_PE_G2_EN | RT3593_LNA_PE_A2_EN; 28729cdb1c70Snonaka if (sc->nrxchains > 1) 28739cdb1c70Snonaka tmp |= RT2860_LNA_PE1_EN; 28749cdb1c70Snonaka if (group == 0) { /* 2GHz */ 28759cdb1c70Snonaka tmp |= RT2860_PA_PE_G0_EN; 28769cdb1c70Snonaka if (sc->ntxchains > 1) 28779cdb1c70Snonaka tmp |= RT2860_PA_PE_G1_EN; 28789cdb1c70Snonaka } else { /* 5GHz */ 28799cdb1c70Snonaka tmp |= RT2860_PA_PE_A0_EN; 28809cdb1c70Snonaka if (sc->ntxchains > 1) 28819cdb1c70Snonaka tmp |= RT2860_PA_PE_A1_EN; 2882d164e220Smlelstv if (sc->mac_ver == 0x3593) { 2883d164e220Smlelstv if (sc->ntxchains > 2) 2884d164e220Smlelstv tmp |= RT3593_PA_PE_G2_EN; 2885d164e220Smlelstv } 28869cdb1c70Snonaka } 28879cdb1c70Snonaka if (sc->mac_ver == 0x3572) { 28889cdb1c70Snonaka run_rt3070_rf_write(sc, 8, 0x00); 28899cdb1c70Snonaka run_write(sc, RT2860_TX_PIN_CFG, tmp); 28909cdb1c70Snonaka run_rt3070_rf_write(sc, 8, 0x80); 28919cdb1c70Snonaka } else 28929cdb1c70Snonaka run_write(sc, RT2860_TX_PIN_CFG, tmp); 28939cdb1c70Snonaka 2894d164e220Smlelstv if (sc->mac_ver == 0x5592) { 2895d164e220Smlelstv run_bbp_write(sc, 195, 0x8d); 2896d164e220Smlelstv run_bbp_write(sc, 196, 0x1a); 2897d164e220Smlelstv } 2898d164e220Smlelstv 2899d164e220Smlelstv if (sc->mac_ver == 0x3593) { 2900d164e220Smlelstv run_read(sc, RT2860_GPIO_CTRL, &tmp); 2901d164e220Smlelstv tmp &= ~0x01010000; 2902d164e220Smlelstv if (group == 0) 2903d164e220Smlelstv tmp |= 0x00010000; 2904d164e220Smlelstv tmp = (tmp & ~0x00009090) | 0x00000090; 2905d164e220Smlelstv run_write(sc, RT2860_GPIO_CTRL, tmp); 2906d164e220Smlelstv } 2907d164e220Smlelstv 29089cdb1c70Snonaka /* set initial AGC value */ 29099cdb1c70Snonaka if (group == 0) { /* 2GHz band */ 29109cdb1c70Snonaka if (sc->mac_ver >= 0x3070) 29119cdb1c70Snonaka agc = 0x1c + sc->lna[0] * 2; 29129cdb1c70Snonaka else 29139cdb1c70Snonaka agc = 0x2e + sc->lna[0]; 29149cdb1c70Snonaka } else { /* 5GHz band */ 29159cdb1c70Snonaka if (sc->mac_ver == 0x3572) 29169cdb1c70Snonaka agc = 0x22 + (sc->lna[group] * 5) / 3; 29179cdb1c70Snonaka else 29189cdb1c70Snonaka agc = 0x32 + (sc->lna[group] * 5) / 3; 29199cdb1c70Snonaka } 29209cdb1c70Snonaka run_set_agc(sc, agc); 29219cdb1c70Snonaka } 29229cdb1c70Snonaka 29239cdb1c70Snonaka static void 29249cdb1c70Snonaka run_rt2870_set_chan(struct run_softc *sc, u_int chan) 29259cdb1c70Snonaka { 29269cdb1c70Snonaka const struct rfprog *rfprog = rt2860_rf2850; 29279cdb1c70Snonaka uint32_t r2, r3, r4; 29289cdb1c70Snonaka int8_t txpow1, txpow2; 29299cdb1c70Snonaka int i; 29309cdb1c70Snonaka 29319cdb1c70Snonaka /* find the settings for this channel (we know it exists) */ 29329cdb1c70Snonaka for (i = 0; rfprog[i].chan != chan; i++); 29339cdb1c70Snonaka 29349cdb1c70Snonaka r2 = rfprog[i].r2; 29359cdb1c70Snonaka if (sc->ntxchains == 1) 29369cdb1c70Snonaka r2 |= 1 << 12; /* 1T: disable Tx chain 2 */ 29379cdb1c70Snonaka if (sc->nrxchains == 1) 29389cdb1c70Snonaka r2 |= 1 << 15 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */ 29399cdb1c70Snonaka else if (sc->nrxchains == 2) 29409cdb1c70Snonaka r2 |= 1 << 4; /* 2R: disable Rx chain 3 */ 29419cdb1c70Snonaka 29429cdb1c70Snonaka /* use Tx power values from EEPROM */ 29439cdb1c70Snonaka txpow1 = sc->txpow1[i]; 29449cdb1c70Snonaka txpow2 = sc->txpow2[i]; 29459cdb1c70Snonaka if (chan > 14) { 29469cdb1c70Snonaka if (txpow1 >= 0) 29479cdb1c70Snonaka txpow1 = txpow1 << 1 | 1; 29489cdb1c70Snonaka else 29499cdb1c70Snonaka txpow1 = (7 + txpow1) << 1; 29509cdb1c70Snonaka if (txpow2 >= 0) 29519cdb1c70Snonaka txpow2 = txpow2 << 1 | 1; 29529cdb1c70Snonaka else 29539cdb1c70Snonaka txpow2 = (7 + txpow2) << 1; 29549cdb1c70Snonaka } 29559cdb1c70Snonaka r3 = rfprog[i].r3 | txpow1 << 7; 29569cdb1c70Snonaka r4 = rfprog[i].r4 | sc->freq << 13 | txpow2 << 4; 29579cdb1c70Snonaka 29589cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1); 29599cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF2, r2); 29609cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF3, r3); 29619cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF4, r4); 29629cdb1c70Snonaka 2963faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 29649cdb1c70Snonaka 29659cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1); 29669cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF2, r2); 29679cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF3, r3 | 1); 29689cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF4, r4); 29699cdb1c70Snonaka 2970faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 29719cdb1c70Snonaka 29729cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1); 29739cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF2, r2); 29749cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF3, r3); 29759cdb1c70Snonaka run_rt2870_rf_write(sc, RT2860_RF4, r4); 29769cdb1c70Snonaka } 29779cdb1c70Snonaka 29789cdb1c70Snonaka static void 29799cdb1c70Snonaka run_rt3070_set_chan(struct run_softc *sc, u_int chan) 29809cdb1c70Snonaka { 29819cdb1c70Snonaka int8_t txpow1, txpow2; 29829cdb1c70Snonaka uint8_t rf; 29839cdb1c70Snonaka int i; 29849cdb1c70Snonaka 29859cdb1c70Snonaka KASSERT(chan >= 1 && chan <= 14); /* RT3070 is 2GHz only */ 29869cdb1c70Snonaka 29879cdb1c70Snonaka /* find the settings for this channel (we know it exists) */ 29889cdb1c70Snonaka for (i = 0; rt2860_rf2850[i].chan != chan; i++) 29899cdb1c70Snonaka continue; 29909cdb1c70Snonaka 29919cdb1c70Snonaka /* use Tx power values from EEPROM */ 29929cdb1c70Snonaka txpow1 = sc->txpow1[i]; 29939cdb1c70Snonaka txpow2 = sc->txpow2[i]; 29949cdb1c70Snonaka 29959cdb1c70Snonaka run_rt3070_rf_write(sc, 2, rt3070_freqs[i].n); 29969cdb1c70Snonaka run_rt3070_rf_write(sc, 3, rt3070_freqs[i].k); 29979cdb1c70Snonaka run_rt3070_rf_read(sc, 6, &rf); 29989cdb1c70Snonaka rf = (rf & ~0x03) | rt3070_freqs[i].r; 29999cdb1c70Snonaka run_rt3070_rf_write(sc, 6, rf); 30009cdb1c70Snonaka 30019cdb1c70Snonaka /* set Tx0 power */ 30029cdb1c70Snonaka run_rt3070_rf_read(sc, 12, &rf); 30039cdb1c70Snonaka rf = (rf & ~0x1f) | txpow1; 30049cdb1c70Snonaka run_rt3070_rf_write(sc, 12, rf); 30059cdb1c70Snonaka 30069cdb1c70Snonaka /* set Tx1 power */ 30079cdb1c70Snonaka run_rt3070_rf_read(sc, 13, &rf); 30089cdb1c70Snonaka rf = (rf & ~0x1f) | txpow2; 30099cdb1c70Snonaka run_rt3070_rf_write(sc, 13, rf); 30109cdb1c70Snonaka 30119cdb1c70Snonaka run_rt3070_rf_read(sc, 1, &rf); 30129cdb1c70Snonaka rf &= ~0xfc; 30139cdb1c70Snonaka if (sc->ntxchains == 1) 30149cdb1c70Snonaka rf |= 1 << 7 | 1 << 5; /* 1T: disable Tx chains 2 & 3 */ 30159cdb1c70Snonaka else if (sc->ntxchains == 2) 30169cdb1c70Snonaka rf |= 1 << 7; /* 2T: disable Tx chain 3 */ 30179cdb1c70Snonaka if (sc->nrxchains == 1) 30189cdb1c70Snonaka rf |= 1 << 6 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */ 30199cdb1c70Snonaka else if (sc->nrxchains == 2) 30209cdb1c70Snonaka rf |= 1 << 6; /* 2R: disable Rx chain 3 */ 30219cdb1c70Snonaka run_rt3070_rf_write(sc, 1, rf); 30229cdb1c70Snonaka 30239cdb1c70Snonaka /* set RF offset */ 30249cdb1c70Snonaka run_rt3070_rf_read(sc, 23, &rf); 30259cdb1c70Snonaka rf = (rf & ~0x7f) | sc->freq; 30269cdb1c70Snonaka run_rt3070_rf_write(sc, 23, rf); 30279cdb1c70Snonaka 30289cdb1c70Snonaka /* program RF filter */ 30299cdb1c70Snonaka run_rt3070_rf_read(sc, 24, &rf); /* Tx */ 30309cdb1c70Snonaka rf = (rf & ~0x3f) | sc->rf24_20mhz; 30319cdb1c70Snonaka run_rt3070_rf_write(sc, 24, rf); 30329cdb1c70Snonaka run_rt3070_rf_read(sc, 31, &rf); /* Rx */ 30339cdb1c70Snonaka rf = (rf & ~0x3f) | sc->rf24_20mhz; 30349cdb1c70Snonaka run_rt3070_rf_write(sc, 31, rf); 30359cdb1c70Snonaka 30369cdb1c70Snonaka /* enable RF tuning */ 30379cdb1c70Snonaka run_rt3070_rf_read(sc, 7, &rf); 30389cdb1c70Snonaka run_rt3070_rf_write(sc, 7, rf | 0x01); 30399cdb1c70Snonaka } 30409cdb1c70Snonaka 30419cdb1c70Snonaka static void 30429cdb1c70Snonaka run_rt3572_set_chan(struct run_softc *sc, u_int chan) 30439cdb1c70Snonaka { 30449cdb1c70Snonaka int8_t txpow1, txpow2; 30459cdb1c70Snonaka uint32_t tmp; 30469cdb1c70Snonaka uint8_t rf; 30479cdb1c70Snonaka int i; 30489cdb1c70Snonaka 30499cdb1c70Snonaka /* find the settings for this channel (we know it exists) */ 30509cdb1c70Snonaka for (i = 0; rt2860_rf2850[i].chan != chan; i++); 30519cdb1c70Snonaka 30529cdb1c70Snonaka /* use Tx power values from EEPROM */ 30539cdb1c70Snonaka txpow1 = sc->txpow1[i]; 30549cdb1c70Snonaka txpow2 = sc->txpow2[i]; 30559cdb1c70Snonaka 30569cdb1c70Snonaka if (chan <= 14) { 30579cdb1c70Snonaka run_bbp_write(sc, 25, sc->bbp25); 30589cdb1c70Snonaka run_bbp_write(sc, 26, sc->bbp26); 30599cdb1c70Snonaka } else { 30609cdb1c70Snonaka /* enable IQ phase correction */ 30619cdb1c70Snonaka run_bbp_write(sc, 25, 0x09); 30629cdb1c70Snonaka run_bbp_write(sc, 26, 0xff); 30639cdb1c70Snonaka } 30649cdb1c70Snonaka 30659cdb1c70Snonaka run_rt3070_rf_write(sc, 2, rt3070_freqs[i].n); 30669cdb1c70Snonaka run_rt3070_rf_write(sc, 3, rt3070_freqs[i].k); 30679cdb1c70Snonaka run_rt3070_rf_read(sc, 6, &rf); 30689cdb1c70Snonaka rf = (rf & ~0x0f) | rt3070_freqs[i].r; 30699cdb1c70Snonaka rf |= (chan <= 14) ? 0x08 : 0x04; 30709cdb1c70Snonaka run_rt3070_rf_write(sc, 6, rf); 30719cdb1c70Snonaka 30729cdb1c70Snonaka /* set PLL mode */ 30739cdb1c70Snonaka run_rt3070_rf_read(sc, 5, &rf); 30749cdb1c70Snonaka rf &= ~(0x08 | 0x04); 30759cdb1c70Snonaka rf |= (chan <= 14) ? 0x04 : 0x08; 30769cdb1c70Snonaka run_rt3070_rf_write(sc, 5, rf); 30779cdb1c70Snonaka 30789cdb1c70Snonaka /* set Tx power for chain 0 */ 30799cdb1c70Snonaka if (chan <= 14) 30809cdb1c70Snonaka rf = 0x60 | txpow1; 30819cdb1c70Snonaka else 30829cdb1c70Snonaka rf = 0xe0 | (txpow1 & 0xc) << 1 | (txpow1 & 0x3); 30839cdb1c70Snonaka run_rt3070_rf_write(sc, 12, rf); 30849cdb1c70Snonaka 30859cdb1c70Snonaka /* set Tx power for chain 1 */ 30869cdb1c70Snonaka if (chan <= 14) 30879cdb1c70Snonaka rf = 0x60 | txpow2; 30889cdb1c70Snonaka else 30899cdb1c70Snonaka rf = 0xe0 | (txpow2 & 0xc) << 1 | (txpow2 & 0x3); 30909cdb1c70Snonaka run_rt3070_rf_write(sc, 13, rf); 30919cdb1c70Snonaka 30929cdb1c70Snonaka /* set Tx/Rx streams */ 30939cdb1c70Snonaka run_rt3070_rf_read(sc, 1, &rf); 30949cdb1c70Snonaka rf &= ~0xfc; 30959cdb1c70Snonaka if (sc->ntxchains == 1) 30969cdb1c70Snonaka rf |= 1 << 7 | 1 << 5; /* 1T: disable Tx chains 2 & 3 */ 30979cdb1c70Snonaka else if (sc->ntxchains == 2) 30989cdb1c70Snonaka rf |= 1 << 7; /* 2T: disable Tx chain 3 */ 30999cdb1c70Snonaka if (sc->nrxchains == 1) 31009cdb1c70Snonaka rf |= 1 << 6 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */ 31019cdb1c70Snonaka else if (sc->nrxchains == 2) 31029cdb1c70Snonaka rf |= 1 << 6; /* 2R: disable Rx chain 3 */ 31039cdb1c70Snonaka run_rt3070_rf_write(sc, 1, rf); 31049cdb1c70Snonaka 31059cdb1c70Snonaka /* set RF offset */ 31069cdb1c70Snonaka run_rt3070_rf_read(sc, 23, &rf); 31079cdb1c70Snonaka rf = (rf & ~0x7f) | sc->freq; 31089cdb1c70Snonaka run_rt3070_rf_write(sc, 23, rf); 31099cdb1c70Snonaka 31109cdb1c70Snonaka /* program RF filter */ 31119cdb1c70Snonaka rf = sc->rf24_20mhz; 31129cdb1c70Snonaka run_rt3070_rf_write(sc, 24, rf); /* Tx */ 31139cdb1c70Snonaka run_rt3070_rf_write(sc, 31, rf); /* Rx */ 31149cdb1c70Snonaka 31159cdb1c70Snonaka /* enable RF tuning */ 31169cdb1c70Snonaka run_rt3070_rf_read(sc, 7, &rf); 31179cdb1c70Snonaka rf = (chan <= 14) ? 0xd8 : ((rf & ~0xc8) | 0x14); 31189cdb1c70Snonaka run_rt3070_rf_write(sc, 7, rf); 31199cdb1c70Snonaka 31209cdb1c70Snonaka /* TSSI */ 31219cdb1c70Snonaka rf = (chan <= 14) ? 0xc3 : 0xc0; 31229cdb1c70Snonaka run_rt3070_rf_write(sc, 9, rf); 31239cdb1c70Snonaka 31249cdb1c70Snonaka /* set loop filter 1 */ 31259cdb1c70Snonaka run_rt3070_rf_write(sc, 10, 0xf1); 31269cdb1c70Snonaka /* set loop filter 2 */ 31279cdb1c70Snonaka run_rt3070_rf_write(sc, 11, (chan <= 14) ? 0xb9 : 0x00); 31289cdb1c70Snonaka 31299cdb1c70Snonaka /* set tx_mx2_ic */ 31309cdb1c70Snonaka run_rt3070_rf_write(sc, 15, (chan <= 14) ? 0x53 : 0x43); 31319cdb1c70Snonaka /* set tx_mx1_ic */ 31329cdb1c70Snonaka if (chan <= 14) 31339cdb1c70Snonaka rf = 0x48 | sc->txmixgain_2ghz; 31349cdb1c70Snonaka else 31359cdb1c70Snonaka rf = 0x78 | sc->txmixgain_5ghz; 31369cdb1c70Snonaka run_rt3070_rf_write(sc, 16, rf); 31379cdb1c70Snonaka 31389cdb1c70Snonaka /* set tx_lo1 */ 31399cdb1c70Snonaka run_rt3070_rf_write(sc, 17, 0x23); 31409cdb1c70Snonaka /* set tx_lo2 */ 31419cdb1c70Snonaka if (chan <= 14) 31429cdb1c70Snonaka rf = 0x93; 31439cdb1c70Snonaka else if (chan <= 64) 31449cdb1c70Snonaka rf = 0xb7; 31459cdb1c70Snonaka else if (chan <= 128) 31469cdb1c70Snonaka rf = 0x74; 31479cdb1c70Snonaka else 31489cdb1c70Snonaka rf = 0x72; 31499cdb1c70Snonaka run_rt3070_rf_write(sc, 19, rf); 31509cdb1c70Snonaka 31519cdb1c70Snonaka /* set rx_lo1 */ 31529cdb1c70Snonaka if (chan <= 14) 31539cdb1c70Snonaka rf = 0xb3; 31549cdb1c70Snonaka else if (chan <= 64) 31559cdb1c70Snonaka rf = 0xf6; 31569cdb1c70Snonaka else if (chan <= 128) 31579cdb1c70Snonaka rf = 0xf4; 31589cdb1c70Snonaka else 31599cdb1c70Snonaka rf = 0xf3; 31609cdb1c70Snonaka run_rt3070_rf_write(sc, 20, rf); 31619cdb1c70Snonaka 31629cdb1c70Snonaka /* set pfd_delay */ 31639cdb1c70Snonaka if (chan <= 14) 31649cdb1c70Snonaka rf = 0x15; 31659cdb1c70Snonaka else if (chan <= 64) 31669cdb1c70Snonaka rf = 0x3d; 31679cdb1c70Snonaka else 31689cdb1c70Snonaka rf = 0x01; 31699cdb1c70Snonaka run_rt3070_rf_write(sc, 25, rf); 31709cdb1c70Snonaka 31719cdb1c70Snonaka /* set rx_lo2 */ 31729cdb1c70Snonaka run_rt3070_rf_write(sc, 26, (chan <= 14) ? 0x85 : 0x87); 31739cdb1c70Snonaka /* set ldo_rf_vc */ 31749cdb1c70Snonaka run_rt3070_rf_write(sc, 27, (chan <= 14) ? 0x00 : 0x01); 31759cdb1c70Snonaka /* set drv_cc */ 31769cdb1c70Snonaka run_rt3070_rf_write(sc, 29, (chan <= 14) ? 0x9b : 0x9f); 31779cdb1c70Snonaka 31789cdb1c70Snonaka run_read(sc, RT2860_GPIO_CTRL, &tmp); 31799cdb1c70Snonaka tmp &= ~0x8080; 31809cdb1c70Snonaka if (chan <= 14) 31819cdb1c70Snonaka tmp |= 0x80; 31829cdb1c70Snonaka run_write(sc, RT2860_GPIO_CTRL, tmp); 31839cdb1c70Snonaka 31849cdb1c70Snonaka /* enable RF tuning */ 31859cdb1c70Snonaka run_rt3070_rf_read(sc, 7, &rf); 31869cdb1c70Snonaka run_rt3070_rf_write(sc, 7, rf | 0x01); 31879cdb1c70Snonaka 3188faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 2); 3189faca41fbSmlelstv } 3190faca41fbSmlelstv 3191faca41fbSmlelstv static void 3192faca41fbSmlelstv run_rt3593_set_chan(struct run_softc *sc, u_int chan) 3193faca41fbSmlelstv { 3194faca41fbSmlelstv int8_t txpow1, txpow2, txpow3; 3195faca41fbSmlelstv uint8_t h20mhz, rf; 3196faca41fbSmlelstv int i; 3197faca41fbSmlelstv 3198faca41fbSmlelstv /* find the settings for this channel (we know it exists) */ 3199faca41fbSmlelstv for (i = 0; rt2860_rf2850[i].chan != chan; i++); 3200faca41fbSmlelstv 3201faca41fbSmlelstv /* use Tx power values from EEPROM */ 3202faca41fbSmlelstv txpow1 = sc->txpow1[i]; 3203faca41fbSmlelstv txpow2 = sc->txpow2[i]; 3204faca41fbSmlelstv txpow3 = (sc->ntxchains == 3) ? sc->txpow3[i] : 0; 3205faca41fbSmlelstv 3206faca41fbSmlelstv if (chan <= 14) { 3207faca41fbSmlelstv run_bbp_write(sc, 25, sc->bbp25); 3208faca41fbSmlelstv run_bbp_write(sc, 26, sc->bbp26); 3209faca41fbSmlelstv } else { 3210faca41fbSmlelstv /* Enable IQ phase correction. */ 3211faca41fbSmlelstv run_bbp_write(sc, 25, 0x09); 3212faca41fbSmlelstv run_bbp_write(sc, 26, 0xff); 3213faca41fbSmlelstv } 3214faca41fbSmlelstv 3215faca41fbSmlelstv run_rt3070_rf_write(sc, 8, rt3070_freqs[i].n); 3216faca41fbSmlelstv run_rt3070_rf_write(sc, 9, rt3070_freqs[i].k & 0x0f); 3217faca41fbSmlelstv run_rt3070_rf_read(sc, 11, &rf); 3218faca41fbSmlelstv rf = (rf & ~0x03) | (rt3070_freqs[i].r & 0x03); 3219faca41fbSmlelstv run_rt3070_rf_write(sc, 11, rf); 3220faca41fbSmlelstv 3221faca41fbSmlelstv /* Set pll_idoh. */ 3222faca41fbSmlelstv run_rt3070_rf_read(sc, 11, &rf); 3223faca41fbSmlelstv rf &= ~0x4c; 3224faca41fbSmlelstv rf |= (chan <= 14) ? 0x44 : 0x48; 3225faca41fbSmlelstv run_rt3070_rf_write(sc, 11, rf); 3226faca41fbSmlelstv 3227faca41fbSmlelstv if (chan <= 14) 3228faca41fbSmlelstv rf = txpow1 & 0x1f; 3229faca41fbSmlelstv else 3230faca41fbSmlelstv rf = 0x40 | ((txpow1 & 0x18) << 1) | (txpow1 & 0x07); 3231faca41fbSmlelstv run_rt3070_rf_write(sc, 53, rf); 3232faca41fbSmlelstv 3233faca41fbSmlelstv if (chan <= 14) 3234faca41fbSmlelstv rf = txpow2 & 0x1f; 3235faca41fbSmlelstv else 3236faca41fbSmlelstv rf = 0x40 | ((txpow2 & 0x18) << 1) | (txpow2 & 0x07); 3237faca41fbSmlelstv run_rt3070_rf_write(sc, 55, rf); 3238faca41fbSmlelstv 3239faca41fbSmlelstv if (chan <= 14) 3240faca41fbSmlelstv rf = txpow3 & 0x1f; 3241faca41fbSmlelstv else 3242faca41fbSmlelstv rf = 0x40 | ((txpow3 & 0x18) << 1) | (txpow3 & 0x07); 3243faca41fbSmlelstv run_rt3070_rf_write(sc, 54, rf); 3244faca41fbSmlelstv 3245faca41fbSmlelstv rf = RT3070_RF_BLOCK | RT3070_PLL_PD; 3246faca41fbSmlelstv if (sc->ntxchains == 3) 3247faca41fbSmlelstv rf |= RT3070_TX0_PD | RT3070_TX1_PD | RT3070_TX2_PD; 3248faca41fbSmlelstv else 3249faca41fbSmlelstv rf |= RT3070_TX0_PD | RT3070_TX1_PD; 3250faca41fbSmlelstv rf |= RT3070_RX0_PD | RT3070_RX1_PD | RT3070_RX2_PD; 3251faca41fbSmlelstv run_rt3070_rf_write(sc, 1, rf); 3252faca41fbSmlelstv 3253faca41fbSmlelstv run_adjust_freq_offset(sc); 3254faca41fbSmlelstv 3255faca41fbSmlelstv run_rt3070_rf_write(sc, 31, (chan <= 14) ? 0xa0 : 0x80); 3256faca41fbSmlelstv 3257faca41fbSmlelstv h20mhz = (sc->rf24_20mhz & 0x20) >> 5; 3258faca41fbSmlelstv run_rt3070_rf_read(sc, 30, &rf); 3259faca41fbSmlelstv rf = (rf & ~0x06) | (h20mhz << 1) | (h20mhz << 2); 3260faca41fbSmlelstv run_rt3070_rf_write(sc, 30, rf); 3261faca41fbSmlelstv 3262faca41fbSmlelstv run_rt3070_rf_read(sc, 36, &rf); 3263faca41fbSmlelstv if (chan <= 14) 3264faca41fbSmlelstv rf |= 0x80; 3265faca41fbSmlelstv else 3266faca41fbSmlelstv rf &= ~0x80; 3267faca41fbSmlelstv run_rt3070_rf_write(sc, 36, rf); 3268faca41fbSmlelstv 3269faca41fbSmlelstv /* Set vcolo_bs. */ 3270faca41fbSmlelstv run_rt3070_rf_write(sc, 34, (chan <= 14) ? 0x3c : 0x20); 3271faca41fbSmlelstv /* Set pfd_delay. */ 3272faca41fbSmlelstv run_rt3070_rf_write(sc, 12, (chan <= 14) ? 0x1a : 0x12); 3273faca41fbSmlelstv 3274faca41fbSmlelstv /* Set vco bias current control. */ 3275faca41fbSmlelstv run_rt3070_rf_read(sc, 6, &rf); 3276faca41fbSmlelstv rf &= ~0xc0; 3277faca41fbSmlelstv if (chan <= 14) 3278faca41fbSmlelstv rf |= 0x40; 3279faca41fbSmlelstv else if (chan <= 128) 3280faca41fbSmlelstv rf |= 0x80; 3281faca41fbSmlelstv else 3282faca41fbSmlelstv rf |= 0x40; 3283faca41fbSmlelstv run_rt3070_rf_write(sc, 6, rf); 3284faca41fbSmlelstv 3285faca41fbSmlelstv run_rt3070_rf_read(sc, 30, &rf); 3286faca41fbSmlelstv rf = (rf & ~0x18) | 0x10; 3287faca41fbSmlelstv run_rt3070_rf_write(sc, 30, rf); 3288faca41fbSmlelstv 3289faca41fbSmlelstv run_rt3070_rf_write(sc, 10, (chan <= 14) ? 0xd3 : 0xd8); 3290faca41fbSmlelstv run_rt3070_rf_write(sc, 13, (chan <= 14) ? 0x12 : 0x23); 3291faca41fbSmlelstv 3292faca41fbSmlelstv run_rt3070_rf_read(sc, 51, &rf); 3293faca41fbSmlelstv rf = (rf & ~0x03) | 0x01; 3294faca41fbSmlelstv run_rt3070_rf_write(sc, 51, rf); 3295faca41fbSmlelstv /* Set tx_mx1_cc. */ 3296faca41fbSmlelstv run_rt3070_rf_read(sc, 51, &rf); 3297faca41fbSmlelstv rf &= ~0x1c; 3298faca41fbSmlelstv rf |= (chan <= 14) ? 0x14 : 0x10; 3299faca41fbSmlelstv run_rt3070_rf_write(sc, 51, rf); 3300faca41fbSmlelstv /* Set tx_mx1_ic. */ 3301faca41fbSmlelstv run_rt3070_rf_read(sc, 51, &rf); 3302faca41fbSmlelstv rf &= ~0xe0; 3303faca41fbSmlelstv rf |= (chan <= 14) ? 0x60 : 0x40; 3304faca41fbSmlelstv run_rt3070_rf_write(sc, 51, rf); 3305faca41fbSmlelstv /* Set tx_lo1_ic. */ 3306faca41fbSmlelstv run_rt3070_rf_read(sc, 49, &rf); 3307faca41fbSmlelstv rf &= ~0x1c; 3308faca41fbSmlelstv rf |= (chan <= 14) ? 0x0c : 0x08; 3309faca41fbSmlelstv run_rt3070_rf_write(sc, 49, rf); 3310faca41fbSmlelstv /* Set tx_lo1_en. */ 3311faca41fbSmlelstv run_rt3070_rf_read(sc, 50, &rf); 3312faca41fbSmlelstv run_rt3070_rf_write(sc, 50, rf & ~0x20); 3313faca41fbSmlelstv /* Set drv_cc. */ 3314faca41fbSmlelstv run_rt3070_rf_read(sc, 57, &rf); 3315faca41fbSmlelstv rf &= ~0xfc; 3316faca41fbSmlelstv rf |= (chan <= 14) ? 0x6c : 0x3c; 3317faca41fbSmlelstv run_rt3070_rf_write(sc, 57, rf); 3318faca41fbSmlelstv /* Set rx_mix1_ic, rxa_lnactr, lna_vc, lna_inbias_en and lna_en. */ 3319faca41fbSmlelstv run_rt3070_rf_write(sc, 44, (chan <= 14) ? 0x93 : 0x9b); 3320faca41fbSmlelstv /* Set drv_gnd_a, tx_vga_cc_a and tx_mx2_gain. */ 3321faca41fbSmlelstv run_rt3070_rf_write(sc, 52, (chan <= 14) ? 0x45 : 0x05); 3322faca41fbSmlelstv /* Enable VCO calibration. */ 3323faca41fbSmlelstv run_rt3070_rf_read(sc, 3, &rf); 3324faca41fbSmlelstv rf &= ~RT5390_VCOCAL; 3325faca41fbSmlelstv rf |= (chan <= 14) ? RT5390_VCOCAL : 0xbe; 3326faca41fbSmlelstv run_rt3070_rf_write(sc, 3, rf); 3327faca41fbSmlelstv 3328faca41fbSmlelstv if (chan <= 14) 3329faca41fbSmlelstv rf = 0x23; 3330faca41fbSmlelstv else if (chan <= 64) 3331faca41fbSmlelstv rf = 0x36; 3332faca41fbSmlelstv else if (chan <= 128) 3333faca41fbSmlelstv rf = 0x32; 3334faca41fbSmlelstv else 3335faca41fbSmlelstv rf = 0x30; 3336faca41fbSmlelstv run_rt3070_rf_write(sc, 39, rf); 3337faca41fbSmlelstv if (chan <= 14) 3338faca41fbSmlelstv rf = 0xbb; 3339faca41fbSmlelstv else if (chan <= 64) 3340faca41fbSmlelstv rf = 0xeb; 3341faca41fbSmlelstv else if (chan <= 128) 3342faca41fbSmlelstv rf = 0xb3; 3343faca41fbSmlelstv else 3344faca41fbSmlelstv rf = 0x9b; 3345faca41fbSmlelstv run_rt3070_rf_write(sc, 45, rf); 3346faca41fbSmlelstv 3347faca41fbSmlelstv /* Set FEQ/AEQ control. */ 3348faca41fbSmlelstv run_bbp_write(sc, 105, 0x34); 3349faca41fbSmlelstv } 3350faca41fbSmlelstv 3351faca41fbSmlelstv static void 3352faca41fbSmlelstv run_rt5390_set_chan(struct run_softc *sc, u_int chan) 3353faca41fbSmlelstv { 3354faca41fbSmlelstv int8_t txpow1, txpow2; 3355faca41fbSmlelstv uint8_t rf; 3356faca41fbSmlelstv int i; 3357faca41fbSmlelstv 3358faca41fbSmlelstv /* find the settings for this channel (we know it exists) */ 3359faca41fbSmlelstv for (i = 0; rt2860_rf2850[i].chan != chan; i++); 3360faca41fbSmlelstv 3361faca41fbSmlelstv /* use Tx power values from EEPROM */ 3362faca41fbSmlelstv txpow1 = sc->txpow1[i]; 3363faca41fbSmlelstv txpow2 = sc->txpow2[i]; 3364faca41fbSmlelstv 3365faca41fbSmlelstv run_rt3070_rf_write(sc, 8, rt3070_freqs[i].n); 3366faca41fbSmlelstv run_rt3070_rf_write(sc, 9, rt3070_freqs[i].k & 0x0f); 3367faca41fbSmlelstv run_rt3070_rf_read(sc, 11, &rf); 3368faca41fbSmlelstv rf = (rf & ~0x03) | (rt3070_freqs[i].r & 0x03); 3369faca41fbSmlelstv run_rt3070_rf_write(sc, 11, rf); 3370faca41fbSmlelstv 3371faca41fbSmlelstv run_rt3070_rf_read(sc, 49, &rf); 3372faca41fbSmlelstv rf = (rf & ~0x3f) | (txpow1 & 0x3f); 3373faca41fbSmlelstv /* The valid range of the RF R49 is 0x00 to 0x27. */ 3374faca41fbSmlelstv if ((rf & 0x3f) > 0x27) 3375faca41fbSmlelstv rf = (rf & ~0x3f) | 0x27; 3376faca41fbSmlelstv run_rt3070_rf_write(sc, 49, rf); 3377faca41fbSmlelstv 3378faca41fbSmlelstv if (sc->mac_ver == 0x5392) { 3379faca41fbSmlelstv run_rt3070_rf_read(sc, 50, &rf); 3380faca41fbSmlelstv rf = (rf & ~0x3f) | (txpow2 & 0x3f); 3381faca41fbSmlelstv /* The valid range of the RF R50 is 0x00 to 0x27. */ 3382faca41fbSmlelstv if ((rf & 0x3f) > 0x27) 3383faca41fbSmlelstv rf = (rf & ~0x3f) | 0x27; 3384faca41fbSmlelstv run_rt3070_rf_write(sc, 50, rf); 3385faca41fbSmlelstv } 3386faca41fbSmlelstv 3387faca41fbSmlelstv run_rt3070_rf_read(sc, 1, &rf); 3388faca41fbSmlelstv rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD; 3389faca41fbSmlelstv if (sc->mac_ver == 0x5392) 3390faca41fbSmlelstv rf |= RT3070_RX1_PD | RT3070_TX1_PD; 3391faca41fbSmlelstv run_rt3070_rf_write(sc, 1, rf); 3392faca41fbSmlelstv 3393faca41fbSmlelstv if (sc->mac_ver != 0x5392) { 3394faca41fbSmlelstv run_rt3070_rf_read(sc, 2, &rf); 3395faca41fbSmlelstv rf |= 0x80; 3396faca41fbSmlelstv run_rt3070_rf_write(sc, 2, rf); 3397faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 3398faca41fbSmlelstv rf &= 0x7f; 3399faca41fbSmlelstv run_rt3070_rf_write(sc, 2, rf); 3400faca41fbSmlelstv } 3401faca41fbSmlelstv 3402faca41fbSmlelstv run_adjust_freq_offset(sc); 3403faca41fbSmlelstv 3404faca41fbSmlelstv if (sc->mac_ver == 0x5392) { 3405faca41fbSmlelstv /* Fix for RT5392C. */ 3406faca41fbSmlelstv if (sc->mac_rev >= 0x0223) { 3407faca41fbSmlelstv if (chan <= 4) 3408faca41fbSmlelstv rf = 0x0f; 3409faca41fbSmlelstv else if (chan >= 5 && chan <= 7) 3410faca41fbSmlelstv rf = 0x0e; 3411faca41fbSmlelstv else 3412faca41fbSmlelstv rf = 0x0d; 3413faca41fbSmlelstv run_rt3070_rf_write(sc, 23, rf); 3414faca41fbSmlelstv 3415faca41fbSmlelstv if (chan <= 4) 3416faca41fbSmlelstv rf = 0x0c; 3417faca41fbSmlelstv else if (chan == 5) 3418faca41fbSmlelstv rf = 0x0b; 3419faca41fbSmlelstv else if (chan >= 6 && chan <= 7) 3420faca41fbSmlelstv rf = 0x0a; 3421faca41fbSmlelstv else if (chan >= 8 && chan <= 10) 3422faca41fbSmlelstv rf = 0x09; 3423faca41fbSmlelstv else 3424faca41fbSmlelstv rf = 0x08; 3425faca41fbSmlelstv run_rt3070_rf_write(sc, 59, rf); 3426faca41fbSmlelstv } else { 3427faca41fbSmlelstv if (chan <= 11) 3428faca41fbSmlelstv rf = 0x0f; 3429faca41fbSmlelstv else 3430faca41fbSmlelstv rf = 0x0b; 3431faca41fbSmlelstv run_rt3070_rf_write(sc, 59, rf); 3432faca41fbSmlelstv } 3433faca41fbSmlelstv } else { 3434faca41fbSmlelstv /* Fix for RT5390F. */ 3435faca41fbSmlelstv if (sc->mac_rev >= 0x0502) { 3436faca41fbSmlelstv if (chan <= 11) 3437faca41fbSmlelstv rf = 0x43; 3438faca41fbSmlelstv else 3439faca41fbSmlelstv rf = 0x23; 3440faca41fbSmlelstv run_rt3070_rf_write(sc, 55, rf); 3441faca41fbSmlelstv 3442faca41fbSmlelstv if (chan <= 11) 3443faca41fbSmlelstv rf = 0x0f; 3444faca41fbSmlelstv else if (chan == 12) 3445faca41fbSmlelstv rf = 0x0d; 3446faca41fbSmlelstv else 3447faca41fbSmlelstv rf = 0x0b; 3448faca41fbSmlelstv run_rt3070_rf_write(sc, 59, rf); 3449faca41fbSmlelstv } else { 3450faca41fbSmlelstv run_rt3070_rf_write(sc, 55, 0x44); 3451faca41fbSmlelstv run_rt3070_rf_write(sc, 59, 0x8f); 3452faca41fbSmlelstv } 3453faca41fbSmlelstv } 3454faca41fbSmlelstv 3455faca41fbSmlelstv /* Enable VCO calibration. */ 3456faca41fbSmlelstv run_rt3070_rf_read(sc, 3, &rf); 3457faca41fbSmlelstv rf |= RT5390_VCOCAL; 3458faca41fbSmlelstv run_rt3070_rf_write(sc, 3, rf); 3459faca41fbSmlelstv } 3460faca41fbSmlelstv 3461faca41fbSmlelstv static void 3462faca41fbSmlelstv run_rt5592_set_chan(struct run_softc *sc, u_int chan) 3463faca41fbSmlelstv { 3464faca41fbSmlelstv const struct rt5592_freqs *freqs; 3465faca41fbSmlelstv uint32_t tmp; 3466faca41fbSmlelstv uint8_t reg, rf, txpow_bound; 3467faca41fbSmlelstv int8_t txpow1, txpow2; 3468faca41fbSmlelstv int i; 3469faca41fbSmlelstv 3470faca41fbSmlelstv run_read(sc, RT5592_DEBUG_INDEX, &tmp); 3471faca41fbSmlelstv freqs = (tmp & RT5592_SEL_XTAL) ? 3472faca41fbSmlelstv rt5592_freqs_40mhz : rt5592_freqs_20mhz; 3473faca41fbSmlelstv 3474faca41fbSmlelstv /* find the settings for this channel (we know it exists) */ 3475faca41fbSmlelstv for (i = 0; rt2860_rf2850[i].chan != chan; i++, freqs++); 3476faca41fbSmlelstv 3477faca41fbSmlelstv /* use Tx power values from EEPROM */ 3478faca41fbSmlelstv txpow1 = sc->txpow1[i]; 3479faca41fbSmlelstv txpow2 = sc->txpow2[i]; 3480faca41fbSmlelstv 3481faca41fbSmlelstv run_read(sc, RT3070_LDO_CFG0, &tmp); 3482faca41fbSmlelstv tmp &= ~0x1c000000; 3483faca41fbSmlelstv if (chan > 14) 3484faca41fbSmlelstv tmp |= 0x14000000; 3485faca41fbSmlelstv run_write(sc, RT3070_LDO_CFG0, tmp); 3486faca41fbSmlelstv 3487faca41fbSmlelstv /* N setting. */ 3488faca41fbSmlelstv run_rt3070_rf_write(sc, 8, freqs->n & 0xff); 3489faca41fbSmlelstv run_rt3070_rf_read(sc, 9, &rf); 3490faca41fbSmlelstv rf &= ~(1 << 4); 3491faca41fbSmlelstv rf |= ((freqs->n & 0x0100) >> 8) << 4; 3492faca41fbSmlelstv run_rt3070_rf_write(sc, 9, rf); 3493faca41fbSmlelstv 3494faca41fbSmlelstv /* K setting. */ 3495faca41fbSmlelstv run_rt3070_rf_read(sc, 9, &rf); 3496faca41fbSmlelstv rf &= ~0x0f; 3497faca41fbSmlelstv rf |= (freqs->k & 0x0f); 3498faca41fbSmlelstv run_rt3070_rf_write(sc, 9, rf); 3499faca41fbSmlelstv 3500faca41fbSmlelstv /* Mode setting. */ 3501faca41fbSmlelstv run_rt3070_rf_read(sc, 11, &rf); 3502faca41fbSmlelstv rf &= ~0x0c; 3503faca41fbSmlelstv rf |= ((freqs->m - 0x8) & 0x3) << 2; 3504faca41fbSmlelstv run_rt3070_rf_write(sc, 11, rf); 3505faca41fbSmlelstv run_rt3070_rf_read(sc, 9, &rf); 3506faca41fbSmlelstv rf &= ~(1 << 7); 3507faca41fbSmlelstv rf |= (((freqs->m - 0x8) & 0x4) >> 2) << 7; 3508faca41fbSmlelstv run_rt3070_rf_write(sc, 9, rf); 3509faca41fbSmlelstv 3510faca41fbSmlelstv /* R setting. */ 3511faca41fbSmlelstv run_rt3070_rf_read(sc, 11, &rf); 3512faca41fbSmlelstv rf &= ~0x03; 3513faca41fbSmlelstv rf |= (freqs->r - 0x1); 3514faca41fbSmlelstv run_rt3070_rf_write(sc, 11, rf); 3515faca41fbSmlelstv 3516faca41fbSmlelstv if (chan <= 14) { 3517faca41fbSmlelstv /* Initialize RF registers for 2GHZ. */ 3518faca41fbSmlelstv for (i = 0; i < (int)__arraycount(rt5592_2ghz_def_rf); i++) { 3519faca41fbSmlelstv run_rt3070_rf_write(sc, rt5592_2ghz_def_rf[i].reg, 3520faca41fbSmlelstv rt5592_2ghz_def_rf[i].val); 3521faca41fbSmlelstv } 3522faca41fbSmlelstv 3523faca41fbSmlelstv rf = (chan <= 10) ? 0x07 : 0x06; 3524faca41fbSmlelstv run_rt3070_rf_write(sc, 23, rf); 3525faca41fbSmlelstv run_rt3070_rf_write(sc, 59, rf); 3526faca41fbSmlelstv 3527faca41fbSmlelstv run_rt3070_rf_write(sc, 55, 0x43); 3528faca41fbSmlelstv 3529faca41fbSmlelstv /* 3530faca41fbSmlelstv * RF R49/R50 Tx power ALC code. 3531faca41fbSmlelstv * G-band bit<7:6>=1:0, bit<5:0> range from 0x0 ~ 0x27. 3532faca41fbSmlelstv */ 3533faca41fbSmlelstv reg = 2; 3534faca41fbSmlelstv txpow_bound = 0x27; 3535faca41fbSmlelstv } else { 3536faca41fbSmlelstv /* Initialize RF registers for 5GHZ. */ 3537faca41fbSmlelstv for (i = 0; i < (int)__arraycount(rt5592_5ghz_def_rf); i++) { 3538faca41fbSmlelstv run_rt3070_rf_write(sc, rt5592_5ghz_def_rf[i].reg, 3539faca41fbSmlelstv rt5592_5ghz_def_rf[i].val); 3540faca41fbSmlelstv } 3541faca41fbSmlelstv for (i = 0; i < (int)__arraycount(rt5592_chan_5ghz); i++) { 3542faca41fbSmlelstv if (chan >= rt5592_chan_5ghz[i].firstchan && 3543faca41fbSmlelstv chan <= rt5592_chan_5ghz[i].lastchan) { 3544faca41fbSmlelstv run_rt3070_rf_write(sc, rt5592_chan_5ghz[i].reg, 3545faca41fbSmlelstv rt5592_chan_5ghz[i].val); 3546faca41fbSmlelstv } 3547faca41fbSmlelstv } 3548faca41fbSmlelstv 3549faca41fbSmlelstv /* 3550faca41fbSmlelstv * RF R49/R50 Tx power ALC code. 3551faca41fbSmlelstv * A-band bit<7:6>=1:1, bit<5:0> range from 0x0 ~ 0x2b. 3552faca41fbSmlelstv */ 3553faca41fbSmlelstv reg = 3; 3554faca41fbSmlelstv txpow_bound = 0x2b; 3555faca41fbSmlelstv } 3556faca41fbSmlelstv 3557faca41fbSmlelstv /* RF R49 ch0 Tx power ALC code. */ 3558faca41fbSmlelstv run_rt3070_rf_read(sc, 49, &rf); 3559faca41fbSmlelstv rf &= ~0xc0; 3560faca41fbSmlelstv rf |= (reg << 6); 3561faca41fbSmlelstv rf = (rf & ~0x3f) | (txpow1 & 0x3f); 3562faca41fbSmlelstv if ((rf & 0x3f) > txpow_bound) 3563faca41fbSmlelstv rf = (rf & ~0x3f) | txpow_bound; 3564faca41fbSmlelstv run_rt3070_rf_write(sc, 49, rf); 3565faca41fbSmlelstv 3566faca41fbSmlelstv /* RF R50 ch1 Tx power ALC code. */ 3567faca41fbSmlelstv run_rt3070_rf_read(sc, 50, &rf); 3568faca41fbSmlelstv rf &= ~(1 << 7 | 1 << 6); 3569faca41fbSmlelstv rf |= (reg << 6); 3570faca41fbSmlelstv rf = (rf & ~0x3f) | (txpow2 & 0x3f); 3571faca41fbSmlelstv if ((rf & 0x3f) > txpow_bound) 3572faca41fbSmlelstv rf = (rf & ~0x3f) | txpow_bound; 3573faca41fbSmlelstv run_rt3070_rf_write(sc, 50, rf); 3574faca41fbSmlelstv 3575faca41fbSmlelstv /* Enable RF_BLOCK, PLL_PD, RX0_PD, and TX0_PD. */ 3576faca41fbSmlelstv run_rt3070_rf_read(sc, 1, &rf); 3577faca41fbSmlelstv rf |= (RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD); 3578faca41fbSmlelstv if (sc->ntxchains > 1) 3579faca41fbSmlelstv rf |= RT3070_TX1_PD; 3580faca41fbSmlelstv if (sc->nrxchains > 1) 3581faca41fbSmlelstv rf |= RT3070_RX1_PD; 3582faca41fbSmlelstv run_rt3070_rf_write(sc, 1, rf); 3583faca41fbSmlelstv 3584faca41fbSmlelstv run_rt3070_rf_write(sc, 6, 0xe4); 3585faca41fbSmlelstv 3586faca41fbSmlelstv run_rt3070_rf_write(sc, 30, 0x10); 3587faca41fbSmlelstv run_rt3070_rf_write(sc, 31, 0x80); 3588faca41fbSmlelstv run_rt3070_rf_write(sc, 32, 0x80); 3589faca41fbSmlelstv 3590faca41fbSmlelstv run_adjust_freq_offset(sc); 3591faca41fbSmlelstv 3592faca41fbSmlelstv /* Enable VCO calibration. */ 3593faca41fbSmlelstv run_rt3070_rf_read(sc, 3, &rf); 3594faca41fbSmlelstv rf |= RT5390_VCOCAL; 3595faca41fbSmlelstv run_rt3070_rf_write(sc, 3, rf); 3596faca41fbSmlelstv } 3597faca41fbSmlelstv 3598faca41fbSmlelstv static void 3599faca41fbSmlelstv run_iq_calib(struct run_softc *sc, u_int chan) 3600faca41fbSmlelstv { 3601faca41fbSmlelstv uint16_t val; 3602faca41fbSmlelstv 3603faca41fbSmlelstv /* Tx0 IQ gain. */ 3604faca41fbSmlelstv run_bbp_write(sc, 158, 0x2c); 3605faca41fbSmlelstv if (chan <= 14) 3606faca41fbSmlelstv run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX0_2GHZ, &val, 1); 3607faca41fbSmlelstv else if (chan <= 64) { 3608faca41fbSmlelstv run_efuse_read(sc, 3609faca41fbSmlelstv RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ, 3610faca41fbSmlelstv &val, 1); 3611faca41fbSmlelstv } else if (chan <= 138) { 3612faca41fbSmlelstv run_efuse_read(sc, 3613faca41fbSmlelstv RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ, 3614faca41fbSmlelstv &val, 1); 3615faca41fbSmlelstv } else if (chan <= 165) { 3616faca41fbSmlelstv run_efuse_read(sc, 3617faca41fbSmlelstv RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ, 3618faca41fbSmlelstv &val, 1); 3619faca41fbSmlelstv } else 3620faca41fbSmlelstv val = 0; 3621faca41fbSmlelstv run_bbp_write(sc, 159, val); 3622faca41fbSmlelstv 3623faca41fbSmlelstv /* Tx0 IQ phase. */ 3624faca41fbSmlelstv run_bbp_write(sc, 158, 0x2d); 3625faca41fbSmlelstv if (chan <= 14) { 3626faca41fbSmlelstv run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX0_2GHZ, 3627faca41fbSmlelstv &val, 1); 3628faca41fbSmlelstv } else if (chan <= 64) { 3629faca41fbSmlelstv run_efuse_read(sc, 3630faca41fbSmlelstv RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ, 3631faca41fbSmlelstv &val, 1); 3632faca41fbSmlelstv } else if (chan <= 138) { 3633faca41fbSmlelstv run_efuse_read(sc, 3634faca41fbSmlelstv RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ, 3635faca41fbSmlelstv &val, 1); 3636faca41fbSmlelstv } else if (chan <= 165) { 3637faca41fbSmlelstv run_efuse_read(sc, 3638faca41fbSmlelstv RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ, 3639faca41fbSmlelstv &val, 1); 3640faca41fbSmlelstv } else 3641faca41fbSmlelstv val = 0; 3642faca41fbSmlelstv run_bbp_write(sc, 159, val); 3643faca41fbSmlelstv 3644faca41fbSmlelstv /* Tx1 IQ gain. */ 3645faca41fbSmlelstv run_bbp_write(sc, 158, 0x4a); 3646faca41fbSmlelstv if (chan <= 14) { 3647faca41fbSmlelstv run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX1_2GHZ, 3648faca41fbSmlelstv &val, 1); 3649faca41fbSmlelstv } else if (chan <= 64) { 3650faca41fbSmlelstv run_efuse_read(sc, 3651faca41fbSmlelstv RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ, 3652faca41fbSmlelstv &val, 1); 3653faca41fbSmlelstv } else if (chan <= 138) { 3654faca41fbSmlelstv run_efuse_read(sc, 3655faca41fbSmlelstv RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ, 3656faca41fbSmlelstv &val, 1); 3657faca41fbSmlelstv } else if (chan <= 165) { 3658faca41fbSmlelstv run_efuse_read(sc, 3659faca41fbSmlelstv RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ, 3660faca41fbSmlelstv &val, 1); 3661faca41fbSmlelstv } else 3662faca41fbSmlelstv val = 0; 3663faca41fbSmlelstv run_bbp_write(sc, 159, val); 3664faca41fbSmlelstv 3665faca41fbSmlelstv /* Tx1 IQ phase. */ 3666faca41fbSmlelstv run_bbp_write(sc, 158, 0x4b); 3667faca41fbSmlelstv if (chan <= 14) { 3668faca41fbSmlelstv run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX1_2GHZ, 3669faca41fbSmlelstv &val, 1); 3670faca41fbSmlelstv } else if (chan <= 64) { 3671faca41fbSmlelstv run_efuse_read(sc, 3672faca41fbSmlelstv RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ, 3673faca41fbSmlelstv &val, 1); 3674faca41fbSmlelstv } else if (chan <= 138) { 3675faca41fbSmlelstv run_efuse_read(sc, 3676faca41fbSmlelstv RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ, 3677faca41fbSmlelstv &val, 1); 3678faca41fbSmlelstv } else if (chan <= 165) { 3679faca41fbSmlelstv run_efuse_read(sc, 3680faca41fbSmlelstv RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ, 3681faca41fbSmlelstv &val, 1); 3682faca41fbSmlelstv } else 3683faca41fbSmlelstv val = 0; 3684faca41fbSmlelstv run_bbp_write(sc, 159, val); 3685faca41fbSmlelstv 3686faca41fbSmlelstv /* RF IQ compensation control. */ 3687faca41fbSmlelstv run_bbp_write(sc, 158, 0x04); 3688faca41fbSmlelstv run_efuse_read(sc, RT5390_EEPROM_RF_IQ_COMPENSATION_CTL, 3689faca41fbSmlelstv &val, 1); 3690faca41fbSmlelstv run_bbp_write(sc, 159, val); 3691faca41fbSmlelstv 3692faca41fbSmlelstv /* RF IQ imbalance compensation control. */ 3693faca41fbSmlelstv run_bbp_write(sc, 158, 0x03); 3694faca41fbSmlelstv run_efuse_read(sc, 3695faca41fbSmlelstv RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL, &val, 1); 3696faca41fbSmlelstv run_bbp_write(sc, 159, val); 36979cdb1c70Snonaka } 36989cdb1c70Snonaka 36999cdb1c70Snonaka static void 37009cdb1c70Snonaka run_set_agc(struct run_softc *sc, uint8_t agc) 37019cdb1c70Snonaka { 37029cdb1c70Snonaka uint8_t bbp; 37039cdb1c70Snonaka 37049cdb1c70Snonaka if (sc->mac_ver == 0x3572) { 37059cdb1c70Snonaka run_bbp_read(sc, 27, &bbp); 37069cdb1c70Snonaka bbp &= ~(0x3 << 5); 37079cdb1c70Snonaka run_bbp_write(sc, 27, bbp | 0 << 5); /* select Rx0 */ 37089cdb1c70Snonaka run_bbp_write(sc, 66, agc); 37099cdb1c70Snonaka run_bbp_write(sc, 27, bbp | 1 << 5); /* select Rx1 */ 37109cdb1c70Snonaka run_bbp_write(sc, 66, agc); 37119cdb1c70Snonaka } else 37129cdb1c70Snonaka run_bbp_write(sc, 66, agc); 37139cdb1c70Snonaka } 37149cdb1c70Snonaka 37159cdb1c70Snonaka static void 37169cdb1c70Snonaka run_set_rx_antenna(struct run_softc *sc, int aux) 37179cdb1c70Snonaka { 37189cdb1c70Snonaka uint32_t tmp; 3719faca41fbSmlelstv uint8_t bbp152; 37209cdb1c70Snonaka 3721d164e220Smlelstv if (aux) { 3722faca41fbSmlelstv if (sc->rf_rev == RT5390_RF_5370) { 3723faca41fbSmlelstv run_bbp_read(sc, 152, &bbp152); 3724faca41fbSmlelstv bbp152 &= ~0x80; 3725d164e220Smlelstv run_bbp_write(sc, 152, bbp152); 3726d164e220Smlelstv } else { 3727d164e220Smlelstv run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, 0); 3728d164e220Smlelstv run_read(sc, RT2860_GPIO_CTRL, &tmp); 3729d164e220Smlelstv tmp &= ~0x0808; 3730d164e220Smlelstv tmp |= 0x08; 3731d164e220Smlelstv run_write(sc, RT2860_GPIO_CTRL, tmp); 3732d164e220Smlelstv } 3733d164e220Smlelstv } else { 3734d164e220Smlelstv if (sc->rf_rev == RT5390_RF_5370) { 3735d164e220Smlelstv run_bbp_read(sc, 152, &bbp152); 3736faca41fbSmlelstv bbp152 |= 0x80; 3737faca41fbSmlelstv run_bbp_write(sc, 152, bbp152); 3738faca41fbSmlelstv } else { 37399cdb1c70Snonaka run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, !aux); 37409cdb1c70Snonaka run_read(sc, RT2860_GPIO_CTRL, &tmp); 37419cdb1c70Snonaka tmp &= ~0x0808; 37429cdb1c70Snonaka run_write(sc, RT2860_GPIO_CTRL, tmp); 37439cdb1c70Snonaka } 3744faca41fbSmlelstv } 3745d164e220Smlelstv } 37469cdb1c70Snonaka 37479cdb1c70Snonaka static int 37489cdb1c70Snonaka run_set_chan(struct run_softc *sc, struct ieee80211_channel *c) 37499cdb1c70Snonaka { 37509cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 37519cdb1c70Snonaka u_int chan, group; 37529cdb1c70Snonaka 37539cdb1c70Snonaka chan = ieee80211_chan2ieee(ic, c); 37549cdb1c70Snonaka if (chan == 0 || chan == IEEE80211_CHAN_ANY) 37554e8e6643Sskrll return EINVAL; 37569cdb1c70Snonaka 3757faca41fbSmlelstv if (sc->mac_ver == 0x5592) 3758faca41fbSmlelstv run_rt5592_set_chan(sc, chan); 3759faca41fbSmlelstv else if (sc->mac_ver >= 0x5390) 3760faca41fbSmlelstv run_rt5390_set_chan(sc, chan); 3761faca41fbSmlelstv else if (sc->mac_ver == 0x3593) 3762faca41fbSmlelstv run_rt3593_set_chan(sc, chan); 3763faca41fbSmlelstv else if (sc->mac_ver == 0x3572) 37649cdb1c70Snonaka run_rt3572_set_chan(sc, chan); 37659cdb1c70Snonaka else if (sc->mac_ver >= 0x3070) 37669cdb1c70Snonaka run_rt3070_set_chan(sc, chan); 37679cdb1c70Snonaka else 37689cdb1c70Snonaka run_rt2870_set_chan(sc, chan); 37699cdb1c70Snonaka 37709cdb1c70Snonaka /* determine channel group */ 37719cdb1c70Snonaka if (chan <= 14) 37729cdb1c70Snonaka group = 0; 37739cdb1c70Snonaka else if (chan <= 64) 37749cdb1c70Snonaka group = 1; 37759cdb1c70Snonaka else if (chan <= 128) 37769cdb1c70Snonaka group = 2; 37779cdb1c70Snonaka else 37789cdb1c70Snonaka group = 3; 37799cdb1c70Snonaka 37809cdb1c70Snonaka /* XXX necessary only when group has changed! */ 37819cdb1c70Snonaka run_select_chan_group(sc, group); 37829cdb1c70Snonaka 3783faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 3784faca41fbSmlelstv 3785faca41fbSmlelstv /* Perform IQ calibration. */ 3786faca41fbSmlelstv if (sc->mac_ver >= 0x5392) 3787faca41fbSmlelstv run_iq_calib(sc, chan); 3788faca41fbSmlelstv 37894e8e6643Sskrll return 0; 37909cdb1c70Snonaka } 37919cdb1c70Snonaka 37929cdb1c70Snonaka static void 3793faca41fbSmlelstv run_updateprot(struct run_softc *sc) 3794faca41fbSmlelstv { 3795faca41fbSmlelstv struct ieee80211com *ic = &sc->sc_ic; 3796faca41fbSmlelstv uint32_t tmp; 3797faca41fbSmlelstv 3798faca41fbSmlelstv tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL; 3799faca41fbSmlelstv /* setup protection frame rate (MCS code) */ 3800faca41fbSmlelstv tmp |= (ic->ic_curmode == IEEE80211_MODE_11A) ? 3801faca41fbSmlelstv rt2860_rates[RT2860_RIDX_OFDM6].mcs | RT2860_PHY_OFDM : 3802faca41fbSmlelstv rt2860_rates[RT2860_RIDX_CCK11].mcs; 3803faca41fbSmlelstv 3804faca41fbSmlelstv /* CCK frames don't require protection */ 3805faca41fbSmlelstv run_write(sc, RT2860_CCK_PROT_CFG, tmp); 3806faca41fbSmlelstv if (ic->ic_flags & IEEE80211_F_USEPROT) { 3807faca41fbSmlelstv if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) 3808faca41fbSmlelstv tmp |= RT2860_PROT_CTRL_RTS_CTS; 3809faca41fbSmlelstv else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) 3810faca41fbSmlelstv tmp |= RT2860_PROT_CTRL_CTS; 3811faca41fbSmlelstv } 3812faca41fbSmlelstv run_write(sc, RT2860_OFDM_PROT_CFG, tmp); 3813faca41fbSmlelstv } 3814faca41fbSmlelstv 3815faca41fbSmlelstv static void 38169cdb1c70Snonaka run_enable_tsf_sync(struct run_softc *sc) 38179cdb1c70Snonaka { 38189cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 38199cdb1c70Snonaka uint32_t tmp; 38209cdb1c70Snonaka 38219cdb1c70Snonaka run_read(sc, RT2860_BCN_TIME_CFG, &tmp); 38229cdb1c70Snonaka tmp &= ~0x1fffff; 38239cdb1c70Snonaka tmp |= ic->ic_bss->ni_intval * 16; 38249cdb1c70Snonaka tmp |= RT2860_TSF_TIMER_EN | RT2860_TBTT_TIMER_EN; 38259cdb1c70Snonaka if (ic->ic_opmode == IEEE80211_M_STA) { 38269cdb1c70Snonaka /* 38279cdb1c70Snonaka * Local TSF is always updated with remote TSF on beacon 38289cdb1c70Snonaka * reception. 38299cdb1c70Snonaka */ 38309cdb1c70Snonaka tmp |= 1 << RT2860_TSF_SYNC_MODE_SHIFT; 38319cdb1c70Snonaka } 38329cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY 38339cdb1c70Snonaka else if (ic->ic_opmode == IEEE80211_M_IBSS) { 38349cdb1c70Snonaka tmp |= RT2860_BCN_TX_EN; 38359cdb1c70Snonaka /* 38369cdb1c70Snonaka * Local TSF is updated with remote TSF on beacon reception 38379cdb1c70Snonaka * only if the remote TSF is greater than local TSF. 38389cdb1c70Snonaka */ 38399cdb1c70Snonaka tmp |= 2 << RT2860_TSF_SYNC_MODE_SHIFT; 38409cdb1c70Snonaka } else if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 38419cdb1c70Snonaka tmp |= RT2860_BCN_TX_EN; 38429cdb1c70Snonaka /* SYNC with nobody */ 38439cdb1c70Snonaka tmp |= 3 << RT2860_TSF_SYNC_MODE_SHIFT; 38449cdb1c70Snonaka } 38459cdb1c70Snonaka #endif 38469cdb1c70Snonaka run_write(sc, RT2860_BCN_TIME_CFG, tmp); 38479cdb1c70Snonaka } 38489cdb1c70Snonaka 38499cdb1c70Snonaka static void 38509cdb1c70Snonaka run_enable_mrr(struct run_softc *sc) 38519cdb1c70Snonaka { 38529cdb1c70Snonaka #define CCK(mcs) (mcs) 38539cdb1c70Snonaka #define OFDM(mcs) (1 << 3 | (mcs)) 38549cdb1c70Snonaka run_write(sc, RT2860_LG_FBK_CFG0, 38559cdb1c70Snonaka OFDM(6) << 28 | /* 54->48 */ 38569cdb1c70Snonaka OFDM(5) << 24 | /* 48->36 */ 38579cdb1c70Snonaka OFDM(4) << 20 | /* 36->24 */ 38589cdb1c70Snonaka OFDM(3) << 16 | /* 24->18 */ 38599cdb1c70Snonaka OFDM(2) << 12 | /* 18->12 */ 38609cdb1c70Snonaka OFDM(1) << 8 | /* 12-> 9 */ 38619cdb1c70Snonaka OFDM(0) << 4 | /* 9-> 6 */ 38629cdb1c70Snonaka OFDM(0)); /* 6-> 6 */ 38639cdb1c70Snonaka 38649cdb1c70Snonaka run_write(sc, RT2860_LG_FBK_CFG1, 38659cdb1c70Snonaka CCK(2) << 12 | /* 11->5.5 */ 38669cdb1c70Snonaka CCK(1) << 8 | /* 5.5-> 2 */ 38679cdb1c70Snonaka CCK(0) << 4 | /* 2-> 1 */ 38689cdb1c70Snonaka CCK(0)); /* 1-> 1 */ 38699cdb1c70Snonaka #undef OFDM 38709cdb1c70Snonaka #undef CCK 38719cdb1c70Snonaka } 38729cdb1c70Snonaka 38739cdb1c70Snonaka static void 38749cdb1c70Snonaka run_set_txpreamble(struct run_softc *sc) 38759cdb1c70Snonaka { 38769cdb1c70Snonaka uint32_t tmp; 38779cdb1c70Snonaka 38789cdb1c70Snonaka run_read(sc, RT2860_AUTO_RSP_CFG, &tmp); 38799cdb1c70Snonaka if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE) 38809cdb1c70Snonaka tmp |= RT2860_CCK_SHORT_EN; 38819cdb1c70Snonaka else 38829cdb1c70Snonaka tmp &= ~RT2860_CCK_SHORT_EN; 38839cdb1c70Snonaka run_write(sc, RT2860_AUTO_RSP_CFG, tmp); 38849cdb1c70Snonaka } 38859cdb1c70Snonaka 38869cdb1c70Snonaka static void 38879cdb1c70Snonaka run_set_basicrates(struct run_softc *sc) 38889cdb1c70Snonaka { 38899cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 38909cdb1c70Snonaka 38919cdb1c70Snonaka /* set basic rates mask */ 38929cdb1c70Snonaka if (ic->ic_curmode == IEEE80211_MODE_11B) 38939cdb1c70Snonaka run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x003); 38949cdb1c70Snonaka else if (ic->ic_curmode == IEEE80211_MODE_11A) 38959cdb1c70Snonaka run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x150); 38969cdb1c70Snonaka else /* 11g */ 38979cdb1c70Snonaka run_write(sc, RT2860_LEGACY_BASIC_RATE, 0x15f); 38989cdb1c70Snonaka } 38999cdb1c70Snonaka 39009cdb1c70Snonaka static void 39019cdb1c70Snonaka run_set_leds(struct run_softc *sc, uint16_t which) 39029cdb1c70Snonaka { 39039cdb1c70Snonaka 39049cdb1c70Snonaka (void)run_mcu_cmd(sc, RT2860_MCU_CMD_LEDS, 39059cdb1c70Snonaka which | (sc->leds & 0x7f)); 39069cdb1c70Snonaka } 39079cdb1c70Snonaka 39089cdb1c70Snonaka static void 39099cdb1c70Snonaka run_set_bssid(struct run_softc *sc, const uint8_t *bssid) 39109cdb1c70Snonaka { 39119cdb1c70Snonaka 39129cdb1c70Snonaka run_write(sc, RT2860_MAC_BSSID_DW0, 39139cdb1c70Snonaka bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24); 39149cdb1c70Snonaka run_write(sc, RT2860_MAC_BSSID_DW1, 39159cdb1c70Snonaka bssid[4] | bssid[5] << 8); 39169cdb1c70Snonaka } 39179cdb1c70Snonaka 39189cdb1c70Snonaka static void 39199cdb1c70Snonaka run_set_macaddr(struct run_softc *sc, const uint8_t *addr) 39209cdb1c70Snonaka { 39219cdb1c70Snonaka 39229cdb1c70Snonaka run_write(sc, RT2860_MAC_ADDR_DW0, 39239cdb1c70Snonaka addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24); 39249cdb1c70Snonaka run_write(sc, RT2860_MAC_ADDR_DW1, 39259cdb1c70Snonaka addr[4] | addr[5] << 8 | 0xff << 16); 39269cdb1c70Snonaka } 39279cdb1c70Snonaka 39289cdb1c70Snonaka static void 39299cdb1c70Snonaka run_updateslot(struct ifnet *ifp) 39309cdb1c70Snonaka { 39319cdb1c70Snonaka 39329cdb1c70Snonaka /* do it in a process context */ 39339cdb1c70Snonaka run_do_async(ifp->if_softc, run_updateslot_cb, NULL, 0); 39349cdb1c70Snonaka } 39359cdb1c70Snonaka 39369cdb1c70Snonaka /* ARGSUSED */ 39379cdb1c70Snonaka static void 39389cdb1c70Snonaka run_updateslot_cb(struct run_softc *sc, void *arg) 39399cdb1c70Snonaka { 39409cdb1c70Snonaka uint32_t tmp; 39419cdb1c70Snonaka 39429cdb1c70Snonaka run_read(sc, RT2860_BKOFF_SLOT_CFG, &tmp); 39439cdb1c70Snonaka tmp &= ~0xff; 39449cdb1c70Snonaka tmp |= (sc->sc_ic.ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; 39459cdb1c70Snonaka run_write(sc, RT2860_BKOFF_SLOT_CFG, tmp); 39469cdb1c70Snonaka } 39479cdb1c70Snonaka 39489cdb1c70Snonaka static int8_t 39499cdb1c70Snonaka run_rssi2dbm(struct run_softc *sc, uint8_t rssi, uint8_t rxchain) 39509cdb1c70Snonaka { 39519cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 39529cdb1c70Snonaka struct ieee80211_channel *c = ic->ic_curchan; 39539cdb1c70Snonaka int delta; 39549cdb1c70Snonaka 39559cdb1c70Snonaka if (IEEE80211_IS_CHAN_5GHZ(c)) { 39569cdb1c70Snonaka u_int chan = ieee80211_chan2ieee(ic, c); 39579cdb1c70Snonaka delta = sc->rssi_5ghz[rxchain]; 39589cdb1c70Snonaka 39599cdb1c70Snonaka /* determine channel group */ 39609cdb1c70Snonaka if (chan <= 64) 39619cdb1c70Snonaka delta -= sc->lna[1]; 39629cdb1c70Snonaka else if (chan <= 128) 39639cdb1c70Snonaka delta -= sc->lna[2]; 39649cdb1c70Snonaka else 39659cdb1c70Snonaka delta -= sc->lna[3]; 39669cdb1c70Snonaka } else 39679cdb1c70Snonaka delta = sc->rssi_2ghz[rxchain] - sc->lna[0]; 39689cdb1c70Snonaka 39694e8e6643Sskrll return -12 - delta - rssi; 39709cdb1c70Snonaka } 39719cdb1c70Snonaka 3972faca41fbSmlelstv static void 3973faca41fbSmlelstv run_rt5390_bbp_init(struct run_softc *sc) 3974faca41fbSmlelstv { 3975faca41fbSmlelstv u_int i; 3976faca41fbSmlelstv uint8_t bbp; 3977faca41fbSmlelstv 3978faca41fbSmlelstv /* Apply maximum likelihood detection for 2 stream case. */ 3979faca41fbSmlelstv run_bbp_read(sc, 105, &bbp); 3980faca41fbSmlelstv if (sc->nrxchains > 1) 3981faca41fbSmlelstv run_bbp_write(sc, 105, bbp | RT5390_MLD); 3982faca41fbSmlelstv 3983faca41fbSmlelstv /* Avoid data lost and CRC error. */ 3984faca41fbSmlelstv run_bbp_read(sc, 4, &bbp); 3985faca41fbSmlelstv run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL); 3986faca41fbSmlelstv 3987faca41fbSmlelstv if (sc->mac_ver == 0x5592) { 3988faca41fbSmlelstv for (i = 0; i < (int)__arraycount(rt5592_def_bbp); i++) { 3989faca41fbSmlelstv run_bbp_write(sc, rt5592_def_bbp[i].reg, 3990faca41fbSmlelstv rt5592_def_bbp[i].val); 3991faca41fbSmlelstv } 3992faca41fbSmlelstv for (i = 0; i < (int)__arraycount(rt5592_bbp_r196); i++) { 3993faca41fbSmlelstv run_bbp_write(sc, 195, i + 0x80); 3994faca41fbSmlelstv run_bbp_write(sc, 196, rt5592_bbp_r196[i]); 3995faca41fbSmlelstv } 3996faca41fbSmlelstv } else { 3997faca41fbSmlelstv for (i = 0; i < (int)__arraycount(rt5390_def_bbp); i++) { 3998faca41fbSmlelstv run_bbp_write(sc, rt5390_def_bbp[i].reg, 3999faca41fbSmlelstv rt5390_def_bbp[i].val); 4000faca41fbSmlelstv } 4001faca41fbSmlelstv } 4002faca41fbSmlelstv if (sc->mac_ver == 0x5392) { 4003faca41fbSmlelstv run_bbp_write(sc, 88, 0x90); 4004faca41fbSmlelstv run_bbp_write(sc, 95, 0x9a); 4005faca41fbSmlelstv run_bbp_write(sc, 98, 0x12); 4006faca41fbSmlelstv run_bbp_write(sc, 106, 0x12); 4007faca41fbSmlelstv run_bbp_write(sc, 134, 0xd0); 4008faca41fbSmlelstv run_bbp_write(sc, 135, 0xf6); 4009faca41fbSmlelstv run_bbp_write(sc, 148, 0x84); 4010faca41fbSmlelstv } 4011faca41fbSmlelstv 4012faca41fbSmlelstv run_bbp_read(sc, 152, &bbp); 4013faca41fbSmlelstv run_bbp_write(sc, 152, bbp | 0x80); 4014faca41fbSmlelstv 4015faca41fbSmlelstv /* Fix BBP254 for RT5592C. */ 4016faca41fbSmlelstv if (sc->mac_ver == 0x5592 && sc->mac_rev >= 0x0221) { 4017faca41fbSmlelstv run_bbp_read(sc, 254, &bbp); 4018faca41fbSmlelstv run_bbp_write(sc, 254, bbp | 0x80); 4019faca41fbSmlelstv } 4020faca41fbSmlelstv 4021faca41fbSmlelstv /* Disable hardware antenna diversity. */ 4022faca41fbSmlelstv if (sc->mac_ver == 0x5390) 4023faca41fbSmlelstv run_bbp_write(sc, 154, 0); 4024faca41fbSmlelstv 4025faca41fbSmlelstv /* Initialize Rx CCK/OFDM frequency offset report. */ 4026faca41fbSmlelstv run_bbp_write(sc, 142, 1); 4027faca41fbSmlelstv run_bbp_write(sc, 143, 57); 4028faca41fbSmlelstv } 4029faca41fbSmlelstv 40309cdb1c70Snonaka static int 40319cdb1c70Snonaka run_bbp_init(struct run_softc *sc) 40329cdb1c70Snonaka { 40339cdb1c70Snonaka int i, error, ntries; 40349cdb1c70Snonaka uint8_t bbp0; 40359cdb1c70Snonaka 40369cdb1c70Snonaka /* wait for BBP to wake up */ 40379cdb1c70Snonaka for (ntries = 0; ntries < 20; ntries++) { 40389cdb1c70Snonaka if ((error = run_bbp_read(sc, 0, &bbp0)) != 0) 40394e8e6643Sskrll return error; 40409cdb1c70Snonaka if (bbp0 != 0 && bbp0 != 0xff) 40419cdb1c70Snonaka break; 40429cdb1c70Snonaka } 40439cdb1c70Snonaka if (ntries == 20) 40444e8e6643Sskrll return ETIMEDOUT; 40459cdb1c70Snonaka 40469cdb1c70Snonaka /* initialize BBP registers to default values */ 4047faca41fbSmlelstv if (sc->mac_ver >= 0x5390) 4048faca41fbSmlelstv run_rt5390_bbp_init(sc); 4049faca41fbSmlelstv else { 40509cdb1c70Snonaka for (i = 0; i < (int)__arraycount(rt2860_def_bbp); i++) { 40519cdb1c70Snonaka run_bbp_write(sc, rt2860_def_bbp[i].reg, 40529cdb1c70Snonaka rt2860_def_bbp[i].val); 40539cdb1c70Snonaka } 4054faca41fbSmlelstv } 4055faca41fbSmlelstv 4056faca41fbSmlelstv if (sc->mac_ver == 0x3593) { 4057faca41fbSmlelstv run_bbp_write(sc, 79, 0x13); 4058faca41fbSmlelstv run_bbp_write(sc, 80, 0x05); 4059faca41fbSmlelstv run_bbp_write(sc, 81, 0x33); 4060faca41fbSmlelstv run_bbp_write(sc, 86, 0x46); 4061faca41fbSmlelstv run_bbp_write(sc, 137, 0x0f); 4062faca41fbSmlelstv } 40639cdb1c70Snonaka 40649cdb1c70Snonaka /* fix BBP84 for RT2860E */ 40659cdb1c70Snonaka if (sc->mac_ver == 0x2860 && sc->mac_rev != 0x0101) 40669cdb1c70Snonaka run_bbp_write(sc, 84, 0x19); 40679cdb1c70Snonaka 4068d164e220Smlelstv if (sc->mac_ver >= 0x3070 && (sc->mac_ver != 0x3593 && 4069d164e220Smlelstv sc->mac_ver != 0x5592)) { 40709cdb1c70Snonaka run_bbp_write(sc, 79, 0x13); 40719cdb1c70Snonaka run_bbp_write(sc, 80, 0x05); 40729cdb1c70Snonaka run_bbp_write(sc, 81, 0x33); 40739cdb1c70Snonaka } else if (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) { 40749cdb1c70Snonaka run_bbp_write(sc, 69, 0x16); 40759cdb1c70Snonaka run_bbp_write(sc, 73, 0x12); 40769cdb1c70Snonaka } 40774e8e6643Sskrll return 0; 40789cdb1c70Snonaka } 40799cdb1c70Snonaka 40809cdb1c70Snonaka static int 40819cdb1c70Snonaka run_rt3070_rf_init(struct run_softc *sc) 40829cdb1c70Snonaka { 40839cdb1c70Snonaka uint32_t tmp; 40849cdb1c70Snonaka uint8_t rf, target, bbp4; 40859cdb1c70Snonaka int i; 40869cdb1c70Snonaka 40879cdb1c70Snonaka run_rt3070_rf_read(sc, 30, &rf); 40889cdb1c70Snonaka /* toggle RF R30 bit 7 */ 40899cdb1c70Snonaka run_rt3070_rf_write(sc, 30, rf | 0x80); 4090faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 40919cdb1c70Snonaka run_rt3070_rf_write(sc, 30, rf & ~0x80); 40929cdb1c70Snonaka 40939cdb1c70Snonaka /* initialize RF registers to default value */ 40949cdb1c70Snonaka if (sc->mac_ver == 0x3572) { 40959cdb1c70Snonaka for (i = 0; i < (int)__arraycount(rt3572_def_rf); i++) { 40969cdb1c70Snonaka run_rt3070_rf_write(sc, rt3572_def_rf[i].reg, 40979cdb1c70Snonaka rt3572_def_rf[i].val); 40989cdb1c70Snonaka } 40999cdb1c70Snonaka } else { 41009cdb1c70Snonaka for (i = 0; i < (int)__arraycount(rt3070_def_rf); i++) { 41019cdb1c70Snonaka run_rt3070_rf_write(sc, rt3070_def_rf[i].reg, 41029cdb1c70Snonaka rt3070_def_rf[i].val); 41039cdb1c70Snonaka } 41049cdb1c70Snonaka } 41059cdb1c70Snonaka if (sc->mac_ver == 0x3572) { 41069cdb1c70Snonaka run_rt3070_rf_read(sc, 6, &rf); 41079cdb1c70Snonaka run_rt3070_rf_write(sc, 6, rf | 0x40); 4108faca41fbSmlelstv run_rt3070_rf_write(sc, 31, 0x14); 41099cdb1c70Snonaka 41109cdb1c70Snonaka run_read(sc, RT3070_LDO_CFG0, &tmp); 4111faca41fbSmlelstv tmp &= ~0x1f000000; 4112faca41fbSmlelstv if (sc->mac_rev < 0x0211 && sc->patch_dac) 4113faca41fbSmlelstv tmp |= 0x0d000000; /* 1.3V */ 4114faca41fbSmlelstv else 4115faca41fbSmlelstv tmp |= 0x01000000; /* 1.2V */ 41169cdb1c70Snonaka run_write(sc, RT3070_LDO_CFG0, tmp); 41179cdb1c70Snonaka } else if (sc->mac_ver == 0x3071) { 41189cdb1c70Snonaka run_rt3070_rf_read(sc, 6, &rf); 41199cdb1c70Snonaka run_rt3070_rf_write(sc, 6, rf | 0x40); 41209cdb1c70Snonaka run_rt3070_rf_write(sc, 31, 0x14); 41219cdb1c70Snonaka 41229cdb1c70Snonaka run_read(sc, RT3070_LDO_CFG0, &tmp); 41239cdb1c70Snonaka tmp &= ~0x1f000000; 41249cdb1c70Snonaka if (sc->mac_rev < 0x0211) 41259cdb1c70Snonaka tmp |= 0x0d000000; /* 1.35V */ 41269cdb1c70Snonaka else 41279cdb1c70Snonaka tmp |= 0x01000000; /* 1.2V */ 41289cdb1c70Snonaka run_write(sc, RT3070_LDO_CFG0, tmp); 41299cdb1c70Snonaka 41309cdb1c70Snonaka /* patch LNA_PE_G1 */ 41319cdb1c70Snonaka run_read(sc, RT3070_GPIO_SWITCH, &tmp); 41329cdb1c70Snonaka run_write(sc, RT3070_GPIO_SWITCH, tmp & ~0x20); 4133d164e220Smlelstv } else if (sc->mac_ver == 0x3070 && sc->mac_rev < 0x0201) { 4134d164e220Smlelstv /* 4135d164e220Smlelstv * Change voltage from 1.2V to 1.35V for RT3070. 4136d164e220Smlelstv * The DAC issue (RT3070_LD0_CFG0) has been fixed 4137d164e220Smlelstv * in RT3070(F). 4138d164e220Smlelstv */ 41399cdb1c70Snonaka run_read(sc, RT3070_LDO_CFG0, &tmp); 41409cdb1c70Snonaka tmp = (tmp & ~0x0f000000) | 0x0d000000; 41419cdb1c70Snonaka run_write(sc, RT3070_LDO_CFG0, tmp); 41429cdb1c70Snonaka } 41439cdb1c70Snonaka 41449cdb1c70Snonaka /* select 20MHz bandwidth */ 41459cdb1c70Snonaka run_rt3070_rf_read(sc, 31, &rf); 41469cdb1c70Snonaka run_rt3070_rf_write(sc, 31, rf & ~0x20); 41479cdb1c70Snonaka 41489cdb1c70Snonaka /* calibrate filter for 20MHz bandwidth */ 41499cdb1c70Snonaka sc->rf24_20mhz = 0x1f; /* default value */ 41509cdb1c70Snonaka target = (sc->mac_ver < 0x3071) ? 0x16 : 0x13; 41519cdb1c70Snonaka run_rt3070_filter_calib(sc, 0x07, target, &sc->rf24_20mhz); 41529cdb1c70Snonaka 41539cdb1c70Snonaka /* select 40MHz bandwidth */ 41549cdb1c70Snonaka run_bbp_read(sc, 4, &bbp4); 41559cdb1c70Snonaka run_bbp_write(sc, 4, (bbp4 & ~0x08) | 0x10); 41569cdb1c70Snonaka run_rt3070_rf_read(sc, 31, &rf); 41579cdb1c70Snonaka run_rt3070_rf_write(sc, 31, rf | 0x20); 41589cdb1c70Snonaka 41599cdb1c70Snonaka /* calibrate filter for 40MHz bandwidth */ 41609cdb1c70Snonaka sc->rf24_40mhz = 0x2f; /* default value */ 41619cdb1c70Snonaka target = (sc->mac_ver < 0x3071) ? 0x19 : 0x15; 41629cdb1c70Snonaka run_rt3070_filter_calib(sc, 0x27, target, &sc->rf24_40mhz); 41639cdb1c70Snonaka 41649cdb1c70Snonaka /* go back to 20MHz bandwidth */ 41659cdb1c70Snonaka run_bbp_read(sc, 4, &bbp4); 41669cdb1c70Snonaka run_bbp_write(sc, 4, bbp4 & ~0x18); 41679cdb1c70Snonaka 41689cdb1c70Snonaka if (sc->mac_ver == 0x3572) { 41699cdb1c70Snonaka /* save default BBP registers 25 and 26 values */ 41709cdb1c70Snonaka run_bbp_read(sc, 25, &sc->bbp25); 41719cdb1c70Snonaka run_bbp_read(sc, 26, &sc->bbp26); 41729cdb1c70Snonaka } else if (sc->mac_rev < 0x0211) 41739cdb1c70Snonaka run_rt3070_rf_write(sc, 27, 0x03); 41749cdb1c70Snonaka 41759cdb1c70Snonaka run_read(sc, RT3070_OPT_14, &tmp); 41769cdb1c70Snonaka run_write(sc, RT3070_OPT_14, tmp | 1); 41779cdb1c70Snonaka 41789cdb1c70Snonaka if (sc->mac_ver == 0x3070 || sc->mac_ver == 0x3071) { 41799cdb1c70Snonaka run_rt3070_rf_read(sc, 17, &rf); 41809cdb1c70Snonaka rf &= ~RT3070_TX_LO1; 41819cdb1c70Snonaka if ((sc->mac_ver == 0x3070 || 41829cdb1c70Snonaka (sc->mac_ver == 0x3071 && sc->mac_rev >= 0x0211)) && 41839cdb1c70Snonaka !sc->ext_2ghz_lna) 41849cdb1c70Snonaka rf |= 0x20; /* fix for long range Rx issue */ 41859cdb1c70Snonaka if (sc->txmixgain_2ghz >= 1) 41869cdb1c70Snonaka rf = (rf & ~0x7) | sc->txmixgain_2ghz; 41879cdb1c70Snonaka run_rt3070_rf_write(sc, 17, rf); 41889cdb1c70Snonaka } 41899cdb1c70Snonaka if (sc->mac_ver == 0x3071) { 41909cdb1c70Snonaka run_rt3070_rf_read(sc, 1, &rf); 41919cdb1c70Snonaka rf &= ~(RT3070_RX0_PD | RT3070_TX0_PD); 41929cdb1c70Snonaka rf |= RT3070_RF_BLOCK | RT3070_RX1_PD | RT3070_TX1_PD; 41939cdb1c70Snonaka run_rt3070_rf_write(sc, 1, rf); 41949cdb1c70Snonaka 41959cdb1c70Snonaka run_rt3070_rf_read(sc, 15, &rf); 41969cdb1c70Snonaka run_rt3070_rf_write(sc, 15, rf & ~RT3070_TX_LO2); 41979cdb1c70Snonaka 41989cdb1c70Snonaka run_rt3070_rf_read(sc, 20, &rf); 41999cdb1c70Snonaka run_rt3070_rf_write(sc, 20, rf & ~RT3070_RX_LO1); 42009cdb1c70Snonaka 42019cdb1c70Snonaka run_rt3070_rf_read(sc, 21, &rf); 42029cdb1c70Snonaka run_rt3070_rf_write(sc, 21, rf & ~RT3070_RX_LO2); 42039cdb1c70Snonaka } 42049cdb1c70Snonaka if (sc->mac_ver == 0x3070 || sc->mac_ver == 0x3071) { 42059cdb1c70Snonaka /* fix Tx to Rx IQ glitch by raising RF voltage */ 42069cdb1c70Snonaka run_rt3070_rf_read(sc, 27, &rf); 42079cdb1c70Snonaka rf &= ~0x77; 42089cdb1c70Snonaka if (sc->mac_rev < 0x0211) 42099cdb1c70Snonaka rf |= 0x03; 42109cdb1c70Snonaka run_rt3070_rf_write(sc, 27, rf); 42119cdb1c70Snonaka } 42124e8e6643Sskrll return 0; 42139cdb1c70Snonaka } 42149cdb1c70Snonaka 42159cdb1c70Snonaka static int 4216faca41fbSmlelstv run_rt3593_rf_init(struct run_softc *sc) 4217faca41fbSmlelstv { 4218faca41fbSmlelstv uint32_t tmp; 4219faca41fbSmlelstv uint8_t rf; 4220faca41fbSmlelstv int i; 4221faca41fbSmlelstv 4222faca41fbSmlelstv /* Disable the GPIO bits 4 and 7 for LNA PE control. */ 4223faca41fbSmlelstv run_read(sc, RT3070_GPIO_SWITCH, &tmp); 4224faca41fbSmlelstv tmp &= ~(1 << 4 | 1 << 7); 4225faca41fbSmlelstv run_write(sc, RT3070_GPIO_SWITCH, tmp); 4226faca41fbSmlelstv 4227faca41fbSmlelstv /* Initialize RF registers to default value. */ 4228faca41fbSmlelstv for (i = 0; i < __arraycount(rt3593_def_rf); i++) { 4229faca41fbSmlelstv run_rt3070_rf_write(sc, rt3593_def_rf[i].reg, 4230faca41fbSmlelstv rt3593_def_rf[i].val); 4231faca41fbSmlelstv } 4232faca41fbSmlelstv 4233faca41fbSmlelstv /* Toggle RF R2 to initiate calibration. */ 4234faca41fbSmlelstv run_rt3070_rf_write(sc, 2, RT5390_RESCAL); 4235faca41fbSmlelstv 4236faca41fbSmlelstv /* Initialize RF frequency offset. */ 4237faca41fbSmlelstv run_adjust_freq_offset(sc); 4238faca41fbSmlelstv 4239faca41fbSmlelstv run_rt3070_rf_read(sc, 18, &rf); 4240faca41fbSmlelstv run_rt3070_rf_write(sc, 18, rf | RT3593_AUTOTUNE_BYPASS); 4241faca41fbSmlelstv 4242faca41fbSmlelstv /* 4243faca41fbSmlelstv * Increase voltage from 1.2V to 1.35V, wait for 1 msec to 4244faca41fbSmlelstv * decrease voltage back to 1.2V. 4245faca41fbSmlelstv */ 4246faca41fbSmlelstv run_read(sc, RT3070_LDO_CFG0, &tmp); 4247faca41fbSmlelstv tmp = (tmp & ~0x1f000000) | 0x0d000000; 4248faca41fbSmlelstv run_write(sc, RT3070_LDO_CFG0, tmp); 4249faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 1); 4250faca41fbSmlelstv tmp = (tmp & ~0x1f000000) | 0x01000000; 4251faca41fbSmlelstv run_write(sc, RT3070_LDO_CFG0, tmp); 4252faca41fbSmlelstv 4253faca41fbSmlelstv sc->rf24_20mhz = 0x1f; 4254faca41fbSmlelstv sc->rf24_40mhz = 0x2f; 4255faca41fbSmlelstv 4256faca41fbSmlelstv /* Save default BBP registers 25 and 26 values. */ 4257faca41fbSmlelstv run_bbp_read(sc, 25, &sc->bbp25); 4258faca41fbSmlelstv run_bbp_read(sc, 26, &sc->bbp26); 4259faca41fbSmlelstv 4260faca41fbSmlelstv run_read(sc, RT3070_OPT_14, &tmp); 4261faca41fbSmlelstv run_write(sc, RT3070_OPT_14, tmp | 1); 426226ee7ba1Sskrll return 0; 4263faca41fbSmlelstv } 4264faca41fbSmlelstv 4265faca41fbSmlelstv static int 4266faca41fbSmlelstv run_rt5390_rf_init(struct run_softc *sc) 4267faca41fbSmlelstv { 4268faca41fbSmlelstv uint32_t tmp; 4269faca41fbSmlelstv uint8_t rf; 4270faca41fbSmlelstv int i; 4271faca41fbSmlelstv 4272faca41fbSmlelstv /* Toggle RF R2 to initiate calibration. */ 4273faca41fbSmlelstv if (sc->mac_ver == 0x5390) { 4274faca41fbSmlelstv run_rt3070_rf_read(sc, 2, &rf); 4275faca41fbSmlelstv run_rt3070_rf_write(sc, 2, rf | RT5390_RESCAL); 4276faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 4277faca41fbSmlelstv run_rt3070_rf_write(sc, 2, rf & ~RT5390_RESCAL); 4278faca41fbSmlelstv } else { 4279faca41fbSmlelstv run_rt3070_rf_write(sc, 2, RT5390_RESCAL); 4280faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 4281faca41fbSmlelstv } 4282faca41fbSmlelstv 4283faca41fbSmlelstv /* Initialize RF registers to default value. */ 4284faca41fbSmlelstv if (sc->mac_ver == 0x5592) { 4285faca41fbSmlelstv for (i = 0; i < __arraycount(rt5592_def_rf); i++) { 4286faca41fbSmlelstv run_rt3070_rf_write(sc, rt5592_def_rf[i].reg, 4287faca41fbSmlelstv rt5592_def_rf[i].val); 4288faca41fbSmlelstv } 4289faca41fbSmlelstv /* Initialize RF frequency offset. */ 4290faca41fbSmlelstv run_adjust_freq_offset(sc); 4291faca41fbSmlelstv } else if (sc->mac_ver == 0x5392) { 4292faca41fbSmlelstv for (i = 0; i < __arraycount(rt5392_def_rf); i++) { 4293faca41fbSmlelstv run_rt3070_rf_write(sc, rt5392_def_rf[i].reg, 4294faca41fbSmlelstv rt5392_def_rf[i].val); 4295faca41fbSmlelstv } 4296faca41fbSmlelstv if (sc->mac_rev >= 0x0223) { 4297faca41fbSmlelstv run_rt3070_rf_write(sc, 23, 0x0f); 4298faca41fbSmlelstv run_rt3070_rf_write(sc, 24, 0x3e); 4299faca41fbSmlelstv run_rt3070_rf_write(sc, 51, 0x32); 4300faca41fbSmlelstv run_rt3070_rf_write(sc, 53, 0x22); 4301faca41fbSmlelstv run_rt3070_rf_write(sc, 56, 0xc1); 4302faca41fbSmlelstv run_rt3070_rf_write(sc, 59, 0x0f); 4303faca41fbSmlelstv } 4304faca41fbSmlelstv } else { 4305faca41fbSmlelstv for (i = 0; i < __arraycount(rt5390_def_rf); i++) { 4306faca41fbSmlelstv run_rt3070_rf_write(sc, rt5390_def_rf[i].reg, 4307faca41fbSmlelstv rt5390_def_rf[i].val); 4308faca41fbSmlelstv } 4309faca41fbSmlelstv if (sc->mac_rev >= 0x0502) { 4310faca41fbSmlelstv run_rt3070_rf_write(sc, 6, 0xe0); 4311faca41fbSmlelstv run_rt3070_rf_write(sc, 25, 0x80); 4312faca41fbSmlelstv run_rt3070_rf_write(sc, 46, 0x73); 4313faca41fbSmlelstv run_rt3070_rf_write(sc, 53, 0x00); 4314faca41fbSmlelstv run_rt3070_rf_write(sc, 56, 0x42); 4315faca41fbSmlelstv run_rt3070_rf_write(sc, 61, 0xd1); 4316faca41fbSmlelstv } 4317faca41fbSmlelstv } 4318faca41fbSmlelstv 4319faca41fbSmlelstv sc->rf24_20mhz = 0x1f; /* default value */ 4320faca41fbSmlelstv sc->rf24_40mhz = (sc->mac_ver == 0x5592) ? 0 : 0x2f; 4321faca41fbSmlelstv 4322faca41fbSmlelstv if (sc->mac_rev < 0x0211) 4323faca41fbSmlelstv run_rt3070_rf_write(sc, 27, 0x3); 4324faca41fbSmlelstv 4325faca41fbSmlelstv run_read(sc, RT3070_OPT_14, &tmp); 4326faca41fbSmlelstv run_write(sc, RT3070_OPT_14, tmp | 1); 432726ee7ba1Sskrll return 0; 4328faca41fbSmlelstv } 4329faca41fbSmlelstv 4330faca41fbSmlelstv static int 43319cdb1c70Snonaka run_rt3070_filter_calib(struct run_softc *sc, uint8_t init, uint8_t target, 43329cdb1c70Snonaka uint8_t *val) 43339cdb1c70Snonaka { 43349cdb1c70Snonaka uint8_t rf22, rf24; 43359cdb1c70Snonaka uint8_t bbp55_pb, bbp55_sb, delta; 43369cdb1c70Snonaka int ntries; 43379cdb1c70Snonaka 43389cdb1c70Snonaka /* program filter */ 43399cdb1c70Snonaka run_rt3070_rf_read(sc, 24, &rf24); 43409cdb1c70Snonaka rf24 = (rf24 & 0xc0) | init; /* initial filter value */ 43419cdb1c70Snonaka run_rt3070_rf_write(sc, 24, rf24); 43429cdb1c70Snonaka 43439cdb1c70Snonaka /* enable baseband loopback mode */ 43449cdb1c70Snonaka run_rt3070_rf_read(sc, 22, &rf22); 43459cdb1c70Snonaka run_rt3070_rf_write(sc, 22, rf22 | 0x01); 43469cdb1c70Snonaka 43479cdb1c70Snonaka /* set power and frequency of passband test tone */ 43489cdb1c70Snonaka run_bbp_write(sc, 24, 0x00); 43499cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) { 43509cdb1c70Snonaka /* transmit test tone */ 43519cdb1c70Snonaka run_bbp_write(sc, 25, 0x90); 4352faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 43539cdb1c70Snonaka /* read received power */ 43549cdb1c70Snonaka run_bbp_read(sc, 55, &bbp55_pb); 43559cdb1c70Snonaka if (bbp55_pb != 0) 43569cdb1c70Snonaka break; 43579cdb1c70Snonaka } 43589cdb1c70Snonaka if (ntries == 100) 43594e8e6643Sskrll return ETIMEDOUT; 43609cdb1c70Snonaka 43619cdb1c70Snonaka /* set power and frequency of stopband test tone */ 43629cdb1c70Snonaka run_bbp_write(sc, 24, 0x06); 43639cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) { 43649cdb1c70Snonaka /* transmit test tone */ 43659cdb1c70Snonaka run_bbp_write(sc, 25, 0x90); 4366faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 43679cdb1c70Snonaka /* read received power */ 43689cdb1c70Snonaka run_bbp_read(sc, 55, &bbp55_sb); 43699cdb1c70Snonaka 43709cdb1c70Snonaka delta = bbp55_pb - bbp55_sb; 43719cdb1c70Snonaka if (delta > target) 43729cdb1c70Snonaka break; 43739cdb1c70Snonaka 43749cdb1c70Snonaka /* reprogram filter */ 43759cdb1c70Snonaka rf24++; 43769cdb1c70Snonaka run_rt3070_rf_write(sc, 24, rf24); 43779cdb1c70Snonaka } 43789cdb1c70Snonaka if (ntries < 100) { 43799cdb1c70Snonaka if (rf24 != init) 43809cdb1c70Snonaka rf24--; /* backtrack */ 43819cdb1c70Snonaka *val = rf24; 43829cdb1c70Snonaka run_rt3070_rf_write(sc, 24, rf24); 43839cdb1c70Snonaka } 43849cdb1c70Snonaka 43859cdb1c70Snonaka /* restore initial state */ 43869cdb1c70Snonaka run_bbp_write(sc, 24, 0x00); 43879cdb1c70Snonaka 43889cdb1c70Snonaka /* disable baseband loopback mode */ 43899cdb1c70Snonaka run_rt3070_rf_read(sc, 22, &rf22); 43909cdb1c70Snonaka run_rt3070_rf_write(sc, 22, rf22 & ~0x01); 43919cdb1c70Snonaka 43924e8e6643Sskrll return 0; 43939cdb1c70Snonaka } 43949cdb1c70Snonaka 43959cdb1c70Snonaka static void 43969cdb1c70Snonaka run_rt3070_rf_setup(struct run_softc *sc) 43979cdb1c70Snonaka { 43989cdb1c70Snonaka uint8_t bbp, rf; 43999cdb1c70Snonaka int i; 44009cdb1c70Snonaka 44019cdb1c70Snonaka if (sc->mac_ver == 0x3572) { 44029cdb1c70Snonaka /* enable DC filter */ 44039cdb1c70Snonaka if (sc->mac_rev >= 0x0201) 44049cdb1c70Snonaka run_bbp_write(sc, 103, 0xc0); 44059cdb1c70Snonaka 44069cdb1c70Snonaka run_bbp_read(sc, 138, &bbp); 44079cdb1c70Snonaka if (sc->ntxchains == 1) 44089cdb1c70Snonaka bbp |= 0x20; /* turn off DAC1 */ 44099cdb1c70Snonaka if (sc->nrxchains == 1) 44109cdb1c70Snonaka bbp &= ~0x02; /* turn off ADC1 */ 44119cdb1c70Snonaka run_bbp_write(sc, 138, bbp); 44129cdb1c70Snonaka 44139cdb1c70Snonaka if (sc->mac_rev >= 0x0211) { 44149cdb1c70Snonaka /* improve power consumption */ 44159cdb1c70Snonaka run_bbp_read(sc, 31, &bbp); 44169cdb1c70Snonaka run_bbp_write(sc, 31, bbp & ~0x03); 44179cdb1c70Snonaka } 44189cdb1c70Snonaka 44199cdb1c70Snonaka run_rt3070_rf_read(sc, 16, &rf); 44209cdb1c70Snonaka rf = (rf & ~0x07) | sc->txmixgain_2ghz; 44219cdb1c70Snonaka run_rt3070_rf_write(sc, 16, rf); 44229cdb1c70Snonaka } else if (sc->mac_ver == 0x3071) { 44239cdb1c70Snonaka /* enable DC filter */ 44249cdb1c70Snonaka if (sc->mac_rev >= 0x0201) 44259cdb1c70Snonaka run_bbp_write(sc, 103, 0xc0); 44269cdb1c70Snonaka 44279cdb1c70Snonaka run_bbp_read(sc, 138, &bbp); 44289cdb1c70Snonaka if (sc->ntxchains == 1) 44299cdb1c70Snonaka bbp |= 0x20; /* turn off DAC1 */ 44309cdb1c70Snonaka if (sc->nrxchains == 1) 44319cdb1c70Snonaka bbp &= ~0x02; /* turn off ADC1 */ 44329cdb1c70Snonaka run_bbp_write(sc, 138, bbp); 44339cdb1c70Snonaka 44349cdb1c70Snonaka if (sc->mac_rev >= 0x0211) { 44359cdb1c70Snonaka /* improve power consumption */ 44369cdb1c70Snonaka run_bbp_read(sc, 31, &bbp); 44379cdb1c70Snonaka run_bbp_write(sc, 31, bbp & ~0x03); 44389cdb1c70Snonaka } 44399cdb1c70Snonaka 44409cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG1, 0); 44419cdb1c70Snonaka if (sc->mac_rev < 0x0211) { 44429cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG2, 44439cdb1c70Snonaka sc->patch_dac ? 0x2c : 0x0f); 44449cdb1c70Snonaka } else 44459cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG2, 0); 44469cdb1c70Snonaka } else if (sc->mac_ver == 0x3070) { 44479cdb1c70Snonaka if (sc->mac_rev >= 0x0201) { 44489cdb1c70Snonaka /* enable DC filter */ 44499cdb1c70Snonaka run_bbp_write(sc, 103, 0xc0); 44509cdb1c70Snonaka 44519cdb1c70Snonaka /* improve power consumption */ 44529cdb1c70Snonaka run_bbp_read(sc, 31, &bbp); 44539cdb1c70Snonaka run_bbp_write(sc, 31, bbp & ~0x03); 44549cdb1c70Snonaka } 44559cdb1c70Snonaka 44569cdb1c70Snonaka if (sc->mac_rev < 0x0211) { 44579cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG1, 0); 44589cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG2, 0x2c); 44599cdb1c70Snonaka } else 44609cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG2, 0); 44619cdb1c70Snonaka } 44629cdb1c70Snonaka 44639cdb1c70Snonaka /* initialize RF registers from ROM for >=RT3071*/ 44649cdb1c70Snonaka if (sc->mac_ver >= 0x3071) { 44659cdb1c70Snonaka for (i = 0; i < 10; i++) { 44669cdb1c70Snonaka if (sc->rf[i].reg == 0 || sc->rf[i].reg == 0xff) 44679cdb1c70Snonaka continue; 44689cdb1c70Snonaka run_rt3070_rf_write(sc, sc->rf[i].reg, sc->rf[i].val); 44699cdb1c70Snonaka } 44709cdb1c70Snonaka } 44719cdb1c70Snonaka } 44729cdb1c70Snonaka 4473faca41fbSmlelstv static void 4474faca41fbSmlelstv run_rt3593_rf_setup(struct run_softc *sc) 4475faca41fbSmlelstv { 4476faca41fbSmlelstv uint8_t bbp, rf; 4477faca41fbSmlelstv 4478faca41fbSmlelstv if (sc->mac_rev >= 0x0211) { 4479faca41fbSmlelstv /* Enable DC filter. */ 4480faca41fbSmlelstv run_bbp_write(sc, 103, 0xc0); 4481faca41fbSmlelstv } 4482faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG1, 0); 4483faca41fbSmlelstv if (sc->mac_rev < 0x0211) { 4484faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG2, 4485faca41fbSmlelstv sc->patch_dac ? 0x2c : 0x0f); 4486faca41fbSmlelstv } else 4487faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG2, 0); 4488faca41fbSmlelstv 4489faca41fbSmlelstv run_rt3070_rf_read(sc, 50, &rf); 4490faca41fbSmlelstv run_rt3070_rf_write(sc, 50, rf & ~RT3593_TX_LO2); 4491faca41fbSmlelstv 4492faca41fbSmlelstv run_rt3070_rf_read(sc, 51, &rf); 4493faca41fbSmlelstv rf = (rf & ~(RT3593_TX_LO1 | 0x0c)) | 4494faca41fbSmlelstv ((sc->txmixgain_2ghz & 0x07) << 2); 4495faca41fbSmlelstv run_rt3070_rf_write(sc, 51, rf); 4496faca41fbSmlelstv 4497faca41fbSmlelstv run_rt3070_rf_read(sc, 38, &rf); 4498faca41fbSmlelstv run_rt3070_rf_write(sc, 38, rf & ~RT5390_RX_LO1); 4499faca41fbSmlelstv 4500faca41fbSmlelstv run_rt3070_rf_read(sc, 39, &rf); 4501faca41fbSmlelstv run_rt3070_rf_write(sc, 39, rf & ~RT5390_RX_LO2); 4502faca41fbSmlelstv 4503faca41fbSmlelstv run_rt3070_rf_read(sc, 1, &rf); 4504faca41fbSmlelstv run_rt3070_rf_write(sc, 1, rf & ~(RT3070_RF_BLOCK | RT3070_PLL_PD)); 4505faca41fbSmlelstv 4506faca41fbSmlelstv run_rt3070_rf_read(sc, 30, &rf); 4507faca41fbSmlelstv rf = (rf & ~0x18) | 0x10; 4508faca41fbSmlelstv run_rt3070_rf_write(sc, 30, rf); 4509faca41fbSmlelstv 4510faca41fbSmlelstv /* Apply maximum likelihood detection for 2 stream case. */ 4511faca41fbSmlelstv run_bbp_read(sc, 105, &bbp); 4512faca41fbSmlelstv if (sc->nrxchains > 1) 4513faca41fbSmlelstv run_bbp_write(sc, 105, bbp | RT5390_MLD); 4514faca41fbSmlelstv 4515faca41fbSmlelstv /* Avoid data lost and CRC error. */ 4516faca41fbSmlelstv run_bbp_read(sc, 4, &bbp); 4517faca41fbSmlelstv run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL); 4518faca41fbSmlelstv 4519faca41fbSmlelstv run_bbp_write(sc, 92, 0x02); 4520faca41fbSmlelstv run_bbp_write(sc, 82, 0x82); 4521faca41fbSmlelstv run_bbp_write(sc, 106, 0x05); 4522faca41fbSmlelstv run_bbp_write(sc, 104, 0x92); 4523faca41fbSmlelstv run_bbp_write(sc, 88, 0x90); 4524faca41fbSmlelstv run_bbp_write(sc, 148, 0xc8); 4525faca41fbSmlelstv run_bbp_write(sc, 47, 0x48); 4526faca41fbSmlelstv run_bbp_write(sc, 120, 0x50); 4527faca41fbSmlelstv 4528faca41fbSmlelstv run_bbp_write(sc, 163, 0x9d); 4529faca41fbSmlelstv 4530faca41fbSmlelstv /* SNR mapping. */ 4531faca41fbSmlelstv run_bbp_write(sc, 142, 0x06); 4532faca41fbSmlelstv run_bbp_write(sc, 143, 0xa0); 4533faca41fbSmlelstv run_bbp_write(sc, 142, 0x07); 4534faca41fbSmlelstv run_bbp_write(sc, 143, 0xa1); 4535faca41fbSmlelstv run_bbp_write(sc, 142, 0x08); 4536faca41fbSmlelstv run_bbp_write(sc, 143, 0xa2); 4537faca41fbSmlelstv 4538faca41fbSmlelstv run_bbp_write(sc, 31, 0x08); 4539faca41fbSmlelstv run_bbp_write(sc, 68, 0x0b); 4540faca41fbSmlelstv run_bbp_write(sc, 105, 0x04); 4541faca41fbSmlelstv } 4542faca41fbSmlelstv 4543faca41fbSmlelstv static void 4544faca41fbSmlelstv run_rt5390_rf_setup(struct run_softc *sc) 4545faca41fbSmlelstv { 4546faca41fbSmlelstv uint8_t bbp, rf; 4547faca41fbSmlelstv 4548faca41fbSmlelstv if (sc->mac_rev >= 0x0211) { 4549faca41fbSmlelstv /* Enable DC filter. */ 4550faca41fbSmlelstv run_bbp_write(sc, 103, 0xc0); 4551faca41fbSmlelstv 4552faca41fbSmlelstv if (sc->mac_ver != 0x5592) { 4553faca41fbSmlelstv /* Improve power consumption. */ 4554faca41fbSmlelstv run_bbp_read(sc, 31, &bbp); 4555faca41fbSmlelstv run_bbp_write(sc, 31, bbp & ~0x03); 4556faca41fbSmlelstv } 4557faca41fbSmlelstv } 4558faca41fbSmlelstv 4559faca41fbSmlelstv run_bbp_read(sc, 138, &bbp); 4560faca41fbSmlelstv if (sc->ntxchains == 1) 4561faca41fbSmlelstv bbp |= 0x20; /* turn off DAC1 */ 4562faca41fbSmlelstv if (sc->nrxchains == 1) 4563faca41fbSmlelstv bbp &= ~0x02; /* turn off ADC1 */ 4564faca41fbSmlelstv run_bbp_write(sc, 138, bbp); 4565faca41fbSmlelstv 4566faca41fbSmlelstv run_rt3070_rf_read(sc, 38, &rf); 4567faca41fbSmlelstv run_rt3070_rf_write(sc, 38, rf & ~RT5390_RX_LO1); 4568faca41fbSmlelstv 4569faca41fbSmlelstv run_rt3070_rf_read(sc, 39, &rf); 4570faca41fbSmlelstv run_rt3070_rf_write(sc, 39, rf & ~RT5390_RX_LO2); 4571faca41fbSmlelstv 4572faca41fbSmlelstv /* Avoid data lost and CRC error. */ 4573faca41fbSmlelstv run_bbp_read(sc, 4, &bbp); 4574faca41fbSmlelstv run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL); 4575faca41fbSmlelstv 4576faca41fbSmlelstv run_rt3070_rf_read(sc, 30, &rf); 4577faca41fbSmlelstv rf = (rf & ~0x18) | 0x10; 4578faca41fbSmlelstv run_rt3070_rf_write(sc, 30, rf); 4579faca41fbSmlelstv 4580faca41fbSmlelstv if (sc->mac_ver != 0x5592) { 4581faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG1, 0); 4582faca41fbSmlelstv if (sc->mac_rev < 0x0211) { 4583faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG2, 4584faca41fbSmlelstv sc->patch_dac ? 0x2c : 0x0f); 4585faca41fbSmlelstv } else 4586faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG2, 0); 4587faca41fbSmlelstv } 4588faca41fbSmlelstv } 4589faca41fbSmlelstv 45909cdb1c70Snonaka static int 45919cdb1c70Snonaka run_txrx_enable(struct run_softc *sc) 45929cdb1c70Snonaka { 45939cdb1c70Snonaka uint32_t tmp; 45949cdb1c70Snonaka int error, ntries; 45959cdb1c70Snonaka 45969cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_TX_EN); 45979cdb1c70Snonaka for (ntries = 0; ntries < 200; ntries++) { 45989cdb1c70Snonaka if ((error = run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp)) != 0) 45994e8e6643Sskrll return error; 46009cdb1c70Snonaka if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) 46019cdb1c70Snonaka break; 4602faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 50); 46039cdb1c70Snonaka } 46049cdb1c70Snonaka if (ntries == 200) 46054e8e6643Sskrll return ETIMEDOUT; 46069cdb1c70Snonaka 4607faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 50); 46089cdb1c70Snonaka 46099cdb1c70Snonaka tmp |= RT2860_RX_DMA_EN | RT2860_TX_DMA_EN | RT2860_TX_WB_DDONE; 46109cdb1c70Snonaka run_write(sc, RT2860_WPDMA_GLO_CFG, tmp); 46119cdb1c70Snonaka 46129cdb1c70Snonaka /* enable Rx bulk aggregation (set timeout and limit) */ 46139cdb1c70Snonaka tmp = RT2860_USB_TX_EN | RT2860_USB_RX_EN | RT2860_USB_RX_AGG_EN | 46149cdb1c70Snonaka RT2860_USB_RX_AGG_TO(128) | RT2860_USB_RX_AGG_LMT(2); 46159cdb1c70Snonaka run_write(sc, RT2860_USB_DMA_CFG, tmp); 46169cdb1c70Snonaka 46179cdb1c70Snonaka /* set Rx filter */ 46189cdb1c70Snonaka tmp = RT2860_DROP_CRC_ERR | RT2860_DROP_PHY_ERR; 46199cdb1c70Snonaka if (sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR) { 46209cdb1c70Snonaka tmp |= RT2860_DROP_UC_NOME | RT2860_DROP_DUPL | 46219cdb1c70Snonaka RT2860_DROP_CTS | RT2860_DROP_BA | RT2860_DROP_ACK | 46229cdb1c70Snonaka RT2860_DROP_VER_ERR | RT2860_DROP_CTRL_RSV | 46239cdb1c70Snonaka RT2860_DROP_CFACK | RT2860_DROP_CFEND; 46249cdb1c70Snonaka if (sc->sc_ic.ic_opmode == IEEE80211_M_STA) 46259cdb1c70Snonaka tmp |= RT2860_DROP_RTS | RT2860_DROP_PSPOLL; 46269cdb1c70Snonaka } 46279cdb1c70Snonaka run_write(sc, RT2860_RX_FILTR_CFG, tmp); 46289cdb1c70Snonaka 46299cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL, 46309cdb1c70Snonaka RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); 46319cdb1c70Snonaka 46324e8e6643Sskrll return 0; 46339cdb1c70Snonaka } 46349cdb1c70Snonaka 46359cdb1c70Snonaka static int 4636faca41fbSmlelstv run_adjust_freq_offset(struct run_softc *sc) 4637faca41fbSmlelstv { 4638faca41fbSmlelstv uint8_t rf, tmp; 4639faca41fbSmlelstv 4640faca41fbSmlelstv run_rt3070_rf_read(sc, 17, &rf); 4641faca41fbSmlelstv tmp = rf; 4642faca41fbSmlelstv rf = (rf & ~0x7f) | (sc->freq & 0x7f); 4643faca41fbSmlelstv rf = MIN(rf, 0x5f); 4644faca41fbSmlelstv 4645faca41fbSmlelstv if (tmp != rf) 4646faca41fbSmlelstv run_mcu_cmd(sc, 0x74, (tmp << 8 ) | rf); 4647faca41fbSmlelstv 464826ee7ba1Sskrll return 0; 4649faca41fbSmlelstv } 4650faca41fbSmlelstv 4651faca41fbSmlelstv static int 46529cdb1c70Snonaka run_init(struct ifnet *ifp) 46539cdb1c70Snonaka { 46549cdb1c70Snonaka struct run_softc *sc = ifp->if_softc; 46559cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 46569cdb1c70Snonaka uint32_t tmp; 46579cdb1c70Snonaka uint8_t bbp1, bbp3; 46589cdb1c70Snonaka int i, error, qid, ridx, ntries; 4659d164e220Smlelstv usbd_status status; 46609cdb1c70Snonaka 46619cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) { 46629cdb1c70Snonaka if ((error = run_read(sc, RT2860_ASIC_VER_ID, &tmp)) != 0) 46639cdb1c70Snonaka goto fail; 46649cdb1c70Snonaka if (tmp != 0 && tmp != 0xffffffff) 46659cdb1c70Snonaka break; 4666faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 46679cdb1c70Snonaka } 46689cdb1c70Snonaka if (ntries == 100) { 46699cdb1c70Snonaka error = ETIMEDOUT; 46709cdb1c70Snonaka goto fail; 46719cdb1c70Snonaka } 46729cdb1c70Snonaka 46739cdb1c70Snonaka if ((sc->sc_flags & RUN_FWLOADED) == 0 && 46749cdb1c70Snonaka (error = run_load_microcode(sc)) != 0) { 46751d5cb2a3Sjakllsch device_printf(sc->sc_dev, 46769cdb1c70Snonaka "could not load 8051 microcode\n"); 46779cdb1c70Snonaka goto fail; 46789cdb1c70Snonaka } 46799cdb1c70Snonaka 46809cdb1c70Snonaka if (ifp->if_flags & IFF_RUNNING) 46819cdb1c70Snonaka run_stop(ifp, 0); 46829cdb1c70Snonaka 46839cdb1c70Snonaka /* init host command ring */ 46849cdb1c70Snonaka sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0; 46859cdb1c70Snonaka 46869cdb1c70Snonaka /* init Tx rings (4 EDCAs) */ 46879cdb1c70Snonaka for (qid = 0; qid < 4; qid++) { 46889cdb1c70Snonaka if ((error = run_alloc_tx_ring(sc, qid)) != 0) 46899cdb1c70Snonaka goto fail; 46909cdb1c70Snonaka } 46919cdb1c70Snonaka /* init Rx ring */ 46929cdb1c70Snonaka if ((error = run_alloc_rx_ring(sc)) != 0) 46939cdb1c70Snonaka goto fail; 46949cdb1c70Snonaka 46959cdb1c70Snonaka IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl)); 46969cdb1c70Snonaka run_set_macaddr(sc, ic->ic_myaddr); 46979cdb1c70Snonaka 46989cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) { 46999cdb1c70Snonaka if ((error = run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp)) != 0) 47009cdb1c70Snonaka goto fail; 47019cdb1c70Snonaka if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) 47029cdb1c70Snonaka break; 4703faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 47049cdb1c70Snonaka } 47059cdb1c70Snonaka if (ntries == 100) { 47061d5cb2a3Sjakllsch device_printf(sc->sc_dev, 47079cdb1c70Snonaka "timeout waiting for DMA engine\n"); 47089cdb1c70Snonaka error = ETIMEDOUT; 47099cdb1c70Snonaka goto fail; 47109cdb1c70Snonaka } 47119cdb1c70Snonaka tmp &= 0xff0; 47129cdb1c70Snonaka tmp |= RT2860_TX_WB_DDONE; 47139cdb1c70Snonaka run_write(sc, RT2860_WPDMA_GLO_CFG, tmp); 47149cdb1c70Snonaka 47159cdb1c70Snonaka /* turn off PME_OEN to solve high-current issue */ 47169cdb1c70Snonaka run_read(sc, RT2860_SYS_CTRL, &tmp); 47179cdb1c70Snonaka run_write(sc, RT2860_SYS_CTRL, tmp & ~RT2860_PME_OEN); 47189cdb1c70Snonaka 47199cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL, 47209cdb1c70Snonaka RT2860_BBP_HRST | RT2860_MAC_SRST); 47219cdb1c70Snonaka run_write(sc, RT2860_USB_DMA_CFG, 0); 47229cdb1c70Snonaka 47239cdb1c70Snonaka if ((error = run_reset(sc)) != 0) { 47241d5cb2a3Sjakllsch device_printf(sc->sc_dev, "could not reset chipset\n"); 47259cdb1c70Snonaka goto fail; 47269cdb1c70Snonaka } 47279cdb1c70Snonaka 47289cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL, 0); 47299cdb1c70Snonaka 47309cdb1c70Snonaka /* init Tx power for all Tx rates (from EEPROM) */ 47319cdb1c70Snonaka for (ridx = 0; ridx < 5; ridx++) { 47329cdb1c70Snonaka if (sc->txpow20mhz[ridx] == 0xffffffff) 47339cdb1c70Snonaka continue; 47349cdb1c70Snonaka run_write(sc, RT2860_TX_PWR_CFG(ridx), sc->txpow20mhz[ridx]); 47359cdb1c70Snonaka } 47369cdb1c70Snonaka 47379cdb1c70Snonaka for (i = 0; i < (int)__arraycount(rt2870_def_mac); i++) 47389cdb1c70Snonaka run_write(sc, rt2870_def_mac[i].reg, rt2870_def_mac[i].val); 47399cdb1c70Snonaka run_write(sc, RT2860_WMM_AIFSN_CFG, 0x00002273); 47409cdb1c70Snonaka run_write(sc, RT2860_WMM_CWMIN_CFG, 0x00002344); 47419cdb1c70Snonaka run_write(sc, RT2860_WMM_CWMAX_CFG, 0x000034aa); 47429cdb1c70Snonaka 4743faca41fbSmlelstv if (sc->mac_ver >= 0x5390) { 4744faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG0, 4745faca41fbSmlelstv 4 << RT2860_DLY_PAPE_EN_SHIFT | 4); 4746faca41fbSmlelstv if (sc->mac_ver >= 0x5392) { 4747faca41fbSmlelstv run_write(sc, RT2860_MAX_LEN_CFG, 0x00002fff); 4748faca41fbSmlelstv if (sc->mac_ver == 0x5592) { 4749faca41fbSmlelstv run_write(sc, RT2860_HT_FBK_CFG1, 0xedcba980); 4750faca41fbSmlelstv run_write(sc, RT2860_TXOP_HLDR_ET, 0x00000082); 4751faca41fbSmlelstv } else { 4752faca41fbSmlelstv run_write(sc, RT2860_HT_FBK_CFG1, 0xedcb4980); 4753faca41fbSmlelstv run_write(sc, RT2860_LG_FBK_CFG0, 0xedcba322); 4754faca41fbSmlelstv } 4755faca41fbSmlelstv } 4756faca41fbSmlelstv } else if (sc->mac_ver >= 0x3593) { 4757faca41fbSmlelstv run_write(sc, RT2860_TX_SW_CFG0, 4758faca41fbSmlelstv 4 << RT2860_DLY_PAPE_EN_SHIFT | 2); 4759faca41fbSmlelstv } else if (sc->mac_ver >= 0x3070) { 47609cdb1c70Snonaka /* set delay of PA_PE assertion to 1us (unit of 0.25us) */ 47619cdb1c70Snonaka run_write(sc, RT2860_TX_SW_CFG0, 47629cdb1c70Snonaka 4 << RT2860_DLY_PAPE_EN_SHIFT); 47639cdb1c70Snonaka } 47649cdb1c70Snonaka 47659cdb1c70Snonaka /* wait while MAC is busy */ 47669cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) { 47679cdb1c70Snonaka if ((error = run_read(sc, RT2860_MAC_STATUS_REG, &tmp)) != 0) 47689cdb1c70Snonaka goto fail; 47699cdb1c70Snonaka if (!(tmp & (RT2860_RX_STATUS_BUSY | RT2860_TX_STATUS_BUSY))) 47709cdb1c70Snonaka break; 47719cdb1c70Snonaka DELAY(1000); 47729cdb1c70Snonaka } 47739cdb1c70Snonaka if (ntries == 100) { 47749cdb1c70Snonaka error = ETIMEDOUT; 47759cdb1c70Snonaka goto fail; 47769cdb1c70Snonaka } 47779cdb1c70Snonaka 47789cdb1c70Snonaka /* clear Host to MCU mailbox */ 47799cdb1c70Snonaka run_write(sc, RT2860_H2M_BBPAGENT, 0); 47809cdb1c70Snonaka run_write(sc, RT2860_H2M_MAILBOX, 0); 4781faca41fbSmlelstv usbd_delay_ms(sc->sc_udev, 10); 47829cdb1c70Snonaka 47839cdb1c70Snonaka if ((error = run_bbp_init(sc)) != 0) { 47841d5cb2a3Sjakllsch device_printf(sc->sc_dev, "could not initialize BBP\n"); 47859cdb1c70Snonaka goto fail; 47869cdb1c70Snonaka } 47879cdb1c70Snonaka 4788faca41fbSmlelstv /* abort TSF synchronization */ 47899cdb1c70Snonaka run_read(sc, RT2860_BCN_TIME_CFG, &tmp); 47909cdb1c70Snonaka tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | 47919cdb1c70Snonaka RT2860_TBTT_TIMER_EN); 47929cdb1c70Snonaka run_write(sc, RT2860_BCN_TIME_CFG, tmp); 47939cdb1c70Snonaka 47949cdb1c70Snonaka /* clear RX WCID search table */ 47959cdb1c70Snonaka run_set_region_4(sc, RT2860_WCID_ENTRY(0), 0, 512); 47969cdb1c70Snonaka /* clear Pair-wise key table */ 47979cdb1c70Snonaka run_set_region_4(sc, RT2860_PKEY(0), 0, 2048); 47989cdb1c70Snonaka /* clear IV/EIV table */ 47999cdb1c70Snonaka run_set_region_4(sc, RT2860_IVEIV(0), 0, 512); 48009cdb1c70Snonaka /* clear WCID attribute table */ 48019cdb1c70Snonaka run_set_region_4(sc, RT2860_WCID_ATTR(0), 0, 8 * 32); 48029cdb1c70Snonaka /* clear shared key table */ 48039cdb1c70Snonaka run_set_region_4(sc, RT2860_SKEY(0, 0), 0, 8 * 32); 48049cdb1c70Snonaka /* clear shared key mode */ 48059cdb1c70Snonaka run_set_region_4(sc, RT2860_SKEY_MODE_0_7, 0, 4); 48069cdb1c70Snonaka 4807faca41fbSmlelstv /* clear RX WCID search table */ 4808faca41fbSmlelstv run_set_region_4(sc, RT2860_WCID_ENTRY(0), 0, 512); 4809faca41fbSmlelstv /* clear WCID attribute table */ 4810faca41fbSmlelstv run_set_region_4(sc, RT2860_WCID_ATTR(0), 0, 8 * 32); 4811faca41fbSmlelstv 48129cdb1c70Snonaka run_read(sc, RT2860_US_CYC_CNT, &tmp); 48139cdb1c70Snonaka tmp = (tmp & ~0xff) | 0x1e; 48149cdb1c70Snonaka run_write(sc, RT2860_US_CYC_CNT, tmp); 48159cdb1c70Snonaka 48169cdb1c70Snonaka if (sc->mac_rev != 0x0101) 48179cdb1c70Snonaka run_write(sc, RT2860_TXOP_CTRL_CFG, 0x0000583f); 48189cdb1c70Snonaka 48199cdb1c70Snonaka run_write(sc, RT2860_WMM_TXOP0_CFG, 0); 48209cdb1c70Snonaka run_write(sc, RT2860_WMM_TXOP1_CFG, 48 << 16 | 96); 48219cdb1c70Snonaka 48229cdb1c70Snonaka /* write vendor-specific BBP values (from EEPROM) */ 4823faca41fbSmlelstv if (sc->mac_ver < 0x3593) { 4824faca41fbSmlelstv for (i = 0; i < 10; i++) { 48259cdb1c70Snonaka if (sc->bbp[i].reg == 0 || sc->bbp[i].reg == 0xff) 48269cdb1c70Snonaka continue; 48279cdb1c70Snonaka run_bbp_write(sc, sc->bbp[i].reg, sc->bbp[i].val); 48289cdb1c70Snonaka } 4829faca41fbSmlelstv } 48309cdb1c70Snonaka 48319cdb1c70Snonaka /* select Main antenna for 1T1R devices */ 4832faca41fbSmlelstv if (sc->rf_rev == RT3070_RF_3020 || sc->rf_rev == RT5390_RF_5370) 48339cdb1c70Snonaka run_set_rx_antenna(sc, 0); 48349cdb1c70Snonaka 48359cdb1c70Snonaka /* send LEDs operating mode to microcontroller */ 48369cdb1c70Snonaka (void)run_mcu_cmd(sc, RT2860_MCU_CMD_LED1, sc->led[0]); 48379cdb1c70Snonaka (void)run_mcu_cmd(sc, RT2860_MCU_CMD_LED2, sc->led[1]); 48389cdb1c70Snonaka (void)run_mcu_cmd(sc, RT2860_MCU_CMD_LED3, sc->led[2]); 48399cdb1c70Snonaka 4840faca41fbSmlelstv if (sc->mac_ver >= 0x5390) 4841faca41fbSmlelstv run_rt5390_rf_init(sc); 4842faca41fbSmlelstv else if (sc->mac_ver == 0x3593) 4843faca41fbSmlelstv run_rt3593_rf_init(sc); 4844faca41fbSmlelstv else if (sc->mac_ver >= 0x3070) 48459cdb1c70Snonaka run_rt3070_rf_init(sc); 48469cdb1c70Snonaka 48479cdb1c70Snonaka /* disable non-existing Rx chains */ 48489cdb1c70Snonaka run_bbp_read(sc, 3, &bbp3); 48499cdb1c70Snonaka bbp3 &= ~(1 << 3 | 1 << 4); 48509cdb1c70Snonaka if (sc->nrxchains == 2) 48519cdb1c70Snonaka bbp3 |= 1 << 3; 48529cdb1c70Snonaka else if (sc->nrxchains == 3) 48539cdb1c70Snonaka bbp3 |= 1 << 4; 48549cdb1c70Snonaka run_bbp_write(sc, 3, bbp3); 48559cdb1c70Snonaka 48569cdb1c70Snonaka /* disable non-existing Tx chains */ 48579cdb1c70Snonaka run_bbp_read(sc, 1, &bbp1); 48589cdb1c70Snonaka if (sc->ntxchains == 1) 48599cdb1c70Snonaka bbp1 &= ~(1 << 3 | 1 << 4); 48609cdb1c70Snonaka run_bbp_write(sc, 1, bbp1); 48619cdb1c70Snonaka 4862faca41fbSmlelstv if (sc->mac_ver >= 0x5390) 4863faca41fbSmlelstv run_rt5390_rf_setup(sc); 4864faca41fbSmlelstv else if (sc->mac_ver == 0x3593) 4865faca41fbSmlelstv run_rt3593_rf_setup(sc); 4866faca41fbSmlelstv else if (sc->mac_ver >= 0x3070) 48679cdb1c70Snonaka run_rt3070_rf_setup(sc); 48689cdb1c70Snonaka 48699cdb1c70Snonaka /* select default channel */ 48709cdb1c70Snonaka run_set_chan(sc, ic->ic_curchan); 48719cdb1c70Snonaka 4872faca41fbSmlelstv /* setup initial protection mode */ 4873faca41fbSmlelstv run_updateprot(sc); 4874faca41fbSmlelstv 48759cdb1c70Snonaka /* turn radio LED on */ 48769cdb1c70Snonaka run_set_leds(sc, RT2860_LED_RADIO); 48779cdb1c70Snonaka 48789cdb1c70Snonaka #ifdef RUN_HWCRYPTO 48799cdb1c70Snonaka if (ic->ic_flags & IEEE80211_F_PRIVACY) { 48809cdb1c70Snonaka /* install WEP keys */ 48819cdb1c70Snonaka for (i = 0; i < IEEE80211_WEP_NKID; i++) 48829cdb1c70Snonaka (void)run_set_key(ic, &ic->ic_crypto.cs_nw_keys[i], 48839cdb1c70Snonaka NULL); 48849cdb1c70Snonaka } 48859cdb1c70Snonaka #endif 48869cdb1c70Snonaka 48879cdb1c70Snonaka for (i = 0; i < RUN_RX_RING_COUNT; i++) { 48889cdb1c70Snonaka struct run_rx_data *data = &sc->rxq.data[i]; 48899cdb1c70Snonaka 48904e8e6643Sskrll usbd_setup_xfer(data->xfer, data, data->buf, RUN_MAX_RXSZ, 48914e8e6643Sskrll USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, run_rxeof); 4892d164e220Smlelstv status = usbd_transfer(data->xfer); 4893d164e220Smlelstv if (status != USBD_NORMAL_COMPLETION && 4894d164e220Smlelstv status != USBD_IN_PROGRESS) { 4895d164e220Smlelstv device_printf(sc->sc_dev, "queuing rx failed: %s\n", 4896d164e220Smlelstv usbd_errstr(status)); 4897d164e220Smlelstv error = EIO; 48989cdb1c70Snonaka goto fail; 48999cdb1c70Snonaka } 4900d164e220Smlelstv } 49019cdb1c70Snonaka 49029cdb1c70Snonaka if ((error = run_txrx_enable(sc)) != 0) 49039cdb1c70Snonaka goto fail; 49049cdb1c70Snonaka 49059cdb1c70Snonaka ifp->if_flags &= ~IFF_OACTIVE; 49069cdb1c70Snonaka ifp->if_flags |= IFF_RUNNING; 49079cdb1c70Snonaka 49089cdb1c70Snonaka if (ic->ic_opmode == IEEE80211_M_MONITOR) 49099cdb1c70Snonaka ieee80211_new_state(ic, IEEE80211_S_RUN, -1); 49109cdb1c70Snonaka else 49119cdb1c70Snonaka ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 49129cdb1c70Snonaka 49139cdb1c70Snonaka if (error != 0) 49149cdb1c70Snonaka fail: run_stop(ifp, 1); 49154e8e6643Sskrll return error; 49169cdb1c70Snonaka } 49179cdb1c70Snonaka 49189cdb1c70Snonaka static void 49199cdb1c70Snonaka run_stop(struct ifnet *ifp, int disable) 49209cdb1c70Snonaka { 49219cdb1c70Snonaka struct run_softc *sc = ifp->if_softc; 49229cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 49239cdb1c70Snonaka uint32_t tmp; 49249cdb1c70Snonaka int ntries, qid; 49259cdb1c70Snonaka 49269cdb1c70Snonaka if (ifp->if_flags & IFF_RUNNING) 49279cdb1c70Snonaka run_set_leds(sc, 0); /* turn all LEDs off */ 49289cdb1c70Snonaka 49299cdb1c70Snonaka sc->sc_tx_timer = 0; 49309cdb1c70Snonaka ifp->if_timer = 0; 49319cdb1c70Snonaka ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 49329cdb1c70Snonaka 49339cdb1c70Snonaka callout_stop(&sc->scan_to); 49349cdb1c70Snonaka callout_stop(&sc->calib_to); 49359cdb1c70Snonaka 49369cdb1c70Snonaka ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 49379cdb1c70Snonaka /* wait for all queued asynchronous commands to complete */ 49389cdb1c70Snonaka while (sc->cmdq.queued > 0) 49399cdb1c70Snonaka tsleep(&sc->cmdq, 0, "cmdq", 0); 49409cdb1c70Snonaka 49419cdb1c70Snonaka /* disable Tx/Rx */ 49429cdb1c70Snonaka run_read(sc, RT2860_MAC_SYS_CTRL, &tmp); 49439cdb1c70Snonaka tmp &= ~(RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); 49449cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL, tmp); 49459cdb1c70Snonaka 49469cdb1c70Snonaka /* wait for pending Tx to complete */ 49479cdb1c70Snonaka for (ntries = 0; ntries < 100; ntries++) { 49489cdb1c70Snonaka if (run_read(sc, RT2860_TXRXQ_PCNT, &tmp) != 0) 49499cdb1c70Snonaka break; 49509cdb1c70Snonaka if ((tmp & RT2860_TX2Q_PCNT_MASK) == 0) 49519cdb1c70Snonaka break; 49529cdb1c70Snonaka } 49539cdb1c70Snonaka DELAY(1000); 49549cdb1c70Snonaka run_write(sc, RT2860_USB_DMA_CFG, 0); 49559cdb1c70Snonaka 49569cdb1c70Snonaka /* reset adapter */ 49579cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL, RT2860_BBP_HRST | RT2860_MAC_SRST); 49589cdb1c70Snonaka run_write(sc, RT2860_MAC_SYS_CTRL, 0); 49599cdb1c70Snonaka 49609cdb1c70Snonaka /* reset Tx and Rx rings */ 49619cdb1c70Snonaka sc->qfullmsk = 0; 49629cdb1c70Snonaka for (qid = 0; qid < 4; qid++) 49639cdb1c70Snonaka run_free_tx_ring(sc, qid); 49649cdb1c70Snonaka run_free_rx_ring(sc); 49659cdb1c70Snonaka } 49669cdb1c70Snonaka 49679cdb1c70Snonaka #ifndef IEEE80211_STA_ONLY 49689cdb1c70Snonaka static int 49699cdb1c70Snonaka run_setup_beacon(struct run_softc *sc) 49709cdb1c70Snonaka { 49719cdb1c70Snonaka struct ieee80211com *ic = &sc->sc_ic; 49729cdb1c70Snonaka struct rt2860_txwi txwi; 49739cdb1c70Snonaka struct mbuf *m; 4974faca41fbSmlelstv uint16_t txwisize; 49759cdb1c70Snonaka int ridx; 49769cdb1c70Snonaka 49779cdb1c70Snonaka if ((m = ieee80211_beacon_alloc(ic, ic->ic_bss, &sc->sc_bo)) == NULL) 49784e8e6643Sskrll return ENOBUFS; 49799cdb1c70Snonaka 49804e8e6643Sskrll memset(&txwi, 0, sizeof(txwi)); 49819cdb1c70Snonaka txwi.wcid = 0xff; 49829cdb1c70Snonaka txwi.len = htole16(m->m_pkthdr.len); 49839cdb1c70Snonaka /* send beacons at the lowest available rate */ 49849cdb1c70Snonaka ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ? 49859cdb1c70Snonaka RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1; 49869cdb1c70Snonaka txwi.phy = htole16(rt2860_rates[ridx].mcs); 49879cdb1c70Snonaka if (rt2860_rates[ridx].phy == IEEE80211_T_OFDM) 49889cdb1c70Snonaka txwi.phy |= htole16(RT2860_PHY_OFDM); 49899cdb1c70Snonaka txwi.txop = RT2860_TX_TXOP_HT; 49909cdb1c70Snonaka txwi.flags = RT2860_TX_TS; 49919cdb1c70Snonaka 4992faca41fbSmlelstv txwisize = (sc->mac_ver == 0x5592) ? 4993faca41fbSmlelstv sizeof(txwi) + sizeof(uint32_t) : sizeof(txwi); 49949cdb1c70Snonaka run_write_region_1(sc, RT2860_BCN_BASE(0), 4995faca41fbSmlelstv (uint8_t *)&txwi, txwisize); 4996faca41fbSmlelstv run_write_region_1(sc, RT2860_BCN_BASE(0) + txwisize, 4997faca41fbSmlelstv mtod(m, uint8_t *), (m->m_pkthdr.len + 1) & ~1); 49989cdb1c70Snonaka 49999cdb1c70Snonaka m_freem(m); 50009cdb1c70Snonaka 50014e8e6643Sskrll return 0; 50029cdb1c70Snonaka } 50039cdb1c70Snonaka #endif 50049cdb1c70Snonaka 500560d3fae6Schristos MODULE(MODULE_CLASS_DRIVER, if_run, NULL); 50069cdb1c70Snonaka 50079cdb1c70Snonaka #ifdef _MODULE 50089cdb1c70Snonaka #include "ioconf.c" 50099cdb1c70Snonaka #endif 50109cdb1c70Snonaka 50119cdb1c70Snonaka static int 50129cdb1c70Snonaka if_run_modcmd(modcmd_t cmd, void *arg) 50139cdb1c70Snonaka { 50149cdb1c70Snonaka int error = 0; 50159cdb1c70Snonaka 50169cdb1c70Snonaka switch (cmd) { 50179cdb1c70Snonaka case MODULE_CMD_INIT: 50189cdb1c70Snonaka #ifdef _MODULE 50199cdb1c70Snonaka error = config_init_component(cfdriver_ioconf_run, 50209cdb1c70Snonaka cfattach_ioconf_run, cfdata_ioconf_run); 50219cdb1c70Snonaka #endif 50224e8e6643Sskrll return error; 50239cdb1c70Snonaka case MODULE_CMD_FINI: 50249cdb1c70Snonaka #ifdef _MODULE 50259cdb1c70Snonaka error = config_fini_component(cfdriver_ioconf_run, 50269cdb1c70Snonaka cfattach_ioconf_run, cfdata_ioconf_run); 50279cdb1c70Snonaka #endif 50284e8e6643Sskrll return error; 50299cdb1c70Snonaka default: 50304e8e6643Sskrll return ENOTTY; 50319cdb1c70Snonaka } 50329cdb1c70Snonaka } 5033