The following reply was made to PR usb/182936; it has been noted by GNATS.

From: dfil...@freebsd.org (dfilter service)
To: bug-follo...@freebsd.org
Cc:  
Subject: Re: usb/182936: commit references a PR
Date: Mon, 16 Dec 2013 08:10:48 +0000 (UTC)

 Author: hselasky
 Date: Mon Dec 16 08:10:38 2013
 New Revision: 259453
 URL: http://svnweb.freebsd.org/changeset/base/259453
 
 Log:
   MFC r238274, r246752, r256720, r256721, r256722, r256955, r257409
    r257429, r257435, r257712, r257732, r257743, r257748, r257955
    r257957, r257958, r258082, r258641, r258643, r258732, r258733,
    r258840, r258919, r258921, r259029, r259030, r259031, r259032 and r259046:
   
   - Add support for the MediaTek/Ralink RT5370/RT5372 chipset.
   - Various minor USB WLAN fixes and improvements.
   
   PR:     usb/182936
 
 Modified:
   stable/10/share/man/man4/run.4
   stable/10/share/man/man4/runfw.4
   stable/10/sys/dev/usb/usbdevs
   stable/10/sys/dev/usb/wlan/if_rsu.c
   stable/10/sys/dev/usb/wlan/if_rum.c
   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
   stable/10/sys/dev/usb/wlan/if_uath.c
   stable/10/sys/dev/usb/wlan/if_upgt.c
   stable/10/sys/dev/usb/wlan/if_ural.c
   stable/10/sys/dev/usb/wlan/if_urtw.c
   stable/10/sys/dev/usb/wlan/if_urtwn.c
   stable/10/sys/dev/usb/wlan/if_zyd.c
 Directory Properties:
   stable/10/   (props changed)
 
 Modified: stable/10/share/man/man4/run.4
 ==============================================================================
 --- stable/10/share/man/man4/run.4     Mon Dec 16 06:56:38 2013        
(r259452)
 +++ stable/10/share/man/man4/run.4     Mon Dec 16 08:10:38 2013        
(r259453)
 @@ -16,7 +16,7 @@
  .\"
  .\" $FreeBSD$
  .\"
 -.Dd July 9, 2012
 +.Dd November 11, 2013
  .Dt RUN 4
  .Os
  .Sh NAME
 @@ -52,7 +52,7 @@ runfw_load="YES"
  The
  .Nm
  driver supports USB 2.0 wireless adapters based on the Ralink RT2700U,
 -RT2800U and RT3000U chipsets.
 +RT2800U, RT3000U and RT3900E chipsets.
  .Pp
  The RT2700U chipset consists of two integrated chips, an RT2770 MAC/BBP and
  an RT2720 (1T2R) or RT2750 (dual-band 1T2R) radio transceiver.
 @@ -64,6 +64,9 @@ 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.
 +.Pp
  These are the modes the
  .Nm
  driver can operate in:
 @@ -129,7 +132,8 @@ 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
 +.It D-Link DWA-140 rev B1, B2, B3
 +.It D-Link DWA-160 rev B2
  .It DrayTek Vigor N61
  .It Edimax EW-7711UAn
  .It Edimax EW-7711UTn
 @@ -156,6 +160,8 @@ driver supports the following wireless a
  .It SMC SMCWUSBS-N2
  .It Sweex LW303
  .It Sweex LW313
 +.It TP-LINK TL-WDN3200
 +.It TP-LINK TL-WN727N v3
  .It Unex DNUR-81
  .It Unex DNUR-82
  .It ZyXEL NWD210N
 
 Modified: stable/10/share/man/man4/runfw.4
 ==============================================================================
 --- stable/10/share/man/man4/runfw.4   Mon Dec 16 06:56:38 2013        
(r259452)
 +++ stable/10/share/man/man4/runfw.4   Mon Dec 16 08:10:38 2013        
(r259453)
 @@ -18,7 +18,7 @@
  .\"
  .\" $FreeBSD$
  .\"
 -.Dd January 12, 2011
 +.Dd November 11, 2013
  .Dt RUNFW 4
  .Os
  .Sh NAME
 @@ -43,7 +43,7 @@ runfw_load="YES"
  .Ed
  .Sh DESCRIPTION
  This module provides firmware sets for the Ralink RT2700U,
 -RT2800U and RT3000U chip based USB WiFi adapters.
 +RT2800U, RT3000U and RT3900E chip based USB WiFi adapters.
  Please read Ralink's license, src/sys/contrib/dev/run/LICENSE.
  .Sh SEE ALSO
  .Xr run 4 ,
 
 Modified: stable/10/sys/dev/usb/usbdevs
 ==============================================================================
 --- stable/10/sys/dev/usb/usbdevs      Mon Dec 16 06:56:38 2013        
(r259452)
 +++ stable/10/sys/dev/usb/usbdevs      Mon Dec 16 08:10:38 2013        
(r259453)
 @@ -1549,6 +1549,8 @@ product DLINK DWLG122            0x3c00  DWL-G122 b
  product DLINK DUBE100B1               0x3c05  DUB-E100 rev B1
  product DLINK RT2870          0x3c09  RT2870
  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 DSB650C         0x4000  10Mbps Ethernet
  product DLINK DSB650TX1               0x4001  10/100 Ethernet
 @@ -3572,6 +3574,7 @@ product RALINK RT3072            0x3072  RT3072
  product RALINK RT3370         0x3370  RT3370
  product RALINK RT3572         0x3572  RT3572
  product RALINK RT5370         0x5370  RT5370
 +product RALINK RT5572         0x5572  RT5572
  product RALINK RT8070         0x8070  RT8070
  product RALINK RT2570_3               0x9020  RT2500USB Wireless Adapter
  product RALINK RT2573_2               0x9021  RT2501USB Wireless Adapter
 
 Modified: stable/10/sys/dev/usb/wlan/if_rsu.c
 ==============================================================================
 --- stable/10/sys/dev/usb/wlan/if_rsu.c        Mon Dec 16 06:56:38 2013        
