summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/compat/ndis/kern_ndis.c43
-rw-r--r--sys/compat/ndis/ndis_var.h2
-rw-r--r--sys/compat/ndis/subr_ndis.c5
-rw-r--r--sys/dev/if_ndis/if_ndis.c423
-rw-r--r--sys/dev/if_ndis/if_ndisvar.h11
5 files changed, 452 insertions, 32 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
index 94e340e..29eb774 100644
--- a/sys/compat/ndis/kern_ndis.c
+++ b/sys/compat/ndis/kern_ndis.c
@@ -58,6 +58,9 @@ __FBSDID("$FreeBSD$");
#include <net/if_dl.h>
#include <net/if_media.h>
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_ioctl.h>
+
#include <dev/pccard/pccardvar.h>
#include "card_if.h"
@@ -118,7 +121,11 @@ ndis_setdone_func(adapter, status)
ndis_handle adapter;
ndis_status status;
{
- printf ("Setup done... %x\n", status);
+ ndis_miniport_block *block;
+ block = adapter;
+
+ block->nmb_setstat = status;
+ wakeup(&block->nmb_wkupdpctimer);
return;
}
@@ -127,7 +134,11 @@ ndis_getdone_func(adapter, status)
ndis_handle adapter;
ndis_status status;
{
- printf ("Query done... %x\n", status);
+ ndis_miniport_block *block;
+ block = adapter;
+
+ block->nmb_getstat = status;
+ wakeup(&block->nmb_wkupdpctimer);
return;
}
@@ -603,6 +614,8 @@ ndis_set_info(arg, oid, buf, buflen)
ndis_handle adapter;
__stdcall ndis_setinfo_handler setfunc;
uint32_t byteswritten = 0, bytesneeded = 0;
+ struct timeval tv;
+ int error;
sc = arg;
setfunc = sc->ndis_chars.nmc_setinfo_func;
@@ -611,6 +624,14 @@ ndis_set_info(arg, oid, buf, buflen)
rval = setfunc(adapter, oid, buf, *buflen,
&byteswritten, &bytesneeded);
+ if (rval == NDIS_STATUS_PENDING) {
+ tv.tv_sec = 60;
+ tv.tv_usec = 0;
+ error = tsleep(&sc->ndis_block.nmb_wkupdpctimer,
+ PPAUSE|PCATCH, "ndis", tvtohz(&tv));
+ rval = sc->ndis_block.nmb_setstat;
+ }
+
if (byteswritten)
*buflen = byteswritten;
if (bytesneeded)
@@ -626,9 +647,6 @@ ndis_set_info(arg, oid, buf, buflen)
rval == NDIS_STATUS_NOT_ACCEPTED)
return(ENOTSUP);
- if (rval == NDIS_STATUS_PENDING)
- return(EAGAIN);
-
return(0);
}
@@ -922,6 +940,8 @@ ndis_get_info(arg, oid, buf, buflen)
ndis_handle adapter;
__stdcall ndis_queryinfo_handler queryfunc;
uint32_t byteswritten = 0, bytesneeded = 0;
+ struct timeval tv;
+ int error;
sc = arg;
queryfunc = sc->ndis_chars.nmc_queryinfo_func;
@@ -930,6 +950,16 @@ ndis_get_info(arg, oid, buf, buflen)
rval = queryfunc(adapter, oid, buf, *buflen,
&byteswritten, &bytesneeded);
+ /* Wait for requests that block. */
+
+ if (rval == NDIS_STATUS_PENDING) {
+ tv.tv_sec = 60;
+ tv.tv_usec = 0;
+ error = tsleep(&sc->ndis_block.nmb_wkupdpctimer,
+ PPAUSE|PCATCH, "ndis", tvtohz(&tv));
+ rval = sc->ndis_block.nmb_getstat;
+ }
+
if (byteswritten)
*buflen = byteswritten;
if (bytesneeded)
@@ -946,9 +976,6 @@ ndis_get_info(arg, oid, buf, buflen)
rval == NDIS_STATUS_NOT_ACCEPTED)
return(ENOTSUP);
- if (rval == NDIS_STATUS_PENDING)
- return(EAGAIN);
-
return(0);
}
diff --git a/sys/compat/ndis/ndis_var.h b/sys/compat/ndis/ndis_var.h
index df6d3ce..c52ef46 100644
--- a/sys/compat/ndis/ndis_var.h
+++ b/sys/compat/ndis/ndis_var.h
@@ -1114,6 +1114,8 @@ struct ndis_miniport_block {
int nmb_pciidx;
device_t nmb_dev;
ndis_resource_list *nmb_rlist;
+ ndis_status nmb_getstat;
+ ndis_status nmb_setstat;
};
typedef ndis_status (*ndis_init_handler)(ndis_status *, uint32_t *,
diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c
index 78d58c4..6a91ce7 100644
--- a/sys/compat/ndis/subr_ndis.c
+++ b/sys/compat/ndis/subr_ndis.c
@@ -79,6 +79,9 @@ __FBSDID("$FreeBSD$");
#include <machine/stdarg.h>
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_ioctl.h>
+
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
@@ -647,7 +650,7 @@ ndis_create_lock(lock)
mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO);
if (mtx == NULL)
return;
- mtx_init(mtx, "ndislock", MTX_NETWORK_LOCK,
+ mtx_init(mtx, "ndislock", "ndis spin lock",
MTX_DEF | MTX_RECURSE | MTX_DUPOK);
lock->nsl_spinlock = (ndis_kspin_lock)mtx;
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c
index 5303df3..9752572 100644
--- a/sys/dev/if_ndis/if_ndis.c
+++ b/sys/dev/if_ndis/if_ndis.c
@@ -62,6 +62,9 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/rman.h>
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_ioctl.h>
+
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
@@ -98,6 +101,9 @@ static __stdcall void ndis_txeof (ndis_handle,
ndis_packet *, ndis_status);
static __stdcall void ndis_rxeof (ndis_handle,
ndis_packet **, uint32_t);
+static __stdcall void ndis_linksts (ndis_handle,
+ ndis_status, void *, uint32_t);
+
static void ndis_intr (void *);
static void ndis_tick (void *);
static void ndis_start (struct ifnet *);
@@ -108,6 +114,8 @@ static void ndis_watchdog (struct ifnet *);
static void ndis_shutdown (device_t);
static int ndis_ifmedia_upd (struct ifnet *);
static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *);
+static void ndis_getstate_80211 (struct ndis_softc *);
+static void ndis_setstate_80211 (struct ndis_softc *);
static void ndis_reset (struct ndis_softc *);
static void ndis_setmulti (struct ndis_softc *);
@@ -204,7 +212,7 @@ ndis_attach(dev)
int unit, error = 0, rid, len;
void *img;
struct ndis_type *t;
- int devidx = 0, defidx = 0;
+ int i, devidx = 0, defidx = 0;
sc = device_get_softc(dev);
@@ -357,11 +365,6 @@ ndis_attach(dev)
len = sizeof(eaddr);
ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len);
- /*
- * An NDIS device was detected. Inform the world.
- */
- printf("ndis%d: Ethernet address: %6D\n", unit, eaddr, ":");
-
sc->ndis_unit = unit;
bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
@@ -392,14 +395,26 @@ ndis_attach(dev)
if (sc->ndis_sc)
ndis_init_dma(sc);
- 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);
+ /*
+ * See if the OID_802_11_NETWORK_TYPES_SUPPORTED OID is
+ * supported by this driver. If it is, then this an 802.11
+ * wireless driver, and we should set up media for wireless.
+ */
+ for (i = 0; i < sc->ndis_oidcnt; i++) {
+ if (sc->ndis_oids[i] == OID_802_11_NETWORK_TYPES_SUPPORTED) {
+ sc->ndis_80211++;
+ break;
+ }
+ }
+
+ /*
+ * An NDIS device was detected. Inform the world.
+ */
+ if (sc->ndis_80211)
+ printf("ndis%d: 802.11 address: %6D\n", unit, eaddr, ":");
+ else
+ printf("ndis%d: Ethernet address: %6D\n", unit, eaddr, ":");
+
ifp = &sc->arpcom.ac_if;
ifp->if_softc = sc;
@@ -419,10 +434,116 @@ ndis_attach(dev)
*/
ether_ifattach(ifp, eaddr);
+ /* Do media setup */
+ if (sc->ndis_80211) {
+ struct ieee80211com *ic = (void *)ifp;
+ ndis_80211_rates rates;
+ uint32_t arg;
+ int r;
+
+ ic->ic_phytype = IEEE80211_T_DS;
+ ic->ic_opmode = IEEE80211_M_STA;
+ ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_IBSS;
+ ic->ic_state = IEEE80211_S_RUN;
+ ic->ic_modecaps = (1<<IEEE80211_MODE_AUTO);
+ len = sizeof(rates);
+ bzero((char *)&rates, len);
+ r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES,
+ (void *)rates, &len);
+ if (r)
+ printf ("get rates failed: 0x%x\n", r);
+ /*
+ * We need a way to distinguish between 802.11b cards
+ * and 802.11g cards. Unfortunately, Microsoft doesn't
+ * really give us one, so we have to apply a bit of a
+ * heuristic here. If we ask for supported rates, and
+ * we get 8 of them, then we know this isn't just a
+ * plain 802.11b card, since those only support up to
+ * 4 rates. This doesn't help us distinguish 802.11g
+ * from 802.11a or turbo cards though.
+ */
+#define SETRATE(x, y) \
+ ic->ic_sup_rates[x].rs_rates[ic->ic_sup_rates[x].rs_nrates] = (y);
+#define INCRATE(x) \
+ ic->ic_sup_rates[x].rs_nrates++;
+
+ if (rates[7]) {
+ ic->ic_curmode = IEEE80211_MODE_11G;
+ ic->ic_modecaps |= (1<<IEEE80211_MODE_11G)|
+ (1<<IEEE80211_MODE_11B);
+ ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
+ 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 22:
+ SETRATE(IEEE80211_MODE_11B, rates[i]);
+ INCRATE(IEEE80211_MODE_11B);
+ break;
+ default:
+ SETRATE(IEEE80211_MODE_11G, rates[i]);
+ INCRATE(IEEE80211_MODE_11G);
+ break;
+ }
+ }
+
+ /* Now cheat by filling in the 54Mbps rates. */
+
+ SETRATE(IEEE80211_MODE_11G, 47);
+ INCRATE(IEEE80211_MODE_11G);
+ SETRATE(IEEE80211_MODE_11G, 72);
+ INCRATE(IEEE80211_MODE_11G);
+ SETRATE(IEEE80211_MODE_11G, 96);
+ INCRATE(IEEE80211_MODE_11G);
+ SETRATE(IEEE80211_MODE_11G, 108);
+ INCRATE(IEEE80211_MODE_11G);
+ } else {
+ ic->ic_curmode = IEEE80211_MODE_11B;
+ ic->ic_modecaps |= (1<<IEEE80211_MODE_11B);
+ ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
+ for (i = 0; i < len; i++) {
+ if (!rates[i])
+ break;
+ SETRATE(IEEE80211_MODE_11B, rates[i]);
+ INCRATE(IEEE80211_MODE_11B);
+ }
+ }
+#undef SETRATE
+#undef INCRATE
+ for (i = 1; i < 11; i++) {
+ ic->ic_channels[i].ic_freq =
+ ieee80211_ieee2mhz(i, IEEE80211_CHAN_B);
+ ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B;
+ }
+ i = sizeof(arg);
+ r = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &i);
+ if (arg != NDIS_80211_WEPSTAT_NOTSUPPORTED)
+ ic->ic_caps |= IEEE80211_C_WEP;
+ ieee80211_node_attach(ifp);
+ ieee80211_media_init(ifp, ieee80211_media_change,
+ ieee80211_media_status);
+ /*ic->ic_bss->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11G];*/
+ } 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);
+ }
+
/* Hook interrupt last to avoid having to lock softc */
error = bus_setup_intr(dev, sc->ndis_irq, INTR_TYPE_NET,
ndis_intr, sc, &sc->ndis_intrhand);
+ /* Override the status handler so we can detect link changes. */
+ sc->ndis_block.nmb_status_func = ndis_linksts;
+
if (error) {
printf("ndis%d: couldn't set up irq\n", unit);
ether_ifdetach(ifp);
@@ -456,11 +577,17 @@ ndis_detach(dev)
ifp = &sc->arpcom.ac_if;
if (device_is_attached(dev)) {
+ if (sc->ndis_80211) {
+ ifmedia_removeall(&sc->ic.ic_media);
+ ieee80211_node_detach(ifp);
+ }
+ ifp->if_flags &= ~IFF_UP;
NDIS_UNLOCK(sc);
ndis_stop(sc);
ether_ifdetach(ifp);
- NDIS_LOCK(sc);
- }
+ } else
+ NDIS_UNLOCK(sc);
+
bus_generic_detach(dev);
@@ -484,7 +611,6 @@ ndis_detach(dev)
sysctl_ctx_free(&sc->ndis_ctx);
- NDIS_UNLOCK(sc);
mtx_destroy(&sc->ndis_mtx);
return(0);
@@ -557,7 +683,6 @@ ndis_txeof(adapter, packet, status)
m = (struct mbuf *)packet->np_rsvd[1];
idx = (int)packet->np_rsvd[0];
ifp->if_opackets++;
- m_freem(m);
if (sc->ndis_sc)
bus_dmamap_unload(sc->ndis_ttag, sc->ndis_tmaps[idx]);
@@ -570,12 +695,54 @@ ndis_txeof(adapter, packet, status)
NDIS_UNLOCK(sc);
+ m_freem(m);
+
if (ifp->if_snd.ifq_head != NULL)
ndis_start(ifp);
return;
}
+__stdcall static void
+ndis_linksts(adapter, status, sbuf, slen)
+ ndis_handle adapter;
+ ndis_status status;
+ void *sbuf;
+ uint32_t slen;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct ifnet *ifp;
+
+ block = adapter;
+ ifp = block->nmb_ifp;
+ sc = ifp->if_softc;
+
+ if (!(ifp->if_flags & IFF_UP))
+ return;
+
+ switch (status) {
+ case NDIS_STATUS_MEDIA_CONNECT:
+ sc->ndis_link = 1;
+ printf("ndis%d: link up\n", sc->ndis_unit);
+ if (sc->ndis_80211)
+ ndis_getstate_80211(sc);
+ if (ifp->if_snd.ifq_head != NULL)
+ ndis_start(ifp);
+ break;
+ case NDIS_STATUS_MEDIA_DISCONNECT:
+ printf("ndis%d: link down\n", sc->ndis_unit);
+ if (sc->ndis_80211)
+ ndis_getstate_80211(sc);
+ sc->ndis_link = 0;
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
static void
ndis_intr(arg)
void *arg;
@@ -615,10 +782,19 @@ ndis_tick(xsc)
struct ndis_softc *sc;
__stdcall ndis_checkforhang_handler hangfunc;
uint8_t rval;
+ ndis_media_state linkstate;
+ int error, len;
sc = xsc;
NDIS_LOCK(sc);
+ len = sizeof(linkstate);
+ error = ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
+ (void *)&linkstate, &len);
+
+ if (linkstate == nmc_connected)
+ sc->ndis_link = 1;
+
hangfunc = sc->ndis_chars.nmc_checkhang_func;
if (hangfunc != NULL) {
@@ -688,6 +864,11 @@ ndis_start(ifp)
NDIS_LOCK(sc);
+ if (!sc->ndis_link || ifp->if_flags & IFF_OACTIVE) {
+ NDIS_UNLOCK(sc);
+ return;
+ }
+
p0 = &sc->ndis_txarray[sc->ndis_txidx];
while(sc->ndis_txpending) {
@@ -809,11 +990,17 @@ ndis_init(xsc)
error = ndis_set_info(sc, OID_GEN_CURRENT_PACKET_FILTER,
&ndis_filter, &i);
+ sc->ndis_filter = ndis_filter;
+
if (error)
printf ("set filter failed: %d\n", error);
sc->ndis_txidx = 0;
sc->ndis_txpending = sc->ndis_maxpkts;
+ sc->ndis_link = 0;
+
+ if (sc->ndis_80211)
+ ndis_setstate_80211(sc);
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
@@ -892,6 +1079,165 @@ ndis_ifmedia_sts(ifp, ifmr)
return;
}
+static void
+ndis_setstate_80211(sc)
+ struct ndis_softc *sc;
+{
+ struct ieee80211com *ic;
+ ndis_80211_ssid ssid;
+ int rval, len;
+ uint32_t arg;
+ struct ifnet *ifp;
+
+ ic = &sc->ic;
+ ifp = &sc->ic.ic_ac.ac_if;
+
+ if (!(ifp->if_flags & IFF_UP))
+ return;
+
+ /* Always set authmode to open for now. */
+
+ arg = NDIS_80211_AUTHMODE_OPEN;
+ len = sizeof(arg);
+ rval = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &len);
+
+ if (rval)
+ printf ("ndis%d: set auth failed: %d\n", sc->ndis_unit, rval);
+
+ /* Set network infrastructure mode. */
+
+ len = sizeof(arg);
+ if (ic->ic_opmode == IEEE80211_M_IBSS)
+ arg = NDIS_80211_NET_INFRA_IBSS;
+ else
+ arg = NDIS_80211_NET_INFRA_BSS;
+
+ rval = ndis_set_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
+
+ if (rval)
+ printf ("ndis%d: set infra failed: %d\n", sc->ndis_unit, rval);
+
+ /* Set SSID. */
+
+ len = sizeof(ssid);
+ bzero((char *)&ssid, len);
+ ssid.ns_ssidlen = ic->ic_des_esslen;
+ bcopy(ic->ic_des_essid, ssid.ns_ssid, ssid.ns_ssidlen);
+ rval = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
+
+ if (rval)
+ printf ("ndis%d: set ssid failed: %d\n", sc->ndis_unit, rval);
+
+
+ return;
+}
+
+static void
+ndis_getstate_80211(sc)
+ struct ndis_softc *sc;
+{
+ struct ieee80211com *ic;
+ ndis_80211_ssid ssid;
+ int rval, len, i = 0;
+ uint32_t arg;
+ struct ifnet *ifp;
+
+ ic = &sc->ic;
+ ifp = &sc->ic.ic_ac.ac_if;
+
+ if (!(ifp->if_flags & IFF_UP))
+ return;
+
+ len = sizeof(arg);
+ rval = ndis_get_info(sc, OID_GEN_MEDIA_CONNECT_STATUS,
+ (void *)&arg, &len);
+
+ if (arg == nmc_connected)
+ ic->ic_state = IEEE80211_S_RUN;
+ else
+ ic->ic_state = IEEE80211_S_ASSOC;
+/*
+ len = sizeof(arg);
+ rval = ndis_get_info(sc, OID_802_11_INFRASTRUCTURE_MODE, &arg, &len);
+
+ if (rval)
+ printf ("ndis%d: get infra failed: %d\n", sc->ndis_unit, rval);
+
+ switch(arg) {
+ case NDIS_80211_NET_INFRA_IBSS:
+ ic->ic_opmode = IEEE80211_M_IBSS;
+ break;
+ case NDIS_80211_NET_INFRA_BSS:
+ ic->ic_opmode = IEEE80211_M_STA;
+ break;
+ default:
+ break;
+ }
+*/
+ len = sizeof(ssid);
+ bzero((char *)&ssid, len);
+ rval = ndis_get_info(sc, OID_802_11_SSID, &ssid, &len);
+
+ if (rval)
+ printf ("ndis%d: get ssid failed: %d\n", sc->ndis_unit, rval);
+ bcopy(ssid.ns_ssid, ic->ic_bss->ni_essid, ssid.ns_ssidlen);
+ ic->ic_bss->ni_esslen = ssid.ns_ssidlen;
+
+ len = sizeof(arg);
+ rval = ndis_get_info(sc, OID_GEN_LINK_SPEED, &arg, &len);
+
+ if (ic->ic_modecaps & (1<<IEEE80211_MODE_11B)) {
+ ic->ic_bss->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11B];
+ for (i = 0; i < ic->ic_bss->ni_rates.rs_nrates; i++) {
+ if ((ic->ic_bss->ni_rates.rs_rates[i] &
+ IEEE80211_RATE_VAL) == (arg / 10000) * 2)
+ break;
+ }
+ }
+
+ if (i == ic->ic_bss->ni_rates.rs_nrates &&
+ ic->ic_modecaps & (1<<IEEE80211_MODE_11G)) {
+ ic->ic_bss->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11G];
+ for (i = 0; i < ic->ic_bss->ni_rates.rs_nrates; i++) {
+ if ((ic->ic_bss->ni_rates.rs_rates[i] &
+ IEEE80211_RATE_VAL) == (arg / 10000) * 2)
+ break;
+ }
+ }
+
+ if (i == ic->ic_bss->ni_rates.rs_nrates)
+ printf ("ndis%d: no matching rate for: %d\n",
+ sc->ndis_unit, (arg / 10000) * 2);
+ else
+ ic->ic_bss->ni_txrate = i;
+
+ len = sizeof(arg);
+ rval = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &len);
+
+ if (rval)
+ printf ("ndis%d: get power mode failed: %d\n",
+ sc->ndis_unit, rval);
+ if (arg == NDIS_80211_POWERMODE_CAM)
+ ic->ic_flags &= ~IEEE80211_F_PMGTON;
+ else
+ ic->ic_flags |= IEEE80211_F_PMGTON;
+
+/*
+ len = sizeof(arg);
+ rval = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &len);
+
+ if (rval)
+ printf ("ndis%d: get wep status failed: %d\n",
+ sc->ndis_unit, rval);
+
+ if (arg == NDIS_80211_WEPSTAT_ENABLED)
+ ic->ic_flags |= IEEE80211_F_WEPON;
+ else
+ ic->ic_flags &= ~IEEE80211_F_WEPON;
+*/
+ return;
+}
+
static int
ndis_ioctl(ifp, command, data)
struct ifnet *ifp;
@@ -900,18 +1246,37 @@ ndis_ioctl(ifp, command, data)
{
struct ndis_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
- int error = 0;
+ int i, error = 0;
/*NDIS_LOCK(sc);*/
+
switch(command) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
- ndis_init(sc);
+ if (ifp->if_flags & IFF_RUNNING &&
+ ifp->if_flags & IFF_PROMISC &&
+ !(sc->ndis_if_flags & IFF_PROMISC)) {
+ sc->ndis_filter |=
+ NDIS_PACKET_TYPE_PROMISCUOUS;
+ ndis_set_info(sc,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ &sc->ndis_filter, &i);
+ } else if (ifp->if_flags & IFF_RUNNING &&
+ !(ifp->if_flags & IFF_PROMISC) &&
+ sc->ndis_if_flags & IFF_PROMISC) {
+ sc->ndis_filter &=
+ ~NDIS_PACKET_TYPE_PROMISCUOUS;
+ ndis_set_info(sc,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ &sc->ndis_filter, &i);
+ } else
+ ndis_init(sc);
} else {
if (ifp->if_flags & IFF_RUNNING)
ndis_stop(sc);
}
+ sc->ndis_if_flags = ifp->if_flags;
error = 0;
break;
case SIOCADDMULTI:
@@ -921,10 +1286,24 @@ ndis_ioctl(ifp, command, data)
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
+ if (sc->ndis_80211) {
+ error = ieee80211_ioctl(ifp, command, data);
+ if (error == ENETRESET) {
+ ndis_setstate_80211(sc);
+ error = 0;
+ }
+ } else
+ error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
break;
default:
- error = ether_ioctl(ifp, command, data);
+ if (sc->ndis_80211) {
+ error = ieee80211_ioctl(ifp, command, data);
+ if (error == ENETRESET) {
+ ndis_setstate_80211(sc);
+ error = 0;
+ }
+ } else
+ error = ether_ioctl(ifp, command, data);
break;
}
diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h
index 5b9c768..8d92759 100644
--- a/sys/dev/if_ndis/if_ndisvar.h
+++ b/sys/dev/if_ndis/if_ndisvar.h
@@ -68,8 +68,13 @@ TAILQ_HEAD(nch, ndis_cfglist);
#define NDIS_INC(x) \
(x)->ndis_txidx = ((x)->ndis_txidx + 1) % (x)->ndis_maxpkts
+#define arpcom ic.ic_ac
+
struct ndis_softc {
- struct arpcom arpcom; /* interface info */
+ struct ieee80211com ic; /* interface info */
+#ifdef notdef
+ struct ieee80211com arpcom; /* interface info */
+#endif
struct ifmedia ifmedia; /* media info */
bus_space_handle_t ndis_bhandle;
bus_space_tag_t ndis_btag;
@@ -101,6 +106,10 @@ struct ndis_softc {
int ndis_sc;
ndis_cfg *ndis_regvals;
struct nch ndis_cfglist_head;
+ int ndis_80211;
+ int ndis_link;
+ uint32_t ndis_filter;
+ int ndis_if_flags;
struct sysctl_ctx_list ndis_ctx;
struct sysctl_oid *ndis_tree;
OpenPOWER on IntegriCloud