Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/usb/wlan/if_rum.c
Show First 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | static void rum_setup_tx_desc(struct rum_softc *, | ||||
int); | int); | ||||
static int rum_tx_mgt(struct rum_softc *, struct mbuf *, | static int rum_tx_mgt(struct rum_softc *, struct mbuf *, | ||||
struct ieee80211_node *); | struct ieee80211_node *); | ||||
static int rum_tx_raw(struct rum_softc *, struct mbuf *, | static int rum_tx_raw(struct rum_softc *, struct mbuf *, | ||||
struct ieee80211_node *, | struct ieee80211_node *, | ||||
const struct ieee80211_bpf_params *); | const struct ieee80211_bpf_params *); | ||||
static int rum_tx_data(struct rum_softc *, struct mbuf *, | static int rum_tx_data(struct rum_softc *, struct mbuf *, | ||||
struct ieee80211_node *); | struct ieee80211_node *); | ||||
static void rum_start(struct ifnet *); | static int rum_transmit(struct ieee80211com *, struct mbuf *); | ||||
static int rum_ioctl(struct ifnet *, u_long, caddr_t); | static void rum_start(struct rum_softc *); | ||||
static void rum_parent(struct ieee80211com *); | |||||
static void rum_eeprom_read(struct rum_softc *, uint16_t, void *, | static void rum_eeprom_read(struct rum_softc *, uint16_t, void *, | ||||
int); | int); | ||||
static uint32_t rum_read(struct rum_softc *, uint16_t); | static uint32_t rum_read(struct rum_softc *, uint16_t); | ||||
static void rum_read_multi(struct rum_softc *, uint16_t, void *, | static void rum_read_multi(struct rum_softc *, uint16_t, void *, | ||||
int); | int); | ||||
static usb_error_t rum_write(struct rum_softc *, uint16_t, uint32_t); | static usb_error_t rum_write(struct rum_softc *, uint16_t, uint32_t); | ||||
static usb_error_t rum_write_multi(struct rum_softc *, uint16_t, void *, | static usb_error_t rum_write_multi(struct rum_softc *, uint16_t, void *, | ||||
size_t); | size_t); | ||||
static void rum_bbp_write(struct rum_softc *, uint8_t, uint8_t); | static void rum_bbp_write(struct rum_softc *, uint8_t, uint8_t); | ||||
static uint8_t rum_bbp_read(struct rum_softc *, uint8_t); | static uint8_t rum_bbp_read(struct rum_softc *, uint8_t); | ||||
static void rum_rf_write(struct rum_softc *, uint8_t, uint32_t); | static void rum_rf_write(struct rum_softc *, uint8_t, uint32_t); | ||||
static void rum_select_antenna(struct rum_softc *); | static void rum_select_antenna(struct rum_softc *); | ||||
static void rum_enable_mrr(struct rum_softc *); | static void rum_enable_mrr(struct rum_softc *); | ||||
static void rum_set_txpreamble(struct rum_softc *); | static void rum_set_txpreamble(struct rum_softc *); | ||||
static void rum_set_basicrates(struct rum_softc *); | static void rum_set_basicrates(struct rum_softc *); | ||||
static void rum_select_band(struct rum_softc *, | static void rum_select_band(struct rum_softc *, | ||||
struct ieee80211_channel *); | struct ieee80211_channel *); | ||||
static void rum_set_chan(struct rum_softc *, | static void rum_set_chan(struct rum_softc *, | ||||
struct ieee80211_channel *); | struct ieee80211_channel *); | ||||
static void rum_enable_tsf_sync(struct rum_softc *); | static void rum_enable_tsf_sync(struct rum_softc *); | ||||
static void rum_enable_tsf(struct rum_softc *); | static void rum_enable_tsf(struct rum_softc *); | ||||
static void rum_update_slot(struct ifnet *); | static void rum_update_slot(struct rum_softc *); | ||||
static void rum_set_bssid(struct rum_softc *, const uint8_t *); | static void rum_set_bssid(struct rum_softc *, const uint8_t *); | ||||
static void rum_set_macaddr(struct rum_softc *, const uint8_t *); | static void rum_set_macaddr(struct rum_softc *, const uint8_t *); | ||||
static void rum_update_mcast(struct ieee80211com *); | static void rum_update_mcast(struct ieee80211com *); | ||||
static void rum_update_promisc(struct ieee80211com *); | static void rum_update_promisc(struct ieee80211com *); | ||||
static void rum_setpromisc(struct rum_softc *); | static void rum_setpromisc(struct rum_softc *); | ||||
static const char *rum_get_rf(int); | static const char *rum_get_rf(int); | ||||
static void rum_read_eeprom(struct rum_softc *); | static void rum_read_eeprom(struct rum_softc *); | ||||
static int rum_bbp_init(struct rum_softc *); | static int rum_bbp_init(struct rum_softc *); | ||||
static void rum_init_locked(struct rum_softc *); | static void rum_init(struct rum_softc *); | ||||
static void rum_init(void *); | |||||
static void rum_stop(struct rum_softc *); | static void rum_stop(struct rum_softc *); | ||||
static void rum_load_microcode(struct rum_softc *, const uint8_t *, | static void rum_load_microcode(struct rum_softc *, const uint8_t *, | ||||
size_t); | size_t); | ||||
static void rum_prepare_beacon(struct rum_softc *, | static void rum_prepare_beacon(struct rum_softc *, | ||||
struct ieee80211vap *); | struct ieee80211vap *); | ||||
static int rum_raw_xmit(struct ieee80211_node *, struct mbuf *, | static int rum_raw_xmit(struct ieee80211_node *, struct mbuf *, | ||||
const struct ieee80211_bpf_params *); | const struct ieee80211_bpf_params *); | ||||
static void rum_scan_start(struct ieee80211com *); | static void rum_scan_start(struct ieee80211com *); | ||||
▲ Show 20 Lines • Show All 200 Lines • ▼ Show 20 Lines | rum_match(device_t self) | ||||
return (usbd_lookup_id_by_uaa(rum_devs, sizeof(rum_devs), uaa)); | return (usbd_lookup_id_by_uaa(rum_devs, sizeof(rum_devs), uaa)); | ||||
} | } | ||||
static int | static int | ||||
rum_attach(device_t self) | rum_attach(device_t self) | ||||
{ | { | ||||
struct usb_attach_arg *uaa = device_get_ivars(self); | struct usb_attach_arg *uaa = device_get_ivars(self); | ||||
struct rum_softc *sc = device_get_softc(self); | struct rum_softc *sc = device_get_softc(self); | ||||
struct ieee80211com *ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ifnet *ifp; | |||||
uint8_t iface_index, bands; | uint8_t iface_index, bands; | ||||
uint32_t tmp; | uint32_t tmp; | ||||
int error, ntries; | int error, ntries; | ||||
device_set_usb_desc(self); | device_set_usb_desc(self); | ||||
sc->sc_udev = uaa->device; | sc->sc_udev = uaa->device; | ||||
sc->sc_dev = self; | sc->sc_dev = self; | ||||
mtx_init(&sc->sc_mtx, device_get_nameunit(self), | mtx_init(&sc->sc_mtx, device_get_nameunit(self), | ||||
MTX_NETWORK_LOCK, MTX_DEF); | MTX_NETWORK_LOCK, MTX_DEF); | ||||
mbufq_init(&sc->sc_snd, ifqmaxlen); | |||||
iface_index = RT2573_IFACE_INDEX; | iface_index = RT2573_IFACE_INDEX; | ||||
error = usbd_transfer_setup(uaa->device, &iface_index, | error = usbd_transfer_setup(uaa->device, &iface_index, | ||||
sc->sc_xfer, rum_config, RUM_N_TRANSFER, sc, &sc->sc_mtx); | sc->sc_xfer, rum_config, RUM_N_TRANSFER, sc, &sc->sc_mtx); | ||||
if (error) { | if (error) { | ||||
device_printf(self, "could not allocate USB transfers, " | device_printf(self, "could not allocate USB transfers, " | ||||
"err=%s\n", usbd_errstr(error)); | "err=%s\n", usbd_errstr(error)); | ||||
goto detach; | goto detach; | ||||
Show All 17 Lines | rum_attach(device_t self) | ||||
rum_read_eeprom(sc); | rum_read_eeprom(sc); | ||||
device_printf(sc->sc_dev, "MAC/BBP RT2573 (rev 0x%05x), RF %s\n", | device_printf(sc->sc_dev, "MAC/BBP RT2573 (rev 0x%05x), RF %s\n", | ||||
tmp, rum_get_rf(sc->rf_rev)); | tmp, rum_get_rf(sc->rf_rev)); | ||||
rum_load_microcode(sc, rt2573_ucode, sizeof(rt2573_ucode)); | rum_load_microcode(sc, rt2573_ucode, sizeof(rt2573_ucode)); | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); | |||||
if (ifp == NULL) { | |||||
device_printf(sc->sc_dev, "can not if_alloc()\n"); | |||||
goto detach; | |||||
} | |||||
ic = ifp->if_l2com; | |||||
ifp->if_softc = sc; | |||||
if_initname(ifp, "rum", device_get_unit(sc->sc_dev)); | |||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | |||||
ifp->if_init = rum_init; | |||||
ifp->if_ioctl = rum_ioctl; | |||||
ifp->if_start = rum_start; | |||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); | |||||
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; | |||||
IFQ_SET_READY(&ifp->if_snd); | |||||
ic->ic_ifp = ifp; | |||||
ic->ic_softc = sc; | ic->ic_softc = sc; | ||||
ic->ic_name = device_get_nameunit(self); | ic->ic_name = device_get_nameunit(self); | ||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ | ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ | ||||
/* set device capabilities */ | /* set device capabilities */ | ||||
ic->ic_caps = | ic->ic_caps = | ||||
IEEE80211_C_STA /* station mode supported */ | IEEE80211_C_STA /* station mode supported */ | ||||
| IEEE80211_C_IBSS /* IBSS mode supported */ | | IEEE80211_C_IBSS /* IBSS mode supported */ | ||||
| IEEE80211_C_MONITOR /* monitor mode supported */ | | IEEE80211_C_MONITOR /* monitor mode supported */ | ||||
| IEEE80211_C_HOSTAP /* HostAp mode supported */ | | IEEE80211_C_HOSTAP /* HostAp mode supported */ | ||||
| IEEE80211_C_TXPMGT /* tx power management */ | | IEEE80211_C_TXPMGT /* tx power management */ | ||||
| IEEE80211_C_SHPREAMBLE /* short preamble supported */ | | IEEE80211_C_SHPREAMBLE /* short preamble supported */ | ||||
| IEEE80211_C_SHSLOT /* short slot time supported */ | | IEEE80211_C_SHSLOT /* short slot time supported */ | ||||
| IEEE80211_C_BGSCAN /* bg scanning supported */ | | IEEE80211_C_BGSCAN /* bg scanning supported */ | ||||
| IEEE80211_C_WPA /* 802.11i */ | | IEEE80211_C_WPA /* 802.11i */ | ||||
; | ; | ||||
bands = 0; | bands = 0; | ||||
setbit(&bands, IEEE80211_MODE_11B); | setbit(&bands, IEEE80211_MODE_11B); | ||||
setbit(&bands, IEEE80211_MODE_11G); | setbit(&bands, IEEE80211_MODE_11G); | ||||
if (sc->rf_rev == RT2573_RF_5225 || sc->rf_rev == RT2573_RF_5226) | if (sc->rf_rev == RT2573_RF_5225 || sc->rf_rev == RT2573_RF_5226) | ||||
setbit(&bands, IEEE80211_MODE_11A); | setbit(&bands, IEEE80211_MODE_11A); | ||||
ieee80211_init_channels(ic, NULL, &bands); | ieee80211_init_channels(ic, NULL, &bands); | ||||
ieee80211_ifattach(ic, sc->sc_bssid); | ieee80211_ifattach(ic); | ||||
ic->ic_update_promisc = rum_update_promisc; | ic->ic_update_promisc = rum_update_promisc; | ||||
ic->ic_raw_xmit = rum_raw_xmit; | ic->ic_raw_xmit = rum_raw_xmit; | ||||
ic->ic_scan_start = rum_scan_start; | ic->ic_scan_start = rum_scan_start; | ||||
ic->ic_scan_end = rum_scan_end; | ic->ic_scan_end = rum_scan_end; | ||||
ic->ic_set_channel = rum_set_channel; | ic->ic_set_channel = rum_set_channel; | ||||
ic->ic_transmit = rum_transmit; | |||||
ic->ic_parent = rum_parent; | |||||
ic->ic_vap_create = rum_vap_create; | ic->ic_vap_create = rum_vap_create; | ||||
ic->ic_vap_delete = rum_vap_delete; | ic->ic_vap_delete = rum_vap_delete; | ||||
ic->ic_update_mcast = rum_update_mcast; | ic->ic_update_mcast = rum_update_mcast; | ||||
ieee80211_radiotap_attach(ic, | ieee80211_radiotap_attach(ic, | ||||
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), | &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), | ||||
RT2573_TX_RADIOTAP_PRESENT, | RT2573_TX_RADIOTAP_PRESENT, | ||||
&sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), | &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), | ||||
RT2573_RX_RADIOTAP_PRESENT); | RT2573_RX_RADIOTAP_PRESENT); | ||||
if (bootverbose) | if (bootverbose) | ||||
ieee80211_announce(ic); | ieee80211_announce(ic); | ||||
return (0); | return (0); | ||||
detach: | detach: | ||||
rum_detach(self); | rum_detach(self); | ||||
return (ENXIO); /* failure */ | return (ENXIO); /* failure */ | ||||
} | } | ||||
static int | static int | ||||
rum_detach(device_t self) | rum_detach(device_t self) | ||||
{ | { | ||||
struct rum_softc *sc = device_get_softc(self); | struct rum_softc *sc = device_get_softc(self); | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct ieee80211com *ic; | |||||
/* Prevent further ioctls */ | /* Prevent further ioctls */ | ||||
RUM_LOCK(sc); | RUM_LOCK(sc); | ||||
sc->sc_detached = 1; | sc->sc_detached = 1; | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
/* stop all USB transfers */ | /* stop all USB transfers */ | ||||
usbd_transfer_unsetup(sc->sc_xfer, RUM_N_TRANSFER); | usbd_transfer_unsetup(sc->sc_xfer, RUM_N_TRANSFER); | ||||
/* free TX list, if any */ | /* free TX list, if any */ | ||||
RUM_LOCK(sc); | RUM_LOCK(sc); | ||||
rum_unsetup_tx_list(sc); | rum_unsetup_tx_list(sc); | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
if (ifp) { | if (sc->sc_ic.ic_softc == sc) | ||||
ic = ifp->if_l2com; | ieee80211_ifdetach(&sc->sc_ic); | ||||
ieee80211_ifdetach(ic); | mbufq_drain(&sc->sc_snd); | ||||
if_free(ifp); | |||||
} | |||||
mtx_destroy(&sc->sc_mtx); | mtx_destroy(&sc->sc_mtx); | ||||
return (0); | return (0); | ||||
} | } | ||||
static usb_error_t | static usb_error_t | ||||
rum_do_request(struct rum_softc *sc, | rum_do_request(struct rum_softc *sc, | ||||
struct usb_device_request *req, void *data) | struct usb_device_request *req, void *data) | ||||
{ | { | ||||
Show All 15 Lines | |||||
} | } | ||||
static struct ieee80211vap * | static struct ieee80211vap * | ||||
rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, | rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, | ||||
enum ieee80211_opmode opmode, int flags, | enum ieee80211_opmode opmode, int flags, | ||||
const uint8_t bssid[IEEE80211_ADDR_LEN], | const uint8_t bssid[IEEE80211_ADDR_LEN], | ||||
const uint8_t mac[IEEE80211_ADDR_LEN]) | const uint8_t mac[IEEE80211_ADDR_LEN]) | ||||
{ | { | ||||
struct rum_softc *sc = ic->ic_ifp->if_softc; | struct rum_softc *sc = ic->ic_softc; | ||||
struct rum_vap *rvp; | struct rum_vap *rvp; | ||||
struct ieee80211vap *vap; | struct ieee80211vap *vap; | ||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ | if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ | ||||
return NULL; | return NULL; | ||||
rvp = (struct rum_vap *) malloc(sizeof(struct rum_vap), | rvp = malloc(sizeof(struct rum_vap), M_80211_VAP, M_WAITOK | M_ZERO); | ||||
M_80211_VAP, M_NOWAIT | M_ZERO); | |||||
if (rvp == NULL) | |||||
return NULL; | |||||
vap = &rvp->vap; | vap = &rvp->vap; | ||||
/* enable s/w bmiss handling for sta mode */ | /* enable s/w bmiss handling for sta mode */ | ||||
if (ieee80211_vap_setup(ic, vap, name, unit, opmode, | if (ieee80211_vap_setup(ic, vap, name, unit, opmode, | ||||
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) { | flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) { | ||||
/* out of memory */ | /* out of memory */ | ||||
free(rvp, M_80211_VAP); | free(rvp, M_80211_VAP); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
/* override state transition machine */ | /* override state transition machine */ | ||||
rvp->newstate = vap->iv_newstate; | rvp->newstate = vap->iv_newstate; | ||||
vap->iv_newstate = rum_newstate; | vap->iv_newstate = rum_newstate; | ||||
usb_callout_init_mtx(&rvp->ratectl_ch, &sc->sc_mtx, 0); | usb_callout_init_mtx(&rvp->ratectl_ch, &sc->sc_mtx, 0); | ||||
TASK_INIT(&rvp->ratectl_task, 0, rum_ratectl_task, rvp); | TASK_INIT(&rvp->ratectl_task, 0, rum_ratectl_task, rvp); | ||||
ieee80211_ratectl_init(vap); | ieee80211_ratectl_init(vap); | ||||
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); | ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); | ||||
/* complete setup */ | /* complete setup */ | ||||
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); | ieee80211_vap_attach(vap, ieee80211_media_change, | ||||
ieee80211_media_status, mac); | |||||
ic->ic_opmode = opmode; | ic->ic_opmode = opmode; | ||||
return vap; | return vap; | ||||
} | } | ||||
static void | static void | ||||
rum_vap_delete(struct ieee80211vap *vap) | rum_vap_delete(struct ieee80211vap *vap) | ||||
{ | { | ||||
struct rum_vap *rvp = RUM_VAP(vap); | struct rum_vap *rvp = RUM_VAP(vap); | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
usb_callout_drain(&rvp->ratectl_ch); | usb_callout_drain(&rvp->ratectl_ch); | ||||
ieee80211_draintask(ic, &rvp->ratectl_task); | ieee80211_draintask(ic, &rvp->ratectl_task); | ||||
ieee80211_ratectl_deinit(vap); | ieee80211_ratectl_deinit(vap); | ||||
ieee80211_vap_detach(vap); | ieee80211_vap_detach(vap); | ||||
free(rvp, M_80211_VAP); | free(rvp, M_80211_VAP); | ||||
} | } | ||||
static void | static void | ||||
rum_tx_free(struct rum_tx_data *data, int txerr) | rum_tx_free(struct rum_tx_data *data, int txerr) | ||||
{ | { | ||||
struct rum_softc *sc = data->sc; | struct rum_softc *sc = data->sc; | ||||
if (data->m != NULL) { | if (data->m != NULL) { | ||||
if (data->m->m_flags & M_TXCB) | ieee80211_tx_complete(data->ni, data->m, txerr); | ||||
ieee80211_process_callback(data->ni, data->m, | |||||
txerr ? ETIMEDOUT : 0); | |||||
m_freem(data->m); | |||||
data->m = NULL; | data->m = NULL; | ||||
ieee80211_free_node(data->ni); | |||||
data->ni = NULL; | data->ni = NULL; | ||||
} | } | ||||
STAILQ_INSERT_TAIL(&sc->tx_free, data, next); | STAILQ_INSERT_TAIL(&sc->tx_free, data, next); | ||||
sc->tx_nfree++; | sc->tx_nfree++; | ||||
} | } | ||||
static void | static void | ||||
rum_setup_tx_list(struct rum_softc *sc) | rum_setup_tx_list(struct rum_softc *sc) | ||||
Show All 40 Lines | rum_unsetup_tx_list(struct rum_softc *sc) | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | ||||
{ | { | ||||
struct rum_vap *rvp = RUM_VAP(vap); | struct rum_vap *rvp = RUM_VAP(vap); | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct rum_softc *sc = ic->ic_ifp->if_softc; | struct rum_softc *sc = ic->ic_softc; | ||||
const struct ieee80211_txparam *tp; | const struct ieee80211_txparam *tp; | ||||
enum ieee80211_state ostate; | enum ieee80211_state ostate; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
uint32_t tmp; | uint32_t tmp; | ||||
ostate = vap->iv_state; | ostate = vap->iv_state; | ||||
DPRINTF("%s -> %s\n", | DPRINTF("%s -> %s\n", | ||||
ieee80211_state_name[ostate], | ieee80211_state_name[ostate], | ||||
Show All 17 Lines | case IEEE80211_S_RUN: | ||||
if (vap->iv_opmode != IEEE80211_M_MONITOR) { | if (vap->iv_opmode != IEEE80211_M_MONITOR) { | ||||
if (ic->ic_bsschan == IEEE80211_CHAN_ANYC) { | if (ic->ic_bsschan == IEEE80211_CHAN_ANYC) { | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
IEEE80211_LOCK(ic); | IEEE80211_LOCK(ic); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
rum_update_slot(ic->ic_ifp); | rum_update_slot(sc); | ||||
rum_enable_mrr(sc); | rum_enable_mrr(sc); | ||||
rum_set_txpreamble(sc); | rum_set_txpreamble(sc); | ||||
rum_set_basicrates(sc); | rum_set_basicrates(sc); | ||||
IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); | IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid); | ||||
rum_set_bssid(sc, sc->sc_bssid); | rum_set_bssid(sc, ic->ic_macaddr); | ||||
} | } | ||||
if (vap->iv_opmode == IEEE80211_M_HOSTAP || | if (vap->iv_opmode == IEEE80211_M_HOSTAP || | ||||
vap->iv_opmode == IEEE80211_M_IBSS) | vap->iv_opmode == IEEE80211_M_IBSS) | ||||
rum_prepare_beacon(sc, vap); | rum_prepare_beacon(sc, vap); | ||||
if (vap->iv_opmode != IEEE80211_M_MONITOR) | if (vap->iv_opmode != IEEE80211_M_MONITOR) | ||||
rum_enable_tsf_sync(sc); | rum_enable_tsf_sync(sc); | ||||
Show All 13 Lines | rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | ||||
IEEE80211_LOCK(ic); | IEEE80211_LOCK(ic); | ||||
return (rvp->newstate(vap, nstate, arg)); | return (rvp->newstate(vap, nstate, arg)); | ||||
} | } | ||||
static void | static void | ||||
rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) | rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) | ||||
{ | { | ||||
struct rum_softc *sc = usbd_xfer_softc(xfer); | struct rum_softc *sc = usbd_xfer_softc(xfer); | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct ieee80211vap *vap; | struct ieee80211vap *vap; | ||||
struct rum_tx_data *data; | struct rum_tx_data *data; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
struct usb_page_cache *pc; | struct usb_page_cache *pc; | ||||
unsigned int len; | unsigned int len; | ||||
int actlen, sumlen; | int actlen, sumlen; | ||||
usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); | usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); | ||||
switch (USB_GET_STATE(xfer)) { | switch (USB_GET_STATE(xfer)) { | ||||
case USB_ST_TRANSFERRED: | case USB_ST_TRANSFERRED: | ||||
DPRINTFN(11, "transfer complete, %d bytes\n", actlen); | DPRINTFN(11, "transfer complete, %d bytes\n", actlen); | ||||
/* free resources */ | /* free resources */ | ||||
data = usbd_xfer_get_priv(xfer); | data = usbd_xfer_get_priv(xfer); | ||||
rum_tx_free(data, 0); | rum_tx_free(data, 0); | ||||
usbd_xfer_set_priv(xfer, NULL); | usbd_xfer_set_priv(xfer, NULL); | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | |||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | |||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case USB_ST_SETUP: | case USB_ST_SETUP: | ||||
tr_setup: | tr_setup: | ||||
data = STAILQ_FIRST(&sc->tx_q); | data = STAILQ_FIRST(&sc->tx_q); | ||||
if (data) { | if (data) { | ||||
STAILQ_REMOVE_HEAD(&sc->tx_q, next); | STAILQ_REMOVE_HEAD(&sc->tx_q, next); | ||||
m = data->m; | m = data->m; | ||||
Show All 26 Lines | if (data) { | ||||
DPRINTFN(11, "sending frame len=%u xferlen=%u\n", | DPRINTFN(11, "sending frame len=%u xferlen=%u\n", | ||||
m->m_pkthdr.len, len); | m->m_pkthdr.len, len); | ||||
usbd_xfer_set_frame_len(xfer, 0, len); | usbd_xfer_set_frame_len(xfer, 0, len); | ||||
usbd_xfer_set_priv(xfer, data); | usbd_xfer_set_priv(xfer, data); | ||||
usbd_transfer_submit(xfer); | usbd_transfer_submit(xfer); | ||||
} | } | ||||
RUM_UNLOCK(sc); | rum_start(sc); | ||||
rum_start(ifp); | |||||
RUM_LOCK(sc); | |||||
break; | break; | ||||
default: /* Error */ | default: /* Error */ | ||||
DPRINTFN(11, "transfer error, %s\n", | DPRINTFN(11, "transfer error, %s\n", | ||||
usbd_errstr(error)); | usbd_errstr(error)); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | counter_u64_add(sc->sc_ic.ic_oerrors, 1); | ||||
data = usbd_xfer_get_priv(xfer); | data = usbd_xfer_get_priv(xfer); | ||||
if (data != NULL) { | if (data != NULL) { | ||||
rum_tx_free(data, error); | rum_tx_free(data, error); | ||||
usbd_xfer_set_priv(xfer, NULL); | usbd_xfer_set_priv(xfer, NULL); | ||||
} | } | ||||
if (error != USB_ERR_CANCELLED) { | if (error != USB_ERR_CANCELLED) { | ||||
if (error == USB_ERR_TIMEOUT) | if (error == USB_ERR_TIMEOUT) | ||||
Show All 10 Lines | default: /* Error */ | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) | rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) | ||||
{ | { | ||||
struct rum_softc *sc = usbd_xfer_softc(xfer); | struct rum_softc *sc = usbd_xfer_softc(xfer); | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct mbuf *m = NULL; | struct mbuf *m = NULL; | ||||
struct usb_page_cache *pc; | struct usb_page_cache *pc; | ||||
uint32_t flags; | uint32_t flags; | ||||
uint8_t rssi = 0; | uint8_t rssi = 0; | ||||
int len; | int len; | ||||
usbd_xfer_status(xfer, &len, NULL, NULL, NULL); | usbd_xfer_status(xfer, &len, NULL, NULL, NULL); | ||||
switch (USB_GET_STATE(xfer)) { | switch (USB_GET_STATE(xfer)) { | ||||
case USB_ST_TRANSFERRED: | case USB_ST_TRANSFERRED: | ||||
DPRINTFN(15, "rx done, actlen=%d\n", len); | DPRINTFN(15, "rx done, actlen=%d\n", len); | ||||
if (len < (int)(RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN)) { | if (len < (int)(RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN)) { | ||||
DPRINTF("%s: xfer too short %d\n", | DPRINTF("%s: xfer too short %d\n", | ||||
device_get_nameunit(sc->sc_dev), len); | device_get_nameunit(sc->sc_dev), len); | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
goto tr_setup; | goto tr_setup; | ||||
} | } | ||||
len -= RT2573_RX_DESC_SIZE; | len -= RT2573_RX_DESC_SIZE; | ||||
pc = usbd_xfer_get_frame(xfer, 0); | pc = usbd_xfer_get_frame(xfer, 0); | ||||
usbd_copy_out(pc, 0, &sc->sc_rx_desc, RT2573_RX_DESC_SIZE); | usbd_copy_out(pc, 0, &sc->sc_rx_desc, RT2573_RX_DESC_SIZE); | ||||
rssi = rum_get_rssi(sc, sc->sc_rx_desc.rssi); | rssi = rum_get_rssi(sc, sc->sc_rx_desc.rssi); | ||||
flags = le32toh(sc->sc_rx_desc.flags); | flags = le32toh(sc->sc_rx_desc.flags); | ||||
if (flags & RT2573_RX_CRC_ERROR) { | if (flags & RT2573_RX_CRC_ERROR) { | ||||
/* | /* | ||||
* This should not happen since we did not | * This should not happen since we did not | ||||
* request to receive those frames when we | * request to receive those frames when we | ||||
* filled RUM_TXRX_CSR2: | * filled RUM_TXRX_CSR2: | ||||
*/ | */ | ||||
DPRINTFN(5, "PHY or CRC error\n"); | DPRINTFN(5, "PHY or CRC error\n"); | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
goto tr_setup; | goto tr_setup; | ||||
} | } | ||||
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); | m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); | ||||
if (m == NULL) { | if (m == NULL) { | ||||
DPRINTF("could not allocate mbuf\n"); | DPRINTF("could not allocate mbuf\n"); | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
goto tr_setup; | goto tr_setup; | ||||
} | } | ||||
usbd_copy_out(pc, RT2573_RX_DESC_SIZE, | usbd_copy_out(pc, RT2573_RX_DESC_SIZE, | ||||
mtod(m, uint8_t *), len); | mtod(m, uint8_t *), len); | ||||
/* finalize mbuf */ | /* finalize mbuf */ | ||||
m->m_pkthdr.rcvif = ifp; | |||||
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff; | m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff; | ||||
if (ieee80211_radiotap_active(ic)) { | if (ieee80211_radiotap_active(ic)) { | ||||
struct rum_rx_radiotap_header *tap = &sc->sc_rxtap; | struct rum_rx_radiotap_header *tap = &sc->sc_rxtap; | ||||
/* XXX read tsf */ | /* XXX read tsf */ | ||||
tap->wr_flags = 0; | tap->wr_flags = 0; | ||||
tap->wr_rate = ieee80211_plcp2rate(sc->sc_rx_desc.rate, | tap->wr_rate = ieee80211_plcp2rate(sc->sc_rx_desc.rate, | ||||
Show All 21 Lines | if (m) { | ||||
if (ni != NULL) { | if (ni != NULL) { | ||||
(void) ieee80211_input(ni, m, rssi, | (void) ieee80211_input(ni, m, rssi, | ||||
RT2573_NOISE_FLOOR); | RT2573_NOISE_FLOOR); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
} else | } else | ||||
(void) ieee80211_input_all(ic, m, rssi, | (void) ieee80211_input_all(ic, m, rssi, | ||||
RT2573_NOISE_FLOOR); | RT2573_NOISE_FLOOR); | ||||
} | } | ||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 && | |||||
!IFQ_IS_EMPTY(&ifp->if_snd)) | |||||
rum_start(ifp); | |||||
RUM_LOCK(sc); | RUM_LOCK(sc); | ||||
rum_start(sc); | |||||
return; | return; | ||||
default: /* Error */ | default: /* Error */ | ||||
if (error != USB_ERR_CANCELLED) { | if (error != USB_ERR_CANCELLED) { | ||||
/* try to clear stall first */ | /* try to clear stall first */ | ||||
usbd_xfer_set_stall(xfer); | usbd_xfer_set_stall(xfer); | ||||
goto tr_setup; | goto tr_setup; | ||||
} | } | ||||
Show All 23 Lines | rum_plcp_signal(int rate) | ||||
} | } | ||||
return 0xff; /* XXX unsupported/unknown rate */ | return 0xff; /* XXX unsupported/unknown rate */ | ||||
} | } | ||||
static void | static void | ||||
rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc, | rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc, | ||||
uint32_t flags, uint16_t xflags, int len, int rate) | uint32_t flags, uint16_t xflags, int len, int rate) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint16_t plcp_length; | uint16_t plcp_length; | ||||
int remainder; | int remainder; | ||||
desc->flags = htole32(flags); | desc->flags = htole32(flags); | ||||
desc->flags |= htole32(RT2573_TX_VALID); | desc->flags |= htole32(RT2573_TX_VALID); | ||||
desc->flags |= htole32(len << 16); | desc->flags |= htole32(len << 16); | ||||
desc->xflags = htole16(xflags); | desc->xflags = htole16(xflags); | ||||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | rum_sendprot(struct rum_softc *sc, | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) | rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) | ||||
{ | { | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct rum_tx_data *data; | struct rum_tx_data *data; | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
const struct ieee80211_txparam *tp; | const struct ieee80211_txparam *tp; | ||||
struct ieee80211_key *k; | struct ieee80211_key *k; | ||||
uint32_t flags = 0; | uint32_t flags = 0; | ||||
uint16_t dur; | uint16_t dur; | ||||
RUM_LOCK_ASSERT(sc, MA_OWNED); | RUM_LOCK_ASSERT(sc, MA_OWNED); | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | rum_tx_raw(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) | rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) | ||||
{ | { | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct rum_tx_data *data; | struct rum_tx_data *data; | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
const struct ieee80211_txparam *tp; | const struct ieee80211_txparam *tp; | ||||
struct ieee80211_key *k; | struct ieee80211_key *k; | ||||
uint32_t flags = 0; | uint32_t flags = 0; | ||||
uint16_t dur; | uint16_t dur; | ||||
int error, rate; | int error, rate; | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | DPRINTFN(10, "sending frame len=%d rate=%d\n", | ||||
m0->m_pkthdr.len + (int)RT2573_TX_DESC_SIZE, rate); | m0->m_pkthdr.len + (int)RT2573_TX_DESC_SIZE, rate); | ||||
STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | STAILQ_INSERT_TAIL(&sc->tx_q, data, next); | ||||
usbd_transfer_start(sc->sc_xfer[RUM_BULK_WR]); | usbd_transfer_start(sc->sc_xfer[RUM_BULK_WR]); | ||||
return 0; | return 0; | ||||
} | } | ||||
static void | static int | ||||
rum_start(struct ifnet *ifp) | rum_transmit(struct ieee80211com *ic, struct mbuf *m) | ||||
{ | { | ||||
struct rum_softc *sc = ifp->if_softc; | struct rum_softc *sc = ic->ic_softc; | ||||
struct ieee80211_node *ni; | int error; | ||||
struct mbuf *m; | |||||
RUM_LOCK(sc); | RUM_LOCK(sc); | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { | if (!sc->sc_running) { | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
return; | return (ENXIO); | ||||
} | } | ||||
for (;;) { | error = mbufq_enqueue(&sc->sc_snd, m); | ||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m); | if (error) { | ||||
if (m == NULL) | RUM_UNLOCK(sc); | ||||
break; | return (error); | ||||
if (sc->tx_nfree < RUM_TX_MINFREE) { | |||||
IFQ_DRV_PREPEND(&ifp->if_snd, m); | |||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
break; | |||||
} | } | ||||
rum_start(sc); | |||||
RUM_UNLOCK(sc); | |||||
return (0); | |||||
} | |||||
static void | |||||
rum_start(struct rum_softc *sc) | |||||
{ | |||||
struct ieee80211_node *ni; | |||||
struct mbuf *m; | |||||
RUM_LOCK_ASSERT(sc, MA_OWNED); | |||||
if (!sc->sc_running) | |||||
return; | |||||
while (sc->tx_nfree >= RUM_TX_MINFREE && | |||||
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) { | |||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; | ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; | ||||
if (rum_tx_data(sc, m, ni) != 0) { | if (rum_tx_data(sc, m, ni) != 0) { | ||||
if_inc_counter(ni->ni_vap->iv_ifp, | |||||
IFCOUNTER_OERRORS, 1); | |||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
RUM_UNLOCK(sc); | |||||
} | } | ||||
static int | static void | ||||
rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) | rum_parent(struct ieee80211com *ic) | ||||
{ | { | ||||
struct rum_softc *sc = ifp->if_softc; | struct rum_softc *sc = ic->ic_softc; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ifreq *ifr = (struct ifreq *) data; | |||||
int error; | |||||
int startall = 0; | int startall = 0; | ||||
RUM_LOCK(sc); | RUM_LOCK(sc); | ||||
error = sc->sc_detached ? ENXIO : 0; | if (sc->sc_detached) { | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
if (error) | return; | ||||
return (error); | } | ||||
if (ic->ic_nrunning > 0) { | |||||
switch (cmd) { | if (!sc->sc_running) { | ||||
case SIOCSIFFLAGS: | rum_init(sc); | ||||
RUM_LOCK(sc); | |||||
if (ifp->if_flags & IFF_UP) { | |||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { | |||||
rum_init_locked(sc); | |||||
startall = 1; | startall = 1; | ||||
} else | } else | ||||
rum_setpromisc(sc); | rum_setpromisc(sc); | ||||
} else { | } else if (sc->sc_running) | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | |||||
rum_stop(sc); | rum_stop(sc); | ||||
} | |||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
if (startall) | if (startall) | ||||
ieee80211_start_all(ic); | ieee80211_start_all(ic); | ||||
break; | |||||
case SIOCGIFMEDIA: | |||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); | |||||
break; | |||||
case SIOCGIFADDR: | |||||
error = ether_ioctl(ifp, cmd, data); | |||||
break; | |||||
default: | |||||
error = EINVAL; | |||||
break; | |||||
} | } | ||||
return error; | |||||
} | |||||
static void | static void | ||||
rum_eeprom_read(struct rum_softc *sc, uint16_t addr, void *buf, int len) | rum_eeprom_read(struct rum_softc *sc, uint16_t addr, void *buf, int len) | ||||
{ | { | ||||
struct usb_device_request req; | struct usb_device_request req; | ||||
usb_error_t error; | usb_error_t error; | ||||
req.bmRequestType = UT_READ_VENDOR_DEVICE; | req.bmRequestType = UT_READ_VENDOR_DEVICE; | ||||
▲ Show 20 Lines • Show All 182 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Enable multi-rate retries for frames sent at OFDM rates. | * Enable multi-rate retries for frames sent at OFDM rates. | ||||
* In 802.11b/g mode, allow fallback to CCK rates. | * In 802.11b/g mode, allow fallback to CCK rates. | ||||
*/ | */ | ||||
static void | static void | ||||
rum_enable_mrr(struct rum_softc *sc) | rum_enable_mrr(struct rum_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
tmp = rum_read(sc, RT2573_TXRX_CSR4); | tmp = rum_read(sc, RT2573_TXRX_CSR4); | ||||
tmp &= ~RT2573_MRR_CCK_FALLBACK; | tmp &= ~RT2573_MRR_CCK_FALLBACK; | ||||
if (!IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan)) | if (!IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan)) | ||||
tmp |= RT2573_MRR_CCK_FALLBACK; | tmp |= RT2573_MRR_CCK_FALLBACK; | ||||
tmp |= RT2573_MRR_ENABLED; | tmp |= RT2573_MRR_ENABLED; | ||||
rum_write(sc, RT2573_TXRX_CSR4, tmp); | rum_write(sc, RT2573_TXRX_CSR4, tmp); | ||||
} | } | ||||
static void | static void | ||||
rum_set_txpreamble(struct rum_softc *sc) | rum_set_txpreamble(struct rum_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
tmp = rum_read(sc, RT2573_TXRX_CSR4); | tmp = rum_read(sc, RT2573_TXRX_CSR4); | ||||
tmp &= ~RT2573_SHORT_PREAMBLE; | tmp &= ~RT2573_SHORT_PREAMBLE; | ||||
if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) | if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) | ||||
tmp |= RT2573_SHORT_PREAMBLE; | tmp |= RT2573_SHORT_PREAMBLE; | ||||
rum_write(sc, RT2573_TXRX_CSR4, tmp); | rum_write(sc, RT2573_TXRX_CSR4, tmp); | ||||
} | } | ||||
static void | static void | ||||
rum_set_basicrates(struct rum_softc *sc) | rum_set_basicrates(struct rum_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
/* update basic rate set */ | /* update basic rate set */ | ||||
if (ic->ic_curmode == IEEE80211_MODE_11B) { | if (ic->ic_curmode == IEEE80211_MODE_11B) { | ||||
/* 11b basic rates: 1, 2Mbps */ | /* 11b basic rates: 1, 2Mbps */ | ||||
rum_write(sc, RT2573_TXRX_CSR5, 0x3); | rum_write(sc, RT2573_TXRX_CSR5, 0x3); | ||||
} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan)) { | } else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan)) { | ||||
/* 11a basic rates: 6, 12, 24Mbps */ | /* 11a basic rates: 6, 12, 24Mbps */ | ||||
rum_write(sc, RT2573_TXRX_CSR5, 0x150); | rum_write(sc, RT2573_TXRX_CSR5, 0x150); | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | rum_select_band(struct rum_softc *sc, struct ieee80211_channel *c) | ||||
else | else | ||||
tmp |= RT2573_PA_PE_5GHZ; | tmp |= RT2573_PA_PE_5GHZ; | ||||
rum_write(sc, RT2573_PHY_CSR0, tmp); | rum_write(sc, RT2573_PHY_CSR0, tmp); | ||||
} | } | ||||
static void | static void | ||||
rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c) | rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
const struct rfprog *rfprog; | const struct rfprog *rfprog; | ||||
uint8_t bbp3, bbp94 = RT2573_BBPR94_DEFAULT; | uint8_t bbp3, bbp94 = RT2573_BBPR94_DEFAULT; | ||||
int8_t power; | int8_t power; | ||||
int i, chan; | int i, chan; | ||||
chan = ieee80211_chan2ieee(ic, c); | chan = ieee80211_chan2ieee(ic, c); | ||||
if (chan == 0 || chan == IEEE80211_CHAN_ANY) | if (chan == 0 || chan == IEEE80211_CHAN_ANY) | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Enable TSF synchronization and tell h/w to start sending beacons for IBSS | * Enable TSF synchronization and tell h/w to start sending beacons for IBSS | ||||
* and HostAP operating modes. | * and HostAP operating modes. | ||||
*/ | */ | ||||
static void | static void | ||||
rum_enable_tsf_sync(struct rum_softc *sc) | rum_enable_tsf_sync(struct rum_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
uint32_t tmp; | uint32_t tmp; | ||||
if (vap->iv_opmode != IEEE80211_M_STA) { | if (vap->iv_opmode != IEEE80211_M_STA) { | ||||
/* | /* | ||||
* Change default 16ms TBTT adjustment to 8ms. | * Change default 16ms TBTT adjustment to 8ms. | ||||
* Must be done before enabling beacon generation. | * Must be done before enabling beacon generation. | ||||
*/ | */ | ||||
Show All 18 Lines | |||||
rum_enable_tsf(struct rum_softc *sc) | rum_enable_tsf(struct rum_softc *sc) | ||||
{ | { | ||||
rum_write(sc, RT2573_TXRX_CSR9, | rum_write(sc, RT2573_TXRX_CSR9, | ||||
(rum_read(sc, RT2573_TXRX_CSR9) & 0xff000000) | | (rum_read(sc, RT2573_TXRX_CSR9) & 0xff000000) | | ||||
RT2573_TSF_TICKING | RT2573_TSF_MODE(2)); | RT2573_TSF_TICKING | RT2573_TSF_MODE(2)); | ||||
} | } | ||||
static void | static void | ||||
rum_update_slot(struct ifnet *ifp) | rum_update_slot(struct rum_softc *sc) | ||||
{ | { | ||||
struct rum_softc *sc = ifp->if_softc; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint8_t slottime; | uint8_t slottime; | ||||
uint32_t tmp; | uint32_t tmp; | ||||
slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; | slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; | ||||
tmp = rum_read(sc, RT2573_MAC_CSR9); | tmp = rum_read(sc, RT2573_MAC_CSR9); | ||||
tmp = (tmp & ~0xff) | slottime; | tmp = (tmp & ~0xff) | slottime; | ||||
rum_write(sc, RT2573_MAC_CSR9, tmp); | rum_write(sc, RT2573_MAC_CSR9, tmp); | ||||
Show All 23 Lines | rum_set_macaddr(struct rum_softc *sc, const uint8_t *addr) | ||||
tmp = addr[4] | addr[5] << 8 | 0xff << 16; | tmp = addr[4] | addr[5] << 8 | 0xff << 16; | ||||
rum_write(sc, RT2573_MAC_CSR3, tmp); | rum_write(sc, RT2573_MAC_CSR3, tmp); | ||||
} | } | ||||
static void | static void | ||||
rum_setpromisc(struct rum_softc *sc) | rum_setpromisc(struct rum_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
tmp = rum_read(sc, RT2573_TXRX_CSR0); | tmp = rum_read(sc, RT2573_TXRX_CSR0); | ||||
tmp &= ~RT2573_DROP_NOT_TO_ME; | tmp &= ~RT2573_DROP_NOT_TO_ME; | ||||
if (!(ifp->if_flags & IFF_PROMISC)) | if (sc->sc_ic.ic_promisc == 0) | ||||
tmp |= RT2573_DROP_NOT_TO_ME; | tmp |= RT2573_DROP_NOT_TO_ME; | ||||
rum_write(sc, RT2573_TXRX_CSR0, tmp); | rum_write(sc, RT2573_TXRX_CSR0, tmp); | ||||
DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ? | DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc > 0 ? | ||||
"entering" : "leaving"); | "entering" : "leaving"); | ||||
} | } | ||||
static void | static void | ||||
rum_update_promisc(struct ieee80211com *ic) | rum_update_promisc(struct ieee80211com *ic) | ||||
{ | { | ||||
struct rum_softc *sc = ic->ic_softc; | struct rum_softc *sc = ic->ic_softc; | ||||
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | |||||
return; | |||||
RUM_LOCK(sc); | RUM_LOCK(sc); | ||||
if (!sc->sc_running) { | |||||
RUM_UNLOCK(sc); | |||||
return; | |||||
} | |||||
rum_setpromisc(sc); | rum_setpromisc(sc); | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
} | } | ||||
static void | static void | ||||
rum_update_mcast(struct ieee80211com *ic) | rum_update_mcast(struct ieee80211com *ic) | ||||
{ | { | ||||
static int warning_printed; | static int warning_printed; | ||||
Show All 20 Lines | |||||
rum_read_eeprom(struct rum_softc *sc) | rum_read_eeprom(struct rum_softc *sc) | ||||
{ | { | ||||
uint16_t val; | uint16_t val; | ||||
#ifdef RUM_DEBUG | #ifdef RUM_DEBUG | ||||
int i; | int i; | ||||
#endif | #endif | ||||
/* read MAC address */ | /* read MAC address */ | ||||
rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_bssid, 6); | rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_ic.ic_macaddr, 6); | ||||
rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2); | rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2); | ||||
val = le16toh(val); | val = le16toh(val); | ||||
sc->rf_rev = (val >> 11) & 0x1f; | sc->rf_rev = (val >> 11) & 0x1f; | ||||
sc->hw_radio = (val >> 10) & 0x1; | sc->hw_radio = (val >> 10) & 0x1; | ||||
sc->rx_ant = (val >> 4) & 0x3; | sc->rx_ant = (val >> 4) & 0x3; | ||||
sc->tx_ant = (val >> 2) & 0x3; | sc->tx_ant = (val >> 2) & 0x3; | ||||
sc->nb_ant = val & 0x3; | sc->nb_ant = val & 0x3; | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | if (sc->bbp_prom[i].reg == 0 || sc->bbp_prom[i].reg == 0xff) | ||||
continue; | continue; | ||||
rum_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val); | rum_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val); | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
static void | static void | ||||
rum_init_locked(struct rum_softc *sc) | rum_init(struct rum_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
uint32_t tmp; | uint32_t tmp; | ||||
usb_error_t error; | usb_error_t error; | ||||
int i, ntries; | int i, ntries; | ||||
RUM_LOCK_ASSERT(sc, MA_OWNED); | RUM_LOCK_ASSERT(sc, MA_OWNED); | ||||
rum_stop(sc); | rum_stop(sc); | ||||
Show All 25 Lines | rum_init(struct rum_softc *sc) | ||||
/* select default channel */ | /* select default channel */ | ||||
rum_select_band(sc, ic->ic_curchan); | rum_select_band(sc, ic->ic_curchan); | ||||
rum_select_antenna(sc); | rum_select_antenna(sc); | ||||
rum_set_chan(sc, ic->ic_curchan); | rum_set_chan(sc, ic->ic_curchan); | ||||
/* clear STA registers */ | /* clear STA registers */ | ||||
rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta); | rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta); | ||||
rum_set_macaddr(sc, IF_LLADDR(ifp)); | rum_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); | ||||
/* initialize ASIC */ | /* initialize ASIC */ | ||||
rum_write(sc, RT2573_MAC_CSR1, 4); | rum_write(sc, RT2573_MAC_CSR1, 4); | ||||
/* | /* | ||||
* Allocate Tx and Rx xfer queues. | * Allocate Tx and Rx xfer queues. | ||||
*/ | */ | ||||
rum_setup_tx_list(sc); | rum_setup_tx_list(sc); | ||||
/* update Rx filter */ | /* update Rx filter */ | ||||
tmp = rum_read(sc, RT2573_TXRX_CSR0) & 0xffff; | tmp = rum_read(sc, RT2573_TXRX_CSR0) & 0xffff; | ||||
tmp |= RT2573_DROP_PHY_ERROR | RT2573_DROP_CRC_ERROR; | tmp |= RT2573_DROP_PHY_ERROR | RT2573_DROP_CRC_ERROR; | ||||
if (ic->ic_opmode != IEEE80211_M_MONITOR) { | if (ic->ic_opmode != IEEE80211_M_MONITOR) { | ||||
tmp |= RT2573_DROP_CTL | RT2573_DROP_VER_ERROR | | tmp |= RT2573_DROP_CTL | RT2573_DROP_VER_ERROR | | ||||
RT2573_DROP_ACKCTS; | RT2573_DROP_ACKCTS; | ||||
if (ic->ic_opmode != IEEE80211_M_HOSTAP) | if (ic->ic_opmode != IEEE80211_M_HOSTAP) | ||||
tmp |= RT2573_DROP_TODS; | tmp |= RT2573_DROP_TODS; | ||||
if (!(ifp->if_flags & IFF_PROMISC)) | if (ic->ic_promisc == 0) | ||||
tmp |= RT2573_DROP_NOT_TO_ME; | tmp |= RT2573_DROP_NOT_TO_ME; | ||||
} | } | ||||
rum_write(sc, RT2573_TXRX_CSR0, tmp); | rum_write(sc, RT2573_TXRX_CSR0, tmp); | ||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | sc->sc_running = 1; | ||||
ifp->if_drv_flags |= IFF_DRV_RUNNING; | |||||
usbd_xfer_set_stall(sc->sc_xfer[RUM_BULK_WR]); | usbd_xfer_set_stall(sc->sc_xfer[RUM_BULK_WR]); | ||||
usbd_transfer_start(sc->sc_xfer[RUM_BULK_RD]); | usbd_transfer_start(sc->sc_xfer[RUM_BULK_RD]); | ||||
return; | return; | ||||
fail: rum_stop(sc); | fail: rum_stop(sc); | ||||
#undef N | #undef N | ||||
} | } | ||||
static void | static void | ||||
rum_init(void *priv) | |||||
{ | |||||
struct rum_softc *sc = priv; | |||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
RUM_LOCK(sc); | |||||
rum_init_locked(sc); | |||||
RUM_UNLOCK(sc); | |||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | |||||
ieee80211_start_all(ic); /* start all vap's */ | |||||
} | |||||
static void | |||||
rum_stop(struct rum_softc *sc) | rum_stop(struct rum_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
RUM_LOCK_ASSERT(sc, MA_OWNED); | RUM_LOCK_ASSERT(sc, MA_OWNED); | ||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); | sc->sc_running = 0; | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
/* | /* | ||||
* Drain the USB transfers, if not already drained: | * Drain the USB transfers, if not already drained: | ||||
*/ | */ | ||||
usbd_transfer_drain(sc->sc_xfer[RUM_BULK_WR]); | usbd_transfer_drain(sc->sc_xfer[RUM_BULK_WR]); | ||||
usbd_transfer_drain(sc->sc_xfer[RUM_BULK_RD]); | usbd_transfer_drain(sc->sc_xfer[RUM_BULK_RD]); | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | rum_prepare_beacon(struct rum_softc *sc, struct ieee80211vap *vap) | ||||
m_freem(m0); | m_freem(m0); | ||||
} | } | ||||
static int | static int | ||||
rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, | rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, | ||||
const struct ieee80211_bpf_params *params) | const struct ieee80211_bpf_params *params) | ||||
{ | { | ||||
struct ifnet *ifp = ni->ni_ic->ic_ifp; | struct rum_softc *sc = ni->ni_ic->ic_softc; | ||||
struct rum_softc *sc = ifp->if_softc; | |||||
RUM_LOCK(sc); | RUM_LOCK(sc); | ||||
/* prevent management frames from being sent if we're not ready */ | /* prevent management frames from being sent if we're not ready */ | ||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { | if (!sc->sc_running) { | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
m_freem(m); | m_freem(m); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
return ENETDOWN; | return ENETDOWN; | ||||
} | } | ||||
if (sc->tx_nfree < RUM_TX_MINFREE) { | if (sc->tx_nfree < RUM_TX_MINFREE) { | ||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
m_freem(m); | m_freem(m); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
return EIO; | return EIO; | ||||
} | } | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | |||||
if (params == NULL) { | if (params == NULL) { | ||||
/* | /* | ||||
* Legacy path; interpret frame contents to decide | * Legacy path; interpret frame contents to decide | ||||
* precisely how to send the frame. | * precisely how to send the frame. | ||||
*/ | */ | ||||
if (rum_tx_mgt(sc, m, ni) != 0) | if (rum_tx_mgt(sc, m, ni) != 0) | ||||
goto bad; | goto bad; | ||||
} else { | } else { | ||||
/* | /* | ||||
* Caller supplied explicit parameters to use in | * Caller supplied explicit parameters to use in | ||||
* sending the frame. | * sending the frame. | ||||
*/ | */ | ||||
if (rum_tx_raw(sc, m, ni, params) != 0) | if (rum_tx_raw(sc, m, ni, params) != 0) | ||||
goto bad; | goto bad; | ||||
} | } | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
return 0; | return 0; | ||||
bad: | bad: | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
return EIO; | return EIO; | ||||
} | } | ||||
static void | static void | ||||
rum_ratectl_start(struct rum_softc *sc, struct ieee80211_node *ni) | rum_ratectl_start(struct rum_softc *sc, struct ieee80211_node *ni) | ||||
{ | { | ||||
Show All 17 Lines | |||||
} | } | ||||
static void | static void | ||||
rum_ratectl_task(void *arg, int pending) | rum_ratectl_task(void *arg, int pending) | ||||
{ | { | ||||
struct rum_vap *rvp = arg; | struct rum_vap *rvp = arg; | ||||
struct ieee80211vap *vap = &rvp->vap; | struct ieee80211vap *vap = &rvp->vap; | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct ifnet *ifp = ic->ic_ifp; | struct rum_softc *sc = ic->ic_softc; | ||||
struct rum_softc *sc = ifp->if_softc; | |||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
int ok, fail; | int ok, fail; | ||||
int sum, retrycnt; | int sum, retrycnt; | ||||
RUM_LOCK(sc); | RUM_LOCK(sc); | ||||
/* read and clear statistic registers (STA_CSR0 to STA_CSR10) */ | /* read and clear statistic registers (STA_CSR0 to STA_CSR10) */ | ||||
rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof(sc->sta)); | rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof(sc->sta)); | ||||
ok = (le32toh(sc->sta[4]) >> 16) + /* TX ok w/o retry */ | ok = (le32toh(sc->sta[4]) >> 16) + /* TX ok w/o retry */ | ||||
(le32toh(sc->sta[5]) & 0xffff); /* TX ok w/ retry */ | (le32toh(sc->sta[5]) & 0xffff); /* TX ok w/ retry */ | ||||
fail = (le32toh(sc->sta[5]) >> 16); /* TX retry-fail count */ | fail = (le32toh(sc->sta[5]) >> 16); /* TX retry-fail count */ | ||||
sum = ok+fail; | sum = ok+fail; | ||||
retrycnt = (le32toh(sc->sta[5]) & 0xffff) + fail; | retrycnt = (le32toh(sc->sta[5]) & 0xffff) + fail; | ||||
ni = ieee80211_ref_node(vap->iv_bss); | ni = ieee80211_ref_node(vap->iv_bss); | ||||
ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt); | ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt); | ||||
(void) ieee80211_ratectl_rate(ni, NULL, 0); | (void) ieee80211_ratectl_rate(ni, NULL, 0); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */ | /* count TX retry-fail as Tx errors */ | ||||
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail); | |||||
usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp); | usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp); | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
} | } | ||||
static void | static void | ||||
rum_scan_start(struct ieee80211com *ic) | rum_scan_start(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ifnet *ifp = ic->ic_ifp; | struct rum_softc *sc = ic->ic_softc; | ||||
struct rum_softc *sc = ifp->if_softc; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
RUM_LOCK(sc); | RUM_LOCK(sc); | ||||
/* abort TSF synchronization */ | /* abort TSF synchronization */ | ||||
tmp = rum_read(sc, RT2573_TXRX_CSR9); | tmp = rum_read(sc, RT2573_TXRX_CSR9); | ||||
rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff); | rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff); | ||||
rum_set_bssid(sc, ifp->if_broadcastaddr); | rum_set_bssid(sc, ieee80211broadcastaddr); | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
} | } | ||||
static void | static void | ||||
rum_scan_end(struct ieee80211com *ic) | rum_scan_end(struct ieee80211com *ic) | ||||
{ | { | ||||
struct rum_softc *sc = ic->ic_ifp->if_softc; | struct rum_softc *sc = ic->ic_softc; | ||||
RUM_LOCK(sc); | RUM_LOCK(sc); | ||||
rum_enable_tsf_sync(sc); | rum_enable_tsf_sync(sc); | ||||
rum_set_bssid(sc, sc->sc_bssid); | rum_set_bssid(sc, ic->ic_macaddr); | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
} | } | ||||
static void | static void | ||||
rum_set_channel(struct ieee80211com *ic) | rum_set_channel(struct ieee80211com *ic) | ||||
{ | { | ||||
struct rum_softc *sc = ic->ic_ifp->if_softc; | struct rum_softc *sc = ic->ic_softc; | ||||
RUM_LOCK(sc); | RUM_LOCK(sc); | ||||
rum_set_chan(sc, ic->ic_curchan); | rum_set_chan(sc, ic->ic_curchan); | ||||
RUM_UNLOCK(sc); | RUM_UNLOCK(sc); | ||||
} | } | ||||
static int | static int | ||||
rum_get_rssi(struct rum_softc *sc, uint8_t raw) | rum_get_rssi(struct rum_softc *sc, uint8_t raw) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
int lna, agc, rssi; | int lna, agc, rssi; | ||||
lna = (raw >> 5) & 0x3; | lna = (raw >> 5) & 0x3; | ||||
agc = raw & 0x1f; | agc = raw & 0x1f; | ||||
if (lna == 0) { | if (lna == 0) { | ||||
/* | /* | ||||
* No RSSI mapping | * No RSSI mapping | ||||
▲ Show 20 Lines • Show All 62 Lines • Show Last 20 Lines |