mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 09:10:28 +00:00
[otus] implement monitor mode.
* break out the operating mode and rx filter into new functions, rather than them being hard-coded * if we're in sniffer mode or not associated, set the BSS MAC to all zero, rather than relying on a chip reset to do it for us * add comments about .. how interestingly buggy the chip is. Tested: * AR9170 + AR9102, STA+monitor mode Obtained from: linux carl9170 (general chip workings, constant definitions)
This commit is contained in:
parent
afce6f3b0b
commit
b35978d0da
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=298919
|
@ -181,6 +181,8 @@ int otus_set_multi(struct otus_softc *);
|
|||
static int otus_updateedca(struct ieee80211com *);
|
||||
static void otus_updateedca_locked(struct otus_softc *);
|
||||
static void otus_updateslot(struct otus_softc *);
|
||||
static void otus_set_operating_mode(struct otus_softc *sc);
|
||||
static void otus_set_rx_filter(struct otus_softc *sc);
|
||||
int otus_init_mac(struct otus_softc *);
|
||||
uint32_t otus_phy_get_def(struct otus_softc *, uint32_t);
|
||||
int otus_set_board_values(struct otus_softc *,
|
||||
|
@ -964,7 +966,7 @@ otus_alloc_cmd_list(struct otus_softc *sc, struct otus_tx_cmd cmd[],
|
|||
|
||||
for (i = 0; i < ndata; i++) {
|
||||
struct otus_tx_cmd *dp = &cmd[i];
|
||||
dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
|
||||
dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT | M_ZERO);
|
||||
dp->odata = NULL;
|
||||
if (dp->buf == NULL) {
|
||||
device_printf(sc->sc_dev,
|
||||
|
@ -1028,7 +1030,7 @@ otus_alloc_list(struct otus_softc *sc, struct otus_data data[],
|
|||
struct otus_data *dp = &data[i];
|
||||
dp->sc = sc;
|
||||
dp->m = NULL;
|
||||
dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
|
||||
dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT | M_ZERO);
|
||||
if (dp->buf == NULL) {
|
||||
device_printf(sc->sc_dev,
|
||||
"could not allocate buffer\n");
|
||||
|
@ -1142,6 +1144,7 @@ _otus_getbuf(struct otus_softc *sc)
|
|||
STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next);
|
||||
else
|
||||
bf = NULL;
|
||||
/* XXX bzero? */
|
||||
return (bf);
|
||||
}
|
||||
|
||||
|
@ -1224,7 +1227,6 @@ otus_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
|||
struct otus_vap *uvp = OTUS_VAP(vap);
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct otus_softc *sc = ic->ic_softc;
|
||||
struct ieee80211_node *ni;
|
||||
enum ieee80211_state ostate;
|
||||
|
||||
ostate = vap->iv_state;
|
||||
|
@ -1239,18 +1241,20 @@ otus_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
|||
/* XXX TODO: more fleshing out! */
|
||||
|
||||
switch (nstate) {
|
||||
case IEEE80211_S_INIT:
|
||||
otus_set_operating_mode(sc);
|
||||
otus_set_rx_filter(sc);
|
||||
break;
|
||||
case IEEE80211_S_RUN:
|
||||
ni = ieee80211_ref_node(vap->iv_bss);
|
||||
|
||||
if (ic->ic_opmode == IEEE80211_M_STA) {
|
||||
otus_updateslot(sc);
|
||||
otus_set_bssid(sc, ni->ni_bssid);
|
||||
otus_set_operating_mode(sc);
|
||||
otus_set_rx_filter(sc);
|
||||
|
||||
/* Start calibration timer. */
|
||||
taskqueue_enqueue_timeout(taskqueue_thread,
|
||||
&sc->calib_to, hz);
|
||||
}
|
||||
ieee80211_free_node(ni);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -2355,6 +2359,7 @@ otus_set_multi(struct otus_softc *sc)
|
|||
otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_L, lo);
|
||||
otus_write(sc, AR_MAC_REG_GROUP_HASH_TBL_H, hi);
|
||||
r = otus_write_barrier(sc);
|
||||
/* XXX operating mode? filter? */
|
||||
OTUS_UNLOCK(sc);
|
||||
return (r);
|
||||
}
|
||||
|
@ -2453,7 +2458,6 @@ otus_init_mac(struct otus_softc *sc)
|
|||
|
||||
otus_write(sc, AR_MAC_REG_ACK_EXTENSION, 0x40);
|
||||
otus_write(sc, AR_MAC_REG_RETRY_MAX, 0);
|
||||
otus_write(sc, AR_MAC_REG_SNIFFER, 0x2000000);
|
||||
otus_write(sc, AR_MAC_REG_RX_THRESHOLD, 0xc1f80);
|
||||
otus_write(sc, AR_MAC_REG_RX_PE_DELAY, 0x70);
|
||||
otus_write(sc, AR_MAC_REG_EIFS_AND_SIFS, 0xa144000);
|
||||
|
@ -2465,13 +2469,14 @@ otus_init_mac(struct otus_softc *sc)
|
|||
otus_write(sc, AR_MAC_REG_BCN_HT1, 0x8000170);
|
||||
otus_write(sc, AR_MAC_REG_BACKOFF_PROTECT, 0x105);
|
||||
otus_write(sc, AR_MAC_REG_AMPDU_FACTOR, 0x10000a);
|
||||
/* Filter any control frames, BAR is bit 24. */
|
||||
// otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, 0x0500ffff);
|
||||
// otus_write(sc, AR_MAC_REG_RX_CONTROL, 0x1);
|
||||
|
||||
otus_set_rx_filter(sc);
|
||||
|
||||
otus_write(sc, AR_MAC_REG_BASIC_RATE, 0x150f);
|
||||
otus_write(sc, AR_MAC_REG_MANDATORY_RATE, 0x150f);
|
||||
otus_write(sc, AR_MAC_REG_RTS_CTS_RATE, 0x10b01bb);
|
||||
otus_write(sc, AR_MAC_REG_ACK_TPC, 0x4003c1e);
|
||||
|
||||
/* Enable LED0 and LED1. */
|
||||
otus_write(sc, AR_GPIO_REG_PORT_TYPE, 0x3);
|
||||
otus_write(sc, AR_GPIO_REG_PORT_DATA, 0x3);
|
||||
|
@ -3067,55 +3072,88 @@ otus_led_newstate_type3(struct otus_softc *sc)
|
|||
#endif
|
||||
}
|
||||
|
||||
static uint8_t zero_macaddr[IEEE80211_ADDR_LEN] = { 0,0,0,0,0,0 };
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
*
|
||||
* + If in monitor mode, set BSSID to all zeros, else the node BSSID.
|
||||
* + Handle STA + monitor (eg tcpdump/promisc/radiotap) as well as
|
||||
* pure monitor mode.
|
||||
* Set up operating mode, MAC/BSS address and RX filter.
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
otus_set_operating_mode(struct otus_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
uint32_t rx_ctrl;
|
||||
uint32_t frm_filt;
|
||||
uint32_t cam_mode;
|
||||
uint32_t rx_sniffer;
|
||||
struct ieee80211vap *vap;
|
||||
uint32_t cam_mode = AR_MAC_CAM_DEFAULTS;
|
||||
uint32_t rx_ctrl = AR_MAC_RX_CTRL_DEAGG | AR_MAC_RX_CTRL_SHORT_FILTER;
|
||||
uint32_t sniffer = AR_MAC_SNIFFER_DEFAULTS;
|
||||
uint32_t enc_mode = 0x78; /* XXX */
|
||||
const uint8_t *macaddr;
|
||||
uint8_t bssid[IEEE80211_ADDR_LEN];
|
||||
struct ieee80211_node *ni;
|
||||
|
||||
OTUS_LOCK_ASSERT(sc);
|
||||
|
||||
/* XXX TODO: too many magic constants */
|
||||
rx_ctrl = 0x1;
|
||||
/* Filter any control frames, BAR is bit 24. */
|
||||
frm_filt = 0x0500ffff;
|
||||
cam_mode = 0x0f000002; /* XXX STA */
|
||||
rx_sniffer = 0x20000000;
|
||||
/*
|
||||
* If we're in sniffer mode or we don't have a MAC
|
||||
* address assigned, ensure it gets reset to all-zero.
|
||||
*/
|
||||
IEEE80211_ADDR_COPY(bssid, zero_macaddr);
|
||||
vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
macaddr = ic->ic_macaddr;
|
||||
|
||||
switch (ic->ic_opmode) {
|
||||
case IEEE80211_M_STA:
|
||||
cam_mode = 0x0f000002; /* XXX STA */
|
||||
rx_ctrl = 0x1;
|
||||
frm_filt = 0x0500ffff;
|
||||
rx_sniffer = 0x20000000;
|
||||
if (vap) {
|
||||
ni = ieee80211_ref_node(vap->iv_bss);
|
||||
IEEE80211_ADDR_COPY(bssid, ni->ni_bssid);
|
||||
ieee80211_free_node(ni);
|
||||
}
|
||||
cam_mode |= AR_MAC_CAM_STA;
|
||||
rx_ctrl |= AR_MAC_RX_CTRL_PASS_TO_HOST;
|
||||
break;
|
||||
case IEEE80211_M_MONITOR:
|
||||
cam_mode = 0x0f000002; /* XXX STA */
|
||||
rx_ctrl = 0x1;
|
||||
frm_filt = 0xffffffff;
|
||||
rx_sniffer = 0x20000001;
|
||||
break;
|
||||
/*
|
||||
* Note: monitor mode ends up causing the MAC to
|
||||
* generate ACK frames for everything it sees.
|
||||
* So don't do that; instead just put it in STA mode
|
||||
* and disable RX filters.
|
||||
*/
|
||||
default:
|
||||
cam_mode |= AR_MAC_CAM_STA;
|
||||
rx_ctrl |= AR_MAC_RX_CTRL_PASS_TO_HOST;
|
||||
break;
|
||||
}
|
||||
|
||||
otus_write(sc, AR_MAC_REG_SNIFFER, rx_sniffer);
|
||||
/*
|
||||
* TODO: if/when we do hardware encryption, ensure it's
|
||||
* disabled if the NIC is in monitor mode.
|
||||
*/
|
||||
otus_write(sc, AR_MAC_REG_SNIFFER, sniffer);
|
||||
otus_write(sc, AR_MAC_REG_CAM_MODE, cam_mode);
|
||||
otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, frm_filt);
|
||||
otus_write(sc, AR_MAC_REG_RX_CONTROL, cam_mode);
|
||||
otus_write(sc, AR_MAC_REG_ENCRYPTION, enc_mode);
|
||||
otus_write(sc, AR_MAC_REG_RX_CONTROL, rx_ctrl);
|
||||
otus_set_macaddr(sc, macaddr);
|
||||
otus_set_bssid(sc, bssid);
|
||||
/* XXX barrier? */
|
||||
}
|
||||
|
||||
(void) otus_write_barrier(sc);
|
||||
return (0);
|
||||
static void
|
||||
otus_set_rx_filter(struct otus_softc *sc)
|
||||
{
|
||||
// struct ieee80211com *ic = &sc->sc_ic;
|
||||
|
||||
OTUS_LOCK_ASSERT(sc);
|
||||
|
||||
#if 0
|
||||
if (ic->ic_allmulti > 0 || ic->ic_promisc > 0 ||
|
||||
ic->ic_opmode == IEEE80211_M_MONITOR) {
|
||||
otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, 0xff00ffff);
|
||||
} else {
|
||||
#endif
|
||||
/* Filter any control frames, BAR is bit 24. */
|
||||
otus_write(sc, AR_MAC_REG_FRAMETYPE_FILTER, 0x0500ffff);
|
||||
#if 0
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -3139,7 +3177,8 @@ otus_init(struct otus_softc *sc)
|
|||
return error;
|
||||
}
|
||||
|
||||
(void) otus_set_macaddr(sc, ic->ic_macaddr);
|
||||
otus_set_operating_mode(sc);
|
||||
otus_set_rx_filter(sc);
|
||||
(void) otus_set_operating_mode(sc);
|
||||
|
||||
sc->bb_reset = 1; /* Force cold reset. */
|
||||
|
|
Loading…
Reference in a new issue