Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/usb/wlan/if_ural.c
Context not available. | |||||
struct ieee80211_node *); | struct ieee80211_node *); | ||||
static int ural_tx_data(struct ural_softc *, struct mbuf *, | static int ural_tx_data(struct ural_softc *, struct mbuf *, | ||||
struct ieee80211_node *); | struct ieee80211_node *); | ||||
static void ural_start(struct ifnet *); | static int ural_transmit(struct ieee80211com *, struct mbuf *); | ||||
static int ural_ioctl(struct ifnet *, u_long, caddr_t); | static void ural_start(struct ural_softc *); | ||||
static void ural_parent(struct ieee80211com *); | |||||
static void ural_set_testmode(struct ural_softc *); | static void ural_set_testmode(struct ural_softc *); | ||||
static void ural_eeprom_read(struct ural_softc *, uint16_t, void *, | static void ural_eeprom_read(struct ural_softc *, uint16_t, void *, | ||||
int); | int); | ||||
Context not available. | |||||
static void ural_disable_rf_tune(struct ural_softc *); | static void ural_disable_rf_tune(struct ural_softc *); | ||||
static void ural_enable_tsf_sync(struct ural_softc *); | static void ural_enable_tsf_sync(struct ural_softc *); | ||||
static void ural_enable_tsf(struct ural_softc *); | static void ural_enable_tsf(struct ural_softc *); | ||||
static void ural_update_slot(struct ifnet *); | static void ural_update_slot(struct ural_softc *); | ||||
static void ural_set_txpreamble(struct ural_softc *); | static void ural_set_txpreamble(struct ural_softc *); | ||||
static void ural_set_basicrates(struct ural_softc *, | static void ural_set_basicrates(struct ural_softc *, | ||||
const struct ieee80211_channel *); | const struct ieee80211_channel *); | ||||
static void ural_set_bssid(struct ural_softc *, const uint8_t *); | static void ural_set_bssid(struct ural_softc *, const uint8_t *); | ||||
static void ural_set_macaddr(struct ural_softc *, uint8_t *); | static void ural_set_macaddr(struct ural_softc *, const uint8_t *); | ||||
static void ural_update_promisc(struct ieee80211com *); | static void ural_update_promisc(struct ieee80211com *); | ||||
static void ural_setpromisc(struct ural_softc *); | static void ural_setpromisc(struct ural_softc *); | ||||
static const char *ural_get_rf(int); | static const char *ural_get_rf(int); | ||||
Context not available. | |||||
static int ural_bbp_init(struct ural_softc *); | static int ural_bbp_init(struct ural_softc *); | ||||
static void ural_set_txantenna(struct ural_softc *, int); | static void ural_set_txantenna(struct ural_softc *, int); | ||||
static void ural_set_rxantenna(struct ural_softc *, int); | static void ural_set_rxantenna(struct ural_softc *, int); | ||||
static void ural_init_locked(struct ural_softc *); | static void ural_init(struct ural_softc *); | ||||
static void ural_init(void *); | |||||
static void ural_stop(struct ural_softc *); | static void ural_stop(struct ural_softc *); | ||||
static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *, | static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *, | ||||
const struct ieee80211_bpf_params *); | const struct ieee80211_bpf_params *); | ||||
Context not available. | |||||
{ | { | ||||
struct usb_attach_arg *uaa = device_get_ivars(self); | struct usb_attach_arg *uaa = device_get_ivars(self); | ||||
struct ural_softc *sc = device_get_softc(self); | struct ural_softc *sc = device_get_softc(self); | ||||
struct ifnet *ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic; | |||||
uint8_t iface_index, bands; | uint8_t iface_index, bands; | ||||
int error; | int error; | ||||
Context not available. | |||||
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 = RAL_IFACE_INDEX; | iface_index = RAL_IFACE_INDEX; | ||||
error = usbd_transfer_setup(uaa->device, | error = usbd_transfer_setup(uaa->device, | ||||
Context not available. | |||||
device_printf(self, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n", | device_printf(self, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n", | ||||
sc->asic_rev, ural_get_rf(sc->rf_rev)); | sc->asic_rev, ural_get_rf(sc->rf_rev)); | ||||
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, "ural", device_get_unit(sc->sc_dev)); | |||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | |||||
ifp->if_init = ural_init; | |||||
ifp->if_ioctl = ural_ioctl; | |||||
ifp->if_start = ural_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 */ | ||||
Context not available. | |||||
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 = ural_update_promisc; | ic->ic_update_promisc = ural_update_promisc; | ||||
ic->ic_raw_xmit = ural_raw_xmit; | ic->ic_raw_xmit = ural_raw_xmit; | ||||
ic->ic_scan_start = ural_scan_start; | ic->ic_scan_start = ural_scan_start; | ||||
ic->ic_scan_end = ural_scan_end; | ic->ic_scan_end = ural_scan_end; | ||||
ic->ic_set_channel = ural_set_channel; | ic->ic_set_channel = ural_set_channel; | ||||
ic->ic_parent = ural_parent; | |||||
ic->ic_transmit = ural_transmit; | |||||
ic->ic_vap_create = ural_vap_create; | ic->ic_vap_create = ural_vap_create; | ||||
ic->ic_vap_delete = ural_vap_delete; | ic->ic_vap_delete = ural_vap_delete; | ||||
Context not available. | |||||
ural_detach(device_t self) | ural_detach(device_t self) | ||||
{ | { | ||||
struct ural_softc *sc = device_get_softc(self); | struct ural_softc *sc = device_get_softc(self); | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic; | |||||
/* prevent further ioctls */ | /* prevent further ioctls */ | ||||
RAL_LOCK(sc); | RAL_LOCK(sc); | ||||
Context not available. | |||||
ural_unsetup_tx_list(sc); | ural_unsetup_tx_list(sc); | ||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
if (ifp) { | if (ic->ic_softc == sc) | ||||
ic = ifp->if_l2com; | |||||
ieee80211_ifdetach(ic); | ieee80211_ifdetach(ic); | ||||
if_free(ifp); | mbufq_drain(&sc->sc_snd); | ||||
} | |||||
mtx_destroy(&sc->sc_mtx); | mtx_destroy(&sc->sc_mtx); | ||||
return (0); | return (0); | ||||
Context not available. | |||||
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 ural_softc *sc = ic->ic_ifp->if_softc; | struct ural_softc *sc = ic->ic_softc; | ||||
struct ural_vap *uvp; | struct ural_vap *uvp; | ||||
struct ieee80211vap *vap; | struct ieee80211vap *vap; | ||||
Context not available. | |||||
/* 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(uvp, M_80211_VAP); | free(uvp, M_80211_VAP); | ||||
return (NULL); | return (NULL); | ||||
Context not available. | |||||
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; | ||||
} | } | ||||
Context not available. | |||||
struct ural_softc *sc = data->sc; | struct ural_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); | ||||
Context not available. | |||||
{ | { | ||||
struct ural_vap *uvp = URAL_VAP(vap); | struct ural_vap *uvp = URAL_VAP(vap); | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct ural_softc *sc = ic->ic_ifp->if_softc; | struct ural_softc *sc = ic->ic_softc; | ||||
const struct ieee80211_txparam *tp; | const struct ieee80211_txparam *tp; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
Context not available. | |||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
ural_update_slot(ic->ic_ifp); | ural_update_slot(sc); | ||||
ural_set_txpreamble(sc); | ural_set_txpreamble(sc); | ||||
ural_set_basicrates(sc, ic->ic_bsschan); | ural_set_basicrates(sc, ic->ic_bsschan); | ||||
IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); | IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid); | ||||
ural_set_bssid(sc, sc->sc_bssid); | ural_set_bssid(sc, ic->ic_macaddr); | ||||
} | } | ||||
if (vap->iv_opmode == IEEE80211_M_HOSTAP || | if (vap->iv_opmode == IEEE80211_M_HOSTAP || | ||||
Context not available. | |||||
ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) | ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) | ||||
{ | { | ||||
struct ural_softc *sc = usbd_xfer_softc(xfer); | struct ural_softc *sc = usbd_xfer_softc(xfer); | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct ieee80211vap *vap; | struct ieee80211vap *vap; | ||||
struct ural_tx_data *data; | struct ural_tx_data *data; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
Context not available. | |||||
ural_tx_free(data, 0); | ural_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: | ||||
Context not available. | |||||
usbd_transfer_submit(xfer); | usbd_transfer_submit(xfer); | ||||
} | } | ||||
RAL_UNLOCK(sc); | ural_start(sc); | ||||
ural_start(ifp); | |||||
RAL_LOCK(sc); | |||||
break; | break; | ||||
default: /* Error */ | default: /* Error */ | ||||
Context not available. | |||||
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); | |||||
data = usbd_xfer_get_priv(xfer); | data = usbd_xfer_get_priv(xfer); | ||||
if (data != NULL) { | if (data != NULL) { | ||||
ural_tx_free(data, error); | ural_tx_free(data, error); | ||||
Context not available. | |||||
ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) | ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) | ||||
{ | { | ||||
struct ural_softc *sc = usbd_xfer_softc(xfer); | struct ural_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; | ||||
Context not available. | |||||
if (len < (int)(RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN)) { | if (len < (int)(RAL_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; | ||||
} | } | ||||
Context not available. | |||||
* filled RAL_TXRX_CSR2: | * filled RAL_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; | ||||
} | } | ||||
Context not available. | |||||
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, 0, mtod(m, uint8_t *), len); | usbd_copy_out(pc, 0, 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)) { | ||||
Context not available. | |||||
} else | } else | ||||
(void) ieee80211_input_all(ic, m, rssi, nf); | (void) ieee80211_input_all(ic, m, rssi, nf); | ||||
} | } | ||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 && | |||||
!IFQ_IS_EMPTY(&ifp->if_snd)) | |||||
ural_start(ifp); | |||||
RAL_LOCK(sc); | RAL_LOCK(sc); | ||||
ural_start(sc); | |||||
return; | return; | ||||
default: /* Error */ | default: /* Error */ | ||||
Context not available. | |||||
ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc, | ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc, | ||||
uint32_t flags, int len, int rate) | uint32_t flags, 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; | ||||
Context not available. | |||||
{ | { | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
const struct ieee80211_txparam *tp; | const struct ieee80211_txparam *tp; | ||||
struct ural_tx_data *data; | struct ural_tx_data *data; | ||||
if (sc->tx_nfree == 0) { | if (sc->tx_nfree == 0) { | ||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
m_freem(m0); | m_freem(m0); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
return (EIO); | return (EIO); | ||||
Context not available. | |||||
return 0; | return 0; | ||||
} | } | ||||
static int | |||||
ural_transmit(struct ieee80211com *ic, struct mbuf *m) | |||||
{ | |||||
struct ural_softc *sc = ic->ic_softc; | |||||
int error; | |||||
RAL_LOCK(sc); | |||||
if (!sc->sc_running) { | |||||
RAL_UNLOCK(sc); | |||||
return (ENXIO); | |||||
} | |||||
error = mbufq_enqueue(&sc->sc_snd, m); | |||||
if (error) { | |||||
RAL_UNLOCK(sc); | |||||
return (error); | |||||
} | |||||
ural_start(sc); | |||||
RAL_UNLOCK(sc); | |||||
return (0); | |||||
} | |||||
static void | static void | ||||
ural_start(struct ifnet *ifp) | ural_start(struct ural_softc *sc) | ||||
{ | { | ||||
struct ural_softc *sc = ifp->if_softc; | |||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
RAL_LOCK(sc); | RAL_LOCK_ASSERT(sc, MA_OWNED); | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { | |||||
RAL_UNLOCK(sc); | if (sc->sc_running == 0) | ||||
return; | return; | ||||
} | |||||
for (;;) { | while (sc->tx_nfree >= RAL_TX_MINFREE && | ||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m); | (m = mbufq_dequeue(&sc->sc_snd)) != NULL) { | ||||
if (m == NULL) | |||||
break; | |||||
if (sc->tx_nfree < RAL_TX_MINFREE) { | |||||
IFQ_DRV_PREPEND(&ifp->if_snd, m); | |||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
break; | |||||
} | |||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; | ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; | ||||
if (ural_tx_data(sc, m, ni) != 0) { | if (ural_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; | ||||
} | } | ||||
} | } | ||||
RAL_UNLOCK(sc); | |||||
} | } | ||||
static int | static void | ||||
ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) | ural_parent(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ural_softc *sc = ifp->if_softc; | struct ural_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; | ||||
RAL_LOCK(sc); | RAL_LOCK(sc); | ||||
error = sc->sc_detached ? ENXIO : 0; | if (sc->sc_detached) { | ||||
RAL_UNLOCK(sc); | |||||
if (error) | |||||
return (error); | |||||
switch (cmd) { | |||||
case SIOCSIFFLAGS: | |||||
RAL_LOCK(sc); | |||||
if (ifp->if_flags & IFF_UP) { | |||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { | |||||
ural_init_locked(sc); | |||||
startall = 1; | |||||
} else | |||||
ural_setpromisc(sc); | |||||
} else { | |||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | |||||
ural_stop(sc); | |||||
} | |||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
if (startall) | return; | ||||
ieee80211_start_all(ic); | |||||
break; | |||||
case SIOCGIFMEDIA: | |||||
case SIOCSIFMEDIA: | |||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); | |||||
break; | |||||
default: | |||||
error = ether_ioctl(ifp, cmd, data); | |||||
break; | |||||
} | } | ||||
return error; | if (ic->ic_nrunning > 0) { | ||||
if (sc->sc_running == 0) { | |||||
ural_init(sc); | |||||
startall = 1; | |||||
} else | |||||
ural_setpromisc(sc); | |||||
} else if (sc->sc_running) | |||||
ural_stop(sc); | |||||
RAL_UNLOCK(sc); | |||||
if (startall) | |||||
ieee80211_start_all(ic); | |||||
} | } | ||||
static void | static void | ||||
Context not available. | |||||
static void | static void | ||||
ural_scan_start(struct ieee80211com *ic) | ural_scan_start(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ifnet *ifp = ic->ic_ifp; | struct ural_softc *sc = ic->ic_softc; | ||||
struct ural_softc *sc = ifp->if_softc; | |||||
RAL_LOCK(sc); | RAL_LOCK(sc); | ||||
ural_write(sc, RAL_TXRX_CSR19, 0); | ural_write(sc, RAL_TXRX_CSR19, 0); | ||||
ural_set_bssid(sc, ifp->if_broadcastaddr); | ural_set_bssid(sc, ieee80211broadcastaddr); | ||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
} | } | ||||
Context not available. | |||||
static void | static void | ||||
ural_scan_end(struct ieee80211com *ic) | ural_scan_end(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ural_softc *sc = ic->ic_ifp->if_softc; | struct ural_softc *sc = ic->ic_softc; | ||||
RAL_LOCK(sc); | RAL_LOCK(sc); | ||||
ural_enable_tsf_sync(sc); | ural_enable_tsf_sync(sc); | ||||
ural_set_bssid(sc, sc->sc_bssid); | ural_set_bssid(sc, ic->ic_macaddr); | ||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
} | } | ||||
Context not available. | |||||
static void | static void | ||||
ural_set_channel(struct ieee80211com *ic) | ural_set_channel(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ural_softc *sc = ic->ic_ifp->if_softc; | struct ural_softc *sc = ic->ic_softc; | ||||
RAL_LOCK(sc); | RAL_LOCK(sc); | ||||
ural_set_chan(sc, ic->ic_curchan); | ural_set_chan(sc, ic->ic_curchan); | ||||
Context not available. | |||||
static void | static void | ||||
ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c) | ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint8_t power, tmp; | uint8_t power, tmp; | ||||
int i, chan; | int i, chan; | ||||
Context not available. | |||||
static void | static void | ||||
ural_enable_tsf_sync(struct ural_softc *sc) | ural_enable_tsf_sync(struct ural_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); | ||||
uint16_t logcwmin, preload, tmp; | uint16_t logcwmin, preload, tmp; | ||||
Context not available. | |||||
#define RAL_RXTX_TURNAROUND 5 /* us */ | #define RAL_RXTX_TURNAROUND 5 /* us */ | ||||
static void | static void | ||||
ural_update_slot(struct ifnet *ifp) | ural_update_slot(struct ural_softc *sc) | ||||
{ | { | ||||
struct ural_softc *sc = ifp->if_softc; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint16_t slottime, sifs, eifs; | uint16_t slottime, sifs, eifs; | ||||
slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; | slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; | ||||
Context not available. | |||||
static void | static void | ||||
ural_set_txpreamble(struct ural_softc *sc) | ural_set_txpreamble(struct ural_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint16_t tmp; | uint16_t tmp; | ||||
tmp = ural_read(sc, RAL_TXRX_CSR10); | tmp = ural_read(sc, RAL_TXRX_CSR10); | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
ural_set_macaddr(struct ural_softc *sc, uint8_t *addr) | ural_set_macaddr(struct ural_softc *sc, const uint8_t *addr) | ||||
{ | { | ||||
uint16_t tmp; | uint16_t tmp; | ||||
Context not available. | |||||
static void | static void | ||||
ural_setpromisc(struct ural_softc *sc) | ural_setpromisc(struct ural_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
tmp = ural_read(sc, RAL_TXRX_CSR2); | tmp = ural_read(sc, RAL_TXRX_CSR2); | ||||
tmp &= ~RAL_DROP_NOT_TO_ME; | tmp &= ~RAL_DROP_NOT_TO_ME; | ||||
if (!(ifp->if_flags & IFF_PROMISC)) | if (sc->sc_ic.ic_promisc == 0) | ||||
tmp |= RAL_DROP_NOT_TO_ME; | tmp |= RAL_DROP_NOT_TO_ME; | ||||
ural_write(sc, RAL_TXRX_CSR2, tmp); | ural_write(sc, RAL_TXRX_CSR2, tmp); | ||||
DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ? | DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc ? | ||||
"entering" : "leaving"); | "entering" : "leaving"); | ||||
} | } | ||||
Context not available. | |||||
{ | { | ||||
struct ural_softc *sc = ic->ic_softc; | struct ural_softc *sc = ic->ic_softc; | ||||
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | |||||
return; | |||||
RAL_LOCK(sc); | RAL_LOCK(sc); | ||||
ural_setpromisc(sc); | if (sc->sc_running) | ||||
ural_setpromisc(sc); | |||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
} | } | ||||
Context not available. | |||||
static void | static void | ||||
ural_read_eeprom(struct ural_softc *sc) | ural_read_eeprom(struct ural_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = &sc->sc_ic; | |||||
uint16_t val; | uint16_t val; | ||||
ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2); | ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2); | ||||
Context not available. | |||||
sc->nb_ant = val & 0x3; | sc->nb_ant = val & 0x3; | ||||
/* read MAC address */ | /* read MAC address */ | ||||
ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, sc->sc_bssid, 6); | ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, ic->ic_macaddr, 6); | ||||
/* read default values for BBP registers */ | /* read default values for BBP registers */ | ||||
ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16); | ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16); | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
ural_init_locked(struct ural_softc *sc) | ural_init(struct ural_softc *sc) | ||||
{ | { | ||||
#define N(a) ((int)(sizeof (a) / sizeof ((a)[0]))) | #define N(a) ((int)(sizeof (a) / sizeof ((a)[0]))) | ||||
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); | ||||
uint16_t tmp; | uint16_t tmp; | ||||
int i, ntries; | int i, ntries; | ||||
Context not available. | |||||
ural_set_txantenna(sc, sc->tx_ant); | ural_set_txantenna(sc, sc->tx_ant); | ||||
ural_set_rxantenna(sc, sc->rx_ant); | ural_set_rxantenna(sc, sc->rx_ant); | ||||
ural_set_macaddr(sc, IF_LLADDR(ifp)); | ural_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); | ||||
/* | /* | ||||
* Allocate Tx and Rx xfer queues. | * Allocate Tx and Rx xfer queues. | ||||
Context not available. | |||||
tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION; | tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION; | ||||
if (ic->ic_opmode != IEEE80211_M_HOSTAP) | if (ic->ic_opmode != IEEE80211_M_HOSTAP) | ||||
tmp |= RAL_DROP_TODS; | tmp |= RAL_DROP_TODS; | ||||
if (!(ifp->if_flags & IFF_PROMISC)) | if (ic->ic_promisc == 0) | ||||
tmp |= RAL_DROP_NOT_TO_ME; | tmp |= RAL_DROP_NOT_TO_ME; | ||||
} | } | ||||
ural_write(sc, RAL_TXRX_CSR2, tmp); | ural_write(sc, RAL_TXRX_CSR2, 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[URAL_BULK_WR]); | usbd_xfer_set_stall(sc->sc_xfer[URAL_BULK_WR]); | ||||
usbd_transfer_start(sc->sc_xfer[URAL_BULK_RD]); | usbd_transfer_start(sc->sc_xfer[URAL_BULK_RD]); | ||||
return; | return; | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
ural_init(void *priv) | |||||
{ | |||||
struct ural_softc *sc = priv; | |||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
RAL_LOCK(sc); | |||||
ural_init_locked(sc); | |||||
RAL_UNLOCK(sc); | |||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | |||||
ieee80211_start_all(ic); /* start all vap's */ | |||||
} | |||||
static void | |||||
ural_stop(struct ural_softc *sc) | ural_stop(struct ural_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
RAL_LOCK_ASSERT(sc, MA_OWNED); | RAL_LOCK_ASSERT(sc, MA_OWNED); | ||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); | sc->sc_running = 0; | ||||
/* | /* | ||||
* Drain all the transfers, if not already drained: | * Drain all the transfers, if not already drained: | ||||
Context not available. | |||||
const struct ieee80211_bpf_params *params) | const struct ieee80211_bpf_params *params) | ||||
{ | { | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
struct ifnet *ifp = ic->ic_ifp; | struct ural_softc *sc = ic->ic_softc; | ||||
struct ural_softc *sc = ifp->if_softc; | |||||
RAL_LOCK(sc); | RAL_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) { | ||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
m_freem(m); | m_freem(m); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
Context not available. | |||||
return ENETDOWN; | return ENETDOWN; | ||||
} | } | ||||
if (sc->tx_nfree < RAL_TX_MINFREE) { | if (sc->tx_nfree < RAL_TX_MINFREE) { | ||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
m_freem(m); | m_freem(m); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
Context not available. | |||||
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 | ||||
Context not available. | |||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
return 0; | return 0; | ||||
bad: | bad: | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
return EIO; /* XXX */ | return EIO; /* XXX */ | ||||
Context not available. | |||||
struct ural_vap *uvp = arg; | struct ural_vap *uvp = arg; | ||||
struct ieee80211vap *vap = &uvp->vap; | struct ieee80211vap *vap = &uvp->vap; | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct ifnet *ifp = ic->ic_ifp; | struct ural_softc *sc = ic->ic_softc; | ||||
struct ural_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; | ||||
Context not available. | |||||
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); | ||||
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(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp); | usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp); | ||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
Context not available. |