Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/usb/wlan/if_urtw.c
Context not available. | |||||
int, const uint8_t [IEEE80211_ADDR_LEN], | int, const uint8_t [IEEE80211_ADDR_LEN], | ||||
const uint8_t [IEEE80211_ADDR_LEN]); | const uint8_t [IEEE80211_ADDR_LEN]); | ||||
static void urtw_vap_delete(struct ieee80211vap *); | static void urtw_vap_delete(struct ieee80211vap *); | ||||
static void urtw_init(void *); | static void urtw_init(struct urtw_softc *); | ||||
static void urtw_stop(struct ifnet *); | static void urtw_stop(struct urtw_softc *); | ||||
static void urtw_stop_locked(struct ifnet *); | static void urtw_parent(struct ieee80211com *); | ||||
static int urtw_ioctl(struct ifnet *, u_long, caddr_t); | static int urtw_transmit(struct ieee80211com *, struct mbuf *); | ||||
static void urtw_start(struct ifnet *); | static void urtw_start(struct urtw_softc *); | ||||
static int urtw_alloc_rx_data_list(struct urtw_softc *); | static int urtw_alloc_rx_data_list(struct urtw_softc *); | ||||
static int urtw_alloc_tx_data_list(struct urtw_softc *); | static int urtw_alloc_tx_data_list(struct urtw_softc *); | ||||
static int urtw_raw_xmit(struct ieee80211_node *, struct mbuf *, | static int urtw_raw_xmit(struct ieee80211_node *, struct mbuf *, | ||||
Context not available. | |||||
int ret = ENXIO; | int ret = ENXIO; | ||||
struct urtw_softc *sc = device_get_softc(dev); | struct urtw_softc *sc = device_get_softc(dev); | ||||
struct usb_attach_arg *uaa = device_get_ivars(dev); | struct usb_attach_arg *uaa = device_get_ivars(dev); | ||||
struct ieee80211com *ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ifnet *ifp; | |||||
uint8_t bands, iface_index = URTW_IFACE_INDEX; /* XXX */ | uint8_t bands, iface_index = URTW_IFACE_INDEX; /* XXX */ | ||||
uint16_t n_setup; | uint16_t n_setup; | ||||
uint32_t data; | uint32_t data; | ||||
Context not available. | |||||
TASK_INIT(&sc->sc_led_task, 0, urtw_ledtask, sc); | TASK_INIT(&sc->sc_led_task, 0, urtw_ledtask, sc); | ||||
TASK_INIT(&sc->sc_updateslot_task, 0, urtw_updateslottask, sc); | TASK_INIT(&sc->sc_updateslot_task, 0, urtw_updateslottask, sc); | ||||
callout_init(&sc->sc_watchdog_ch, 0); | callout_init(&sc->sc_watchdog_ch, 0); | ||||
mbufq_init(&sc->sc_snd, ifqmaxlen); | |||||
if (sc->sc_flags & URTW_RTL8187B) { | if (sc->sc_flags & URTW_RTL8187B) { | ||||
setup_start = urtw_8187b_usbconfig; | setup_start = urtw_8187b_usbconfig; | ||||
Context not available. | |||||
sc->sc_currate = 3; | sc->sc_currate = 3; | ||||
sc->sc_preamble_mode = urtw_preamble_mode; | sc->sc_preamble_mode = urtw_preamble_mode; | ||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); | |||||
if (ifp == NULL) { | |||||
device_printf(sc->sc_dev, "can not allocate ifnet\n"); | |||||
ret = ENOMEM; | |||||
goto fail1; | |||||
} | |||||
ifp->if_softc = sc; | |||||
if_initname(ifp, "urtw", device_get_unit(sc->sc_dev)); | |||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | |||||
ifp->if_init = urtw_init; | |||||
ifp->if_ioctl = urtw_ioctl; | |||||
ifp->if_start = urtw_start; | |||||
/* XXX URTW_TX_DATA_LIST_COUNT */ | |||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); | |||||
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; | |||||
IFQ_SET_READY(&ifp->if_snd); | |||||
ic = ifp->if_l2com; | |||||
ic->ic_ifp = ifp; | |||||
ic->ic_softc = sc; | ic->ic_softc = sc; | ||||
ic->ic_name = device_get_nameunit(dev); | ic->ic_name = device_get_nameunit(dev); | ||||
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_11G); | setbit(&bands, IEEE80211_MODE_11G); | ||||
ieee80211_init_channels(ic, NULL, &bands); | ieee80211_init_channels(ic, NULL, &bands); | ||||
ieee80211_ifattach(ic, sc->sc_bssid); | ieee80211_ifattach(ic); | ||||
ic->ic_raw_xmit = urtw_raw_xmit; | ic->ic_raw_xmit = urtw_raw_xmit; | ||||
ic->ic_scan_start = urtw_scan_start; | ic->ic_scan_start = urtw_scan_start; | ||||
ic->ic_scan_end = urtw_scan_end; | ic->ic_scan_end = urtw_scan_end; | ||||
Context not available. | |||||
ic->ic_vap_create = urtw_vap_create; | ic->ic_vap_create = urtw_vap_create; | ||||
ic->ic_vap_delete = urtw_vap_delete; | ic->ic_vap_delete = urtw_vap_delete; | ||||
ic->ic_update_mcast = urtw_update_mcast; | ic->ic_update_mcast = urtw_update_mcast; | ||||
ic->ic_parent = urtw_parent; | |||||
ic->ic_transmit = urtw_transmit; | |||||
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), | ||||
Context not available. | |||||
ieee80211_announce(ic); | ieee80211_announce(ic); | ||||
return (0); | return (0); | ||||
fail: URTW_UNLOCK(sc); | fail: | ||||
fail1: usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ? | URTW_UNLOCK(sc); | ||||
usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ? | |||||
URTW_8187B_N_XFERS : URTW_8187L_N_XFERS); | URTW_8187B_N_XFERS : URTW_8187L_N_XFERS); | ||||
fail0: | fail0: | ||||
return (ret); | return (ret); | ||||
Context not available. | |||||
urtw_detach(device_t dev) | urtw_detach(device_t dev) | ||||
{ | { | ||||
struct urtw_softc *sc = device_get_softc(dev); | struct urtw_softc *sc = device_get_softc(dev); | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
unsigned int x; | unsigned int x; | ||||
unsigned int n_xfers; | unsigned int n_xfers; | ||||
Context not available. | |||||
/* Prevent further ioctls */ | /* Prevent further ioctls */ | ||||
URTW_LOCK(sc); | URTW_LOCK(sc); | ||||
sc->sc_flags |= URTW_DETACHED; | sc->sc_flags |= URTW_DETACHED; | ||||
urtw_stop(sc); | |||||
URTW_UNLOCK(sc); | URTW_UNLOCK(sc); | ||||
urtw_stop(ifp); | |||||
ieee80211_draintask(ic, &sc->sc_updateslot_task); | ieee80211_draintask(ic, &sc->sc_updateslot_task); | ||||
ieee80211_draintask(ic, &sc->sc_led_task); | ieee80211_draintask(ic, &sc->sc_led_task); | ||||
Context not available. | |||||
usbd_transfer_unsetup(sc->sc_xfer, n_xfers); | usbd_transfer_unsetup(sc->sc_xfer, n_xfers); | ||||
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. | |||||
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); | ||||
uvp = (struct urtw_vap *) malloc(sizeof(struct urtw_vap), | uvp = malloc(sizeof(struct urtw_vap), M_80211_VAP, M_WAITOK | M_ZERO); | ||||
M_80211_VAP, M_NOWAIT | M_ZERO); | |||||
if (uvp == NULL) | |||||
return (NULL); | |||||
vap = &uvp->vap; | vap = &uvp->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(uvp, M_80211_VAP); | free(uvp, M_80211_VAP); | ||||
return (NULL); | return (NULL); | ||||
Context not available. | |||||
/* complete setup */ | /* complete setup */ | ||||
ieee80211_vap_attach(vap, ieee80211_media_change, | ieee80211_vap_attach(vap, ieee80211_media_change, | ||||
ieee80211_media_status); | ieee80211_media_status, mac); | ||||
ic->ic_opmode = opmode; | ic->ic_opmode = opmode; | ||||
return (vap); | return (vap); | ||||
} | } | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
urtw_init_locked(void *arg) | urtw_init(struct urtw_softc *sc) | ||||
{ | { | ||||
usb_error_t error; | |||||
int ret; | int ret; | ||||
struct urtw_softc *sc = arg; | |||||
struct ifnet *ifp = sc->sc_ifp; | |||||
usb_error_t error; | |||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | URTW_ASSERT_LOCKED(sc); | ||||
urtw_stop_locked(ifp); | |||||
if (sc->sc_flags & URTW_RUNNING) | |||||
urtw_stop(sc); | |||||
error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) : | error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) : | ||||
urtw_adapter_start(sc); | urtw_adapter_start(sc); | ||||
if (error != 0) | if (error != 0) | ||||
Context not available. | |||||
if (sc->sc_flags & URTW_RTL8187B) | if (sc->sc_flags & URTW_RTL8187B) | ||||
usbd_transfer_start(sc->sc_xfer[URTW_8187B_BULK_TX_STATUS]); | usbd_transfer_start(sc->sc_xfer[URTW_8187B_BULK_TX_STATUS]); | ||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | sc->sc_flags |= URTW_RUNNING; | ||||
ifp->if_drv_flags |= IFF_DRV_RUNNING; | |||||
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); | callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); | ||||
fail: | fail: | ||||
Context not available. | |||||
return; | return; | ||||
} | } | ||||
static void | |||||
urtw_init(void *arg) | |||||
{ | |||||
struct urtw_softc *sc = arg; | |||||
URTW_LOCK(sc); | |||||
urtw_init_locked(arg); | |||||
URTW_UNLOCK(sc); | |||||
} | |||||
static usb_error_t | static usb_error_t | ||||
urtw_adapter_start_b(struct urtw_softc *sc) | urtw_adapter_start_b(struct urtw_softc *sc) | ||||
{ | { | ||||
Context not available. | |||||
static usb_error_t | static usb_error_t | ||||
urtw_adapter_start(struct urtw_softc *sc) | urtw_adapter_start(struct urtw_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = &sc->sc_ic; | |||||
usb_error_t error; | usb_error_t error; | ||||
error = urtw_reset(sc); | error = urtw_reset(sc); | ||||
Context not available. | |||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
/* applying MAC address again. */ | /* applying MAC address again. */ | ||||
urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]); | urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]); | ||||
urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff); | urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff); | ||||
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); | error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
urtw_stop_locked(struct ifnet *ifp) | urtw_stop(struct urtw_softc *sc) | ||||
{ | { | ||||
struct urtw_softc *sc = ifp->if_softc; | |||||
uint8_t data8; | uint8_t data8; | ||||
usb_error_t error; | usb_error_t error; | ||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); | URTW_ASSERT_LOCKED(sc); | ||||
sc->sc_flags &= ~URTW_RUNNING; | |||||
error = urtw_intr_disable(sc); | error = urtw_intr_disable(sc); | ||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
urtw_stop(struct ifnet *ifp) | |||||
{ | |||||
struct urtw_softc *sc = ifp->if_softc; | |||||
URTW_LOCK(sc); | |||||
urtw_stop_locked(ifp); | |||||
URTW_UNLOCK(sc); | |||||
} | |||||
static void | |||||
urtw_abort_xfers(struct urtw_softc *sc) | urtw_abort_xfers(struct urtw_softc *sc) | ||||
{ | { | ||||
int i, max; | int i, max; | ||||
Context not available. | |||||
usbd_transfer_stop(sc->sc_xfer[i]); | usbd_transfer_stop(sc->sc_xfer[i]); | ||||
} | } | ||||
static int | static void | ||||
urtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) | urtw_parent(struct ieee80211com *ic) | ||||
{ | { | ||||
struct urtw_softc *sc = ifp->if_softc; | struct urtw_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; | ||||
URTW_LOCK(sc); | URTW_LOCK(sc); | ||||
error = (sc->sc_flags & URTW_DETACHED) ? ENXIO : 0; | if (sc->sc_flags & URTW_DETACHED) { | ||||
URTW_UNLOCK(sc); | URTW_UNLOCK(sc); | ||||
if (error) | return; | ||||
return (error); | } | ||||
switch (cmd) { | if (ic->ic_nrunning > 0) { | ||||
case SIOCSIFFLAGS: | if (sc->sc_flags & URTW_RUNNING) { | ||||
if (ifp->if_flags & IFF_UP) { | if (ic->ic_promisc > 0 || ic->ic_allmulti > 0) | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) { | urtw_set_multi(sc); | ||||
if ((ifp->if_flags ^ sc->sc_if_flags) & | |||||
(IFF_ALLMULTI | IFF_PROMISC)) | |||||
urtw_set_multi(sc); | |||||
} else { | |||||
urtw_init(ifp->if_softc); | |||||
startall = 1; | |||||
} | |||||
} else { | } else { | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | urtw_init(sc); | ||||
urtw_stop(ifp); | startall = 1; | ||||
} | } | ||||
sc->sc_if_flags = ifp->if_flags; | } else if (sc->sc_flags & URTW_RUNNING) | ||||
if (startall) | urtw_stop(sc); | ||||
ieee80211_start_all(ic); | URTW_UNLOCK(sc); | ||||
break; | if (startall) | ||||
case SIOCGIFMEDIA: | ieee80211_start_all(ic); | ||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); | } | ||||
break; | |||||
case SIOCGIFADDR: | static int | ||||
error = ether_ioctl(ifp, cmd, data); | urtw_transmit(struct ieee80211com *ic, struct mbuf *m) | ||||
break; | { | ||||
default: | struct urtw_softc *sc = ic->ic_softc; | ||||
error = EINVAL; | int error; | ||||
break; | |||||
URTW_LOCK(sc); | |||||
if ((sc->sc_flags & URTW_RUNNING) == 0) { | |||||
URTW_UNLOCK(sc); | |||||
return (ENXIO); | |||||
} | } | ||||
return (error); | error = mbufq_enqueue(&sc->sc_snd, m); | ||||
if (error) { | |||||
URTW_UNLOCK(sc); | |||||
return (error); | |||||
} | |||||
urtw_start(sc); | |||||
URTW_UNLOCK(sc); | |||||
return (0); | |||||
} | } | ||||
static void | static void | ||||
urtw_start(struct ifnet *ifp) | urtw_start(struct urtw_softc *sc) | ||||
{ | { | ||||
struct urtw_data *bf; | struct urtw_data *bf; | ||||
struct urtw_softc *sc = ifp->if_softc; | |||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | URTW_ASSERT_LOCKED(sc); | ||||
if ((sc->sc_flags & URTW_RUNNING) == 0) | |||||
return; | return; | ||||
URTW_LOCK(sc); | while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { | ||||
for (;;) { | |||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m); | |||||
if (m == NULL) | |||||
break; | |||||
bf = urtw_getbuf(sc); | bf = urtw_getbuf(sc); | ||||
if (bf == NULL) { | if (bf == NULL) { | ||||
IFQ_DRV_PREPEND(&ifp->if_snd, m); | mbufq_prepend(&sc->sc_snd, m); | ||||
break; | break; | ||||
} | } | ||||
Context not available. | |||||
m->m_pkthdr.rcvif = NULL; | m->m_pkthdr.rcvif = NULL; | ||||
if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_NORMAL) != 0) { | if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_NORMAL) != 0) { | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | if_inc_counter(ni->ni_vap->iv_ifp, | ||||
IFCOUNTER_OERRORS, 1); | |||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); | STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
break; | break; | ||||
Context not available. | |||||
sc->sc_txtimer = 5; | sc->sc_txtimer = 5; | ||||
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); | callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); | ||||
} | } | ||||
URTW_UNLOCK(sc); | |||||
} | } | ||||
static int | static int | ||||
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 urtw_softc *sc = ic->ic_softc; | ||||
struct urtw_data *bf; | struct urtw_data *bf; | ||||
struct urtw_softc *sc = ifp->if_softc; | |||||
/* 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_flags & URTW_RUNNING)) { | ||||
m_freem(m); | m_freem(m); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
return ENETDOWN; | return ENETDOWN; | ||||
Context not available. | |||||
return (ENOBUFS); /* XXX */ | return (ENOBUFS); /* XXX */ | ||||
} | } | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | |||||
if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_LOW) != 0) { | if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_LOW) != 0) { | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); | STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); | ||||
URTW_UNLOCK(sc); | URTW_UNLOCK(sc); | ||||
return (EIO); | return (EIO); | ||||
Context not available. | |||||
static void | static void | ||||
urtw_set_channel(struct ieee80211com *ic) | urtw_set_channel(struct ieee80211com *ic) | ||||
{ | { | ||||
struct urtw_softc *sc = ic->ic_ifp->if_softc; | struct urtw_softc *sc = ic->ic_softc; | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
uint32_t data, orig; | uint32_t data, orig; | ||||
usb_error_t error; | usb_error_t error; | ||||
Context not available. | |||||
* initialization would be failed if setting a channel is called before | * initialization would be failed if setting a channel is called before | ||||
* the init have done. | * the init have done. | ||||
*/ | */ | ||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) | if (!(sc->sc_flags & URTW_RUNNING)) | ||||
return; | return; | ||||
if (sc->sc_curchan != NULL && sc->sc_curchan == ic->ic_curchan) | if (sc->sc_curchan != NULL && sc->sc_curchan == ic->ic_curchan) | ||||
Context not available. | |||||
urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, | urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, | ||||
struct urtw_data *data, int prior) | struct urtw_data *data, int prior) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct ieee80211_frame *wh = mtod(m0, struct ieee80211_frame *); | struct ieee80211_frame *wh = mtod(m0, struct ieee80211_frame *); | ||||
struct ieee80211_key *k; | struct ieee80211_key *k; | ||||
const struct ieee80211_txparam *tp; | const struct ieee80211_txparam *tp; | ||||
struct ieee80211com *ic = ifp->if_l2com; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct usb_xfer *rtl8187b_pipes[URTW_8187B_TXPIPE_MAX] = { | struct usb_xfer *rtl8187b_pipes[URTW_8187B_TXPIPE_MAX] = { | ||||
sc->sc_xfer[URTW_8187B_BULK_TX_BE], | sc->sc_xfer[URTW_8187B_BULK_TX_BE], | ||||
Context not available. | |||||
urtw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | urtw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | ||||
{ | { | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct urtw_softc *sc = ic->ic_ifp->if_softc; | struct urtw_softc *sc = ic->ic_softc; | ||||
struct urtw_vap *uvp = URTW_VAP(vap); | struct urtw_vap *uvp = URTW_VAP(vap); | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
usb_error_t error = 0; | usb_error_t error = 0; | ||||
Context not available. | |||||
urtw_watchdog(void *arg) | urtw_watchdog(void *arg) | ||||
{ | { | ||||
struct urtw_softc *sc = arg; | struct urtw_softc *sc = arg; | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
if (sc->sc_txtimer > 0) { | if (sc->sc_txtimer > 0) { | ||||
if (--sc->sc_txtimer == 0) { | if (--sc->sc_txtimer == 0) { | ||||
device_printf(sc->sc_dev, "device timeout\n"); | device_printf(sc->sc_dev, "device timeout\n"); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | counter_u64_add(sc->sc_ic.ic_oerrors, 1); | ||||
return; | return; | ||||
} | } | ||||
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); | callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); | ||||
Context not available. | |||||
static void | static void | ||||
urtw_set_multi(void *arg) | urtw_set_multi(void *arg) | ||||
{ | { | ||||
struct urtw_softc *sc = arg; | /* XXX don't know how to set a device. Lack of docs. */ | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
if (!(ifp->if_flags & IFF_UP)) | |||||
return; | |||||
/* | |||||
* XXX don't know how to set a device. Lack of docs. Just try to set | |||||
* IFF_ALLMULTI flag here. | |||||
*/ | |||||
ifp->if_flags |= IFF_ALLMULTI; | |||||
} | } | ||||
static usb_error_t | static usb_error_t | ||||
Context not available. | |||||
static usb_error_t | static usb_error_t | ||||
urtw_update_msr(struct urtw_softc *sc) | urtw_update_msr(struct urtw_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint8_t data; | uint8_t data; | ||||
usb_error_t error; | usb_error_t error; | ||||
Context not available. | |||||
static usb_error_t | static usb_error_t | ||||
urtw_get_macaddr(struct urtw_softc *sc) | urtw_get_macaddr(struct urtw_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = &sc->sc_ic; | |||||
uint32_t data; | uint32_t data; | ||||
usb_error_t error; | usb_error_t error; | ||||
Context not available. | |||||
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR, &data); | error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR, &data); | ||||
if (error != 0) | if (error != 0) | ||||
goto fail; | goto fail; | ||||
sc->sc_bssid[0] = data & 0xff; | ic->ic_macaddr[0] = data & 0xff; | ||||
sc->sc_bssid[1] = (data & 0xff00) >> 8; | ic->ic_macaddr[1] = (data & 0xff00) >> 8; | ||||
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data); | error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data); | ||||
if (error != 0) | if (error != 0) | ||||
goto fail; | goto fail; | ||||
sc->sc_bssid[2] = data & 0xff; | ic->ic_macaddr[2] = data & 0xff; | ||||
sc->sc_bssid[3] = (data & 0xff00) >> 8; | ic->ic_macaddr[3] = (data & 0xff00) >> 8; | ||||
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data); | error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data); | ||||
if (error != 0) | if (error != 0) | ||||
goto fail; | goto fail; | ||||
sc->sc_bssid[4] = data & 0xff; | ic->ic_macaddr[4] = data & 0xff; | ||||
sc->sc_bssid[5] = (data & 0xff00) >> 8; | ic->ic_macaddr[5] = (data & 0xff00) >> 8; | ||||
fail: | fail: | ||||
return (error); | return (error); | ||||
} | } | ||||
Context not available. | |||||
static usb_error_t | static usb_error_t | ||||
urtw_8225v2b_rf_init(struct urtw_softc *sc) | urtw_8225v2b_rf_init(struct urtw_softc *sc) | ||||
{ | { | ||||
#define N(a) ((int)(sizeof(a) / sizeof((a)[0]))) | struct ieee80211com *ic = &sc->sc_ic; | ||||
int i; | int i; | ||||
uint8_t data8; | uint8_t data8; | ||||
usb_error_t error; | usb_error_t error; | ||||
Context not available. | |||||
urtw_write8_m(sc, URTW_CONFIG1, data8); | urtw_write8_m(sc, URTW_CONFIG1, data8); | ||||
/* applying MAC address again. */ | /* applying MAC address again. */ | ||||
urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]); | urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]); | ||||
urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff); | urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff); | ||||
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); | error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); | ||||
if (error) | if (error) | ||||
Context not available. | |||||
/* | /* | ||||
* MAC configuration | * MAC configuration | ||||
*/ | */ | ||||
for (i = 0; i < N(urtw_8225v2b_rf_part1); i++) | for (i = 0; i < nitems(urtw_8225v2b_rf_part1); i++) | ||||
urtw_write8_m(sc, urtw_8225v2b_rf_part1[i].reg, | urtw_write8_m(sc, urtw_8225v2b_rf_part1[i].reg, | ||||
urtw_8225v2b_rf_part1[i].val); | urtw_8225v2b_rf_part1[i].val); | ||||
urtw_write16_m(sc, URTW_TID_AC_MAP, 0xfa50); | urtw_write16_m(sc, URTW_TID_AC_MAP, 0xfa50); | ||||
Context not available. | |||||
urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1fff); | urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1fff); | ||||
usb_pause_mtx(&sc->sc_mtx, 1100); | usb_pause_mtx(&sc->sc_mtx, 1100); | ||||
for (i = 0; i < N(urtw_8225v2b_rf_part0); i++) { | for (i = 0; i < nitems(urtw_8225v2b_rf_part0); i++) { | ||||
urtw_8225_write(sc, urtw_8225v2b_rf_part0[i].reg, | urtw_8225_write(sc, urtw_8225v2b_rf_part0[i].reg, | ||||
urtw_8225v2b_rf_part0[i].val); | urtw_8225v2b_rf_part0[i].val); | ||||
usb_pause_mtx(&sc->sc_mtx, 1); | usb_pause_mtx(&sc->sc_mtx, 1); | ||||
Context not available. | |||||
} | } | ||||
urtw_8187_write_phy_ofdm(sc, 0x80, 0x10); | urtw_8187_write_phy_ofdm(sc, 0x80, 0x10); | ||||
for (i = 0; i < N(urtw_8225v2b_rf_part2); i++) | for (i = 0; i < nitems(urtw_8225v2b_rf_part2); i++) | ||||
urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2b_rf_part2[i].val); | urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2b_rf_part2[i].val); | ||||
urtw_write32_m(sc, URTW_8187B_AC_VO, (7 << 12) | (3 << 8) | 0x1c); | urtw_write32_m(sc, URTW_8187B_AC_VO, (7 << 12) | (3 << 8) | 0x1c); | ||||
Context not available. | |||||
urtw_led_ch(void *arg) | urtw_led_ch(void *arg) | ||||
{ | { | ||||
struct urtw_softc *sc = arg; | struct urtw_softc *sc = arg; | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
ieee80211_runtask(ic, &sc->sc_led_task); | ieee80211_runtask(ic, &sc->sc_led_task); | ||||
} | } | ||||
Context not available. | |||||
static usb_error_t | static usb_error_t | ||||
urtw_rx_setconf(struct urtw_softc *sc) | urtw_rx_setconf(struct urtw_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint32_t data; | uint32_t data; | ||||
usb_error_t error; | usb_error_t error; | ||||
Context not available. | |||||
data = data | URTW_RX_FILTER_CRCERR; | data = data | URTW_RX_FILTER_CRCERR; | ||||
if (ic->ic_opmode == IEEE80211_M_MONITOR || | if (ic->ic_opmode == IEEE80211_M_MONITOR || | ||||
(ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) { | ic->ic_promisc > 0 || ic->ic_allmulti > 0) { | ||||
data = data | URTW_RX_FILTER_ALLMAC; | data = data | URTW_RX_FILTER_ALLMAC; | ||||
} else { | } else { | ||||
data = data | URTW_RX_FILTER_NICMAC; | data = data | URTW_RX_FILTER_NICMAC; | ||||
Context not available. | |||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
struct mbuf *m, *mnew; | struct mbuf *m, *mnew; | ||||
struct urtw_softc *sc = data->sc; | struct urtw_softc *sc = data->sc; | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint8_t noise = 0, rate; | uint8_t noise = 0, rate; | ||||
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); | usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); | ||||
if (actlen < (int)URTW_MIN_RXBUFSZ) { | if (actlen < (int)URTW_MIN_RXBUFSZ) { | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
Context not available. | |||||
(actlen - (sizeof(struct urtw_8187b_rxhdr)))); | (actlen - (sizeof(struct urtw_8187b_rxhdr)))); | ||||
flen = le32toh(rx->flag) & 0xfff; | flen = le32toh(rx->flag) & 0xfff; | ||||
if (flen > actlen) { | if (flen > actlen) { | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf; | rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf; | ||||
Context not available. | |||||
(actlen - (sizeof(struct urtw_8187l_rxhdr)))); | (actlen - (sizeof(struct urtw_8187l_rxhdr)))); | ||||
flen = le32toh(rx->flag) & 0xfff; | flen = le32toh(rx->flag) & 0xfff; | ||||
if (flen > actlen) { | if (flen > actlen) { | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
Context not available. | |||||
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); | mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); | ||||
if (mnew == NULL) { | if (mnew == NULL) { | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
Context not available. | |||||
data->buf = mtod(mnew, uint8_t *); | data->buf = mtod(mnew, uint8_t *); | ||||
/* finalize mbuf */ | /* finalize mbuf */ | ||||
m->m_pkthdr.rcvif = ifp; | |||||
m->m_pkthdr.len = m->m_len = flen - IEEE80211_CRC_LEN; | m->m_pkthdr.len = m->m_len = flen - IEEE80211_CRC_LEN; | ||||
if (ieee80211_radiotap_active(ic)) { | if (ieee80211_radiotap_active(ic)) { | ||||
Context not available. | |||||
urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) | urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) | ||||
{ | { | ||||
struct urtw_softc *sc = usbd_xfer_softc(xfer); | struct urtw_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_frame *wh; | struct ieee80211_frame *wh; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct mbuf *m = NULL; | struct mbuf *m = NULL; | ||||
Context not available. | |||||
} | } | ||||
if (error != USB_ERR_CANCELLED) { | if (error != USB_ERR_CANCELLED) { | ||||
usbd_xfer_set_stall(xfer); | usbd_xfer_set_stall(xfer); | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
goto setup; | goto setup; | ||||
} | } | ||||
break; | break; | ||||
Context not available. | |||||
urtw_txstatus_eof(struct usb_xfer *xfer) | urtw_txstatus_eof(struct usb_xfer *xfer) | ||||
{ | { | ||||
struct urtw_softc *sc = usbd_xfer_softc(xfer); | struct urtw_softc *sc = usbd_xfer_softc(xfer); | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
int actlen, type, pktretry, seq; | int actlen, type, pktretry, seq; | ||||
uint64_t val; | uint64_t val; | ||||
Context not available. | |||||
pktretry = val & 0xff; | pktretry = val & 0xff; | ||||
seq = (val >> 16) & 0xff; | seq = (val >> 16) & 0xff; | ||||
if (pktretry == URTW_TX_MAXRETRY) | if (pktretry == URTW_TX_MAXRETRY) | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | counter_u64_add(ic->ic_oerrors, 1); | ||||
DPRINTF(sc, URTW_DEBUG_TXSTATUS, "pktretry %d seq %#x\n", | DPRINTF(sc, URTW_DEBUG_TXSTATUS, "pktretry %d seq %#x\n", | ||||
pktretry, seq); | pktretry, seq); | ||||
} | } | ||||
Context not available. | |||||
urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error) | urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error) | ||||
{ | { | ||||
struct urtw_softc *sc = usbd_xfer_softc(xfer); | struct urtw_softc *sc = usbd_xfer_softc(xfer); | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0); | void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0); | ||||
URTW_ASSERT_LOCKED(sc); | URTW_ASSERT_LOCKED(sc); | ||||
Context not available. | |||||
default: | default: | ||||
if (error != USB_ERR_CANCELLED) { | if (error != USB_ERR_CANCELLED) { | ||||
usbd_xfer_set_stall(xfer); | usbd_xfer_set_stall(xfer); | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
goto setup; | goto setup; | ||||
} | } | ||||
break; | break; | ||||
Context not available. | |||||
urtw_txeof(struct usb_xfer *xfer, struct urtw_data *data) | urtw_txeof(struct usb_xfer *xfer, struct urtw_data *data) | ||||
{ | { | ||||
struct urtw_softc *sc = usbd_xfer_softc(xfer); | struct urtw_softc *sc = usbd_xfer_softc(xfer); | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct mbuf *m; | |||||
URTW_ASSERT_LOCKED(sc); | URTW_ASSERT_LOCKED(sc); | ||||
/* | |||||
* Do any tx complete callback. Note this must be done before releasing | |||||
* the node reference. | |||||
*/ | |||||
if (data->m) { | if (data->m) { | ||||
m = data->m; | /* XXX status? */ | ||||
if (m->m_flags & M_TXCB) { | ieee80211_tx_complete(data->ni, data->m, 0); | ||||
/* XXX status? */ | |||||
ieee80211_process_callback(data->ni, m, 0); | |||||
} | |||||
m_freem(m); | |||||
data->m = NULL; | data->m = NULL; | ||||
} | |||||
if (data->ni) { | |||||
ieee80211_free_node(data->ni); | |||||
data->ni = NULL; | data->ni = NULL; | ||||
} | } | ||||
sc->sc_txtimer = 0; | sc->sc_txtimer = 0; | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | |||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | |||||
} | } | ||||
static void | static void | ||||
Context not available. | |||||
urtw_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error) | urtw_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error) | ||||
{ | { | ||||
struct urtw_softc *sc = usbd_xfer_softc(xfer); | struct urtw_softc *sc = usbd_xfer_softc(xfer); | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct urtw_data *data; | struct urtw_data *data; | ||||
URTW_ASSERT_LOCKED(sc); | URTW_ASSERT_LOCKED(sc); | ||||
Context not available. | |||||
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen); | usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen); | ||||
usbd_transfer_submit(xfer); | usbd_transfer_submit(xfer); | ||||
URTW_UNLOCK(sc); | urtw_start(sc); | ||||
urtw_start(ifp); | |||||
URTW_LOCK(sc); | |||||
break; | break; | ||||
default: | default: | ||||
data = STAILQ_FIRST(&sc->sc_tx_active); | data = STAILQ_FIRST(&sc->sc_tx_active); | ||||
Context not available. | |||||
if (data == NULL) | if (data == NULL) | ||||
goto setup; | goto setup; | ||||
if (data->ni != NULL) { | if (data->ni != NULL) { | ||||
if_inc_counter(data->ni->ni_vap->iv_ifp, | |||||
IFCOUNTER_OERRORS, 1); | |||||
ieee80211_free_node(data->ni); | ieee80211_free_node(data->ni); | ||||
data->ni = NULL; | data->ni = NULL; | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
} | } | ||||
if (error != USB_ERR_CANCELLED) { | if (error != USB_ERR_CANCELLED) { | ||||
usbd_xfer_set_stall(xfer); | usbd_xfer_set_stall(xfer); | ||||
Context not available. | |||||
URTW_ASSERT_LOCKED(sc); | URTW_ASSERT_LOCKED(sc); | ||||
bf = _urtw_getbuf(sc); | bf = _urtw_getbuf(sc); | ||||
if (bf == NULL) { | if (bf == NULL) | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
DPRINTF(sc, URTW_DEBUG_XMIT, "%s: stop queue\n", __func__); | DPRINTF(sc, URTW_DEBUG_XMIT, "%s: stop queue\n", __func__); | ||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
} | |||||
return (bf); | return (bf); | ||||
} | } | ||||
Context not available. | |||||
urtw_updateslottask(void *arg, int pending) | urtw_updateslottask(void *arg, int pending) | ||||
{ | { | ||||
struct urtw_softc *sc = arg; | struct urtw_softc *sc = arg; | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
int error; | int error; | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | URTW_LOCK(sc); | ||||
if ((sc->sc_flags & URTW_RUNNING) == 0) { | |||||
URTW_UNLOCK(sc); | |||||
return; | return; | ||||
} | |||||
URTW_LOCK(sc); | |||||
if (sc->sc_flags & URTW_RTL8187B) { | if (sc->sc_flags & URTW_RTL8187B) { | ||||
urtw_write8_m(sc, URTW_SIFS, 0x22); | urtw_write8_m(sc, URTW_SIFS, 0x22); | ||||
if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) | if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) | ||||
Context not available. |