Big round of updates:
- Make ndis_get_info()/ndis_set_info() sleep on the setdone/getdone routines if they get back NDIS_STATUS_PENDING. - Add a bunch of net80211 support so that 802.11 cards can be twiddled with ifconfig. This still needs more work and is not guaranteed to work for everyone. It works on my 802.11b/g card anyway. The problem here is Microsoft doesn't provide a good way to a) learn all the rates that a card supports (if it has more than 8, you're kinda hosed) and b) doesn't provide a good way to distinguish between 802.11b, 802.11b/g an 802.11a/b/g cards, so you sort of have to guess. Setting the SSID and switching between infrastructure/adhoc modes should work. WEP still needs to be implemented. I can't find any API for getting/setting the channel other than the registry/sysctl keys.
This commit is contained in:
parent
249e0bea8f
commit
b4f5e8d8cd
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 *,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user