Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/if_ndis/if_ndis.c
Context not available. | |||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/kthread.h> | #include <sys/kthread.h> | ||||
#include <sys/limits.h> | |||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_var.h> | #include <net/if_var.h> | ||||
Context not available. | |||||
static void ndis_resettask (device_object *, void *); | static void ndis_resettask (device_object *, void *); | ||||
static void ndis_inputtask (device_object *, void *); | static void ndis_inputtask (device_object *, void *); | ||||
static int ndis_ioctl (struct ifnet *, u_long, caddr_t); | static int ndis_ioctl (struct ifnet *, u_long, caddr_t); | ||||
static int ndis_ioctl_80211 (struct ifnet *, u_long, caddr_t); | |||||
static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state, | static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state, | ||||
int); | int); | ||||
static int ndis_nettype_chan (uint32_t); | static int ndis_nettype_chan (uint32_t); | ||||
Context not available. | |||||
const struct ieee80211_key *, const u_int8_t []); | const struct ieee80211_key *, const u_int8_t []); | ||||
static int ndis_del_key (struct ieee80211vap *, | static int ndis_del_key (struct ieee80211vap *, | ||||
const struct ieee80211_key *); | const struct ieee80211_key *); | ||||
static void ndis_setmulti (struct ndis_softc *); | static void ndis_setmulti (struct ndis_softc *); | ||||
static void ndis_map_sclist (void *, bus_dma_segment_t *, | static void ndis_map_sclist (void *, bus_dma_segment_t *, | ||||
int, bus_size_t, int); | int, bus_size_t, int); | ||||
static int ndis_ifattach(struct ndis_softc *); | |||||
static int ndis_80211attach(struct ndis_softc *); | |||||
static int ndis_80211ioctl(struct ieee80211com *, u_long , void *); | |||||
static int ndis_80211transmit(struct ieee80211com *, struct mbuf *); | |||||
static void ndis_80211parent(struct ieee80211com *); | |||||
static int ndisdrv_loaded = 0; | static int ndisdrv_loaded = 0; | ||||
/* | /* | ||||
Context not available. | |||||
* setup and ethernet/BPF attach. | * setup and ethernet/BPF attach. | ||||
*/ | */ | ||||
int | int | ||||
ndis_attach(dev) | ndis_attach(device_t dev) | ||||
device_t dev; | |||||
{ | { | ||||
u_char eaddr[ETHER_ADDR_LEN]; | |||||
struct ndis_softc *sc; | struct ndis_softc *sc; | ||||
driver_object *pdrv; | driver_object *pdrv; | ||||
device_object *pdo; | device_object *pdo; | ||||
struct ifnet *ifp = NULL; | int error = 0, len; | ||||
int error = 0, len, mode; | |||||
uint8_t bands = 0; | |||||
int i; | int i; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
Context not available. | |||||
InitializeListHead(&sc->ndisusb_tasklist); | InitializeListHead(&sc->ndisusb_tasklist); | ||||
InitializeListHead(&sc->ndisusb_xferdonelist); | InitializeListHead(&sc->ndisusb_xferdonelist); | ||||
callout_init(&sc->ndis_stat_callout, 1); | callout_init(&sc->ndis_stat_callout, 1); | ||||
mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */ | |||||
if (sc->ndis_iftype == PCMCIABus) { | if (sc->ndis_iftype == PCMCIABus) { | ||||
error = ndis_alloc_amem(sc); | error = ndis_alloc_amem(sc); | ||||
Context not available. | |||||
} | } | ||||
/* | /* | ||||
* Get station address from the driver. | |||||
*/ | |||||
len = sizeof(eaddr); | |||||
ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len); | |||||
/* | |||||
* Figure out how big to make the TX buffer pool. | * Figure out how big to make the TX buffer pool. | ||||
*/ | */ | ||||
len = sizeof(sc->ndis_maxpkts); | len = sizeof(sc->ndis_maxpkts); | ||||
if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS, | if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS, | ||||
&sc->ndis_maxpkts, &len)) { | &sc->ndis_maxpkts, &len)) { | ||||
Context not available. | |||||
*/ | */ | ||||
for (i = 0; i < sc->ndis_oidcnt; i++) | for (i = 0; i < sc->ndis_oidcnt; i++) | ||||
if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) { | if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) { | ||||
sc->ndis_80211++; | sc->ndis_80211 = 1; | ||||
break; | break; | ||||
} | } | ||||
if (sc->ndis_80211) | if (sc->ndis_80211) | ||||
ifp = if_alloc(IFT_IEEE80211); | error = ndis_80211attach(sc); | ||||
else | else | ||||
ifp = if_alloc(IFT_ETHER); | error = ndis_ifattach(sc); | ||||
if (ifp == NULL) { | |||||
error = ENOSPC; | fail: | ||||
goto fail; | if (error) { | ||||
ndis_detach(dev); | |||||
return (error); | |||||
} | } | ||||
sc->ifp = ifp; | |||||
ifp->if_softc = sc; | |||||
/* Check for task offload support. */ | if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0) | ||||
ndis_probe_offload(sc); | return (error); | ||||
if_initname(ifp, device_get_name(dev), device_get_unit(dev)); | DPRINTF(("attach done.\n")); | ||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | /* We're done talking to the NIC for now; halt it. */ | ||||
ifp->if_ioctl = ndis_ioctl; | ndis_halt_nic(sc); | ||||
ifp->if_start = ndis_start; | DPRINTF(("halting done.\n")); | ||||
ifp->if_init = ndis_init; | |||||
ifp->if_baudrate = 10000000; | |||||
IFQ_SET_MAXLEN(&ifp->if_snd, 50); | |||||
ifp->if_snd.ifq_drv_maxlen = 25; | |||||
IFQ_SET_READY(&ifp->if_snd); | |||||
ifp->if_capenable = ifp->if_capabilities; | |||||
ifp->if_hwassist = sc->ndis_hwassist; | |||||
/* Do media setup */ | return (error); | ||||
if (sc->ndis_80211) { | } | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
ndis_80211_rates_ex rates; | |||||
struct ndis_80211_nettype_list *ntl; | |||||
uint32_t arg; | |||||
int r; | |||||
callout_init(&sc->ndis_scan_callout, 1); | static int | ||||
ndis_80211attach(struct ndis_softc *sc) | |||||
{ | |||||
struct ieee80211com *ic = &sc->ndis_ic; | |||||
ndis_80211_rates_ex rates; | |||||
struct ndis_80211_nettype_list *ntl; | |||||
uint32_t arg; | |||||
int mode, i, r, len; | |||||
uint8_t bands = 0; | |||||
ifp->if_ioctl = ndis_ioctl_80211; | callout_init(&sc->ndis_scan_callout, 1); | ||||
ic->ic_ifp = ifp; | |||||
ic->ic_softc = sc; | |||||
ic->ic_name = device_get_nameunit(dev); | |||||
ic->ic_opmode = IEEE80211_M_STA; | |||||
ic->ic_phytype = IEEE80211_T_DS; | |||||
ic->ic_caps = IEEE80211_C_8023ENCAP | | |||||
IEEE80211_C_STA | IEEE80211_C_IBSS; | |||||
setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO); | |||||
len = 0; | |||||
r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, | |||||
NULL, &len); | |||||
if (r != ENOSPC) | |||||
goto nonettypes; | |||||
ntl = malloc(len, M_DEVBUF, M_NOWAIT|M_ZERO); | |||||
r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, | |||||
ntl, &len); | |||||
if (r != 0) { | |||||
free(ntl, M_DEVBUF); | |||||
goto nonettypes; | |||||
} | |||||
for (i = 0; i < ntl->ntl_items; i++) { | ic->ic_softc = sc; | ||||
mode = ndis_nettype_mode(ntl->ntl_type[i]); | ic->ic_ioctl = ndis_80211ioctl; | ||||
if (mode) { | ic->ic_name = device_get_nameunit(sc->ndis_dev); | ||||
setbit(ic->ic_modecaps, mode); | ic->ic_opmode = IEEE80211_M_STA; | ||||
setbit(&bands, mode); | ic->ic_phytype = IEEE80211_T_DS; | ||||
} else | ic->ic_caps = IEEE80211_C_8023ENCAP | | ||||
device_printf(dev, "Unknown nettype %d\n", | IEEE80211_C_STA | IEEE80211_C_IBSS; | ||||
ntl->ntl_type[i]); | setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO); | ||||
} | len = 0; | ||||
r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len); | |||||
if (r != ENOSPC) | |||||
goto nonettypes; | |||||
ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); | |||||
r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len); | |||||
if (r != 0) { | |||||
free(ntl, M_DEVBUF); | free(ntl, M_DEVBUF); | ||||
goto nonettypes; | |||||
} | |||||
for (i = 0; i < ntl->ntl_items; i++) { | |||||
mode = ndis_nettype_mode(ntl->ntl_type[i]); | |||||
if (mode) { | |||||
setbit(ic->ic_modecaps, mode); | |||||
setbit(&bands, mode); | |||||
} else | |||||
device_printf(sc->ndis_dev, "Unknown nettype %d\n", | |||||
ntl->ntl_type[i]); | |||||
} | |||||
free(ntl, M_DEVBUF); | |||||
nonettypes: | nonettypes: | ||||
/* Default to 11b channels if the card did not supply any */ | /* Default to 11b channels if the card did not supply any */ | ||||
if (bands == 0) { | if (bands == 0) { | ||||
setbit(ic->ic_modecaps, IEEE80211_MODE_11B); | setbit(ic->ic_modecaps, IEEE80211_MODE_11B); | ||||
setbit(&bands, IEEE80211_MODE_11B); | setbit(&bands, IEEE80211_MODE_11B); | ||||
} | } | ||||
len = sizeof(rates); | len = sizeof(rates); | ||||
bzero((char *)&rates, len); | bzero((char *)&rates, len); | ||||
r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, | r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len); | ||||
(void *)rates, &len); | if (r != 0) | ||||
if (r) | device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r); | ||||
device_printf(dev, "get rates failed: 0x%x\n", r); | /* | ||||
/* | * Since the supported rates only up to 8 can be supported, | ||||
* Since the supported rates only up to 8 can be supported, | * if this is not 802.11b we're just going to be faking it | ||||
* if this is not 802.11b we're just going to be faking it | * all up to heck. | ||||
* all up to heck. | */ | ||||
*/ | |||||
#define TESTSETRATE(x, y) \ | #define TESTSETRATE(x, y) \ | ||||
do { \ | do { \ | ||||
Context not available. | |||||
#define INCRATE(x) \ | #define INCRATE(x) \ | ||||
ic->ic_sup_rates[x].rs_nrates++ | ic->ic_sup_rates[x].rs_nrates++ | ||||
ic->ic_curmode = IEEE80211_MODE_AUTO; | ic->ic_curmode = IEEE80211_MODE_AUTO; | ||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) | if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) | ||||
ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0; | ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0; | ||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) | if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) | ||||
ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0; | ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0; | ||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) | if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) | ||||
ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0; | ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0; | ||||
for (i = 0; i < len; i++) { | for (i = 0; i < len; i++) { | ||||
switch (rates[i] & IEEE80211_RATE_VAL) { | switch (rates[i] & IEEE80211_RATE_VAL) { | ||||
case 2: | case 2: | ||||
case 4: | case 4: | ||||
case 11: | case 11: | ||||
case 10: | case 10: | ||||
case 22: | case 22: | ||||
if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) { | if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) { | ||||
/* Lazy-init 802.11b. */ | /* Lazy-init 802.11b. */ | ||||
setbit(ic->ic_modecaps, | setbit(ic->ic_modecaps, IEEE80211_MODE_11B); | ||||
IEEE80211_MODE_11B); | ic->ic_sup_rates[IEEE80211_MODE_11B]. | ||||
ic->ic_sup_rates[IEEE80211_MODE_11B]. | rs_nrates = 0; | ||||
rs_nrates = 0; | |||||
} | |||||
SETRATE(IEEE80211_MODE_11B, rates[i]); | |||||
INCRATE(IEEE80211_MODE_11B); | |||||
break; | |||||
default: | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { | |||||
SETRATE(IEEE80211_MODE_11A, rates[i]); | |||||
INCRATE(IEEE80211_MODE_11A); | |||||
} | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { | |||||
SETRATE(IEEE80211_MODE_11G, rates[i]); | |||||
INCRATE(IEEE80211_MODE_11G); | |||||
} | |||||
break; | |||||
} | } | ||||
SETRATE(IEEE80211_MODE_11B, rates[i]); | |||||
INCRATE(IEEE80211_MODE_11B); | |||||
break; | |||||
default: | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { | |||||
SETRATE(IEEE80211_MODE_11A, rates[i]); | |||||
INCRATE(IEEE80211_MODE_11A); | |||||
} | |||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { | |||||
SETRATE(IEEE80211_MODE_11G, rates[i]); | |||||
INCRATE(IEEE80211_MODE_11G); | |||||
} | |||||
break; | |||||
} | } | ||||
} | |||||
/* | /* | ||||
* If the hardware supports 802.11g, it most | * If the hardware supports 802.11g, it most | ||||
* likely supports 802.11b and all of the | * likely supports 802.11b and all of the | ||||
* 802.11b and 802.11g speeds, so maybe we can | * 802.11b and 802.11g speeds, so maybe we can | ||||
* just cheat here. Just how in the heck do | * just cheat here. Just how in the heck do | ||||
* we detect turbo modes, though? | * we detect turbo modes, though? | ||||
*/ | */ | ||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) { | if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) { | ||||
TESTSETRATE(IEEE80211_MODE_11B, | TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2); | ||||
IEEE80211_RATE_BASIC|2); | TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4); | ||||
TESTSETRATE(IEEE80211_MODE_11B, | TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11); | ||||
IEEE80211_RATE_BASIC|4); | TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22); | ||||
TESTSETRATE(IEEE80211_MODE_11B, | } | ||||
IEEE80211_RATE_BASIC|11); | if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { | ||||
TESTSETRATE(IEEE80211_MODE_11B, | TESTSETRATE(IEEE80211_MODE_11G, 48); | ||||
IEEE80211_RATE_BASIC|22); | TESTSETRATE(IEEE80211_MODE_11G, 72); | ||||
} | TESTSETRATE(IEEE80211_MODE_11G, 96); | ||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { | TESTSETRATE(IEEE80211_MODE_11G, 108); | ||||
TESTSETRATE(IEEE80211_MODE_11G, 48); | } | ||||
TESTSETRATE(IEEE80211_MODE_11G, 72); | if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { | ||||
TESTSETRATE(IEEE80211_MODE_11G, 96); | TESTSETRATE(IEEE80211_MODE_11A, 48); | ||||
TESTSETRATE(IEEE80211_MODE_11G, 108); | TESTSETRATE(IEEE80211_MODE_11A, 72); | ||||
} | TESTSETRATE(IEEE80211_MODE_11A, 96); | ||||
if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { | TESTSETRATE(IEEE80211_MODE_11A, 108); | ||||
TESTSETRATE(IEEE80211_MODE_11A, 48); | } | ||||
TESTSETRATE(IEEE80211_MODE_11A, 72); | |||||
TESTSETRATE(IEEE80211_MODE_11A, 96); | |||||
TESTSETRATE(IEEE80211_MODE_11A, 108); | |||||
} | |||||
#undef SETRATE | #undef SETRATE | ||||
#undef INCRATE | #undef INCRATE | ||||
ieee80211_init_channels(ic, NULL, &bands); | #undef TESTSETRATE | ||||
/* | ieee80211_init_channels(ic, NULL, &bands); | ||||
* To test for WPA support, we need to see if we can | |||||
* set AUTHENTICATION_MODE to WPA and read it back | |||||
* successfully. | |||||
*/ | |||||
i = sizeof(arg); | |||||
arg = NDIS_80211_AUTHMODE_WPA; | |||||
r = ndis_set_info(sc, | |||||
OID_802_11_AUTHENTICATION_MODE, &arg, &i); | |||||
if (r == 0) { | |||||
r = ndis_get_info(sc, | |||||
OID_802_11_AUTHENTICATION_MODE, &arg, &i); | |||||
if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA) | |||||
ic->ic_caps |= IEEE80211_C_WPA; | |||||
} | |||||
/* | /* | ||||
* To test for supported ciphers, we set each | * To test for WPA support, we need to see if we can | ||||
* available encryption type in descending order. | * set AUTHENTICATION_MODE to WPA and read it back | ||||
* If ENC3 works, then we have WEP, TKIP and AES. | * successfully. | ||||
* If only ENC2 works, then we have WEP and TKIP. | */ | ||||
* If only ENC1 works, then we have just WEP. | i = sizeof(arg); | ||||
*/ | arg = NDIS_80211_AUTHMODE_WPA; | ||||
i = sizeof(arg); | r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i); | ||||
arg = NDIS_80211_WEPSTAT_ENC3ENABLED; | if (r == 0) { | ||||
r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); | r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i); | ||||
if (r == 0) { | if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA) | ||||
ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP | ic->ic_caps |= IEEE80211_C_WPA; | ||||
| IEEE80211_CRYPTO_TKIP | } | ||||
| IEEE80211_CRYPTO_AES_CCM; | |||||
goto got_crypto; | /* | ||||
} | * To test for supported ciphers, we set each | ||||
arg = NDIS_80211_WEPSTAT_ENC2ENABLED; | * available encryption type in descending order. | ||||
r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); | * If ENC3 works, then we have WEP, TKIP and AES. | ||||
if (r == 0) { | * If only ENC2 works, then we have WEP and TKIP. | ||||
ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP | * If only ENC1 works, then we have just WEP. | ||||
| IEEE80211_CRYPTO_TKIP; | */ | ||||
goto got_crypto; | i = sizeof(arg); | ||||
} | arg = NDIS_80211_WEPSTAT_ENC3ENABLED; | ||||
arg = NDIS_80211_WEPSTAT_ENC1ENABLED; | r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); | ||||
r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); | if (r == 0) { | ||||
if (r == 0) | ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP | ||||
ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP; | | IEEE80211_CRYPTO_TKIP | ||||
| IEEE80211_CRYPTO_AES_CCM; | |||||
goto got_crypto; | |||||
} | |||||
arg = NDIS_80211_WEPSTAT_ENC2ENABLED; | |||||
r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); | |||||
if (r == 0) { | |||||
ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP | |||||
| IEEE80211_CRYPTO_TKIP; | |||||
goto got_crypto; | |||||
} | |||||
arg = NDIS_80211_WEPSTAT_ENC1ENABLED; | |||||
r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); | |||||
if (r == 0) | |||||
ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP; | |||||
got_crypto: | got_crypto: | ||||
i = sizeof(arg); | i = sizeof(arg); | ||||
r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i); | r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i); | ||||
if (r == 0) | if (r == 0) | ||||
ic->ic_caps |= IEEE80211_C_PMGT; | ic->ic_caps |= IEEE80211_C_PMGT; | ||||
r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i); | r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i); | ||||
if (r == 0) | if (r == 0) | ||||
ic->ic_caps |= IEEE80211_C_TXPMGT; | ic->ic_caps |= IEEE80211_C_TXPMGT; | ||||
ieee80211_ifattach(ic, eaddr); | /* | ||||
ic->ic_raw_xmit = ndis_raw_xmit; | * Get station address from the driver. | ||||
ic->ic_scan_start = ndis_scan_start; | */ | ||||
ic->ic_scan_end = ndis_scan_end; | len = sizeof(ic->ic_macaddr); | ||||
ic->ic_set_channel = ndis_set_channel; | ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len); | ||||
ic->ic_scan_curchan = ndis_scan_curchan; | |||||
ic->ic_scan_mindwell = ndis_scan_mindwell; | |||||
ic->ic_bsschan = IEEE80211_CHAN_ANYC; | |||||
//ic->ic_bss->ni_chan = ic->ic_bsschan; | |||||
ic->ic_vap_create = ndis_vap_create; | |||||
ic->ic_vap_delete = ndis_vap_delete; | |||||
ic->ic_update_mcast = ndis_update_mcast; | |||||
ic->ic_update_promisc = ndis_update_promisc; | |||||
if (bootverbose) | ieee80211_ifattach(ic); | ||||
ieee80211_announce(ic); | ic->ic_raw_xmit = ndis_raw_xmit; | ||||
ic->ic_scan_start = ndis_scan_start; | |||||
ic->ic_scan_end = ndis_scan_end; | |||||
ic->ic_set_channel = ndis_set_channel; | |||||
ic->ic_scan_curchan = ndis_scan_curchan; | |||||
ic->ic_scan_mindwell = ndis_scan_mindwell; | |||||
ic->ic_bsschan = IEEE80211_CHAN_ANYC; | |||||
ic->ic_vap_create = ndis_vap_create; | |||||
ic->ic_vap_delete = ndis_vap_delete; | |||||
ic->ic_update_mcast = ndis_update_mcast; | |||||
ic->ic_update_promisc = ndis_update_promisc; | |||||
ic->ic_transmit = ndis_80211transmit; | |||||
ic->ic_parent = ndis_80211parent; | |||||
} else { | if (bootverbose) | ||||
ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd, | ieee80211_announce(ic); | ||||
ndis_ifmedia_sts); | |||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); | |||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); | |||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL); | |||||
ifmedia_add(&sc->ifmedia, | |||||
IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); | |||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); | |||||
ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO); | |||||
ether_ifattach(ifp, eaddr); | |||||
} | |||||
fail: | return (0); | ||||
if (error) { | } | ||||
ndis_detach(dev); | |||||
return (error); | |||||
} | |||||
if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0) | static int | ||||
return (error); | ndis_ifattach(struct ndis_softc *sc) | ||||
{ | |||||
struct ifnet *ifp; | |||||
u_char eaddr[ETHER_ADDR_LEN]; | |||||
int len; | |||||
DPRINTF(("attach done.\n")); | ifp = if_alloc(IFT_ETHER); | ||||
/* We're done talking to the NIC for now; halt it. */ | if (ifp == NULL) | ||||
ndis_halt_nic(sc); | return (ENOSPC); | ||||
DPRINTF(("halting done.\n")); | sc->ifp = ifp; | ||||
ifp->if_softc = sc; | |||||
return (error); | /* Check for task offload support. */ | ||||
ndis_probe_offload(sc); | |||||
/* | |||||
* Get station address from the driver. | |||||
*/ | |||||
len = sizeof(eaddr); | |||||
ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len); | |||||
if_initname(ifp, device_get_name(sc->ndis_dev), | |||||
device_get_unit(sc->ndis_dev)); | |||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | |||||
ifp->if_ioctl = ndis_ioctl; | |||||
ifp->if_start = ndis_start; | |||||
ifp->if_init = ndis_init; | |||||
ifp->if_baudrate = 10000000; | |||||
IFQ_SET_MAXLEN(&ifp->if_snd, 50); | |||||
ifp->if_snd.ifq_drv_maxlen = 25; | |||||
IFQ_SET_READY(&ifp->if_snd); | |||||
ifp->if_capenable = ifp->if_capabilities; | |||||
ifp->if_hwassist = sc->ndis_hwassist; | |||||
ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd, | |||||
ndis_ifmedia_sts); | |||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); | |||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); | |||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL); | |||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); | |||||
ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); | |||||
ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO); | |||||
ether_ifattach(ifp, eaddr); | |||||
return (0); | |||||
} | } | ||||
static struct ieee80211vap * | static struct ieee80211vap * | ||||
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; | ||||
nvp = (struct ndis_vap *) malloc(sizeof(struct ndis_vap), | nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO); | ||||
M_80211_VAP, M_NOWAIT | M_ZERO); | |||||
if (nvp == NULL) | |||||
return NULL; | |||||
vap = &nvp->vap; | vap = &nvp->vap; | ||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); | ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); | ||||
/* override with driver methods */ | /* override with driver methods */ | ||||
nvp->newstate = vap->iv_newstate; | nvp->newstate = vap->iv_newstate; | ||||
vap->iv_newstate = ndis_newstate; | vap->iv_newstate = ndis_newstate; | ||||
/* complete setup */ | /* complete setup */ | ||||
ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status); | ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status, | ||||
mac); | |||||
ic->ic_opmode = opmode; | ic->ic_opmode = opmode; | ||||
/* install key handing routines */ | /* install key handing routines */ | ||||
vap->iv_key_set = ndis_add_key; | vap->iv_key_set = ndis_add_key; | ||||
Context not available. | |||||
{ | { | ||||
struct ndis_vap *nvp = NDIS_VAP(vap); | struct ndis_vap *nvp = NDIS_VAP(vap); | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct ifnet *ifp = ic->ic_ifp; | struct ndis_softc *sc = ic->ic_softc; | ||||
struct ndis_softc *sc = ifp->if_softc; | |||||
ndis_stop(sc); | ndis_stop(sc); | ||||
callout_drain(&sc->ndis_scan_callout); | callout_drain(&sc->ndis_scan_callout); | ||||
Context not available. | |||||
* allocated. | * allocated. | ||||
*/ | */ | ||||
int | int | ||||
ndis_detach(dev) | ndis_detach(device_t dev) | ||||
device_t dev; | |||||
{ | { | ||||
struct ifnet *ifp; | |||||
struct ndis_softc *sc; | struct ndis_softc *sc; | ||||
struct ifnet *ifp; | |||||
driver_object *drv; | driver_object *drv; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
NDIS_LOCK(sc); | NDIS_LOCK(sc); | ||||
ifp = sc->ifp; | if (!sc->ndis_80211) | ||||
ifp = sc->ifp; | |||||
else | |||||
ifp = NULL; | |||||
if (ifp != NULL) | if (ifp != NULL) | ||||
ifp->if_flags &= ~IFF_UP; | ifp->if_flags &= ~IFF_UP; | ||||
if (device_is_attached(dev)) { | if (device_is_attached(dev)) { | ||||
NDIS_UNLOCK(sc); | NDIS_UNLOCK(sc); | ||||
ndis_stop(sc); | ndis_stop(sc); | ||||
if (ifp != NULL) { | if (sc->ndis_80211) | ||||
if (sc->ndis_80211) | ieee80211_ifdetach(&sc->ndis_ic); | ||||
ieee80211_ifdetach(ifp->if_l2com); | else if (ifp != NULL) | ||||
else | ether_ifdetach(ifp); | ||||
ether_ifdetach(ifp); | |||||
} | |||||
} else | } else | ||||
NDIS_UNLOCK(sc); | NDIS_UNLOCK(sc); | ||||
Context not available. | |||||
IoFreeMdl(p->np_private.npp_head); | IoFreeMdl(p->np_private.npp_head); | ||||
NdisFreePacket(p); | NdisFreePacket(p); | ||||
KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); | KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); | ||||
_IF_ENQUEUE(&sc->ndis_rxqueue, m); | mbufq_enqueue(&sc->ndis_rxqueue, m); | ||||
KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); | KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); | ||||
IoQueueWorkItem(sc->ndis_inputitem, | IoQueueWorkItem(sc->ndis_inputitem, | ||||
(io_workitem_func)ndis_inputtask_wrap, | (io_workitem_func)ndis_inputtask_wrap, | ||||
WORKQUEUE_CRITICAL, ifp); | WORKQUEUE_CRITICAL, sc); | ||||
} | } | ||||
if (status == NDIS_STATUS_FAILURE) | if (status == NDIS_STATUS_FAILURE) | ||||
Context not available. | |||||
m->m_len = m->m_pkthdr.len; | m->m_len = m->m_pkthdr.len; | ||||
m->m_pkthdr.rcvif = ifp; | m->m_pkthdr.rcvif = ifp; | ||||
KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); | KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); | ||||
_IF_ENQUEUE(&sc->ndis_rxqueue, m); | mbufq_enqueue(&sc->ndis_rxqueue, m); | ||||
KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); | KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); | ||||
IoQueueWorkItem(sc->ndis_inputitem, | IoQueueWorkItem(sc->ndis_inputitem, | ||||
(io_workitem_func)ndis_inputtask_wrap, | (io_workitem_func)ndis_inputtask_wrap, | ||||
WORKQUEUE_CRITICAL, ifp); | WORKQUEUE_CRITICAL, sc); | ||||
} | } | ||||
/* | /* | ||||
* A frame has been uploaded: pass the resulting mbuf chain up to | * A frame has been uploaded: pass the resulting mbuf chain up to | ||||
Context not available. | |||||
* before we're completely ready to handle them. If we detect this, | * before we're completely ready to handle them. If we detect this, | ||||
* we need to return them to the miniport and ignore them. | * we need to return them to the miniport and ignore them. | ||||
*/ | */ | ||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { | if (!sc->ndis_running) { | ||||
for (i = 0; i < pktcnt; i++) { | for (i = 0; i < pktcnt; i++) { | ||||
p = packets[i]; | p = packets[i]; | ||||
if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) { | if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) { | ||||
Context not available. | |||||
} | } | ||||
KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); | KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); | ||||
_IF_ENQUEUE(&sc->ndis_rxqueue, m0); | mbufq_enqueue(&sc->ndis_rxqueue, m0); | ||||
KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); | KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); | ||||
IoQueueWorkItem(sc->ndis_inputitem, | IoQueueWorkItem(sc->ndis_inputitem, | ||||
(io_workitem_func)ndis_inputtask_wrap, | (io_workitem_func)ndis_inputtask_wrap, | ||||
WORKQUEUE_CRITICAL, ifp); | WORKQUEUE_CRITICAL, sc); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
* 'dispatch level' per-cpu sleep lock). | * 'dispatch level' per-cpu sleep lock). | ||||
*/ | */ | ||||
static void | static void | ||||
ndis_inputtask(dobj, arg) | ndis_inputtask(device_object *dobj, void *arg) | ||||
device_object *dobj; | |||||
void *arg; | |||||
{ | { | ||||
ndis_miniport_block *block; | ndis_miniport_block *block; | ||||
struct ifnet *ifp; | struct ndis_softc *sc = arg; | ||||
struct ndis_softc *sc; | |||||
struct mbuf *m; | struct mbuf *m; | ||||
struct ieee80211com *ic; | |||||
struct ieee80211vap *vap; | |||||
uint8_t irql; | uint8_t irql; | ||||
ifp = arg; | |||||
sc = ifp->if_softc; | |||||
ic = ifp->if_l2com; | |||||
vap = TAILQ_FIRST(&ic->ic_vaps); | |||||
block = dobj->do_devext; | block = dobj->do_devext; | ||||
KeAcquireSpinLock(&sc->ndis_rxlock, &irql); | KeAcquireSpinLock(&sc->ndis_rxlock, &irql); | ||||
while(1) { | while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) { | ||||
_IF_DEQUEUE(&sc->ndis_rxqueue, m); | |||||
if (m == NULL) | |||||
break; | |||||
KeReleaseSpinLock(&sc->ndis_rxlock, irql); | KeReleaseSpinLock(&sc->ndis_rxlock, irql); | ||||
if ((sc->ndis_80211 != 0) && (vap != NULL)) | if ((sc->ndis_80211 != 0)) { | ||||
vap->iv_deliver_data(vap, vap->iv_bss, m); | struct ieee80211com *ic = &sc->ndis_ic; | ||||
else | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
if (vap != NULL) | |||||
vap->iv_deliver_data(vap, vap->iv_bss, m); | |||||
} else { | |||||
struct ifnet *ifp = sc->ifp; | |||||
(*ifp->if_input)(ifp, m); | (*ifp->if_input)(ifp, m); | ||||
} | |||||
KeAcquireSpinLock(&sc->ndis_rxlock, &irql); | KeAcquireSpinLock(&sc->ndis_rxlock, &irql); | ||||
} | } | ||||
KeReleaseSpinLock(&sc->ndis_rxlock, irql); | KeReleaseSpinLock(&sc->ndis_rxlock, irql); | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
ndis_ticktask(d, xsc) | ndis_ticktask(device_object *d, void *xsc) | ||||
device_object *d; | |||||
void *xsc; | |||||
{ | { | ||||
struct ndis_softc *sc; | struct ndis_softc *sc = xsc; | ||||
struct ieee80211com *ic; | |||||
struct ieee80211vap *vap; | |||||
ndis_checkforhang_handler hangfunc; | ndis_checkforhang_handler hangfunc; | ||||
uint8_t rval; | uint8_t rval; | ||||
sc = xsc; | |||||
ic = sc->ifp->if_l2com; | |||||
vap = TAILQ_FIRST(&ic->ic_vaps); | |||||
NDIS_LOCK(sc); | NDIS_LOCK(sc); | ||||
if (!NDIS_INITIALIZED(sc)) { | if (!NDIS_INITIALIZED(sc)) { | ||||
NDIS_UNLOCK(sc); | NDIS_UNLOCK(sc); | ||||
Context not available. | |||||
if (sc->ndis_link == 0 && | if (sc->ndis_link == 0 && | ||||
sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) { | sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) { | ||||
sc->ndis_link = 1; | sc->ndis_link = 1; | ||||
if ((sc->ndis_80211 != 0) && (vap != NULL)) { | if (sc->ndis_80211 != 0) { | ||||
NDIS_UNLOCK(sc); | struct ieee80211com *ic = &sc->ndis_ic; | ||||
ndis_getstate_80211(sc); | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
ieee80211_new_state(vap, IEEE80211_S_RUN, -1); | |||||
NDIS_LOCK(sc); | if (vap != NULL) { | ||||
if_link_state_change(vap->iv_ifp, LINK_STATE_UP); | NDIS_UNLOCK(sc); | ||||
ndis_getstate_80211(sc); | |||||
ieee80211_new_state(vap, IEEE80211_S_RUN, -1); | |||||
NDIS_LOCK(sc); | |||||
if_link_state_change(vap->iv_ifp, | |||||
LINK_STATE_UP); | |||||
} | |||||
} else | } else | ||||
if_link_state_change(sc->ifp, LINK_STATE_UP); | if_link_state_change(sc->ifp, LINK_STATE_UP); | ||||
} | } | ||||
Context not available. | |||||
if (sc->ndis_link == 1 && | if (sc->ndis_link == 1 && | ||||
sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) { | sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) { | ||||
sc->ndis_link = 0; | sc->ndis_link = 0; | ||||
if ((sc->ndis_80211 != 0) && (vap != NULL)) { | if (sc->ndis_80211 != 0) { | ||||
NDIS_UNLOCK(sc); | struct ieee80211com *ic = &sc->ndis_ic; | ||||
ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
NDIS_LOCK(sc); | |||||
if_link_state_change(vap->iv_ifp, LINK_STATE_DOWN); | if (vap != NULL) { | ||||
NDIS_UNLOCK(sc); | |||||
ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); | |||||
NDIS_LOCK(sc); | |||||
if_link_state_change(vap->iv_ifp, | |||||
LINK_STATE_DOWN); | |||||
} | |||||
} else | } else | ||||
if_link_state_change(sc->ifp, LINK_STATE_DOWN); | if_link_state_change(sc->ifp, LINK_STATE_DOWN); | ||||
} | } | ||||
Context not available. | |||||
return; | return; | ||||
} | } | ||||
static int | |||||
ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m) | |||||
{ | |||||
struct ndis_softc *sc = ic->ic_softc; | |||||
ndis_packet **p0 = NULL, *p = NULL; | |||||
int status; | |||||
NDIS_LOCK(sc); | |||||
if (!sc->ndis_link || !sc->ndis_running) { | |||||
NDIS_UNLOCK(sc); | |||||
return (ENXIO); | |||||
} | |||||
if (sc->ndis_txpending == 0) { | |||||
NDIS_UNLOCK(sc); | |||||
return (ENOBUFS); | |||||
} | |||||
p0 = &sc->ndis_txarray[sc->ndis_txidx]; | |||||
NdisAllocatePacket(&status, | |||||
&sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool); | |||||
if (status != NDIS_STATUS_SUCCESS) { | |||||
NDIS_UNLOCK(sc); | |||||
return (ENOBUFS); | |||||
} | |||||
if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) { | |||||
NDIS_UNLOCK(sc); | |||||
return (ENOBUFS); | |||||
} | |||||
/* | |||||
* Save pointer to original mbuf | |||||
* so we can free it later. | |||||
*/ | |||||
p = sc->ndis_txarray[sc->ndis_txidx]; | |||||
p->np_txidx = sc->ndis_txidx; | |||||
p->np_m0 = m; | |||||
p->np_oob.npo_status = NDIS_STATUS_PENDING; | |||||
/* | |||||
* Do scatter/gather processing, if driver requested it. | |||||
*/ | |||||
if (sc->ndis_sc) { | |||||
bus_dmamap_load_mbuf(sc->ndis_ttag, | |||||
sc->ndis_tmaps[sc->ndis_txidx], m, | |||||
ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT); | |||||
bus_dmamap_sync(sc->ndis_ttag, | |||||
sc->ndis_tmaps[sc->ndis_txidx], | |||||
BUS_DMASYNC_PREREAD); | |||||
p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist; | |||||
} | |||||
NDIS_INC(sc); | |||||
sc->ndis_txpending--; | |||||
/* | |||||
* Set a timeout in case the chip goes out to lunch. | |||||
*/ | |||||
sc->ndis_tx_timer = 5; | |||||
NDIS_UNLOCK(sc); | |||||
/* | |||||
* According to NDIS documentation, if a driver exports | |||||
* a MiniportSendPackets() routine, we prefer that over | |||||
* a MiniportSend() routine (which sends just a single | |||||
* packet). | |||||
*/ | |||||
if (sc->ndis_chars->nmc_sendmulti_func != NULL) | |||||
ndis_send_packets(sc, p0, 1); | |||||
else | |||||
ndis_send_packet(sc, p); | |||||
return (0); | |||||
} | |||||
static void | static void | ||||
ndis_init(xsc) | ndis_80211parent(struct ieee80211com *ic) | ||||
void *xsc; | |||||
{ | { | ||||
struct ndis_softc *sc = ic->ic_softc; | |||||
/*NDIS_LOCK(sc);*/ | |||||
if (ic->ic_nrunning > 0) { | |||||
if (!sc->ndis_running) | |||||
ndis_init(sc); | |||||
} else if (sc->ndis_running) | |||||
ndis_stop(sc); | |||||
/*NDIS_UNLOCK(sc);*/ | |||||
} | |||||
static void | |||||
ndis_init(void *xsc) | |||||
{ | |||||
struct ndis_softc *sc = xsc; | struct ndis_softc *sc = xsc; | ||||
struct ifnet *ifp = sc->ifp; | |||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
int i, len, error; | int i, len, error; | ||||
/* | /* | ||||
Context not available. | |||||
} | } | ||||
} | } | ||||
/* Init our MAC address */ | |||||
/* Program the packet filter */ | /* Program the packet filter */ | ||||
sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED | | |||||
NDIS_PACKET_TYPE_BROADCAST; | |||||
sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED; | if (sc->ndis_80211) { | ||||
struct ieee80211com *ic = &sc->ndis_ic; | |||||
if (ifp->if_flags & IFF_BROADCAST) | if (ic->ic_promisc > 0) | ||||
sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST; | sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; | ||||
} else { | |||||
struct ifnet *ifp = sc->ifp; | |||||
if (ifp->if_flags & IFF_PROMISC) | if (ifp->if_flags & IFF_PROMISC) | ||||
sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; | sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; | ||||
} | |||||
len = sizeof(sc->ndis_filter); | len = sizeof(sc->ndis_filter); | ||||
Context not available. | |||||
/* | /* | ||||
* Set lookahead. | * Set lookahead. | ||||
*/ | */ | ||||
i = ifp->if_mtu; | if (sc->ndis_80211) | ||||
i = ETHERMTU; | |||||
else | |||||
i = sc->ifp->if_mtu; | |||||
len = sizeof(i); | len = sizeof(i); | ||||
ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len); | ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len); | ||||
Context not available. | |||||
sc->ndis_txpending = sc->ndis_maxpkts; | sc->ndis_txpending = sc->ndis_maxpkts; | ||||
sc->ndis_link = 0; | sc->ndis_link = 0; | ||||
if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN); | if (!sc->ndis_80211) { | ||||
if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN); | |||||
sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; | |||||
sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | |||||
} | |||||
ifp->if_drv_flags |= IFF_DRV_RUNNING; | |||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | |||||
sc->ndis_tx_timer = 0; | sc->ndis_tx_timer = 0; | ||||
/* | /* | ||||
Context not available. | |||||
sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs; | sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs; | ||||
callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc); | callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc); | ||||
sc->ndis_running = 1; | |||||
NDIS_UNLOCK(sc); | NDIS_UNLOCK(sc); | ||||
/* XXX force handling */ | /* XXX force handling */ | ||||
if (sc->ndis_80211) | if (sc->ndis_80211) | ||||
ieee80211_start_all(ic); /* start all vap's */ | ieee80211_start_all(&sc->ndis_ic); /* start all vap's */ | ||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
} | } | ||||
static int | static int | ||||
ndis_set_cipher(sc, cipher) | ndis_set_cipher(struct ndis_softc *sc, int cipher) | ||||
struct ndis_softc *sc; | |||||
int cipher; | |||||
{ | { | ||||
struct ieee80211com *ic; | struct ieee80211com *ic = &sc->ndis_ic; | ||||
int rval = 0, len; | int rval = 0, len; | ||||
uint32_t arg, save; | uint32_t arg, save; | ||||
ic = sc->ifp->if_l2com; | |||||
len = sizeof(arg); | len = sizeof(arg); | ||||
if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) { | if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) { | ||||
Context not available. | |||||
ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr) | ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr) | ||||
{ | { | ||||
struct ieee80211vap *vap = ifp->if_softc; | struct ieee80211vap *vap = ifp->if_softc; | ||||
struct ndis_softc *sc = vap->iv_ic->ic_ifp->if_softc; | struct ndis_softc *sc = vap->iv_ic->ic_softc; | ||||
uint32_t txrate; | uint32_t txrate; | ||||
int len; | int len; | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
ndis_setstate_80211(sc) | ndis_setstate_80211(struct ndis_softc *sc) | ||||
struct ndis_softc *sc; | |||||
{ | { | ||||
struct ieee80211com *ic; | struct ieee80211com *ic = &sc->ndis_ic; | ||||
struct ieee80211vap *vap; | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
ndis_80211_macaddr bssid; | ndis_80211_macaddr bssid; | ||||
ndis_80211_config config; | ndis_80211_config config; | ||||
int rval = 0, len; | int rval = 0, len; | ||||
uint32_t arg; | uint32_t arg; | ||||
struct ifnet *ifp; | |||||
ifp = sc->ifp; | |||||
ic = ifp->if_l2com; | |||||
vap = TAILQ_FIRST(&ic->ic_vaps); | |||||
if (!NDIS_INITIALIZED(sc)) { | if (!NDIS_INITIALIZED(sc)) { | ||||
DPRINTF(("%s: NDIS not initialized\n", __func__)); | DPRINTF(("%s: NDIS not initialized\n", __func__)); | ||||
return; | return; | ||||
Context not available. | |||||
/* Set the BSSID to our value so the driver doesn't associate */ | /* Set the BSSID to our value so the driver doesn't associate */ | ||||
len = IEEE80211_ADDR_LEN; | len = IEEE80211_ADDR_LEN; | ||||
bcopy(IF_LLADDR(ifp), bssid, len); | bcopy(vap->iv_myaddr, bssid, len); | ||||
DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":")); | DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":")); | ||||
rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len); | rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len); | ||||
if (rval) | if (rval) | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
ndis_auth_and_assoc(sc, vap) | ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap) | ||||
struct ndis_softc *sc; | |||||
struct ieee80211vap *vap; | |||||
{ | { | ||||
struct ieee80211com *ic; | struct ieee80211_node *ni = vap->iv_bss; | ||||
struct ieee80211_node *ni; | |||||
ndis_80211_ssid ssid; | ndis_80211_ssid ssid; | ||||
ndis_80211_macaddr bssid; | ndis_80211_macaddr bssid; | ||||
ndis_80211_wep wep; | ndis_80211_wep wep; | ||||
int i, rval = 0, len, error; | int i, rval = 0, len, error; | ||||
uint32_t arg; | uint32_t arg; | ||||
struct ifnet *ifp; | |||||
ifp = sc->ifp; | |||||
ic = ifp->if_l2com; | |||||
ni = vap->iv_bss; | |||||
if (!NDIS_INITIALIZED(sc)) { | if (!NDIS_INITIALIZED(sc)) { | ||||
DPRINTF(("%s: NDIS not initialized\n", __func__)); | DPRINTF(("%s: NDIS not initialized\n", __func__)); | ||||
return; | return; | ||||
Context not available. | |||||
vap->iv_opmode != IEEE80211_M_IBSS) | vap->iv_opmode != IEEE80211_M_IBSS) | ||||
bcopy(ni->ni_bssid, bssid, len); | bcopy(ni->ni_bssid, bssid, len); | ||||
else | else | ||||
bcopy(ifp->if_broadcastaddr, bssid, len); | bcopy(ieee80211broadcastaddr, bssid, len); | ||||
DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":")); | DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":")); | ||||
rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len); | rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len); | ||||
Context not available. | |||||
} | } | ||||
static int | static int | ||||
ndis_get_assoc(sc, assoc) | ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc) | ||||
struct ndis_softc *sc; | |||||
ndis_wlan_bssid_ex **assoc; | |||||
{ | { | ||||
struct ifnet *ifp = sc->ifp; | struct ieee80211com *ic = &sc->ndis_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ieee80211vap *vap; | struct ieee80211vap *vap; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
ndis_80211_bssid_list_ex *bl; | ndis_80211_bssid_list_ex *bl; | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
ndis_getstate_80211(sc) | ndis_getstate_80211(struct ndis_softc *sc) | ||||
struct ndis_softc *sc; | |||||
{ | { | ||||
struct ieee80211com *ic; | struct ieee80211com *ic = &sc->ndis_ic; | ||||
struct ieee80211vap *vap; | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni = vap->iv_bss; | ||||
ndis_wlan_bssid_ex *bs; | ndis_wlan_bssid_ex *bs; | ||||
int rval, len, i = 0; | int rval, len, i = 0; | ||||
int chanflag; | int chanflag; | ||||
uint32_t arg; | uint32_t arg; | ||||
struct ifnet *ifp; | |||||
ifp = sc->ifp; | |||||
ic = ifp->if_l2com; | |||||
vap = TAILQ_FIRST(&ic->ic_vaps); | |||||
ni = vap->iv_bss; | |||||
if (!NDIS_INITIALIZED(sc)) | if (!NDIS_INITIALIZED(sc)) | ||||
return; | return; | ||||
Context not available. | |||||
switch (command) { | switch (command) { | ||||
case SIOCSIFFLAGS: | case SIOCSIFFLAGS: | ||||
if (ifp->if_flags & IFF_UP) { | if (ifp->if_flags & IFF_UP) { | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING && | if (sc->ndis_running && | ||||
ifp->if_flags & IFF_PROMISC && | ifp->if_flags & IFF_PROMISC && | ||||
!(sc->ndis_if_flags & IFF_PROMISC)) { | !(sc->ndis_if_flags & IFF_PROMISC)) { | ||||
sc->ndis_filter |= | sc->ndis_filter |= | ||||
Context not available. | |||||
error = ndis_set_info(sc, | error = ndis_set_info(sc, | ||||
OID_GEN_CURRENT_PACKET_FILTER, | OID_GEN_CURRENT_PACKET_FILTER, | ||||
&sc->ndis_filter, &i); | &sc->ndis_filter, &i); | ||||
} else if (ifp->if_drv_flags & IFF_DRV_RUNNING && | } else if (sc->ndis_running && | ||||
!(ifp->if_flags & IFF_PROMISC) && | !(ifp->if_flags & IFF_PROMISC) && | ||||
sc->ndis_if_flags & IFF_PROMISC) { | sc->ndis_if_flags & IFF_PROMISC) { | ||||
sc->ndis_filter &= | sc->ndis_filter &= | ||||
Context not available. | |||||
} else | } else | ||||
ndis_init(sc); | ndis_init(sc); | ||||
} else { | } else { | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (sc->ndis_running) | ||||
ndis_stop(sc); | ndis_stop(sc); | ||||
} | } | ||||
sc->ndis_if_flags = ifp->if_flags; | sc->ndis_if_flags = ifp->if_flags; | ||||
Context not available. | |||||
} | } | ||||
static int | static int | ||||
ndis_ioctl_80211(ifp, command, data) | ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data) | ||||
struct ifnet *ifp; | |||||
u_long command; | |||||
caddr_t data; | |||||
{ | { | ||||
struct ndis_softc *sc = ifp->if_softc; | struct ndis_softc *sc = ic->ic_softc; | ||||
struct ieee80211com *ic = ifp->if_l2com; | struct ifreq *ifr = data; | ||||
struct ifreq *ifr = (struct ifreq *) data; | struct ndis_oid_data oid; | ||||
struct ndis_oid_data oid; | struct ndis_evt evt; | ||||
struct ndis_evt evt; | void *oidbuf = NULL; | ||||
void *oidbuf; | int error = 0; | ||||
int error = 0; | |||||
switch (command) { | if ((error = priv_check(curthread, PRIV_DRIVER)) != 0) | ||||
case SIOCSIFFLAGS: | return (error); | ||||
/*NDIS_LOCK(sc);*/ | |||||
if (ifp->if_flags & IFF_UP) { | switch (cmd) { | ||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) | |||||
ndis_init(sc); | |||||
} else { | |||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | |||||
ndis_stop(sc); | |||||
} | |||||
sc->ndis_if_flags = ifp->if_flags; | |||||
error = 0; | |||||
/*NDIS_UNLOCK(sc);*/ | |||||
break; | |||||
case SIOCGDRVSPEC: | case SIOCGDRVSPEC: | ||||
if ((error = priv_check(curthread, PRIV_DRIVER))) | case SIOCSDRVSPEC: | ||||
break; | error = copyin(ifr->ifr_data, &oid, sizeof(oid)); | ||||
error = copyin(ifr->ifr_data, &oid, sizeof(oid)); | |||||
if (error) | if (error) | ||||
break; | break; | ||||
oidbuf = malloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO); | oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO); | ||||
if (oidbuf == NULL) { | error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len); | ||||
error = ENOMEM; | } | ||||
break; | |||||
} | if (error) { | ||||
error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len); | free(oidbuf, M_TEMP); | ||||
if (error) { | return (error); | ||||
free(oidbuf, M_TEMP); | } | ||||
break; | |||||
} | switch (cmd) { | ||||
case SIOCGDRVSPEC: | |||||
error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len); | error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len); | ||||
if (error) { | |||||
free(oidbuf, M_TEMP); | |||||
break; | |||||
} | |||||
error = copyout(&oid, ifr->ifr_data, sizeof(oid)); | |||||
if (error) { | |||||
free(oidbuf, M_TEMP); | |||||
break; | |||||
} | |||||
error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len); | |||||
free(oidbuf, M_TEMP); | |||||
break; | break; | ||||
case SIOCSDRVSPEC: | case SIOCSDRVSPEC: | ||||
if ((error = priv_check(curthread, PRIV_DRIVER))) | |||||
break; | |||||
error = copyin(ifr->ifr_data, &oid, sizeof(oid)); | |||||
if (error) | |||||
break; | |||||
oidbuf = malloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO); | |||||
if (oidbuf == NULL) { | |||||
error = ENOMEM; | |||||
break; | |||||
} | |||||
error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len); | |||||
if (error) { | |||||
free(oidbuf, M_TEMP); | |||||
break; | |||||
} | |||||
error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len); | error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len); | ||||
if (error) { | |||||
free(oidbuf, M_TEMP); | |||||
break; | |||||
} | |||||
error = copyout(&oid, ifr->ifr_data, sizeof(oid)); | |||||
if (error) { | |||||
free(oidbuf, M_TEMP); | |||||
break; | |||||
} | |||||
error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len); | |||||
free(oidbuf, M_TEMP); | |||||
break; | break; | ||||
case SIOCGPRIVATE_0: | case SIOCGPRIVATE_0: | ||||
if ((error = priv_check(curthread, PRIV_DRIVER))) | |||||
break; | |||||
NDIS_LOCK(sc); | NDIS_LOCK(sc); | ||||
if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) { | if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) { | ||||
error = ENOENT; | error = ENOENT; | ||||
Context not available. | |||||
NDIS_UNLOCK(sc); | NDIS_UNLOCK(sc); | ||||
break; | break; | ||||
} | } | ||||
error = copyin(ifr->ifr_data, &evt, sizeof(evt)); | error = copyin(ifr->ifr_data, &evt, sizeof(evt)); | ||||
if (error) { | if (error) { | ||||
NDIS_UNLOCK(sc); | NDIS_UNLOCK(sc); | ||||
break; | break; | ||||
Context not available. | |||||
NDIS_EVTINC(sc->ndis_evtcidx); | NDIS_EVTINC(sc->ndis_evtcidx); | ||||
NDIS_UNLOCK(sc); | NDIS_UNLOCK(sc); | ||||
break; | break; | ||||
case SIOCGIFMEDIA: | |||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command); | |||||
break; | |||||
case SIOCGIFADDR: | |||||
error = ether_ioctl(ifp, command, data); | |||||
break; | |||||
default: | default: | ||||
error = EINVAL; | error = ENOTTY; | ||||
break; | break; | ||||
} | } | ||||
switch (cmd) { | |||||
case SIOCGDRVSPEC: | |||||
case SIOCSDRVSPEC: | |||||
error = copyout(&oid, ifr->ifr_data, sizeof(oid)); | |||||
if (error) | |||||
break; | |||||
error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len); | |||||
} | |||||
free(oidbuf, M_TEMP); | |||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
ndis_del_key(vap, key) | ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key) | ||||
struct ieee80211vap *vap; | |||||
const struct ieee80211_key *key; | |||||
{ | { | ||||
struct ndis_softc *sc; | struct ndis_softc *sc = vap->iv_ic->ic_softc; | ||||
ndis_80211_key rkey; | ndis_80211_key rkey; | ||||
int len, error = 0; | int len, error = 0; | ||||
sc = vap->iv_ic->ic_ifp->if_softc; | |||||
bzero((char *)&rkey, sizeof(rkey)); | bzero((char *)&rkey, sizeof(rkey)); | ||||
len = sizeof(rkey); | len = sizeof(rkey); | ||||
Context not available. | |||||
* set after initial authentication with the AP. | * set after initial authentication with the AP. | ||||
*/ | */ | ||||
static int | static int | ||||
ndis_add_key(vap, key, mac) | ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key, | ||||
struct ieee80211vap *vap; | const uint8_t mac[IEEE80211_ADDR_LEN]) | ||||
const struct ieee80211_key *key; | |||||
const uint8_t mac[IEEE80211_ADDR_LEN]; | |||||
{ | { | ||||
struct ndis_softc *sc; | struct ndis_softc *sc = vap->iv_ic->ic_softc; | ||||
struct ifnet *ifp; | |||||
ndis_80211_key rkey; | ndis_80211_key rkey; | ||||
int len, error = 0; | int len, error = 0; | ||||
ifp = vap->iv_ic->ic_ifp; | |||||
sc = ifp->if_softc; | |||||
switch (key->wk_cipher->ic_cipher) { | switch (key->wk_cipher->ic_cipher) { | ||||
case IEEE80211_CIPHER_TKIP: | case IEEE80211_CIPHER_TKIP: | ||||
Context not available. | |||||
rkey.nk_keyidx |= 1 << 31; | rkey.nk_keyidx |= 1 << 31; | ||||
if (key->wk_flags & IEEE80211_KEY_GROUP) { | if (key->wk_flags & IEEE80211_KEY_GROUP) { | ||||
bcopy(ifp->if_broadcastaddr, | bcopy(ieee80211broadcastaddr, | ||||
rkey.nk_bssid, IEEE80211_ADDR_LEN); | rkey.nk_bssid, IEEE80211_ADDR_LEN); | ||||
} else { | } else { | ||||
bcopy(vap->iv_bss->ni_bssid, | bcopy(vap->iv_bss->ni_bssid, | ||||
Context not available. | |||||
* RX and TX lists. | * RX and TX lists. | ||||
*/ | */ | ||||
static void | static void | ||||
ndis_stop(sc) | ndis_stop(struct ndis_softc *sc) | ||||
struct ndis_softc *sc; | |||||
{ | { | ||||
struct ifnet *ifp; | |||||
int i; | int i; | ||||
ifp = sc->ifp; | |||||
callout_drain(&sc->ndis_stat_callout); | callout_drain(&sc->ndis_stat_callout); | ||||
NDIS_LOCK(sc); | NDIS_LOCK(sc); | ||||
sc->ndis_tx_timer = 0; | sc->ndis_tx_timer = 0; | ||||
sc->ndis_link = 0; | sc->ndis_link = 0; | ||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); | if (!sc->ndis_80211) | ||||
sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); | |||||
sc->ndis_running = 0; | |||||
NDIS_UNLOCK(sc); | NDIS_UNLOCK(sc); | ||||
if (sc->ndis_iftype != PNPBus || | if (sc->ndis_iftype != PNPBus || | ||||
Context not available. | |||||
{ | { | ||||
struct ndis_vap *nvp = NDIS_VAP(vap); | struct ndis_vap *nvp = NDIS_VAP(vap); | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct ifnet *ifp = ic->ic_ifp; | struct ndis_softc *sc = ic->ic_softc; | ||||
struct ndis_softc *sc = ifp->if_softc; | |||||
enum ieee80211_state ostate; | enum ieee80211_state ostate; | ||||
DPRINTF(("%s: %s -> %s\n", __func__, | DPRINTF(("%s: %s -> %s\n", __func__, | ||||
Context not available. | |||||
static void | static void | ||||
ndis_scan_results(struct ndis_softc *sc) | ndis_scan_results(struct ndis_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic; | struct ieee80211com *ic = &sc->ndis_ic; | ||||
struct ieee80211vap *vap; | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
ndis_80211_bssid_list_ex *bl; | ndis_80211_bssid_list_ex *bl; | ||||
ndis_wlan_bssid_ex *wb; | ndis_wlan_bssid_ex *wb; | ||||
struct ieee80211_scanparams sp; | struct ieee80211_scanparams sp; | ||||
Context not available. | |||||
uint8_t rates[2+IEEE80211_RATE_MAXSIZE]; | uint8_t rates[2+IEEE80211_RATE_MAXSIZE]; | ||||
uint8_t *frm, *efrm; | uint8_t *frm, *efrm; | ||||
ic = sc->ifp->if_l2com; | |||||
vap = TAILQ_FIRST(&ic->ic_vaps); | |||||
saved_chan = ic->ic_curchan; | saved_chan = ic->ic_curchan; | ||||
noise = -96; | noise = -96; | ||||
Context not available. | |||||
static void | static void | ||||
ndis_scan_start(struct ieee80211com *ic) | ndis_scan_start(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ifnet *ifp = ic->ic_ifp; | struct ndis_softc *sc = ic->ic_softc; | ||||
struct ndis_softc *sc = ifp->if_softc; | |||||
struct ieee80211vap *vap; | struct ieee80211vap *vap; | ||||
struct ieee80211_scan_state *ss; | struct ieee80211_scan_state *ss; | ||||
ndis_80211_ssid ssid; | ndis_80211_ssid ssid; | ||||
Context not available. | |||||
static void | static void | ||||
ndis_scan_end(struct ieee80211com *ic) | ndis_scan_end(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ndis_softc *sc = ic->ic_ifp->if_softc; | struct ndis_softc *sc = ic->ic_softc; | ||||
ndis_scan_results(sc); | ndis_scan_results(sc); | ||||
} | } | ||||
Context not available. |