Implement support for single packet sends. The Intel Centrino driver

that Asus provides on its CDs has both a MiniportSend() routine
and a MiniportSendPackets() function. The Microsoft NDIS docs say
that if a driver has both, only the MiniportSendPackets() routine
will be used. Although I think I implemented the support correctly,
calling the MiniportSend() routine seems to result in no packets going
out on the air, even though no error status is returned. The
MiniportSendPackets() function does work though, so at least in
this case it doesn't matter.

In if_ndis.c:ndis_getstate_80211(), if ndis_get_assoc() returns
an error, don't bother trying to obtain any other state since the
calls may fail, or worse cause the underlying driver to crash.

(The above two changes make the Asus-supplied Centrino work.)

Also, when calling the OID_802_11_CONFIGURATION OID, remember
to initialize the structure lengths correctly.

In subr_ndis.c:ndis_open_file(), set the current working directory
to rootvnode if we're in a thread that doesn't have a current
working directory set.
This commit is contained in:
Bill Paul 2004-02-03 07:39:23 +00:00
parent 2104ae4ea4
commit cea179a3fe
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=125377
3 changed files with 65 additions and 7 deletions

View file

@ -1060,6 +1060,32 @@ ndis_send_packets(arg, packets, cnt)
return(0);
}
int
ndis_send_packet(arg, packet)
void *arg;
ndis_packet *packet;
{
struct ndis_softc *sc;
ndis_handle adapter;
ndis_status status;
__stdcall ndis_sendsingle_handler sendfunc;
__stdcall ndis_senddone_func senddonefunc;
sc = arg;
adapter = sc->ndis_block.nmb_miniportadapterctx;
sendfunc = sc->ndis_chars.nmc_sendsingle_func;
senddonefunc = sc->ndis_block.nmb_senddone_func;
status = sendfunc(adapter, packet, packet->np_private.npp_flags);
if (status == NDIS_STATUS_PENDING)
return(0);
senddonefunc(&sc->ndis_block, packet, status);
return(0);
}
int
ndis_init_dma(arg)
void *arg;

View file

@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <sys/smp.h>
#include <sys/queue.h>
#include <sys/proc.h>
#include <sys/filedesc.h>
#include <sys/namei.h>
#include <sys/fcntl.h>
#include <sys/vnode.h>
@ -2392,6 +2393,14 @@ ndis_open_file(status, filehandle, filelength, filename, highestaddr)
}
mtx_lock(&Giant);
/* Some threads don't have a current working directory. */
if (td->td_proc->p_fd->fd_rdir == NULL)
td->td_proc->p_fd->fd_rdir = rootvnode;
if (td->td_proc->p_fd->fd_cdir == NULL)
td->td_proc->p_fd->fd_cdir = rootvnode;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
flags = FREAD;
@ -2400,6 +2409,7 @@ ndis_open_file(status, filehandle, filelength, filename, highestaddr)
mtx_unlock(&Giant);
*status = NDIS_STATUS_FILE_NOT_FOUND;
free(fh, M_TEMP);
printf("ndis_open_file(): unable to open file '%s'\n", path);
return;
}

View file

@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
#include <compat/ndis/pe_var.h>
#include <compat/ndis/resource_var.h>
#include <compat/ndis/ntoskrnl_var.h>
#include <compat/ndis/ndis_var.h>
#include <compat/ndis/cfg_var.h>
#include <dev/if_ndis/if_ndisvar.h>
@ -629,16 +630,18 @@ ndis_attach(dev)
* with this driver, and if so, how many.
*/
if (sc->ndis_chars.nmc_sendsingle_func)
if (sc->ndis_chars.nmc_sendsingle_func &&
sc->ndis_chars.nmc_sendmulti_func == NULL) {
sc->ndis_maxpkts = 1;
else {
} else {
len = sizeof(sc->ndis_maxpkts);
ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
&sc->ndis_maxpkts, &len);
sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
}
sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
sc->ndis_txpending = sc->ndis_maxpkts;
sc->ndis_oidcnt = 0;
@ -841,6 +844,8 @@ ndis_attach(dev)
if (r == 0)
ic->ic_caps |= IEEE80211_C_PMGT;
i = sizeof(config);
config.nc_length = i;
config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
r = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &i);
if (r == 0) {
int chan;
@ -1426,7 +1431,10 @@ ndis_start(ifp)
NDIS_UNLOCK(sc);
ndis_send_packets(sc, p0, pcnt);
if (sc->ndis_maxpkts == 1)
ndis_send_packet(sc, p);
else
ndis_send_packets(sc, p0, pcnt);
return;
}
@ -1702,6 +1710,9 @@ ndis_setstate_80211(sc)
device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
len = sizeof(config);
bzero((char *)&config, len);
config.nc_length = len;
config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
if (rval == 0) {
int chan;
@ -1710,6 +1721,10 @@ ndis_setstate_80211(sc)
if (chan != ieee80211_mhz2ieee(config.nc_dsconfig / 1000, 0)) {
config.nc_dsconfig =
ic->ic_bss->ni_chan->ic_freq * 1000;
len = sizeof(config);
config.nc_length = len;
config.nc_fhconfig.ncf_length =
sizeof(ndis_80211_config_fh);
rval = ndis_set_info(sc, OID_802_11_CONFIGURATION,
&config, &len);
if (rval)
@ -1851,7 +1866,7 @@ ndis_getstate_80211(sc)
/*
* If we're associated, retrieve info on the current bssid.
*/
if (ndis_get_assoc(sc, &bs) == 0) {
if ((rval = ndis_get_assoc(sc, &bs)) == 0) {
switch(bs.nwbx_nettype) {
case NDIS_80211_NETTYPE_11FH:
case NDIS_80211_NETTYPE_11DS:
@ -1868,7 +1883,8 @@ ndis_getstate_80211(sc)
"unknown nettype %d\n", arg);
break;
}
}
} else
return;
len = sizeof(ssid);
bzero((char *)&ssid, len);
@ -1881,6 +1897,9 @@ ndis_getstate_80211(sc)
len = sizeof(arg);
rval = ndis_get_info(sc, OID_GEN_LINK_SPEED, &arg, &len);
if (rval)
device_printf (sc->ndis_dev, "get link speed failed: %d\n",
rval);
if (ic->ic_modecaps & (1<<IEEE80211_MODE_11B)) {
ic->ic_bss->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11B];
@ -1921,6 +1940,9 @@ ndis_getstate_80211(sc)
}
len = sizeof(config);
bzero((char *)&config, len);
config.nc_length = len;
config.nc_fhconfig.ncf_length = sizeof(ndis_80211_config_fh);
rval = ndis_get_info(sc, OID_802_11_CONFIGURATION, &config, &len);
if (rval == 0) {
int chan;