diff options
Diffstat (limited to 'sys/dev/if_ndis/if_ndis.c')
-rw-r--r-- | sys/dev/if_ndis/if_ndis.c | 998 |
1 files changed, 508 insertions, 490 deletions
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index 9c57aed..c30f31c 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include <sys/proc.h> #include <sys/sysctl.h> #include <sys/kthread.h> +#include <sys/limits.h> #include <net/if.h> #include <net/if_var.h> @@ -166,7 +167,6 @@ static void ndis_starttask (device_object *, void *); static void ndis_resettask (device_object *, void *); static void ndis_inputtask (device_object *, void *); 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, int); static int ndis_nettype_chan (uint32_t); @@ -197,10 +197,15 @@ static int ndis_add_key (struct ieee80211vap *, const struct ieee80211_key *, const u_int8_t []); static int ndis_del_key (struct ieee80211vap *, const struct ieee80211_key *); - static void ndis_setmulti (struct ndis_softc *); static void ndis_map_sclist (void *, bus_dma_segment_t *, 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; @@ -536,16 +541,12 @@ ndis_nettype_mode(uint32_t type) * setup and ethernet/BPF attach. */ int -ndis_attach(dev) - device_t dev; +ndis_attach(device_t dev) { - u_char eaddr[ETHER_ADDR_LEN]; struct ndis_softc *sc; driver_object *pdrv; device_object *pdo; - struct ifnet *ifp = NULL; - int error = 0, len, mode; - uint8_t bands = 0; + int error = 0, len; int i; sc = device_get_softc(dev); @@ -559,6 +560,7 @@ ndis_attach(dev) InitializeListHead(&sc->ndisusb_tasklist); InitializeListHead(&sc->ndisusb_xferdonelist); callout_init(&sc->ndis_stat_callout, 1); + mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */ if (sc->ndis_iftype == PCMCIABus) { error = ndis_alloc_amem(sc); @@ -635,15 +637,8 @@ ndis_attach(dev) } /* - * 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. */ - len = sizeof(sc->ndis_maxpkts); if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS, &sc->ndis_maxpkts, &len)) { @@ -696,95 +691,89 @@ ndis_attach(dev) */ for (i = 0; i < sc->ndis_oidcnt; i++) if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) { - sc->ndis_80211++; + sc->ndis_80211 = 1; break; } if (sc->ndis_80211) - ifp = if_alloc(IFT_IEEE80211); + error = ndis_80211attach(sc); else - ifp = if_alloc(IFT_ETHER); - if (ifp == NULL) { - error = ENOSPC; - goto fail; + error = ndis_ifattach(sc); + +fail: + if (error) { + ndis_detach(dev); + return (error); } - sc->ifp = ifp; - ifp->if_softc = sc; - /* Check for task offload support. */ - ndis_probe_offload(sc); + if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0) + return (error); - if_initname(ifp, device_get_name(dev), device_get_unit(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; + DPRINTF(("attach done.\n")); + /* We're done talking to the NIC for now; halt it. */ + ndis_halt_nic(sc); + DPRINTF(("halting done.\n")); - /* Do media setup */ - 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); - - ifp->if_ioctl = ndis_ioctl_80211; - 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; - } + return (error); +} - 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(dev, "Unknown nettype %d\n", - ntl->ntl_type[i]); - } +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; + + callout_init(&sc->ndis_scan_callout, 1); + + ic->ic_softc = sc; + ic->ic_ioctl = ndis_80211ioctl; + ic->ic_name = device_get_nameunit(sc->ndis_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_WAITOK | 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++) { + 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: - /* Default to 11b channels if the card did not supply any */ - if (bands == 0) { - setbit(ic->ic_modecaps, IEEE80211_MODE_11B); - setbit(&bands, IEEE80211_MODE_11B); - } - len = sizeof(rates); - bzero((char *)&rates, len); - r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, - (void *)rates, &len); - if (r) - device_printf(dev, "get rates failed: 0x%x\n", r); - /* - * 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 - * all up to heck. - */ + /* Default to 11b channels if the card did not supply any */ + if (bands == 0) { + setbit(ic->ic_modecaps, IEEE80211_MODE_11B); + setbit(&bands, IEEE80211_MODE_11B); + } + len = sizeof(rates); + bzero((char *)&rates, len); + r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len); + if (r != 0) + device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r); + /* + * 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 + * all up to heck. + */ #define TESTSETRATE(x, y) \ do { \ @@ -804,174 +793,198 @@ nonettypes: #define INCRATE(x) \ ic->ic_sup_rates[x].rs_nrates++ - ic->ic_curmode = IEEE80211_MODE_AUTO; - if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) - ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0; - if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) - ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0; - if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) - ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0; - for (i = 0; i < len; i++) { - switch (rates[i] & IEEE80211_RATE_VAL) { - case 2: - case 4: - case 11: - case 10: - case 22: - if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) { - /* Lazy-init 802.11b. */ - setbit(ic->ic_modecaps, - IEEE80211_MODE_11B); - ic->ic_sup_rates[IEEE80211_MODE_11B]. - 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; + ic->ic_curmode = IEEE80211_MODE_AUTO; + if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) + ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0; + if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) + ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0; + if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) + ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0; + for (i = 0; i < len; i++) { + switch (rates[i] & IEEE80211_RATE_VAL) { + case 2: + case 4: + case 11: + case 10: + case 22: + if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) { + /* Lazy-init 802.11b. */ + setbit(ic->ic_modecaps, IEEE80211_MODE_11B); + ic->ic_sup_rates[IEEE80211_MODE_11B]. + 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; } + } + + /* + * If the hardware supports 802.11g, it most + * likely supports 802.11b and all of the + * 802.11b and 802.11g speeds, so maybe we can + * just cheat here. Just how in the heck do + * we detect turbo modes, though? + */ + if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) { + TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2); + TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4); + TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11); + TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22); + } + if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { + TESTSETRATE(IEEE80211_MODE_11G, 48); + TESTSETRATE(IEEE80211_MODE_11G, 72); + TESTSETRATE(IEEE80211_MODE_11G, 96); + TESTSETRATE(IEEE80211_MODE_11G, 108); + } + if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { + TESTSETRATE(IEEE80211_MODE_11A, 48); + TESTSETRATE(IEEE80211_MODE_11A, 72); + TESTSETRATE(IEEE80211_MODE_11A, 96); + TESTSETRATE(IEEE80211_MODE_11A, 108); + } - /* - * If the hardware supports 802.11g, it most - * likely supports 802.11b and all of the - * 802.11b and 802.11g speeds, so maybe we can - * just cheat here. Just how in the heck do - * we detect turbo modes, though? - */ - if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) { - TESTSETRATE(IEEE80211_MODE_11B, - IEEE80211_RATE_BASIC|2); - TESTSETRATE(IEEE80211_MODE_11B, - IEEE80211_RATE_BASIC|4); - TESTSETRATE(IEEE80211_MODE_11B, - IEEE80211_RATE_BASIC|11); - TESTSETRATE(IEEE80211_MODE_11B, - IEEE80211_RATE_BASIC|22); - } - if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) { - TESTSETRATE(IEEE80211_MODE_11G, 48); - TESTSETRATE(IEEE80211_MODE_11G, 72); - TESTSETRATE(IEEE80211_MODE_11G, 96); - TESTSETRATE(IEEE80211_MODE_11G, 108); - } - if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) { - TESTSETRATE(IEEE80211_MODE_11A, 48); - TESTSETRATE(IEEE80211_MODE_11A, 72); - TESTSETRATE(IEEE80211_MODE_11A, 96); - TESTSETRATE(IEEE80211_MODE_11A, 108); - } #undef SETRATE #undef INCRATE - ieee80211_init_channels(ic, NULL, &bands); +#undef TESTSETRATE - /* - * 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; - } + ieee80211_init_channels(ic, NULL, &bands); - /* - * To test for supported ciphers, we set each - * available encryption type in descending order. - * If ENC3 works, then we have WEP, TKIP and AES. - * 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_WEPSTAT_ENC3ENABLED; - r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); - if (r == 0) { - 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; + /* + * 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 + * available encryption type in descending order. + * If ENC3 works, then we have WEP, TKIP and AES. + * 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_WEPSTAT_ENC3ENABLED; + r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i); + if (r == 0) { + 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: - i = sizeof(arg); - r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i); - if (r == 0) - ic->ic_caps |= IEEE80211_C_PMGT; - - r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i); - if (r == 0) - ic->ic_caps |= IEEE80211_C_TXPMGT; - - ieee80211_ifattach(ic, eaddr); - 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_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_announce(ic); + i = sizeof(arg); + r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i); + if (r == 0) + ic->ic_caps |= IEEE80211_C_PMGT; - } else { - 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); - } + r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i); + if (r == 0) + ic->ic_caps |= IEEE80211_C_TXPMGT; -fail: - if (error) { - ndis_detach(dev); - return (error); - } + /* + * Get station address from the driver. + */ + len = sizeof(ic->ic_macaddr); + ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len); + + ieee80211_ifattach(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; + + if (bootverbose) + ieee80211_announce(ic); - if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0) - return (error); + return (0); +} - DPRINTF(("attach done.\n")); - /* We're done talking to the NIC for now; halt it. */ - ndis_halt_nic(sc); - DPRINTF(("halting done.\n")); +static int +ndis_ifattach(struct ndis_softc *sc) +{ + struct ifnet *ifp; + u_char eaddr[ETHER_ADDR_LEN]; + int len; - return (error); + ifp = if_alloc(IFT_ETHER); + if (ifp == NULL) + return (ENOSPC); + sc->ifp = ifp; + ifp->if_softc = sc; + + /* 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 * @@ -985,18 +998,16 @@ ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return NULL; - nvp = (struct ndis_vap *) malloc(sizeof(struct ndis_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (nvp == NULL) - return NULL; + nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO); 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 */ nvp->newstate = vap->iv_newstate; vap->iv_newstate = ndis_newstate; /* 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; /* install key handing routines */ vap->iv_key_set = ndis_add_key; @@ -1009,8 +1020,7 @@ ndis_vap_delete(struct ieee80211vap *vap) { struct ndis_vap *nvp = NDIS_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct ndis_softc *sc = ifp->if_softc; + struct ndis_softc *sc = ic->ic_softc; ndis_stop(sc); callout_drain(&sc->ndis_scan_callout); @@ -1026,28 +1036,27 @@ ndis_vap_delete(struct ieee80211vap *vap) * allocated. */ int -ndis_detach(dev) - device_t dev; +ndis_detach(device_t dev) { - struct ndis_softc *sc; struct ifnet *ifp; + struct ndis_softc *sc; driver_object *drv; sc = device_get_softc(dev); NDIS_LOCK(sc); - ifp = sc->ifp; + if (!sc->ndis_80211) + ifp = sc->ifp; + else + ifp = NULL; if (ifp != NULL) ifp->if_flags &= ~IFF_UP; - if (device_is_attached(dev)) { NDIS_UNLOCK(sc); ndis_stop(sc); - if (ifp != NULL) { - if (sc->ndis_80211) - ieee80211_ifdetach(ifp->if_l2com); - else - ether_ifdetach(ifp); - } + if (sc->ndis_80211) + ieee80211_ifdetach(&sc->ndis_ic); + else if (ifp != NULL) + ether_ifdetach(ifp); } else NDIS_UNLOCK(sc); @@ -1302,11 +1311,11 @@ ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2) IoFreeMdl(p->np_private.npp_head); NdisFreePacket(p); KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); - _IF_ENQUEUE(&sc->ndis_rxqueue, m); + mbufq_enqueue(&sc->ndis_rxqueue, m); KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); IoQueueWorkItem(sc->ndis_inputitem, (io_workitem_func)ndis_inputtask_wrap, - WORKQUEUE_CRITICAL, ifp); + WORKQUEUE_CRITICAL, sc); } if (status == NDIS_STATUS_FAILURE) @@ -1350,11 +1359,11 @@ ndis_rxeof_xfr_done(adapter, packet, status, len) m->m_len = m->m_pkthdr.len; m->m_pkthdr.rcvif = ifp; KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); - _IF_ENQUEUE(&sc->ndis_rxqueue, m); + mbufq_enqueue(&sc->ndis_rxqueue, m); KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); IoQueueWorkItem(sc->ndis_inputitem, (io_workitem_func)ndis_inputtask_wrap, - WORKQUEUE_CRITICAL, ifp); + WORKQUEUE_CRITICAL, sc); } /* * A frame has been uploaded: pass the resulting mbuf chain up to @@ -1399,7 +1408,7 @@ ndis_rxeof(adapter, packets, pktcnt) * before we're completely ready to handle them. If we detect this, * 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++) { p = packets[i]; if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) { @@ -1473,11 +1482,11 @@ ndis_rxeof(adapter, packets, pktcnt) } KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock); - _IF_ENQUEUE(&sc->ndis_rxqueue, m0); + mbufq_enqueue(&sc->ndis_rxqueue, m0); KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock); IoQueueWorkItem(sc->ndis_inputitem, (io_workitem_func)ndis_inputtask_wrap, - WORKQUEUE_CRITICAL, ifp); + WORKQUEUE_CRITICAL, sc); } } } @@ -1489,34 +1498,29 @@ ndis_rxeof(adapter, packets, pktcnt) * 'dispatch level' per-cpu sleep lock). */ static void -ndis_inputtask(dobj, arg) - device_object *dobj; - void *arg; +ndis_inputtask(device_object *dobj, void *arg) { ndis_miniport_block *block; - struct ifnet *ifp; - struct ndis_softc *sc; + struct ndis_softc *sc = arg; struct mbuf *m; - struct ieee80211com *ic; - struct ieee80211vap *vap; uint8_t irql; - ifp = arg; - sc = ifp->if_softc; - ic = ifp->if_l2com; - vap = TAILQ_FIRST(&ic->ic_vaps); block = dobj->do_devext; KeAcquireSpinLock(&sc->ndis_rxlock, &irql); - while(1) { - _IF_DEQUEUE(&sc->ndis_rxqueue, m); - if (m == NULL) - break; + while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) { KeReleaseSpinLock(&sc->ndis_rxlock, irql); - if ((sc->ndis_80211 != 0) && (vap != NULL)) - vap->iv_deliver_data(vap, vap->iv_bss, m); - else + if ((sc->ndis_80211 != 0)) { + struct ieee80211com *ic = &sc->ndis_ic; + 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); + } KeAcquireSpinLock(&sc->ndis_rxlock, &irql); } KeReleaseSpinLock(&sc->ndis_rxlock, irql); @@ -1676,20 +1680,12 @@ ndis_tick(xsc) } static void -ndis_ticktask(d, xsc) - device_object *d; - void *xsc; +ndis_ticktask(device_object *d, void *xsc) { - struct ndis_softc *sc; - struct ieee80211com *ic; - struct ieee80211vap *vap; + struct ndis_softc *sc = xsc; ndis_checkforhang_handler hangfunc; uint8_t rval; - sc = xsc; - ic = sc->ifp->if_l2com; - vap = TAILQ_FIRST(&ic->ic_vaps); - NDIS_LOCK(sc); if (!NDIS_INITIALIZED(sc)) { NDIS_UNLOCK(sc); @@ -1712,12 +1708,18 @@ ndis_ticktask(d, xsc) if (sc->ndis_link == 0 && sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) { sc->ndis_link = 1; - if ((sc->ndis_80211 != 0) && (vap != NULL)) { - 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); + if (sc->ndis_80211 != 0) { + struct ieee80211com *ic = &sc->ndis_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + + if (vap != NULL) { + 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 if_link_state_change(sc->ifp, LINK_STATE_UP); } @@ -1725,11 +1727,17 @@ ndis_ticktask(d, xsc) if (sc->ndis_link == 1 && sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) { sc->ndis_link = 0; - if ((sc->ndis_80211 != 0) && (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); + if (sc->ndis_80211 != 0) { + struct ieee80211com *ic = &sc->ndis_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + + 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 if_link_state_change(sc->ifp, LINK_STATE_DOWN); } @@ -1939,13 +1947,103 @@ ndis_start(ifp) 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 -ndis_init(xsc) - void *xsc; +ndis_80211parent(struct ieee80211com *ic) +{ + 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 ifnet *ifp = sc->ifp; - struct ieee80211com *ic = ifp->if_l2com; int i, len, error; /* @@ -1971,17 +2069,21 @@ ndis_init(xsc) } } - /* Init our MAC address */ - /* 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) - sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST; + if (ic->ic_promisc > 0) + sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; + } else { + struct ifnet *ifp = sc->ifp; - if (ifp->if_flags & IFF_PROMISC) - sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; + if (ifp->if_flags & IFF_PROMISC) + sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; + } len = sizeof(sc->ndis_filter); @@ -1994,7 +2096,10 @@ ndis_init(xsc) /* * Set lookahead. */ - i = ifp->if_mtu; + if (sc->ndis_80211) + i = ETHERMTU; + else + i = sc->ifp->if_mtu; len = sizeof(i); ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len); @@ -2012,10 +2117,12 @@ ndis_init(xsc) sc->ndis_txpending = sc->ndis_maxpkts; 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; /* @@ -2029,11 +2136,12 @@ ndis_init(xsc) sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs; callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc); + sc->ndis_running = 1; NDIS_UNLOCK(sc); /* XXX force handling */ if (sc->ndis_80211) - ieee80211_start_all(ic); /* start all vap's */ + ieee80211_start_all(&sc->ndis_ic); /* start all vap's */ } /* @@ -2101,16 +2209,12 @@ ndis_ifmedia_sts(ifp, ifmr) } static int -ndis_set_cipher(sc, cipher) - struct ndis_softc *sc; - int cipher; +ndis_set_cipher(struct ndis_softc *sc, int cipher) { - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->ndis_ic; int rval = 0, len; uint32_t arg, save; - ic = sc->ifp->if_l2com; - len = sizeof(arg); if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) { @@ -2239,7 +2343,7 @@ static void ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr) { 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; int len; @@ -2253,20 +2357,14 @@ ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr) } static void -ndis_setstate_80211(sc) - struct ndis_softc *sc; +ndis_setstate_80211(struct ndis_softc *sc) { - struct ieee80211com *ic; - struct ieee80211vap *vap; + struct ieee80211com *ic = &sc->ndis_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); ndis_80211_macaddr bssid; ndis_80211_config config; int rval = 0, len; uint32_t arg; - struct ifnet *ifp; - - ifp = sc->ifp; - ic = ifp->if_l2com; - vap = TAILQ_FIRST(&ic->ic_vaps); if (!NDIS_INITIALIZED(sc)) { DPRINTF(("%s: NDIS not initialized\n", __func__)); @@ -2371,7 +2469,7 @@ ndis_setstate_80211(sc) /* Set the BSSID to our value so the driver doesn't associate */ 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, ":")); rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len); if (rval) @@ -2380,22 +2478,14 @@ ndis_setstate_80211(sc) } static void -ndis_auth_and_assoc(sc, vap) - struct ndis_softc *sc; - struct ieee80211vap *vap; +ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap) { - struct ieee80211com *ic; - struct ieee80211_node *ni; + struct ieee80211_node *ni = vap->iv_bss; ndis_80211_ssid ssid; ndis_80211_macaddr bssid; ndis_80211_wep wep; int i, rval = 0, len, error; uint32_t arg; - struct ifnet *ifp; - - ifp = sc->ifp; - ic = ifp->if_l2com; - ni = vap->iv_bss; if (!NDIS_INITIALIZED(sc)) { DPRINTF(("%s: NDIS not initialized\n", __func__)); @@ -2562,7 +2652,7 @@ ndis_auth_and_assoc(sc, vap) vap->iv_opmode != IEEE80211_M_IBSS) bcopy(ni->ni_bssid, bssid, len); else - bcopy(ifp->if_broadcastaddr, bssid, len); + bcopy(ieee80211broadcastaddr, bssid, len); DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":")); rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len); @@ -2627,12 +2717,9 @@ ndis_get_bssid_list(sc, bl) } static int -ndis_get_assoc(sc, assoc) - struct ndis_softc *sc; - ndis_wlan_bssid_ex **assoc; +ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc) { - struct ifnet *ifp = sc->ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->ndis_ic; struct ieee80211vap *vap; struct ieee80211_node *ni; ndis_80211_bssid_list_ex *bl; @@ -2679,22 +2766,15 @@ ndis_get_assoc(sc, assoc) } static void -ndis_getstate_80211(sc) - struct ndis_softc *sc; +ndis_getstate_80211(struct ndis_softc *sc) { - struct ieee80211com *ic; - struct ieee80211vap *vap; - struct ieee80211_node *ni; + struct ieee80211com *ic = &sc->ndis_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + struct ieee80211_node *ni = vap->iv_bss; ndis_wlan_bssid_ex *bs; int rval, len, i = 0; int chanflag; 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)) return; @@ -2813,7 +2893,7 @@ ndis_ioctl(ifp, command, data) switch (command) { case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING && + if (sc->ndis_running && ifp->if_flags & IFF_PROMISC && !(sc->ndis_if_flags & IFF_PROMISC)) { sc->ndis_filter |= @@ -2822,7 +2902,7 @@ ndis_ioctl(ifp, command, data) error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER, &sc->ndis_filter, &i); - } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && + } else if (sc->ndis_running && !(ifp->if_flags & IFF_PROMISC) && sc->ndis_if_flags & IFF_PROMISC) { sc->ndis_filter &= @@ -2834,7 +2914,7 @@ ndis_ioctl(ifp, command, data) } else ndis_init(sc); } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (sc->ndis_running) ndis_stop(sc); } sc->ndis_if_flags = ifp->if_flags; @@ -2868,101 +2948,48 @@ ndis_ioctl(ifp, command, data) } static int -ndis_ioctl_80211(ifp, command, data) - struct ifnet *ifp; - u_long command; - caddr_t data; +ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data) { - struct ndis_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - struct ndis_oid_data oid; - struct ndis_evt evt; - void *oidbuf; - int error = 0; + struct ndis_softc *sc = ic->ic_softc; + struct ifreq *ifr = data; + struct ndis_oid_data oid; + struct ndis_evt evt; + void *oidbuf = NULL; + int error = 0; + + if ((error = priv_check(curthread, PRIV_DRIVER)) != 0) + return (error); - switch (command) { - case SIOCSIFFLAGS: - /*NDIS_LOCK(sc);*/ - if (ifp->if_flags & IFF_UP) { - 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; + switch (cmd) { case SIOCGDRVSPEC: - if ((error = priv_check(curthread, PRIV_DRIVER))) - break; - error = copyin(ifr->ifr_data, &oid, sizeof(oid)); + case SIOCSDRVSPEC: + 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_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); + oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO); + error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len); + } + + if (error) { free(oidbuf, M_TEMP); + return (error); + } + + switch (cmd) { + case SIOCGDRVSPEC: + error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len); break; 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); - 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; case SIOCGPRIVATE_0: - if ((error = priv_check(curthread, PRIV_DRIVER))) - break; NDIS_LOCK(sc); if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) { error = ENOENT; NDIS_UNLOCK(sc); break; } - error = copyin(ifr->ifr_data, &evt, sizeof(evt)); + error = copyin(ifr->ifr_data, &evt, sizeof(evt)); if (error) { NDIS_UNLOCK(sc); break; @@ -2994,30 +3021,32 @@ ndis_ioctl_80211(ifp, command, data) NDIS_EVTINC(sc->ndis_evtcidx); NDIS_UNLOCK(sc); break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command); - break; - case SIOCGIFADDR: - error = ether_ioctl(ifp, command, data); - break; default: - error = EINVAL; + error = ENOTTY; 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); } int -ndis_del_key(vap, key) - struct ieee80211vap *vap; - const struct ieee80211_key *key; +ndis_del_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; int len, error = 0; - sc = vap->iv_ic->ic_ifp->if_softc; - bzero((char *)&rkey, sizeof(rkey)); len = sizeof(rkey); @@ -3041,19 +3070,13 @@ ndis_del_key(vap, key) * set after initial authentication with the AP. */ static int -ndis_add_key(vap, key, mac) - struct ieee80211vap *vap; - const struct ieee80211_key *key; - const uint8_t mac[IEEE80211_ADDR_LEN]; +ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key, + const uint8_t mac[IEEE80211_ADDR_LEN]) { - struct ndis_softc *sc; - struct ifnet *ifp; + struct ndis_softc *sc = vap->iv_ic->ic_softc; ndis_80211_key rkey; int len, error = 0; - ifp = vap->iv_ic->ic_ifp; - sc = ifp->if_softc; - switch (key->wk_cipher->ic_cipher) { case IEEE80211_CIPHER_TKIP: @@ -3077,7 +3100,7 @@ ndis_add_key(vap, key, mac) rkey.nk_keyidx |= 1 << 31; if (key->wk_flags & IEEE80211_KEY_GROUP) { - bcopy(ifp->if_broadcastaddr, + bcopy(ieee80211broadcastaddr, rkey.nk_bssid, IEEE80211_ADDR_LEN); } else { bcopy(vap->iv_bss->ni_bssid, @@ -3138,19 +3161,18 @@ ndis_resettask(d, arg) * RX and TX lists. */ static void -ndis_stop(sc) - struct ndis_softc *sc; +ndis_stop(struct ndis_softc *sc) { - struct ifnet *ifp; int i; - ifp = sc->ifp; callout_drain(&sc->ndis_stat_callout); NDIS_LOCK(sc); sc->ndis_tx_timer = 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); if (sc->ndis_iftype != PNPBus || @@ -3192,8 +3214,7 @@ ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { struct ndis_vap *nvp = NDIS_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct ndis_softc *sc = ifp->if_softc; + struct ndis_softc *sc = ic->ic_softc; enum ieee80211_state ostate; DPRINTF(("%s: %s -> %s\n", __func__, @@ -3239,8 +3260,8 @@ ndis_scan(void *arg) static void ndis_scan_results(struct ndis_softc *sc) { - struct ieee80211com *ic; - struct ieee80211vap *vap; + struct ieee80211com *ic = &sc->ndis_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); ndis_80211_bssid_list_ex *bl; ndis_wlan_bssid_ex *wb; struct ieee80211_scanparams sp; @@ -3252,8 +3273,6 @@ ndis_scan_results(struct ndis_softc *sc) uint8_t rates[2+IEEE80211_RATE_MAXSIZE]; uint8_t *frm, *efrm; - ic = sc->ifp->if_l2com; - vap = TAILQ_FIRST(&ic->ic_vaps); saved_chan = ic->ic_curchan; noise = -96; @@ -3329,8 +3348,7 @@ done: static void ndis_scan_start(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct ndis_softc *sc = ifp->if_softc; + struct ndis_softc *sc = ic->ic_softc; struct ieee80211vap *vap; struct ieee80211_scan_state *ss; ndis_80211_ssid ssid; @@ -3391,7 +3409,7 @@ ndis_scan_mindwell(struct ieee80211_scan_state *ss) static void 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); } |