(r259452)
 +++ stable/10/sys/dev/usb/wlan/if_rsu.c        Mon Dec 16 08:10:38 2013        
(r259453)
 @@ -480,8 +480,13 @@ rsu_vap_create(struct ieee80211com *ic, 
        if (uvp == NULL)
                return (NULL);
        vap = &uvp->vap;
 -      ieee80211_vap_setup(ic, vap, name, unit, opmode,
 -          flags, bssid, mac);
 +
 +      if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
 +          flags, bssid, mac) != 0) {
 +              /* out of memory */
 +              free(uvp, M_80211_VAP);
 +              return (NULL);
 +      }
  
        /* override state transition machine */
        uvp->newstate = vap->iv_newstate;
 @@ -1153,7 +1158,7 @@ rsu_event_survey(struct rsu_softc *sc, u
        wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
            IEEE80211_FC0_SUBTYPE_BEACON;
        wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
 -      *(uint16_t *)wh->i_dur = 0;
 +      USETW(wh->i_dur, 0);
        IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
        IEEE80211_ADDR_COPY(wh->i_addr2, bss->macaddr);
        IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr);
 
 Modified: stable/10/sys/dev/usb/wlan/if_rum.c
 ==============================================================================
 --- stable/10/sys/dev/usb/wlan/if_rum.c        Mon Dec 16 06:56:38 2013        
(r259452)
 +++ stable/10/sys/dev/usb/wlan/if_rum.c        Mon Dec 16 08:10:38 2013        
