From owner-svn-src-stable-10@FreeBSD.ORG Fri Feb 14 03:45:50 2014 Return-Path: Delivered-To: svn-src-stable-10@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 1F157EC3; Fri, 14 Feb 2014 03:45:50 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 08A0418BF; Fri, 14 Feb 2014 03:45:50 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s1E3jo0Z017512; Fri, 14 Feb 2014 03:45:50 GMT (envelope-from kevlo@svn.freebsd.org) Received: (from kevlo@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s1E3jn2c017508; Fri, 14 Feb 2014 03:45:49 GMT (envelope-from kevlo@svn.freebsd.org) Message-Id: <201402140345.s1E3jn2c017508@svn.freebsd.org> From: Kevin Lo Date: Fri, 14 Feb 2014 03:45:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r261868 - in stable/10: share/man/man4 sys/dev/usb sys/dev/usb/wlan X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Feb 2014 03:45:50 -0000 Author: kevlo Date: Fri Feb 14 03:45:49 2014 New Revision: 261868 URL: http://svnweb.freebsd.org/changeset/base/261868 Log: MFC r259544, r259545, r259546, r259547, r259812, r259939, r260219, r260542, r261118, r261124, r261330: - Add support for the MediaTek/Ralink RT3593 chipset. - Various minor USB WLAN fixes and improvements. Modified: stable/10/share/man/man4/run.4 stable/10/sys/dev/usb/usbdevs stable/10/sys/dev/usb/wlan/if_run.c stable/10/sys/dev/usb/wlan/if_runreg.h stable/10/sys/dev/usb/wlan/if_runvar.h Directory Properties: stable/10/ (props changed) Modified: stable/10/share/man/man4/run.4 ============================================================================== --- stable/10/share/man/man4/run.4 Fri Feb 14 03:34:12 2014 (r261867) +++ stable/10/share/man/man4/run.4 Fri Feb 14 03:45:49 2014 (r261868) @@ -16,7 +16,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 11, 2013 +.Dd January 3, 2014 .Dt RUN 4 .Os .Sh NAME @@ -64,8 +64,17 @@ The RT3000U is a single-chip solution ba an RT3020 (1T1R), RT3021 (1T2R) or RT3022 (2T2R) single-band radio transceiver. .Pp -The RT3900E is a single-chip solution based on an RT5390 MAC/BBP and -an RT5370 (1T1R) or RT5372 (2T2R) single-band radio transceiver. +The RT3900E is a single-chip USB 2.0 802.11n solution. +The MAC/Baseband Processor can be an RT3593, RT5390, RT5392 or an RT5592. +The radio can be an RT3053, RT5370, RT5372 or an RT5572. +The RT3053 chip operates in the 2GHz and 5GHz spectra and supports up to +3 transmit paths and 3 receiver paths (3T3R). +The RT5370 chip operates in the 2GHz spectrum and supports 1 transmit path +and 1 receiver path (1T1R). +The RT5372 chip operates in the 2GHz spectrum and supports up to 2 transmit +paths and 2 receiver paths (2T2R). +The RT5572 chip operates in the 2GHz and 5GHz spectra and supports up to +2 transmit paths and 2 receiver paths (2T2R). .Pp These are the modes the .Nm @@ -116,11 +125,13 @@ driver supports the following wireless a .It Airlink101 AWLL6090 .It ASUS USB-N11 .It ASUS USB-N13 ver. A1 +.It ASUS USB-N66 .It ASUS WL-160N .It Belkin F5D8051 ver 3000 .It Belkin F5D8053 .It Belkin F5D8055 .It Belkin F6D4050 ver 1 +.It Belkin F9L1103 .It Buffalo WLI-UC-AG300N .It Buffalo WLI-UC-G300N .It Buffalo WLI-UC-G301N @@ -132,13 +143,15 @@ driver supports the following wireless a .It Corega CG-WLUSB300AGN .It Corega CG-WLUSB300GNM .It D-Link DWA-130 rev B1 -.It D-Link DWA-140 rev B1, B2, B3 +.It D-Link DWA-140 rev B1, B2, B3, D1 .It D-Link DWA-160 rev B2 +.It D-Link DWA-162 .It DrayTek Vigor N61 .It Edimax EW-7711UAn .It Edimax EW-7711UTn .It Edimax EW-7717Un .It Edimax EW-7718Un +.It Edimax EW-7733UnD .It Gigabyte GN-WB30N .It Gigabyte GN-WB31N .It Gigabyte GN-WB32L @@ -164,6 +177,7 @@ driver supports the following wireless a .It TP-LINK TL-WN727N v3 .It Unex DNUR-81 .It Unex DNUR-82 +.It ZyXEL NWD2705 .It ZyXEL NWD210N .It ZyXEL NWD270N .El @@ -235,4 +249,4 @@ driver was written by The .Nm driver does not support any of the 802.11n capabilities offered by the -RT2800 and RT3000 chipsets. +RT2800, RT3000 and RT3900 chipsets. Modified: stable/10/sys/dev/usb/usbdevs ============================================================================== --- stable/10/sys/dev/usb/usbdevs Fri Feb 14 03:34:12 2014 (r261867) +++ stable/10/sys/dev/usb/usbdevs Fri Feb 14 03:45:49 2014 (r261868) @@ -1183,6 +1183,7 @@ product ASUS USBN13 0x1784 USB-N13 product ASUS RT3070_1 0x1790 RT3070 product ASUS USBN10 0x1786 USB-N10 product ASUS RTL8192CU 0x17ab RTL8192CU +product ASUS USBN66 0x17ad USB-N66 product ASUS RTL8192SU 0x1791 RTL8192SU product ASUS A730W 0x4202 ASUS MyPal A730W product ASUS P535 0x420f ASUS P535 PDA @@ -1285,6 +1286,7 @@ product BELKIN F5U409 0x0409 F5U409 Ser product BELKIN F6C550AVR 0x0551 F6C550-AVR UPS product BELKIN F5U120 0x1203 F5U120-PC Hub product BELKIN RTL8188CU 0x1102 RTL8188CU Wireless Adapter +product BELKIN F9L1103 0x1103 F9L1103 Wireless Adapter product BELKIN RTL8192CU 0x2102 RTL8192CU Wireless Adapter product BELKIN F7D2102 0x2103 F7D2102 Wireless Adapter product BELKIN ZD1211B 0x4050 ZD1211B @@ -1598,6 +1600,8 @@ product DLINK RT3072 0x3c0a RT3072 product DLINK DWA140B3 0x3c15 DWA-140 rev B3 product DLINK DWA160B2 0x3c1a DWA-160 rev B2 product DLINK DWA127 0x3c1b DWA-127 Wireless Adapter +product DLINK DWA162 0x3c1f DWA-162 Wireless Adapter +product DLINK DWA140D1 0x3c20 DWA-140 rev D1 product DLINK DSB650C 0x4000 10Mbps Ethernet product DLINK DSB650TX1 0x4001 10/100 Ethernet product DLINK DSB650TX 0x4002 10/100 Ethernet @@ -1658,6 +1662,7 @@ product EDIMAX RTL8192SU_3 0x7622 RTL819 product EDIMAX RT2870_1 0x7711 RT2870 product EDIMAX EW7717 0x7717 EW-7717 product EDIMAX EW7718 0x7718 EW-7718 +product EDIMAX EW7733UND 0x7733 EW-7733UnD product EDIMAX EW7811UN 0x7811 EW-7811Un product EDIMAX RTL8192CU 0x7822 RTL8192CU @@ -3617,11 +3622,13 @@ product RALINK RT2573 0x2573 RT2501USB product RALINK RT2671 0x2671 RT2601USB Wireless Adapter product RALINK RT2770 0x2770 RT2770 product RALINK RT2870 0x2870 RT2870 +product RALINK RT_STOR 0x2878 USB Storage product RALINK RT3070 0x3070 RT3070 product RALINK RT3071 0x3071 RT3071 product RALINK RT3072 0x3072 RT3072 product RALINK RT3370 0x3370 RT3370 product RALINK RT3572 0x3572 RT3572 +product RALINK RT3573 0x3573 RT3573 product RALINK RT5370 0x5370 RT5370 product RALINK RT5572 0x5572 RT5572 product RALINK RT8070 0x8070 RT8070 @@ -3643,10 +3650,11 @@ product REALTEK RTL8171 0x8171 RTL8171 product REALTEK RTL8172 0x8172 RTL8172 product REALTEK RTL8173 0x8173 RTL8173 product REALTEK RTL8174 0x8174 RTL8174 -product REALTEK RTL8188CE_1 0x817e RTL8188CE -product REALTEK RTL8188CU_0 0x8176 RTL8188CU -product REALTEK RTL8188CU_1 0x817a RTL8188CU -product REALTEK RTL8188CU_2 0x817b RTL8188CU +product REALTEK RTL8188CU_0 0x8176 RTL8188CU +product REALTEK RTL8188EU 0x8179 RTL8188EU +product REALTEK RTL8188CE_1 0x817e RTL8188CE +product REALTEK RTL8188CU_1 0x817a RTL8188CU +product REALTEK RTL8188CU_2 0x817b RTL8188CU product REALTEK RTL8187 0x8187 RTL8187 Wireless Adapter product REALTEK RTL8187B_0 0x8189 RTL8187B Wireless Adapter product REALTEK RTL8187B_1 0x8197 RTL8187B Wireless Adapter @@ -4486,3 +4494,4 @@ product ZYXEL G202 0x3410 G-202 product ZYXEL RT2870_1 0x3416 RT2870 product ZYXEL RT2870_2 0x341a RT2870 product ZYXEL RTL8192CU 0x341f RTL8192CU +product ZYXEL NWD2705 0x3421 NWD2705 Modified: stable/10/sys/dev/usb/wlan/if_run.c ============================================================================== --- stable/10/sys/dev/usb/wlan/if_run.c Fri Feb 14 03:34:12 2014 (r261867) +++ stable/10/sys/dev/usb/wlan/if_run.c Fri Feb 14 03:45:49 2014 (r261868) @@ -2,7 +2,7 @@ * Copyright (c) 2008,2010 Damien Bergamini * ported to FreeBSD by Akinori Furukoshi * USB Consulting, Hans Petter Selasky - * Copyright (c) 2013 Kevin Lo + * Copyright (c) 2013-2014 Kevin Lo * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -69,14 +69,15 @@ __FBSDID("$FreeBSD$"); #include #include "usbdevs.h" -#define USB_DEBUG_VAR run_debug +#define USB_DEBUG_VAR run_debug #include +#include #include #include #ifdef USB_DEBUG -#define RUN_DEBUG +#define RUN_DEBUG #endif #ifdef RUN_DEBUG @@ -86,17 +87,19 @@ SYSCTL_INT(_hw_usb_run, OID_AUTO, debug, "run debug level"); #endif -#define IEEE80211_HAS_ADDR4(wh) \ +#define IEEE80211_HAS_ADDR4(wh) \ (((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) /* * Because of LOR in run_key_delete(), use atomic instead. * '& RUN_CMDQ_MASQ' is to loop cmdq[]. */ -#define RUN_CMDQ_GET(c) (atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ) +#define RUN_CMDQ_GET(c) (atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ) static const STRUCT_USB_HOST_ID run_devs[] = { -#define RUN_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } +#define RUN_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } +#define RUN_DEV_EJECT(v,p) \ + { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, 0) } RUN_DEV(ABOCOM, RT2770), RUN_DEV(ABOCOM, RT2870), RUN_DEV(ABOCOM, RT3070), @@ -135,6 +138,7 @@ static const STRUCT_USB_HOST_ID run_devs RUN_DEV(ASUS, RT2870_5), RUN_DEV(ASUS, USBN13), RUN_DEV(ASUS, RT3070_1), + RUN_DEV(ASUS, USBN66), RUN_DEV(ASUS, USB_N53), RUN_DEV(ASUS2, USBN11), RUN_DEV(AZUREWAVE, RT2870_1), @@ -142,6 +146,7 @@ static const STRUCT_USB_HOST_ID run_devs RUN_DEV(AZUREWAVE, RT3070_1), RUN_DEV(AZUREWAVE, RT3070_2), RUN_DEV(AZUREWAVE, RT3070_3), + RUN_DEV(BELKIN, F9L1103), RUN_DEV(BELKIN, F5D8053V3), RUN_DEV(BELKIN, F5D8055), RUN_DEV(BELKIN, F5D8055V2), @@ -174,6 +179,7 @@ static const STRUCT_USB_HOST_ID run_devs RUN_DEV(DLINK, DWA127), RUN_DEV(DLINK, DWA140B3), RUN_DEV(DLINK, DWA160B2), + RUN_DEV(DLINK, DWA162), RUN_DEV(DLINK2, DWA130), RUN_DEV(DLINK2, RT2870_1), RUN_DEV(DLINK2, RT2870_2), @@ -186,6 +192,7 @@ static const STRUCT_USB_HOST_ID run_devs RUN_DEV(DLINK2, RT3072_1), RUN_DEV(EDIMAX, EW7717), RUN_DEV(EDIMAX, EW7718), + RUN_DEV(EDIMAX, EW7733UND), RUN_DEV(EDIMAX, RT2870_1), RUN_DEV(ENCORE, RT3070_1), RUN_DEV(ENCORE, RT3070_2), @@ -257,6 +264,7 @@ static const STRUCT_USB_HOST_ID run_devs RUN_DEV(RALINK, RT3072), RUN_DEV(RALINK, RT3370), RUN_DEV(RALINK, RT3572), + RUN_DEV(RALINK, RT3573), RUN_DEV(RALINK, RT5370), RUN_DEV(RALINK, RT5572), RUN_DEV(RALINK, RT8070), @@ -306,6 +314,9 @@ static const STRUCT_USB_HOST_ID run_devs RUN_DEV(ZINWELL, RT3072_2), RUN_DEV(ZYXEL, RT2870_1), RUN_DEV(ZYXEL, RT2870_2), + RUN_DEV(ZYXEL, NWD2705), + RUN_DEV_EJECT(RALINK, RT_STOR), +#undef RUN_DEV_EJECT #undef RUN_DEV }; @@ -321,6 +332,9 @@ static usb_callback_t run_bulk_tx_callba static usb_callback_t run_bulk_tx_callback4; static usb_callback_t run_bulk_tx_callback5; +static void run_autoinst(void *, struct usb_device *, + struct usb_attach_arg *); +static int run_driver_loaded(struct module *, int, void *); static void run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index); static struct ieee80211vap *run_vap_create(struct ieee80211com *, @@ -344,6 +358,7 @@ static int run_write(struct run_softc *, static int run_write_region_1(struct run_softc *, uint16_t, const uint8_t *, int); static int run_set_region_4(struct run_softc *, uint16_t, uint32_t, int); +static int run_efuse_read(struct run_softc *, uint16_t, uint16_t *, int); static int run_efuse_read_2(struct run_softc *, uint16_t, uint16_t *); static int run_eeprom_read_2(struct run_softc *, uint16_t, uint16_t *); static int run_rt2870_rf_write(struct run_softc *, uint32_t); @@ -353,6 +368,8 @@ static int run_bbp_read(struct run_softc static int run_bbp_write(struct run_softc *, uint8_t, uint8_t); static int run_mcu_cmd(struct run_softc *, uint8_t, uint16_t); static const char *run_get_rf(uint16_t); +static void run_rt3593_get_txpower(struct run_softc *); +static void run_get_txpower(struct run_softc *); static int run_read_eeprom(struct run_softc *); static struct ieee80211_node *run_node_alloc(struct ieee80211vap *, const uint8_t mac[IEEE80211_ADDR_LEN]); @@ -390,12 +407,14 @@ static int run_raw_xmit(struct ieee80211 const struct ieee80211_bpf_params *); static void run_start(struct ifnet *); static int run_ioctl(struct ifnet *, u_long, caddr_t); +static void run_iq_calib(struct run_softc *, u_int); static void run_set_agc(struct run_softc *, uint8_t); static void run_select_chan_group(struct run_softc *, int); static void run_set_rx_antenna(struct run_softc *, int); static void run_rt2870_set_chan(struct run_softc *, u_int); static void run_rt3070_set_chan(struct run_softc *, u_int); static void run_rt3572_set_chan(struct run_softc *, u_int); +static void run_rt3593_set_chan(struct run_softc *, u_int); static void run_rt5390_set_chan(struct run_softc *, u_int); static void run_rt5592_set_chan(struct run_softc *, u_int); static int run_set_chan(struct run_softc *, struct ieee80211_channel *); @@ -424,10 +443,13 @@ static void run_update_promisc(struct if static void run_rt5390_bbp_init(struct run_softc *); static int run_bbp_init(struct run_softc *); static int run_rt3070_rf_init(struct run_softc *); +static void run_rt3593_rf_init(struct run_softc *); static void run_rt5390_rf_init(struct run_softc *); static int run_rt3070_filter_calib(struct run_softc *, uint8_t, uint8_t, uint8_t *); static void run_rt3070_rf_setup(struct run_softc *); +static void run_rt3593_rf_setup(struct run_softc *); +static void run_rt5390_rf_setup(struct run_softc *); static int run_txrx_enable(struct run_softc *); static void run_adjust_freq_offset(struct run_softc *); static void run_init(void *); @@ -435,6 +457,30 @@ static void run_init_locked(struct run_s static void run_stop(void *); static void run_delay(struct run_softc *, u_int); +static eventhandler_tag run_etag; + +static const struct rt2860_rate { + uint8_t rate; + uint8_t mcs; + enum ieee80211_phytype phy; + uint8_t ctl_ridx; + uint16_t sp_ack_dur; + uint16_t lp_ack_dur; +} rt2860_rates[] = { + { 2, 0, IEEE80211_T_DS, 0, 314, 314 }, + { 4, 1, IEEE80211_T_DS, 1, 258, 162 }, + { 11, 2, IEEE80211_T_DS, 2, 223, 127 }, + { 22, 3, IEEE80211_T_DS, 3, 213, 117 }, + { 12, 0, IEEE80211_T_OFDM, 4, 60, 60 }, + { 18, 1, IEEE80211_T_OFDM, 4, 52, 52 }, + { 24, 2, IEEE80211_T_OFDM, 6, 48, 48 }, + { 36, 3, IEEE80211_T_OFDM, 6, 44, 44 }, + { 48, 4, IEEE80211_T_OFDM, 8, 44, 44 }, + { 72, 5, IEEE80211_T_OFDM, 8, 40, 40 }, + { 96, 6, IEEE80211_T_OFDM, 8, 40, 40 }, + { 108, 7, IEEE80211_T_OFDM, 8, 40, 40 } +}; + static const struct { uint16_t reg; uint32_t val; @@ -497,6 +543,8 @@ static const struct { RT3070_DEF_RF },rt3572_def_rf[] = { RT3572_DEF_RF +},rt3593_def_rf[] = { + RT3593_DEF_RF },rt5390_def_rf[] = { RT5390_DEF_RF },rt5392_def_rf[] = { @@ -589,6 +637,46 @@ static const struct usb_config run_confi } }; +static void +run_autoinst(void *arg, struct usb_device *udev, + struct usb_attach_arg *uaa) +{ + struct usb_interface *iface; + struct usb_interface_descriptor *id; + + if (uaa->dev_state != UAA_DEV_READY) + return; + + iface = usbd_get_iface(udev, 0); + if (iface == NULL) + return; + id = iface->idesc; + if (id == NULL || id->bInterfaceClass != UICLASS_MASS) + return; + if (usbd_lookup_id_by_uaa(run_devs, sizeof(run_devs), uaa)) + return; + + if (usb_msc_eject(udev, 0, MSC_EJECT_STOPUNIT) == 0) + uaa->dev_state = UAA_DEV_EJECTING; +} + +static int +run_driver_loaded(struct module *mod, int what, void *arg) +{ + switch (what) { + case MOD_LOAD: + run_etag = EVENTHANDLER_REGISTER(usb_dev_configured, + run_autoinst, NULL, EVENTHANDLER_PRI_ANY); + break; + case MOD_UNLOAD: + EVENTHANDLER_DEREGISTER(usb_dev_configured, run_etag); + break; + default: + return (EOPNOTSUPP); + } + return (0); +} + static int run_match(device_t self) { @@ -710,7 +798,8 @@ run_attach(device_t self) setbit(&bands, IEEE80211_MODE_11B); setbit(&bands, IEEE80211_MODE_11G); if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 || - sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT5592_RF_5592) + sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 || + sc->rf_rev == RT5592_RF_5592) setbit(&bands, IEEE80211_MODE_11A); ieee80211_init_channels(ic, NULL, &bands); @@ -1061,9 +1150,11 @@ run_load_microcode(struct run_softc *sc) } /* write microcode image */ - run_write_region_1(sc, RT2870_FW_BASE, base, 4096); - run_write(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff); - run_write(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff); + if (sc->mac_ver != 0x3593) { + run_write_region_1(sc, RT2870_FW_BASE, base, 4096); + run_write(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff); + run_write(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff); + } req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = RT2870_RESET; @@ -1078,15 +1169,16 @@ run_load_microcode(struct run_softc *sc) run_delay(sc, 10); + run_write(sc, RT2860_H2M_BBPAGENT, 0); run_write(sc, RT2860_H2M_MAILBOX, 0); + run_write(sc, RT2860_H2M_INTSRC, 0); if ((error = run_mcu_cmd(sc, RT2860_MCU_CMD_RFRESET, 0)) != 0) goto fail; /* wait until microcontroller is ready */ for (ntries = 0; ntries < 1000; ntries++) { - if ((error = run_read(sc, RT2860_SYS_CTRL, &tmp)) != 0) { + if ((error = run_read(sc, RT2860_SYS_CTRL, &tmp)) != 0) goto fail; - } if (tmp & RT2860_MCU_READY) break; run_delay(sc, 10); @@ -1248,9 +1340,8 @@ run_set_region_4(struct run_softc *sc, u return (error); } -/* Read 16-bit from eFUSE ROM (RT3070 only.) */ static int -run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val) +run_efuse_read(struct run_softc *sc, uint16_t addr, uint16_t *val, int count) { uint32_t tmp; uint16_t reg; @@ -1259,7 +1350,8 @@ run_efuse_read_2(struct run_softc *sc, u if ((error = run_read(sc, RT3070_EFUSE_CTRL, &tmp)) != 0) return (error); - addr *= 2; + if (count == 2) + addr *= 2; /*- * Read one 16-byte block into registers EFUSE_DATA[0-3]: * DATA0: F E D C @@ -1289,10 +1381,19 @@ run_efuse_read_2(struct run_softc *sc, u if ((error = run_read(sc, reg, &tmp)) != 0) return (error); - *val = (addr & 2) ? tmp >> 16 : tmp & 0xffff; + tmp >>= (8 * (addr & 0x3)); + *val = (addr & 1) ? tmp >> 16 : tmp & 0xffff; + return (0); } +/* Read 16-bit from eFUSE ROM for RT3xxx. */ +static int +run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val) +{ + return (run_efuse_read(sc, addr, val, 2)); +} + static int run_eeprom_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val) { @@ -1305,7 +1406,7 @@ run_eeprom_read_2(struct run_softc *sc, req.bRequest = RT2870_EEPROM_READ; USETW(req.wValue, 0); USETW(req.wIndex, addr); - USETW(req.wLength, sizeof tmp); + USETW(req.wLength, sizeof(tmp)); error = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, &tmp); if (error == 0) @@ -1500,6 +1601,7 @@ run_get_rf(uint16_t rev) case RT3070_RF_3021: return "RT3021"; case RT3070_RF_3022: return "RT3022"; case RT3070_RF_3052: return "RT3052"; + case RT3593_RF_3053: return "RT3053"; case RT5592_RF_5592: return "RT5592"; case RT5390_RF_5370: return "RT5370"; case RT5390_RF_5372: return "RT5372"; @@ -1507,6 +1609,125 @@ run_get_rf(uint16_t rev) return ("unknown"); } +static void +run_rt3593_get_txpower(struct run_softc *sc) +{ + uint16_t addr, val; + int i; + + /* Read power settings for 2GHz channels. */ + for (i = 0; i < 14; i += 2) { + addr = (sc->ntxchains == 3) ? RT3593_EEPROM_PWR2GHZ_BASE1 : + RT2860_EEPROM_PWR2GHZ_BASE1; + run_srom_read(sc, addr + i / 2, &val); + sc->txpow1[i + 0] = (int8_t)(val & 0xff); + sc->txpow1[i + 1] = (int8_t)(val >> 8); + + addr = (sc->ntxchains == 3) ? RT3593_EEPROM_PWR2GHZ_BASE2 : + RT2860_EEPROM_PWR2GHZ_BASE2; + run_srom_read(sc, addr + i / 2, &val); + sc->txpow2[i + 0] = (int8_t)(val & 0xff); + sc->txpow2[i + 1] = (int8_t)(val >> 8); + + if (sc->ntxchains == 3) { + run_srom_read(sc, RT3593_EEPROM_PWR2GHZ_BASE3 + i / 2, + &val); + sc->txpow3[i + 0] = (int8_t)(val & 0xff); + sc->txpow3[i + 1] = (int8_t)(val >> 8); + } + } + /* Fix broken Tx power entries. */ + for (i = 0; i < 14; i++) { + if (sc->txpow1[i] > 31) + sc->txpow1[i] = 5; + if (sc->txpow2[i] > 31) + sc->txpow2[i] = 5; + if (sc->ntxchains == 3) { + if (sc->txpow3[i] > 31) + sc->txpow3[i] = 5; + } + } + /* Read power settings for 5GHz channels. */ + for (i = 0; i < 40; i += 2) { + run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE1 + i / 2, &val); + sc->txpow1[i + 14] = (int8_t)(val & 0xff); + sc->txpow1[i + 15] = (int8_t)(val >> 8); + + run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE2 + i / 2, &val); + sc->txpow2[i + 14] = (int8_t)(val & 0xff); + sc->txpow2[i + 15] = (int8_t)(val >> 8); + + if (sc->ntxchains == 3) { + run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE3 + i / 2, + &val); + sc->txpow3[i + 14] = (int8_t)(val & 0xff); + sc->txpow3[i + 15] = (int8_t)(val >> 8); + } + } +} + +static void +run_get_txpower(struct run_softc *sc) +{ + uint16_t val; + int i; + + /* Read power settings for 2GHz channels. */ + for (i = 0; i < 14; i += 2) { + run_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2, &val); + sc->txpow1[i + 0] = (int8_t)(val & 0xff); + sc->txpow1[i + 1] = (int8_t)(val >> 8); + + if (sc->mac_ver != 0x5390) { + run_srom_read(sc, + RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2, &val); + sc->txpow2[i + 0] = (int8_t)(val & 0xff); + sc->txpow2[i + 1] = (int8_t)(val >> 8); + } + } + /* Fix broken Tx power entries. */ + for (i = 0; i < 14; i++) { + if (sc->mac_ver >= 0x5390) { + if (sc->txpow1[i] < 0 || sc->txpow1[i] > 27) + sc->txpow1[i] = 5; + } else { + if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31) + sc->txpow1[i] = 5; + } + if (sc->mac_ver > 0x5390) { + if (sc->txpow2[i] < 0 || sc->txpow2[i] > 27) + sc->txpow2[i] = 5; + } else if (sc->mac_ver < 0x5390) { + if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31) + sc->txpow2[i] = 5; + } + DPRINTF("chan %d: power1=%d, power2=%d\n", + rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]); + } + /* Read power settings for 5GHz channels. */ + for (i = 0; i < 40; i += 2) { + run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2, &val); + sc->txpow1[i + 14] = (int8_t)(val & 0xff); + sc->txpow1[i + 15] = (int8_t)(val >> 8); + + run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2, &val); + sc->txpow2[i + 14] = (int8_t)(val & 0xff); + sc->txpow2[i + 15] = (int8_t)(val >> 8); + } + /* Fix broken Tx power entries. */ + for (i = 0; i < 40; i++ ) { + if (sc->mac_ver != 0x5592) { + if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15) + sc->txpow1[14 + i] = 5; + if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15) + sc->txpow2[14 + i] = 5; + } + DPRINTF("chan %d: power1=%d, power2=%d\n", + rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i], + sc->txpow2[14 + i]); + } +} + static int run_read_eeprom(struct run_softc *sc) { @@ -1520,7 +1741,7 @@ run_read_eeprom(struct run_softc *sc) if (sc->mac_ver >= 0x3070) { run_read(sc, RT3070_EFUSE_CTRL, &tmp); DPRINTF("EFUSE_CTRL=0x%08x\n", tmp); - if (tmp & RT3070_SEL_EFUSE) + if ((tmp & RT3070_SEL_EFUSE) || sc->mac_ver == 0x3593) sc->sc_srom_read = run_efuse_read_2; } @@ -1539,7 +1760,7 @@ run_read_eeprom(struct run_softc *sc) sc->sc_bssid[4] = val & 0xff; sc->sc_bssid[5] = val >> 8; - if (sc->mac_ver < 0x5390) { + if (sc->mac_ver < 0x3593) { /* read vender BBP settings */ for (i = 0; i < 10; i++) { run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val); @@ -1562,16 +1783,22 @@ run_read_eeprom(struct run_softc *sc) } /* read RF frequency offset from EEPROM */ - run_srom_read(sc, RT2860_EEPROM_FREQ_LEDS, &val); + run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS : + RT3593_EEPROM_FREQ, &val); sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0; DPRINTF("EEPROM freq offset %d\n", sc->freq & 0xff); + run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS : + RT3593_EEPROM_FREQ_LEDS, &val); if (val >> 8 != 0xff) { /* read LEDs operating mode */ sc->leds = val >> 8; - run_srom_read(sc, RT2860_EEPROM_LED1, &sc->led[0]); - run_srom_read(sc, RT2860_EEPROM_LED2, &sc->led[1]); - run_srom_read(sc, RT2860_EEPROM_LED3, &sc->led[2]); + run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED1 : + RT3593_EEPROM_LED1, &sc->led[0]); + run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED2 : + RT3593_EEPROM_LED2, &sc->led[1]); + run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED3 : + RT3593_EEPROM_LED3, &sc->led[2]); } else { /* broken EEPROM, use default settings */ sc->leds = 0x01; @@ -1589,6 +1816,8 @@ run_read_eeprom(struct run_softc *sc) run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val); if (val == 0xffff) { + device_printf(sc->sc_dev, + "invalid EEPROM antenna info, using default\n"); DPRINTF("invalid EEPROM antenna info, using default\n"); if (sc->mac_ver == 0x3572) { /* default to RF3052 2T2R */ @@ -1633,60 +1862,11 @@ run_read_eeprom(struct run_softc *sc) sc->rfswitch = val & 1; } - /* read power settings for 2GHz channels */ - for (i = 0; i < 14; i += 2) { - run_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2, &val); - sc->txpow1[i + 0] = (int8_t)(val & 0xff); - sc->txpow1[i + 1] = (int8_t)(val >> 8); - - if (sc->mac_ver != 0x5390) { - run_srom_read(sc, - RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2, &val); - sc->txpow2[i + 0] = (int8_t)(val & 0xff); - sc->txpow2[i + 1] = (int8_t)(val >> 8); - } - } - /* fix broken Tx power entries */ - for (i = 0; i < 14; i++) { - if (sc->mac_ver >= 0x5390) { - if (sc->txpow1[i] < 0 || sc->txpow1[i] > 27) - sc->txpow1[i] = 5; - } else { - if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31) - sc->txpow1[i] = 5; - } - if (sc->mac_ver > 0x5390) { - if (sc->txpow2[i] < 0 || sc->txpow2[i] > 27) - sc->txpow2[i] = 5; - } else if (sc->mac_ver < 0x5390) { - if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31) - sc->txpow2[i] = 5; - } - DPRINTF("chan %d: power1=%d, power2=%d\n", - rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]); - } - /* read power settings for 5GHz channels */ - for (i = 0; i < 40; i += 2) { - run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2, &val); - sc->txpow1[i + 14] = (int8_t)(val & 0xff); - sc->txpow1[i + 15] = (int8_t)(val >> 8); - - run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2, &val); - sc->txpow2[i + 14] = (int8_t)(val & 0xff); - sc->txpow2[i + 15] = (int8_t)(val >> 8); - } - /* fix broken Tx power entries */ - for (i = 0; i < 40; i++ ) { - if (sc->mac_ver != 0x5592) { - if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15) - sc->txpow1[14 + i] = 5; - if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15) - sc->txpow2[14 + i] = 5; - } - DPRINTF("chan %d: power1=%d, power2=%d\n", - rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i], - sc->txpow2[14 + i]); - } + /* Read Tx power settings. */ + if (sc->mac_ver == 0x3593) + run_rt3593_get_txpower(sc); + else + run_get_txpower(sc); /* read Tx power compensation for each Tx rate */ run_srom_read(sc, RT2860_EEPROM_DELTAPWR, &val); @@ -1722,27 +1902,38 @@ run_read_eeprom(struct run_softc *sc) sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx]); } - /* read RSSI offsets and LNA gains from EEPROM */ - run_srom_read(sc, RT2860_EEPROM_RSSI1_2GHZ, &val); + /* Read RSSI offsets and LNA gains from EEPROM. */ + run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_2GHZ : + RT3593_EEPROM_RSSI1_2GHZ, &val); sc->rssi_2ghz[0] = val & 0xff; /* Ant A */ sc->rssi_2ghz[1] = val >> 8; /* Ant B */ - run_srom_read(sc, RT2860_EEPROM_RSSI2_2GHZ, &val); + run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_2GHZ : + RT3593_EEPROM_RSSI2_2GHZ, &val); if (sc->mac_ver >= 0x3070) { - /* - * On RT3070 chips (limited to 2 Rx chains), this ROM - * field contains the Tx mixer gain for the 2GHz band. - */ - if ((val & 0xff) != 0xff) - sc->txmixgain_2ghz = val & 0x7; + if (sc->mac_ver == 0x3593) { + sc->txmixgain_2ghz = 0; + sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ + } else { + /* + * On RT3070 chips (limited to 2 Rx chains), this ROM + * field contains the Tx mixer gain for the 2GHz band. + */ + if ((val & 0xff) != 0xff) + sc->txmixgain_2ghz = val & 0x7; + } DPRINTF("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz); } else sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ + if (sc->mac_ver == 0x3593) + run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val); sc->lna[2] = val >> 8; /* channel group 2 */ - run_srom_read(sc, RT2860_EEPROM_RSSI1_5GHZ, &val); + run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_5GHZ : + RT3593_EEPROM_RSSI1_5GHZ, &val); sc->rssi_5ghz[0] = val & 0xff; /* Ant A */ sc->rssi_5ghz[1] = val >> 8; /* Ant B */ - run_srom_read(sc, RT2860_EEPROM_RSSI2_5GHZ, &val); + run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_5GHZ : + RT3593_EEPROM_RSSI2_5GHZ, &val); if (sc->mac_ver == 0x3572) { /* * On RT3572 chips (limited to 2 Rx chains), this ROM @@ -1753,9 +1944,14 @@ run_read_eeprom(struct run_softc *sc) DPRINTF("tx mixer gain=%u (5GHz)\n", sc->txmixgain_5ghz); } else sc->rssi_5ghz[2] = val & 0xff; /* Ant C */ + if (sc->mac_ver == 0x3593) { + sc->txmixgain_5ghz = 0; + run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val); + } sc->lna[3] = val >> 8; /* channel group 3 */ - run_srom_read(sc, RT2860_EEPROM_LNA, &val); + run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LNA : + RT3593_EEPROM_LNA, &val); sc->lna[0] = val & 0xff; /* channel group 0 */ sc->lna[1] = val >> 8; /* channel group 1 */ @@ -2570,9 +2766,11 @@ run_rx_frame(struct run_softc *sc, struc rxwi = mtod(m, struct rt2860_rxwi *); len = le16toh(rxwi->len) & 0xfff; - rxwisize = (sc->mac_ver == 0x5592) ? - sizeof(struct rt2860_rxwi) + sizeof(uint64_t) : - sizeof(struct rt2860_rxwi); + rxwisize = sizeof(struct rt2860_rxwi); + if (sc->mac_ver == 0x5592) + rxwisize += sizeof(uint64_t); + else if (sc->mac_ver == 0x3593) + rxwisize += sizeof(uint32_t); if (__predict_false(len > dmalen)) { m_freem(m); ifp->if_ierrors++; @@ -2683,9 +2881,11 @@ run_bulk_rx_callback(struct usb_xfer *xf uint16_t rxwisize; int xferlen; - rxwisize = (sc->mac_ver == 0x5592) ? - sizeof(struct rt2860_rxwi) + sizeof(uint64_t) : - sizeof(struct rt2860_rxwi); + rxwisize = sizeof(struct rt2860_rxwi); + if (sc->mac_ver == 0x5592) + rxwisize += sizeof(uint64_t); + else if (sc->mac_ver == 0x3593) + rxwisize += sizeof(uint32_t); usbd_xfer_status(xfer, &xferlen, NULL, NULL, NULL); @@ -2869,10 +3069,10 @@ tr_setup: STAILQ_REMOVE_HEAD(&pq->tx_qh, next); m = data->m; - size = (sc->mac_ver == 0x5592) ? - RUN_MAX_TXSZ + sizeof(uint32_t) : RUN_MAX_TXSZ; + size = (sc->mac_ver == 0x5592) ? + sizeof(data->desc) + sizeof(uint32_t) : sizeof(data->desc); if ((m->m_pkthdr.len + - sizeof(data->desc) + 3 + 8) > size) { + size + 3 + 8) > RUN_MAX_TXSZ) { DPRINTF("data overflow, %u bytes\n", m->m_pkthdr.len); @@ -2884,8 +3084,6 @@ tr_setup: } pc = usbd_xfer_get_frame(xfer, 0); - size = (sc->mac_ver == 0x5592) ? - sizeof(data->desc) + sizeof(uint32_t) : sizeof(data->desc); usbd_copy_in(pc, 0, &data->desc, size); usbd_m_copy_in(pc, size, m, 0, m->m_pkthdr.len); size += m->m_pkthdr.len; @@ -3599,6 +3797,107 @@ run_ioctl(struct ifnet *ifp, u_long cmd, } static void +run_iq_calib(struct run_softc *sc, u_int chan) +{ + uint16_t val; + + /* Tx0 IQ gain. */ + run_bbp_write(sc, 158, 0x2c); + if (chan <= 14) + run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX0_2GHZ, &val, 1); + else if (chan <= 64) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ, + &val, 1); + } else if (chan <= 138) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ, + &val, 1); + } else if (chan <= 165) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ, + &val, 1); + } else + val = 0; + run_bbp_write(sc, 159, val); + + /* Tx0 IQ phase. */ + run_bbp_write(sc, 158, 0x2d); + if (chan <= 14) { + run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX0_2GHZ, + &val, 1); + } else if (chan <= 64) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ, + &val, 1); + } else if (chan <= 138) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ, + &val, 1); + } else if (chan <= 165) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ, + &val, 1); + } else + val = 0; + run_bbp_write(sc, 159, val); + + /* Tx1 IQ gain. */ + run_bbp_write(sc, 158, 0x4a); + if (chan <= 14) { + run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX1_2GHZ, + &val, 1); + } else if (chan <= 64) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ, + &val, 1); + } else if (chan <= 138) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ, + &val, 1); + } else if (chan <= 165) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ, + &val, 1); + } else + val = 0; + run_bbp_write(sc, 159, val); + + /* Tx1 IQ phase. */ + run_bbp_write(sc, 158, 0x4b); + if (chan <= 14) { + run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX1_2GHZ, + &val, 1); + } else if (chan <= 64) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ, + &val, 1); + } else if (chan <= 138) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ, + &val, 1); + } else if (chan <= 165) { + run_efuse_read(sc, + RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ, + &val, 1); + } else + val = 0; + run_bbp_write(sc, 159, val); + + /* RF IQ compensation control. */ + run_bbp_write(sc, 158, 0x04); + run_efuse_read(sc, RT5390_EEPROM_RF_IQ_COMPENSATION_CTL, + &val, 1); + run_bbp_write(sc, 159, val); + + /* RF IQ imbalance compensation control. */ + run_bbp_write(sc, 158, 0x03); + run_efuse_read(sc, + RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL, &val, 1); + run_bbp_write(sc, 159, val); +} + +static void run_set_agc(struct run_softc *sc, uint8_t agc) { uint8_t bbp; @@ -3626,6 +3925,11 @@ run_select_chan_group(struct run_softc * if (sc->mac_ver < 0x3572) run_bbp_write(sc, 86, 0x00); + if (sc->mac_ver == 0x3593) { + run_bbp_write(sc, 77, 0x98); + run_bbp_write(sc, 83, (group == 0) ? 0x8a : 0x9a); + } + if (group == 0) { if (sc->ext_2ghz_lna) { if (sc->mac_ver >= 0x5390) @@ -3656,7 +3960,8 @@ run_select_chan_group(struct run_softc * } else if (sc->mac_ver >= 0x5390) run_bbp_write(sc, 75, 0x50); else { - run_bbp_write(sc, 82, 0x84); + run_bbp_write(sc, 82, + (sc->mac_ver == 0x3593) ? 0x62 : 0x84); run_bbp_write(sc, 75, 0x50); } } @@ -3682,7 +3987,8 @@ run_select_chan_group(struct run_softc * } else if (sc->mac_ver == 0x3572) run_bbp_write(sc, 82, 0x94); else - run_bbp_write(sc, 82, 0xf2); + run_bbp_write(sc, 82, + (sc->mac_ver == 0x3593) ? 0x82 : 0xf2); if (sc->ext_5ghz_lna) run_bbp_write(sc, 75, 0x46); else @@ -3696,12 +4002,18 @@ run_select_chan_group(struct run_softc * *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***