(r259453)
 @@ -604,8 +604,13 @@ rum_vap_create(struct ieee80211com *ic, 
                return NULL;
        vap = &rvp->vap;
        /* enable s/w bmiss handling for sta mode */
 -      ieee80211_vap_setup(ic, vap, name, unit, opmode,
 -          flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
 +
 +      if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
 +          flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
 +              /* out of memory */
 +              free(rvp, M_80211_VAP);
 +              return (NULL);
 +      }
  
        /* override state transition machine */
        rvp->newstate = vap->iv_newstate;
 @@ -1131,7 +1136,7 @@ rum_tx_mgt(struct rum_softc *sc, struct 
  
                dur = ieee80211_ack_duration(ic->ic_rt, tp->mgmtrate, 
                    ic->ic_flags & IEEE80211_F_SHPREAMBLE);
 -              *(uint16_t *)wh->i_dur = htole16(dur);
 +              USETW(wh->i_dur, dur);
  
                /* tell hardware to add timestamp for probe responses */
                if ((wh->i_fc[0] &
 @@ -1275,7 +1280,7 @@ rum_tx_data(struct rum_softc *sc, struct
  
                dur = ieee80211_ack_duration(ic->ic_rt, rate, 
                    ic->ic_flags & IEEE80211_F_SHPREAMBLE);
 -              *(uint16_t *)wh->i_dur = htole16(dur);
 +              USETW(wh->i_dur, dur);
        }
  
        rum_setup_tx_desc(sc, &data->desc, flags, 0, m0->m_pkthdr.len, rate);
 
 Modified: stable/10/sys/dev/usb/wlan/if_run.c
 ==============================================================================
 --- stable/10/sys/dev/usb/wlan/if_run.c        Mon Dec 16 06:56:38 2013        
(r259452)
 +++ stable/10/sys/dev/usb/wlan/if_run.c        Mon Dec 16 08:10:38 2013        
(r259453)
 @@ -2,6 +2,7 @@
   * Copyright (c) 2008,2010 Damien Bergamini <damien.bergam...@free.fr>
   * ported to FreeBSD by Akinori Furukoshi <moonlightak...@yahoo.ca>
   * USB Consulting, Hans Petter Selasky <hsela...@freebsd.org>
 + * Copyright (c) 2013 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
 @@ -20,7 +21,7 @@
  __FBSDID("$FreeBSD$");
  
  /*-
 - * Ralink Technology RT2700U/RT2800U/RT3000U chipset driver.
 + * Ralink Technology RT2700U/RT2800U/RT3000U/RT3900E chipset driver.
   * http://www.ralinktech.com/
   */
  
 @@ -74,8 +75,6 @@ __FBSDID("$FreeBSD$");
  #include <dev/usb/wlan/if_runreg.h>
  #include <dev/usb/wlan/if_runvar.h>
  
 -#define       N(_a) ((int)(sizeof((_a)) / sizeof((_a)[0])))
 -
  #ifdef        USB_DEBUG
  #define RUN_DEBUG
  #endif
 @@ -173,6 +172,8 @@ static const STRUCT_USB_HOST_ID run_devs
      RUN_DEV(DLINK,            RT2870),
      RUN_DEV(DLINK,            RT3072),
      RUN_DEV(DLINK,            DWA127),
 +    RUN_DEV(DLINK,            DWA140B3),
 +    RUN_DEV(DLINK,            DWA160B2),
      RUN_DEV(DLINK2,           DWA130),
      RUN_DEV(DLINK2,           RT2870_1),
      RUN_DEV(DLINK2,           RT2870_2),
 @@ -256,6 +257,8 @@ static const STRUCT_USB_HOST_ID run_devs
      RUN_DEV(RALINK,           RT3072),
      RUN_DEV(RALINK,           RT3370),
      RUN_DEV(RALINK,           RT3572),
 +    RUN_DEV(RALINK,           RT5370),
 +    RUN_DEV(RALINK,           RT5572),
      RUN_DEV(RALINK,           RT8070),
      RUN_DEV(SAMSUNG,          WIS09ABGN),
      RUN_DEV(SAMSUNG2,         RT2870_1),
 @@ -319,7 +322,7 @@ static usb_callback_t      run_bulk_tx_callba
  static usb_callback_t run_bulk_tx_callback5;
  
  static void   run_bulk_tx_callbackN(struct usb_xfer *xfer,
 -                  usb_error_t error, unsigned int index);
 +                  usb_error_t error, u_int index);
  static struct ieee80211vap *run_vap_create(struct ieee80211com *,
                    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
                    const uint8_t [IEEE80211_ADDR_LEN],
 @@ -343,13 +346,13 @@ static int       run_write_region_1(struct run
  static int    run_set_region_4(struct run_softc *, uint16_t, uint32_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 *, uint8_t, uint32_t);
 +static int    run_rt2870_rf_write(struct run_softc *, uint32_t);
  static int    run_rt3070_rf_read(struct run_softc *, uint8_t, uint8_t *);
  static int    run_rt3070_rf_write(struct run_softc *, uint8_t, uint8_t);
  static int    run_bbp_read(struct run_softc *, uint8_t, uint8_t *);
  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(int);
 +static const char *run_get_rf(uint16_t);
  static int    run_read_eeprom(struct run_softc *);
  static struct ieee80211_node *run_node_alloc(struct ieee80211vap *,
                            const uint8_t mac[IEEE80211_ADDR_LEN]);
 @@ -361,7 +364,7 @@ static void        run_key_update_begin(struct 
  static void   run_key_update_end(struct ieee80211vap *);
  static void   run_key_set_cb(void *);
  static int    run_key_set(struct ieee80211vap *, struct ieee80211_key *,
 -                          const uint8_t mac[IEEE80211_ADDR_LEN]);
 +                  const uint8_t mac[IEEE80211_ADDR_LEN]);
  static void   run_key_delete_cb(void *);
  static int    run_key_delete(struct ieee80211vap *, struct ieee80211_key *);
  static void   run_ratectl_to(void *);
 @@ -393,6 +396,8 @@ static void        run_set_rx_antenna(struct ru
  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_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 *);
  static void   run_set_channel(struct ieee80211com *);
  static void   run_scan_start(struct ieee80211com *);
 @@ -416,16 +421,19 @@ static void      run_update_mcast(struct ifne
  static int8_t run_rssi2dbm(struct run_softc *, uint8_t, uint8_t);
  static void   run_update_promisc_locked(struct ifnet *);
  static void   run_update_promisc(struct ifnet *);
 +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_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 int    run_txrx_enable(struct run_softc *);
 +static void   run_adjust_freq_offset(struct run_softc *);
  static void   run_init(void *);
  static void   run_init_locked(struct run_softc *);
  static void   run_stop(void *);
 -static void   run_delay(struct run_softc *, unsigned int);
 +static void   run_delay(struct run_softc *, u_int);
  
  static const struct {
        uint16_t        reg;
 @@ -439,6 +447,25 @@ static const struct {
        uint8_t val;
  } rt2860_def_bbp[] = {
        RT2860_DEF_BBP
 +},rt5390_def_bbp[] = {
 +      RT5390_DEF_BBP
 +},rt5592_def_bbp[] = {
 +      RT5592_DEF_BBP
 +};
 +
 +/* 
 + * Default values for BBP register R196 for RT5592.
 + */
 +static const uint8_t rt5592_bbp_r196[] = {
 +      0xe0, 0x1f, 0x38, 0x32, 0x08, 0x28, 0x19, 0x0a, 0xff, 0x00,
 +      0x16, 0x10, 0x10, 0x0b, 0x36, 0x2c, 0x26, 0x24, 0x42, 0x36,
 +      0x30, 0x2d, 0x4c, 0x46, 0x3d, 0x40, 0x3e, 0x42, 0x3d, 0x40,
 +      0x3c, 0x34, 0x2c, 0x2f, 0x3c, 0x35, 0x2e, 0x2a, 0x49, 0x41,
 +      0x36, 0x31, 0x30, 0x30, 0x0e, 0x0d, 0x28, 0x21, 0x1c, 0x16,
 +      0x50, 0x4a, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
 +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 +      0x00, 0x00, 0x7d, 0x14, 0x32, 0x2c, 0x36, 0x4c, 0x43, 0x2c,
 +      0x2e, 0x36, 0x30, 0x6e
  };
  
  static const struct rfprog {
 @@ -454,6 +481,15 @@ struct {
        RT3070_RF3052
  };
  
 +static const struct rt5592_freqs {
 +      uint16_t        n;
 +      uint8_t         k, m, r;
 +} rt5592_freqs_20mhz[] = {
 +      RT5592_RF5592_20MHZ
 +},rt5592_freqs_40mhz[] = {
 +      RT5592_RF5592_40MHZ
 +};
 +
  static const struct {
        uint8_t reg;
        uint8_t val;
 @@ -461,6 +497,25 @@ static const struct {
        RT3070_DEF_RF
  },rt3572_def_rf[] = {
        RT3572_DEF_RF
 +},rt5390_def_rf[] = {
 +      RT5390_DEF_RF
 +},rt5392_def_rf[] = {
 +      RT5392_DEF_RF
 +},rt5592_def_rf[] = {
 +      RT5592_DEF_RF
 +},rt5592_2ghz_def_rf[] = {
 +      RT5592_2GHZ_DEF_RF
 +},rt5592_5ghz_def_rf[] = {
 +      RT5592_5GHZ_DEF_RF
 +};
 +
 +static const struct {
 +      u_int   firstchan;
 +      u_int   lastchan;
 +      uint8_t reg;
 +      uint8_t val;
 +} rt5592_chan_5ghz[] = {
 +      RT5592_CHAN_5GHZ
  };
  
  static const struct usb_config run_config[RUN_N_XFER] = {
 @@ -557,7 +612,7 @@ run_attach(device_t self)
        struct ieee80211com *ic;
        struct ifnet *ifp;
        uint32_t ver;
 -      int i, ntries, error;
 +      int ntries, error;
        uint8_t iface_index, bands;
  
        device_set_usb_desc(self);
 @@ -654,27 +709,11 @@ run_attach(device_t self)
        bands = 0;
        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)
 +              setbit(&bands, IEEE80211_MODE_11A);
        ieee80211_init_channels(ic, NULL, &bands);
  
 -      /*
 -       * Do this by own because h/w supports
 -       * more channels than ieee80211_init_channels()
 -       */
 -      if (sc->rf_rev == RT2860_RF_2750 ||
 -          sc->rf_rev == RT2860_RF_2850 ||
 -          sc->rf_rev == RT3070_RF_3052) {
 -              /* set supported .11a rates */
 -              for (i = 14; i < N(rt2860_rf2850); i++) {
 -                      uint8_t chan = rt2860_rf2850[i].chan;
 -                      ic->ic_channels[ic->ic_nchans].ic_freq =
 -                          ieee80211_ieee2mhz(chan, IEEE80211_CHAN_A);
 -                      ic->ic_channels[ic->ic_nchans].ic_ieee = chan;
 -                      ic->ic_channels[ic->ic_nchans].ic_flags = 
IEEE80211_CHAN_A;
 -                      ic->ic_channels[ic->ic_nchans].ic_extieee = 0;
 -                      ic->ic_nchans++;
 -              }
 -      }
 -
        ieee80211_ifattach(ic, sc->sc_bssid);
  
        ic->ic_scan_start = run_scan_start;
 @@ -699,7 +738,7 @@ run_attach(device_t self)
  
        TASK_INIT(&sc->cmdq_task, 0, run_cmdq_cb, sc);
        TASK_INIT(&sc->ratectl_task, 0, run_ratectl_cb, sc);
 -      callout_init((struct callout *)&sc->ratectl_ch, 1);
 +      usb_callout_init_mtx(&sc->ratectl_ch, &sc->sc_mtx, 0);
  
        if (bootverbose)
                ieee80211_announce(ic);
 @@ -803,7 +842,13 @@ run_vap_create(struct ieee80211com *ic, 
        if (rvp == NULL)
                return (NULL);
        vap = &rvp->vap;
 -      ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
 +
 +      if (ieee80211_vap_setup(ic, vap, name, unit,
 +          opmode, flags, bssid, mac) != 0) {
 +              /* out of memory */
 +              free(rvp, M_80211_VAP);
 +              return (NULL);
 +      }
  
        vap->iv_key_update_begin = run_key_update_begin;
        vap->iv_key_update_end = run_key_update_end;
 @@ -1009,13 +1054,12 @@ run_load_microcode(struct run_softc *sc)
        /* cheap sanity check */
        temp = fw->data;
        bytes = *temp;
 -      if (bytes != be64toh(0xffffff0210280210)) {
 +      if (bytes != be64toh(0xffffff0210280210ULL)) {
                device_printf(sc->sc_dev, "firmware checksum failed\n");
                error = EINVAL;
                goto fail;
        }
  
 -      run_read(sc, RT2860_ASIC_VER_ID, &tmp);
        /* write microcode image */
        run_write_region_1(sc, RT2870_FW_BASE, base, 4096);
        run_write(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff);
 @@ -1062,7 +1106,7 @@ fail:
        return (error);
  }
  
 -int
 +static int
  run_reset(struct run_softc *sc)
  {
        usb_device_request_t req;
 @@ -1164,13 +1208,32 @@ run_write_region_1(struct run_softc *sc,
        return (error);
  #else
        usb_device_request_t req;
 +      int error = 0;
  
 -      req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
 -      req.bRequest = RT2870_WRITE_REGION_1;
 -      USETW(req.wValue, 0);
 -      USETW(req.wIndex, reg);
 -      USETW(req.wLength, len);
 -      return (run_do_request(sc, &req, buf));
 +      /*
 +       * NOTE: It appears the WRITE_REGION_1 command cannot be
 +       * passed a huge amount of data, which will crash the
 +       * firmware. Limit amount of data passed to 64-bytes at a
 +       * time.
 +       */
 +      while (len > 0) {
 +              int delta = 64;
 +              if (delta > len)
 +                      delta = len;
 +
 +              req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
 +              req.bRequest = RT2870_WRITE_REGION_1;
 +              USETW(req.wValue, 0);
 +              USETW(req.wIndex, reg);
 +              USETW(req.wLength, delta);
 +              error = run_do_request(sc, &req, __DECONST(uint8_t *, buf));
 +              if (error != 0)
 +                      break;
 +              reg += delta;
 +              buf += delta;
 +              len -= delta;
 +      }
 +      return (error);
  #endif
  }
  
 @@ -1260,7 +1323,7 @@ run_srom_read(struct run_softc *sc, uint
  }
  
  static int
 -run_rt2870_rf_write(struct run_softc *sc, uint8_t reg, uint32_t val)
 +run_rt2870_rf_write(struct run_softc *sc, uint32_t val)
  {
        uint32_t tmp;
        int error, ntries;
 @@ -1274,10 +1337,7 @@ run_rt2870_rf_write(struct run_softc *sc
        if (ntries == 10)
                return (ETIMEDOUT);
  
 -      /* RF registers are 24-bit on the RT2860 */
 -      tmp = RT2860_RF_REG_CTRL | 24 << RT2860_RF_REG_WIDTH_SHIFT |
 -          (val & 0x3fffff) << 2 | (reg & 3);
 -      return (run_write(sc, RT2860_RF_CSR_CFG0, tmp));
 +      return (run_write(sc, RT2860_RF_CSR_CFG0, val));
  }
  
  static int
 @@ -1428,7 +1488,7 @@ b4inc(uint32_t b32, int8_t delta)
  }
  
  static const char *
 -run_get_rf(int rev)
 +run_get_rf(uint16_t rev)
  {
        switch (rev) {
        case RT2860_RF_2820:    return "RT2820";
 @@ -1440,11 +1500,14 @@ run_get_rf(int rev)
        case RT3070_RF_3021:    return "RT3021";
        case RT3070_RF_3022:    return "RT3022";
        case RT3070_RF_3052:    return "RT3052";
 +      case RT5592_RF_5592:    return "RT5592";
 +      case RT5390_RF_5370:    return "RT5370";
 +      case RT5390_RF_5372:    return "RT5372";
        }
        return ("unknown");
  }
  
 -int
 +static int
  run_read_eeprom(struct run_softc *sc)
  {
        int8_t delta_2ghz, delta_5ghz;
 @@ -1476,21 +1539,25 @@ run_read_eeprom(struct run_softc *sc)
        sc->sc_bssid[4] = val & 0xff;
        sc->sc_bssid[5] = val >> 8;
  
 -      /* read vender BBP settings */
 -      for (i = 0; i < 10; i++) {
 -              run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val);
 -              sc->bbp[i].val = val & 0xff;
 -              sc->bbp[i].reg = val >> 8;
 -              DPRINTF("BBP%d=0x%02x\n", sc->bbp[i].reg, sc->bbp[i].val);
 -      }
 -      if (sc->mac_ver >= 0x3071) {
 -              /* read vendor RF settings */
 +      if (sc->mac_ver < 0x5390) {
 +              /* read vender BBP settings */
                for (i = 0; i < 10; i++) {
 -                      run_srom_read(sc, RT3071_EEPROM_RF_BASE + i, &val);
 -                      sc->rf[i].val = val & 0xff;
 -                      sc->rf[i].reg = val >> 8;
 -                      DPRINTF("RF%d=0x%02x\n", sc->rf[i].reg,
 -                          sc->rf[i].val);
 +                      run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val);
 +                      sc->bbp[i].val = val & 0xff;
 +                      sc->bbp[i].reg = val >> 8;
 +                      DPRINTF("BBP%d=0x%02x\n", sc->bbp[i].reg,
 +                          sc->bbp[i].val);
 +              }
 +              if (sc->mac_ver >= 0x3071) {
 +                      /* read vendor RF settings */
 +                      for (i = 0; i < 10; i++) {
 +                              run_srom_read(sc, RT3071_EEPROM_RF_BASE + i,
 +                                 &val);
 +                              sc->rf[i].val = val & 0xff;
 +                              sc->rf[i].reg = val >> 8;
 +                              DPRINTF("RF%d=0x%02x\n", sc->rf[i].reg,
 +                                  sc->rf[i].val);
 +                      }
                }
        }
  
 @@ -1516,7 +1583,11 @@ run_read_eeprom(struct run_softc *sc)
            sc->leds, sc->led[0], sc->led[1], sc->led[2]);
  
        /* read RF information */
 -      run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val);
 +      if (sc->mac_ver == 0x5390 || sc->mac_ver ==0x5392)
 +              run_srom_read(sc, 0x00, &val);
 +      else
 +              run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val);
 +
        if (val == 0xffff) {
                DPRINTF("invalid EEPROM antenna info, using default\n");
                if (sc->mac_ver == 0x3572) {
 @@ -1536,11 +1607,15 @@ run_read_eeprom(struct run_softc *sc)
                        sc->nrxchains = 2;
                }
        } else {
 -              sc->rf_rev = (val >> 8) & 0xf;
 +              if (sc->mac_ver == 0x5390 || sc->mac_ver ==0x5392) {
 +                      sc->rf_rev = val;
 +                      run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val);
 +              } else
 +                      sc->rf_rev = (val >> 8) & 0xf;
                sc->ntxchains = (val >> 4) & 0xf;
                sc->nrxchains = val & 0xf;
        }
 -      DPRINTF("EEPROM RF rev=0x%02x chains=%dT%dR\n",
 +      DPRINTF("EEPROM RF rev=0x%04x chains=%dT%dR\n",
            sc->rf_rev, sc->ntxchains, sc->nrxchains);
  
        /* check if RF supports automatic Tx access gain control */
 @@ -1564,16 +1639,29 @@ run_read_eeprom(struct run_softc *sc)
                sc->txpow1[i + 0] = (int8_t)(val & 0xff);
                sc->txpow1[i + 1] = (int8_t)(val >> 8);
  
 -              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);
 +              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->txpow1[i] < 0 || sc->txpow1[i] > 31)
 -                      sc->txpow1[i] = 5;
 -              if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31)
 -                      sc->txpow2[i] = 5;
 +              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]);
        }
 @@ -1588,11 +1676,13 @@ run_read_eeprom(struct run_softc *sc)
                sc->txpow2[i + 15] = (int8_t)(val >> 8);
        }
        /* fix broken Tx power entries */
 -      for (i = 0; i < 40; i++) {
 -              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;
 +      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]);
 @@ -2236,8 +2326,10 @@ run_ratectl_cb(void *arg, int pending)
                ieee80211_iterate_nodes(&ic->ic_sta, run_iter_func, sc);
        }
  
 +      RUN_LOCK(sc);
        if(sc->ratectl_run != RUN_RATECTL_OFF)
                usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc);
 +      RUN_UNLOCK(sc);
  }
  
  static void
 @@ -2472,12 +2564,15 @@ run_rx_frame(struct run_softc *sc, struc
        struct rt2870_rxd *rxd;
        struct rt2860_rxwi *rxwi;
        uint32_t flags;
 -      uint16_t len, phy;
 +      uint16_t len, rxwisize;
        uint8_t ant, rssi;
        int8_t nf;
  
        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);
        if (__predict_false(len > dmalen)) {
                m_freem(m);
                ifp->if_ierrors++;
 @@ -2495,8 +2590,8 @@ run_rx_frame(struct run_softc *sc, struc
                return;
        }
  
 -      m->m_data += sizeof(struct rt2860_rxwi);
 -      m->m_pkthdr.len = m->m_len -= sizeof(struct rt2860_rxwi);
 +      m->m_data += rxwisize;
 +      m->m_pkthdr.len = m->m_len -= rxwisize;
  
        wh = mtod(m, struct ieee80211_frame *);
  
 @@ -2516,7 +2611,8 @@ run_rx_frame(struct run_softc *sc, struc
        if (__predict_false(flags & RT2860_RX_MICERR)) {
                /* report MIC failures to net80211 for TKIP */
                if (ni != NULL)
 -                      ieee80211_notify_michael_failure(ni->ni_vap, wh, 
rxwi->keyidx);
 +                      ieee80211_notify_michael_failure(ni->ni_vap, wh,
 +                          rxwi->keyidx);
                m_freem(m);
                ifp->if_ierrors++;
                DPRINTF("MIC error. Someone is lying.\n");
 @@ -2539,6 +2635,7 @@ run_rx_frame(struct run_softc *sc, struc
  
        if (__predict_false(ieee80211_radiotap_active(ic))) {
                struct run_rx_radiotap_header *tap = &sc->sc_rxtap;
 +              uint16_t phy;
  
                tap->wr_flags = 0;
                tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
 @@ -2583,8 +2680,13 @@ run_bulk_rx_callback(struct usb_xfer *xf
        struct mbuf *m = NULL;
        struct mbuf *m0;
        uint32_t dmalen;
 +      uint16_t rxwisize;
        int xferlen;
  
 +      rxwisize = (sc->mac_ver == 0x5592) ?
 +          sizeof(struct rt2860_rxwi) + sizeof(uint64_t) :
 +          sizeof(struct rt2860_rxwi);
 +
        usbd_xfer_status(xfer, &xferlen, NULL, NULL, NULL);
  
        switch (USB_GET_STATE(xfer)) {
 @@ -2592,8 +2694,8 @@ run_bulk_rx_callback(struct usb_xfer *xf
  
                DPRINTFN(15, "rx done, actlen=%d\n", xferlen);
  
 -              if (xferlen < (int)(sizeof(uint32_t) +
 -                  sizeof(struct rt2860_rxwi) + sizeof(struct rt2870_rxd))) {
 +              if (xferlen < (int)(sizeof(uint32_t) + rxwisize +
 +                  sizeof(struct rt2870_rxd))) {
                        DPRINTF("xfer too short %d\n", xferlen);
                        goto tr_setup;
                }
 @@ -2675,6 +2777,7 @@ tr_setup:
                        m->m_data += 4;
                        m->m_pkthdr.len = m->m_len -= 4;
                        run_rx_frame(sc, m, dmalen);
 +                      m = NULL;       /* don't free source buffer */
                        break;
                }
  
 @@ -2696,6 +2799,9 @@ tr_setup:
                m->m_pkthdr.len = m->m_len -= dmalen + 8;
        }
  
 +      /* make sure we free the source buffer, if any */
 +      m_freem(m);
 +
        RUN_LOCK(sc);
  }
  
 @@ -2723,7 +2829,7 @@ run_tx_free(struct run_endpoint_queue *p
  }
  
  static void
 -run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, unsigned int 
index)
 +run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
  {
        struct run_softc *sc = usbd_xfer_softc(xfer);
        struct ifnet *ifp = sc->sc_ifp;
 @@ -2763,8 +2869,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;
                if ((m->m_pkthdr.len +
 -                  sizeof(data->desc) + 3 + 8) > RUN_MAX_TXSZ) {
 +                  sizeof(data->desc) + 3 + 8) > size) {
                        DPRINTF("data overflow, %u bytes\n",
                            m->m_pkthdr.len);
  
 @@ -2776,7 +2884,8 @@ tr_setup:
                }
  
                pc = usbd_xfer_get_frame(xfer, 0);
 -              size = sizeof(data->desc);
 +              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;
 @@ -2791,9 +2900,8 @@ tr_setup:
                vap = data->ni->ni_vap;
                if (ieee80211_radiotap_active_vap(vap)) {
                        struct run_tx_radiotap_header *tap = &sc->sc_txtap;
 -                      struct rt2860_txwi *txwi =
 +                      struct rt2860_txwi *txwi = 
                            (struct rt2860_txwi *)(&data->desc + sizeof(struct 
rt2870_txd));
 -
                        tap->wt_flags = 0;
                        tap->wt_rate = rt2860_rates[data->ridx].rate;
                        tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
 @@ -2903,7 +3011,7 @@ run_set_tx_desc(struct run_softc *sc, st
        struct ieee80211_frame *wh;
        struct rt2870_txd *txd;
        struct rt2860_txwi *txwi;
 -      uint16_t xferlen;
 +      uint16_t xferlen, txwisize;
        uint16_t mcs;
        uint8_t ridx = data->ridx;
        uint8_t pad;
 @@ -2911,7 +3019,9 @@ run_set_tx_desc(struct run_softc *sc, st
        /* get MCS code from rate index */
        mcs = rt2860_rates[ridx].mcs;
  
 -      xferlen = sizeof(*txwi) + m->m_pkthdr.len;
 +      txwisize = (sc->mac_ver == 0x5592) ?
 +          sizeof(*txwi) + sizeof(uint32_t) : sizeof(*txwi);
 +      xferlen = txwisize + m->m_pkthdr.len;
  
        /* roundup to 32-bit alignment */
        xferlen = (xferlen + 3) & ~3;
 @@ -3037,7 +3147,7 @@ run_tx(struct run_softc *sc, struct mbuf
                        dur = rt2860_rates[ctl_ridx].sp_ack_dur;
                else
                        dur = rt2860_rates[ctl_ridx].lp_ack_dur;
 -              *(uint16_t *)wh->i_dur = htole16(dur);
 +              USETW(wh->i_dur, dur);
        }
  
        /* reserve slots for mgmt packets, just in case */
 @@ -3054,12 +3164,12 @@ run_tx(struct run_softc *sc, struct mbuf
        txd->flags = qflags;
        txwi = (struct rt2860_txwi *)(txd + 1);
        txwi->xflags = xflags;
 -      if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
 +      if (IEEE80211_IS_MULTICAST(wh->i_addr1))
                txwi->wcid = 0;
 -      } else {
 +      else
                txwi->wcid = (vap->iv_opmode == IEEE80211_M_STA) ?
                    1 : RUN_AID2WCID(ni->ni_associd);
 -      }
 +
        /* clear leftover garbage bits */
        txwi->flags = 0;
        txwi->txop = 0;
 @@ -3117,9 +3227,9 @@ run_tx(struct run_softc *sc, struct mbuf
  
        usbd_transfer_start(sc->sc_xfer[qid]);
  
 -      DPRINTFN(8, "sending data frame len=%d rate=%d qid=%d\n", 
m->m_pkthdr.len +
 -          (int)(sizeof (struct rt2870_txd) + sizeof (struct rt2860_rxwi)),
 -          rt2860_rates[ridx].rate, qid);
 +      DPRINTFN(8, "sending data frame len=%d rate=%d qid=%d\n",
 +          m->m_pkthdr.len + (int)(sizeof(struct rt2870_txd) +
 +          sizeof(struct rt2860_txwi)), rt2860_rates[ridx].rate, qid);
  
        return (0);
  }
 @@ -3156,7 +3266,7 @@ run_tx_mgt(struct run_softc *sc, struct 
  
                dur = ieee80211_ack_duration(ic->ic_rt, 
rt2860_rates[ridx].rate, 
                    ic->ic_flags & IEEE80211_F_SHPREAMBLE);
 -              *(uint16_t *)wh->i_dur = htole16(dur);
 +              USETW(wh->i_dur, dur);
        }
  
        if (sc->sc_epq[0].tx_nfree == 0) {
 @@ -3183,7 +3293,7 @@ run_tx_mgt(struct run_softc *sc, struct 
        run_set_tx_desc(sc, data);
  
        DPRINTFN(10, "sending mgt frame len=%d rate=%d\n", m->m_pkthdr.len +
 -          (int)(sizeof (struct rt2870_txd) + sizeof (struct rt2860_rxwi)),
 +          (int)(sizeof(struct rt2870_txd) + sizeof(struct rt2860_txwi)),
            rt2860_rates[ridx].rate);
  
        STAILQ_INSERT_TAIL(&sc->sc_epq[0].tx_qh, data, next);
 @@ -3513,18 +3623,63 @@ run_select_chan_group(struct run_softc *
        run_bbp_write(sc, 62, 0x37 - sc->lna[group]);
        run_bbp_write(sc, 63, 0x37 - sc->lna[group]);
        run_bbp_write(sc, 64, 0x37 - sc->lna[group]);
 -      run_bbp_write(sc, 86, 0x00);
 +      if (sc->mac_ver < 0x3572)
 +              run_bbp_write(sc, 86, 0x00);
  
        if (group == 0) {
                if (sc->ext_2ghz_lna) {
 -                      run_bbp_write(sc, 82, 0x62);
 -                      run_bbp_write(sc, 75, 0x46);
 +                      if (sc->mac_ver >= 0x5390)
 +                              run_bbp_write(sc, 75, 0x52);
 +                      else {
 +                              run_bbp_write(sc, 82, 0x62);
 +                              run_bbp_write(sc, 75, 0x46);
 +                      }
                } else {
 -                      run_bbp_write(sc, 82, 0x84);
 -                      run_bbp_write(sc, 75, 0x50);
 +                      if (sc->mac_ver == 0x5592) {
 +                              run_bbp_write(sc, 79, 0x1c);
 +                              run_bbp_write(sc, 80, 0x0e);
 +                              run_bbp_write(sc, 81, 0x3a);
 +                              run_bbp_write(sc, 82, 0x62);
 +
 +                              run_bbp_write(sc, 195, 0x80);
 +                              run_bbp_write(sc, 196, 0xe0);
 +                              run_bbp_write(sc, 195, 0x81);
 +                              run_bbp_write(sc, 196, 0x1f);
 +                              run_bbp_write(sc, 195, 0x82);
 +                              run_bbp_write(sc, 196, 0x38);
 +                              run_bbp_write(sc, 195, 0x83);
 +                              run_bbp_write(sc, 196, 0x32);
 +                              run_bbp_write(sc, 195, 0x85);
 +                              run_bbp_write(sc, 196, 0x28);
 +                              run_bbp_write(sc, 195, 0x86);
 +                              run_bbp_write(sc, 196, 0x19);
 +                      } else if (sc->mac_ver >= 0x5390)
 +                              run_bbp_write(sc, 75, 0x50);
 +                      else {
 +                              run_bbp_write(sc, 82, 0x84);
 +                              run_bbp_write(sc, 75, 0x50);
 +                      }
                }
        } else {
 -              if (sc->mac_ver == 0x3572)
 +              if (sc->mac_ver == 0x5592) {
 +                      run_bbp_write(sc, 79, 0x18);
 +                      run_bbp_write(sc, 80, 0x08);
 +                      run_bbp_write(sc, 81, 0x38);
 +                      run_bbp_write(sc, 82, 0x92);
 +
 +                      run_bbp_write(sc, 195, 0x80);
 +                      run_bbp_write(sc, 196, 0xf0);
 +                      run_bbp_write(sc, 195, 0x81);
 +                      run_bbp_write(sc, 196, 0x1e);
 +                      run_bbp_write(sc, 195, 0x82);
 +                      run_bbp_write(sc, 196, 0x28);
 +                      run_bbp_write(sc, 195, 0x83);
 +                      run_bbp_write(sc, 196, 0x20);
 +                      run_bbp_write(sc, 195, 0x85);
 +                      run_bbp_write(sc, 196, 0x7f);
 +                      run_bbp_write(sc, 195, 0x86);
 +                      run_bbp_write(sc, 196, 0x7f);
 +              } else if (sc->mac_ver == 0x3572)
                        run_bbp_write(sc, 82, 0x94);
                else
                        run_bbp_write(sc, 82, 0xf2);
 @@ -3559,6 +3714,11 @@ run_select_chan_group(struct run_softc *
        } else
                run_write(sc, RT2860_TX_PIN_CFG, tmp);
  
 +      if (sc->mac_ver == 0x5592) {
 +              run_bbp_write(sc, 195, 0x8d);
 +              run_bbp_write(sc, 196, 0x1a);
 +      }
 +
        /* set initial AGC value */
        if (group == 0) {       /* 2GHz band */
                if (sc->mac_ver >= 0x3070)
 @@ -3566,7 +3726,9 @@ run_select_chan_group(struct run_softc *
                else
                        agc = 0x2e + sc->lna[0];
        } else {                /* 5GHz band */
 -              if (sc->mac_ver == 0x3572)
 +              if (sc->mac_ver == 0x5592)
 +                      agc = 0x24 + sc->lna[group] * 2;
 +              else if (sc->mac_ver == 0x3572)
                        agc = 0x22 + (sc->lna[group] * 5) / 3;
                else
                        agc = 0x32 + (sc->lna[group] * 5) / 3;
 @@ -3575,7 +3737,7 @@ run_select_chan_group(struct run_softc *
  }
  
  static void
 -run_rt2870_set_chan(struct run_softc *sc, uint32_t chan)
 +run_rt2870_set_chan(struct run_softc *sc, u_int chan)
  {
        const struct rfprog *rfprog = rt2860_rf2850;
        uint32_t r2, r3, r4;
 @@ -3587,58 +3749,71 @@ run_rt2870_set_chan(struct run_softc *sc
  
        r2 = rfprog[i].r2;
        if (sc->ntxchains == 1)
 -              r2 |= 1 << 12;          /* 1T: disable Tx chain 2 */
 +              r2 |= 1 << 14;          /* 1T: disable Tx chain 2 */
        if (sc->nrxchains == 1)
 -              r2 |= 1 << 15 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */
 +              r2 |= 1 << 17 | 1 << 6; /* 1R: disable Rx chains 2 & 3 */
        else if (sc->nrxchains == 2)
 -              r2 |= 1 << 4;           /* 2R: disable Rx chain 3 */
 +              r2 |= 1 << 6;           /* 2R: disable Rx chain 3 */
  
        /* use Tx power values from EEPROM */
        txpow1 = sc->txpow1[i];
        txpow2 = sc->txpow2[i];
 +
 +      /* Initialize RF R3 and R4. */
 +      r3 = rfprog[i].r3 & 0xffffc1ff;
 +      r4 = (rfprog[i].r4 & ~(0x001f87c0)) | (sc->freq << 15);
        if (chan > 14) {
 -              if (txpow1 >= 0)
 -                      txpow1 = txpow1 << 1 | 1;
 -              else
 -                      txpow1 = (7 + txpow1) << 1;
 -              if (txpow2 >= 0)
 -                      txpow2 = txpow2 << 1 | 1;
 -              else
 -                      txpow2 = (7 + txpow2) << 1;
 +              if (txpow1 >= 0) {
 +                      txpow1 = (txpow1 > 0xf) ? (0xf) : (txpow1);
 +                      r3 |= (txpow1 << 10) | (1 << 9);
 +              } else {
 +                      txpow1 += 7;
 +
 +                      /* txpow1 is not possible larger than 15. */
 +                      r3 |= (txpow1 << 10);
 +              }
 +              if (txpow2 >= 0) {
 +                      txpow2 = (txpow2 > 0xf) ? (0xf) : (txpow2);
 +                      r4 |= (txpow2 << 7) | (1 << 6);
 +              } else {
 +                      txpow2 += 7;
 +                      r4 |= (txpow2 << 7);
 +              }
 +      } else {
 +              /* Set Tx0 power. */
 +              r3 |= (txpow1 << 9);
 +
 +              /* Set frequency offset and Tx1 power. */
 +              r4 |= (txpow2 << 6);
 
 *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
 _______________________________________________
 svn-src-...@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"
 
_______________________________________________
freebsd-usb@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-usb
To unsubscribe, send any mail to "freebsd-usb-unsubscr...@freebsd.org"

Reply via email to