MFC: synchronize the NDISulator with the head and RELENG_5 branches,
add -D ndis support to wpa_supplicant Approved by: re
This commit is contained in:
parent
18a30ec710
commit
14b480eac9
@ -20,10 +20,19 @@ if [ -z "$ifn" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
case ${ifn} in
|
||||
ndis*)
|
||||
driver="ndis"
|
||||
;;
|
||||
*)
|
||||
driver="bsd"
|
||||
;;
|
||||
esac
|
||||
|
||||
load_rc_config $name
|
||||
|
||||
pid_file="/var/run/${name}/${ifn}.pid"
|
||||
command_args="-B -q -i $ifn -P $pid_file -c $conf_file"
|
||||
command_args="-B -q -i $ifn -c $conf_file -D $driver -P $pid_file"
|
||||
required_files=$conf_file
|
||||
|
||||
run_rc_command "$1"
|
||||
|
@ -82,9 +82,9 @@ static void ndis_setdone_func(ndis_handle, ndis_status);
|
||||
static void ndis_getdone_func(ndis_handle, ndis_status);
|
||||
static void ndis_resetdone_func(ndis_handle, ndis_status, uint8_t);
|
||||
static void ndis_sendrsrcavail_func(ndis_handle);
|
||||
static void ndis_intrhand(kdpc *, device_object *,
|
||||
static void ndis_intrsetup(kdpc *, device_object *,
|
||||
irp *, struct ndis_softc *);
|
||||
static void ndis_return(kdpc *, void *, void *, void *);
|
||||
static void ndis_return(device_object *, void *);
|
||||
|
||||
static image_patch_table kernndis_functbl[] = {
|
||||
IMPORT_SFUNC(ndis_status_func, 4),
|
||||
@ -93,21 +93,31 @@ static image_patch_table kernndis_functbl[] = {
|
||||
IMPORT_SFUNC(ndis_getdone_func, 2),
|
||||
IMPORT_SFUNC(ndis_resetdone_func, 3),
|
||||
IMPORT_SFUNC(ndis_sendrsrcavail_func, 1),
|
||||
IMPORT_SFUNC(ndis_intrhand, 4),
|
||||
IMPORT_SFUNC(ndis_intrsetup, 4),
|
||||
IMPORT_SFUNC(ndis_return, 1),
|
||||
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
struct nd_head ndis_devhead;
|
||||
|
||||
static struct mtx ndis_req_mtx;
|
||||
static struct nd_head ndis_devhead;
|
||||
|
||||
/*
|
||||
* This allows us to export our symbols to other modules.
|
||||
* Note that we call ourselves 'ndisapi' to avoid a namespace
|
||||
* collision with if_ndis.ko, which internally calls itself
|
||||
* 'ndis.'
|
||||
*
|
||||
* Note: some of the subsystems depend on each other, so the
|
||||
* order in which they're started is important. The order of
|
||||
* importance is:
|
||||
*
|
||||
* HAL - spinlocks and IRQL manipulation
|
||||
* ntoskrnl - DPC and workitem threads, object waiting
|
||||
* windrv - driver/device registration
|
||||
*
|
||||
* The HAL should also be the last thing shut down, since
|
||||
* the ntoskrnl subsystem will use spinlocks right up until
|
||||
* the DPC and workitem threads are terminated.
|
||||
*/
|
||||
|
||||
static int
|
||||
@ -119,10 +129,10 @@ ndis_modevent(module_t mod, int cmd, void *arg)
|
||||
switch (cmd) {
|
||||
case MOD_LOAD:
|
||||
/* Initialize subsystems */
|
||||
windrv_libinit();
|
||||
hal_libinit();
|
||||
ndis_libinit();
|
||||
ntoskrnl_libinit();
|
||||
windrv_libinit();
|
||||
ndis_libinit();
|
||||
usbd_libinit();
|
||||
|
||||
patch = kernndis_functbl;
|
||||
@ -135,34 +145,30 @@ ndis_modevent(module_t mod, int cmd, void *arg)
|
||||
|
||||
TAILQ_INIT(&ndis_devhead);
|
||||
|
||||
mtx_init(&ndis_req_mtx, "NDIS request lock",
|
||||
MTX_NDIS_LOCK, MTX_DEF);
|
||||
|
||||
break;
|
||||
case MOD_SHUTDOWN:
|
||||
if (TAILQ_FIRST(&ndis_devhead) == NULL) {
|
||||
/* Shut down subsystems */
|
||||
hal_libfini();
|
||||
ndis_libfini();
|
||||
ntoskrnl_libfini();
|
||||
usbd_libfini();
|
||||
windrv_libfini();
|
||||
ntoskrnl_libfini();
|
||||
hal_libfini();
|
||||
|
||||
patch = kernndis_functbl;
|
||||
while (patch->ipt_func != NULL) {
|
||||
windrv_unwrap(patch->ipt_wrap);
|
||||
patch++;
|
||||
}
|
||||
mtx_destroy(&ndis_req_mtx);
|
||||
}
|
||||
break;
|
||||
case MOD_UNLOAD:
|
||||
/* Shut down subsystems */
|
||||
hal_libfini();
|
||||
ndis_libfini();
|
||||
ntoskrnl_libfini();
|
||||
usbd_libfini();
|
||||
windrv_libfini();
|
||||
ntoskrnl_libfini();
|
||||
hal_libfini();
|
||||
|
||||
patch = kernndis_functbl;
|
||||
while (patch->ipt_func != NULL) {
|
||||
@ -170,8 +176,6 @@ ndis_modevent(module_t mod, int cmd, void *arg)
|
||||
patch++;
|
||||
}
|
||||
|
||||
mtx_destroy(&ndis_req_mtx);
|
||||
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
@ -183,34 +187,6 @@ ndis_modevent(module_t mod, int cmd, void *arg)
|
||||
DEV_MODULE(ndisapi, ndis_modevent, NULL);
|
||||
MODULE_VERSION(ndisapi, 1);
|
||||
|
||||
int
|
||||
ndis_thsuspend(p, m, timo)
|
||||
struct proc *p;
|
||||
struct mtx *m;
|
||||
int timo;
|
||||
{
|
||||
int error;
|
||||
|
||||
if (m != NULL) {
|
||||
error = msleep(&p->p_siglist, m,
|
||||
curthread->td_priority, "ndissp", timo);
|
||||
} else {
|
||||
PROC_LOCK(p);
|
||||
error = msleep(&p->p_siglist, &p->p_mtx,
|
||||
curthread->td_priority|PDROP, "ndissp", timo);
|
||||
}
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
void
|
||||
ndis_thresume(p)
|
||||
struct proc *p;
|
||||
{
|
||||
wakeup(&p->p_siglist);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ndis_sendrsrcavail_func(adapter)
|
||||
ndis_handle adapter;
|
||||
@ -262,7 +238,7 @@ ndis_setdone_func(adapter, status)
|
||||
block = adapter;
|
||||
|
||||
block->nmb_setstat = status;
|
||||
wakeup(&block->nmb_setstat);
|
||||
KeSetEvent(&block->nmb_setevent, IO_NO_INCREMENT, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -275,7 +251,7 @@ ndis_getdone_func(adapter, status)
|
||||
block = adapter;
|
||||
|
||||
block->nmb_getstat = status;
|
||||
wakeup(&block->nmb_getstat);
|
||||
KeSetEvent(&block->nmb_getevent, IO_NO_INCREMENT, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -295,7 +271,8 @@ ndis_resetdone_func(adapter, status, addressingreset)
|
||||
|
||||
if (ifp->if_flags & IFF_DEBUG)
|
||||
device_printf (sc->ndis_dev, "reset done...\n");
|
||||
wakeup(sc);
|
||||
KeSetEvent(&block->nmb_resetevent, IO_NO_INCREMENT, FALSE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -328,7 +305,6 @@ ndis_create_sysctls(arg)
|
||||
#endif
|
||||
/* Add the driver-specific registry keys. */
|
||||
|
||||
vals = sc->ndis_regvals;
|
||||
while(1) {
|
||||
if (vals->nc_cfgkey == NULL)
|
||||
break;
|
||||
@ -358,17 +334,8 @@ ndis_create_sysctls(arg)
|
||||
continue;
|
||||
}
|
||||
|
||||
#if __FreeBSD_version < 502113
|
||||
SYSCTL_ADD_STRING(&sc->ndis_ctx,
|
||||
SYSCTL_CHILDREN(sc->ndis_tree),
|
||||
#else
|
||||
SYSCTL_ADD_STRING(device_get_sysctl_ctx(sc->ndis_dev),
|
||||
SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ndis_dev)),
|
||||
#endif
|
||||
OID_AUTO, vals->nc_cfgkey,
|
||||
CTLFLAG_RW, vals->nc_val,
|
||||
sizeof(vals->nc_val),
|
||||
vals->nc_cfgdesc);
|
||||
ndis_add_sysctl(sc, vals->nc_cfgkey, vals->nc_cfgdesc,
|
||||
vals->nc_val, CTLFLAG_RW);
|
||||
vals++;
|
||||
}
|
||||
|
||||
@ -420,8 +387,10 @@ ndis_add_sysctl(arg, key, desc, val, flag)
|
||||
|
||||
cfg = malloc(sizeof(struct ndis_cfglist), M_DEVBUF, M_NOWAIT|M_ZERO);
|
||||
|
||||
if (cfg == NULL)
|
||||
if (cfg == NULL) {
|
||||
printf("failed for %s\n", key);
|
||||
return(ENOMEM);
|
||||
}
|
||||
|
||||
cfg->ndis_cfg.nc_cfgkey = strdup(key, M_DEVBUF);
|
||||
if (desc == NULL) {
|
||||
@ -433,6 +402,7 @@ ndis_add_sysctl(arg, key, desc, val, flag)
|
||||
|
||||
TAILQ_INSERT_TAIL(&sc->ndis_cfglist_head, cfg, link);
|
||||
|
||||
cfg->ndis_oid =
|
||||
#if __FreeBSD_version < 502113
|
||||
SYSCTL_ADD_STRING(&sc->ndis_ctx, SYSCTL_CHILDREN(sc->ndis_tree),
|
||||
#else
|
||||
@ -446,18 +416,34 @@ ndis_add_sysctl(arg, key, desc, val, flag)
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Somewhere, somebody decided "hey, let's automatically create
|
||||
* a sysctl tree for each device instance as it's created -- it'll
|
||||
* make life so much easier!" Lies. Why must they turn the kernel
|
||||
* into a house of lies?
|
||||
*/
|
||||
|
||||
int
|
||||
ndis_flush_sysctls(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct ndis_softc *sc;
|
||||
struct ndis_cfglist *cfg;
|
||||
struct sysctl_ctx_list *clist;
|
||||
|
||||
sc = arg;
|
||||
|
||||
#if __FreeBSD_version < 502113
|
||||
clist = &sc->ndis_ctx;
|
||||
#else
|
||||
clist = device_get_sysctl_ctx(sc->ndis_dev);
|
||||
#endif
|
||||
|
||||
while (!TAILQ_EMPTY(&sc->ndis_cfglist_head)) {
|
||||
cfg = TAILQ_FIRST(&sc->ndis_cfglist_head);
|
||||
TAILQ_REMOVE(&sc->ndis_cfglist_head, cfg, link);
|
||||
sysctl_ctx_entry_del(clist, cfg->ndis_oid);
|
||||
sysctl_remove_oid(cfg->ndis_oid, 1, 0);
|
||||
free(cfg->ndis_cfg.nc_cfgkey, M_DEVBUF);
|
||||
free(cfg->ndis_cfg.nc_cfgdesc, M_DEVBUF);
|
||||
free(cfg, M_DEVBUF);
|
||||
@ -467,30 +453,39 @@ ndis_flush_sysctls(arg)
|
||||
}
|
||||
|
||||
static void
|
||||
ndis_return(dpc, arg, sysarg1, sysarg2)
|
||||
kdpc *dpc;
|
||||
ndis_return(dobj, arg)
|
||||
device_object *dobj;
|
||||
void *arg;
|
||||
void *sysarg1;
|
||||
void *sysarg2;
|
||||
{
|
||||
struct ndis_softc *sc;
|
||||
ndis_miniport_block *block;
|
||||
ndis_miniport_characteristics *ch;
|
||||
ndis_return_handler returnfunc;
|
||||
ndis_handle adapter;
|
||||
ndis_packet *p;
|
||||
uint8_t irql;
|
||||
list_entry *l;
|
||||
|
||||
block = arg;
|
||||
ch = IoGetDriverObjectExtension(dobj->do_drvobj, (void *)1);
|
||||
|
||||
p = arg;
|
||||
sc = p->np_softc;
|
||||
adapter = sc->ndis_block->nmb_miniportadapterctx;
|
||||
adapter = block->nmb_miniportadapterctx;
|
||||
|
||||
if (adapter == NULL)
|
||||
return;
|
||||
|
||||
returnfunc = sc->ndis_chars->nmc_return_packet_func;
|
||||
returnfunc = ch->nmc_return_packet_func;
|
||||
|
||||
KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
|
||||
MSCALL2(returnfunc, adapter, p);
|
||||
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
|
||||
KeAcquireSpinLock(&block->nmb_returnlock, &irql);
|
||||
while (!IsListEmpty(&block->nmb_returnlist)) {
|
||||
l = RemoveHeadList((&block->nmb_returnlist));
|
||||
p = CONTAINING_RECORD(l, ndis_packet, np_list);
|
||||
InitializeListHead((&p->np_list));
|
||||
KeReleaseSpinLock(&block->nmb_returnlock, irql);
|
||||
MSCALL2(returnfunc, adapter, p);
|
||||
KeAcquireSpinLock(&block->nmb_returnlock, &irql);
|
||||
}
|
||||
KeReleaseSpinLock(&block->nmb_returnlock, irql);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -501,6 +496,7 @@ ndis_return_packet(buf, arg)
|
||||
void *arg;
|
||||
{
|
||||
ndis_packet *p;
|
||||
ndis_miniport_block *block;
|
||||
|
||||
if (arg == NULL)
|
||||
return;
|
||||
@ -514,8 +510,16 @@ ndis_return_packet(buf, arg)
|
||||
if (p->np_refcnt)
|
||||
return;
|
||||
|
||||
KeInitializeDpc(&p->np_dpc, kernndis_functbl[7].ipt_wrap, p);
|
||||
KeInsertQueueDpc(&p->np_dpc, NULL, NULL);
|
||||
block = ((struct ndis_softc *)p->np_softc)->ndis_block;
|
||||
|
||||
KeAcquireSpinLockAtDpcLevel(&block->nmb_returnlock);
|
||||
InitializeListHead((&p->np_list));
|
||||
InsertHeadList((&block->nmb_returnlist), (&p->np_list));
|
||||
KeReleaseSpinLockFromDpcLevel(&block->nmb_returnlock);
|
||||
|
||||
IoQueueWorkItem(block->nmb_returnitem,
|
||||
(io_workitem_func)kernndis_functbl[7].ipt_wrap,
|
||||
WORKQUEUE_CRITICAL, block);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -645,8 +649,13 @@ ndis_convert_res(arg)
|
||||
case SYS_RES_IRQ:
|
||||
prd->cprd_type = CmResourceTypeInterrupt;
|
||||
prd->cprd_flags = 0;
|
||||
/*
|
||||
* Always mark interrupt resources as
|
||||
* shared, since in our implementation,
|
||||
* they will be.
|
||||
*/
|
||||
prd->cprd_sharedisp =
|
||||
CmResourceShareDeviceExclusive;
|
||||
CmResourceShareShared;
|
||||
prd->u.cprd_intr.cprd_level = brle->start;
|
||||
prd->u.cprd_intr.cprd_vector = brle->start;
|
||||
prd->u.cprd_intr.cprd_affinity = 0;
|
||||
@ -691,10 +700,13 @@ ndis_ptom(m0, p)
|
||||
struct mbuf **m0;
|
||||
ndis_packet *p;
|
||||
{
|
||||
struct mbuf *m, *prev = NULL;
|
||||
struct mbuf *m = NULL, *prev = NULL;
|
||||
ndis_buffer *buf;
|
||||
ndis_packet_private *priv;
|
||||
uint32_t totlen = 0;
|
||||
struct ifnet *ifp;
|
||||
struct ether_header *eh;
|
||||
int diff;
|
||||
|
||||
if (p == NULL || m0 == NULL)
|
||||
return(EINVAL);
|
||||
@ -718,6 +730,7 @@ ndis_ptom(m0, p)
|
||||
MEXTADD(m, m->m_data, m->m_len, ndis_return_packet,
|
||||
p, 0, EXT_NDIS);
|
||||
p->np_refcnt++;
|
||||
|
||||
totlen += m->m_len;
|
||||
if (m->m_flags & M_PKTHDR)
|
||||
*m0 = m;
|
||||
@ -726,6 +739,24 @@ ndis_ptom(m0, p)
|
||||
prev = m;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a hack to deal with the Marvell 8335 driver
|
||||
* which, when associated with an AP in WPA-PSK mode,
|
||||
* seems to overpad its frames by 8 bytes. I don't know
|
||||
* that the extra 8 bytes are for, and they're not there
|
||||
* in open mode, so for now clamp the frame size at 1514
|
||||
* until I can figure out how to deal with this properly,
|
||||
* otherwise if_ethersubr() will spank us by discarding
|
||||
* the 'oversize' frames.
|
||||
*/
|
||||
|
||||
eh = mtod((*m0), struct ether_header *);
|
||||
ifp = ((struct ndis_softc *)p->np_softc)->ifp;
|
||||
if (totlen > ETHER_MAX_FRAME(ifp, eh->ether_type, FALSE)) {
|
||||
diff = totlen - ETHER_MAX_FRAME(ifp, eh->ether_type, FALSE);
|
||||
totlen -= diff;
|
||||
m->m_len -= diff;
|
||||
}
|
||||
(*m0)->m_pkthdr.len = totlen;
|
||||
|
||||
return(0);
|
||||
@ -770,6 +801,7 @@ ndis_mtop(m0, p)
|
||||
*p = NULL;
|
||||
return(ENOMEM);
|
||||
}
|
||||
MmBuildMdlForNonPagedPool(buf);
|
||||
|
||||
if (priv->npp_head == NULL)
|
||||
priv->npp_head = buf;
|
||||
@ -826,8 +858,8 @@ ndis_set_info(arg, oid, buf, buflen)
|
||||
ndis_handle adapter;
|
||||
ndis_setinfo_handler setfunc;
|
||||
uint32_t byteswritten = 0, bytesneeded = 0;
|
||||
int error;
|
||||
uint8_t irql;
|
||||
uint64_t duetime;
|
||||
|
||||
/*
|
||||
* According to the NDIS spec, MiniportQueryInformation()
|
||||
@ -840,25 +872,22 @@ ndis_set_info(arg, oid, buf, buflen)
|
||||
|
||||
KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
|
||||
|
||||
if (sc->ndis_block->nmb_pendingreq != NULL)
|
||||
if (sc->ndis_block->nmb_pendingreq != NULL) {
|
||||
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
|
||||
panic("ndis_set_info() called while other request pending");
|
||||
else
|
||||
} else
|
||||
sc->ndis_block->nmb_pendingreq = (ndis_request *)sc;
|
||||
|
||||
NDIS_LOCK(sc);
|
||||
setfunc = sc->ndis_chars->nmc_setinfo_func;
|
||||
adapter = sc->ndis_block->nmb_miniportadapterctx;
|
||||
|
||||
if (adapter == NULL || setfunc == NULL ||
|
||||
sc->ndis_block->nmb_devicectx == NULL) {
|
||||
sc->ndis_block->nmb_pendingreq = NULL;
|
||||
NDIS_UNLOCK(sc);
|
||||
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
NDIS_UNLOCK(sc);
|
||||
|
||||
rval = MSCALL6(setfunc, adapter, oid, buf, *buflen,
|
||||
&byteswritten, &bytesneeded);
|
||||
|
||||
@ -867,15 +896,14 @@ ndis_set_info(arg, oid, buf, buflen)
|
||||
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
|
||||
|
||||
if (rval == NDIS_STATUS_PENDING) {
|
||||
mtx_lock(&ndis_req_mtx);
|
||||
error = msleep(&sc->ndis_block->nmb_setstat,
|
||||
&ndis_req_mtx,
|
||||
curthread->td_priority|PDROP,
|
||||
"ndisset", 5 * hz);
|
||||
/* Wait up to 5 seconds. */
|
||||
duetime = (5 * 1000000) * -10;
|
||||
KeResetEvent(&sc->ndis_block->nmb_setevent);
|
||||
KeWaitForSingleObject(&sc->ndis_block->nmb_setevent,
|
||||
0, 0, FALSE, &duetime);
|
||||
rval = sc->ndis_block->nmb_setstat;
|
||||
}
|
||||
|
||||
|
||||
if (byteswritten)
|
||||
*buflen = byteswritten;
|
||||
if (bytesneeded)
|
||||
@ -1072,16 +1100,14 @@ ndis_reset_nic(arg)
|
||||
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
|
||||
|
||||
if (rval == NDIS_STATUS_PENDING) {
|
||||
mtx_lock(&ndis_req_mtx);
|
||||
msleep(sc, &ndis_req_mtx,
|
||||
curthread->td_priority|PDROP, "ndisrst", 0);
|
||||
KeResetEvent(&sc->ndis_block->nmb_resetevent);
|
||||
KeWaitForSingleObject(&sc->ndis_block->nmb_resetevent,
|
||||
0, 0, FALSE, NULL);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#define NDIS_REAP_TIMERS
|
||||
|
||||
int
|
||||
ndis_halt_nic(arg)
|
||||
void *arg;
|
||||
@ -1089,32 +1115,28 @@ ndis_halt_nic(arg)
|
||||
struct ndis_softc *sc;
|
||||
ndis_handle adapter;
|
||||
ndis_halt_handler haltfunc;
|
||||
#ifdef NDIS_REAP_TIMERS
|
||||
ndis_miniport_timer *t, *n;
|
||||
#endif
|
||||
ndis_miniport_block *block;
|
||||
int empty = 0;
|
||||
uint8_t irql;
|
||||
|
||||
sc = arg;
|
||||
block = sc->ndis_block;
|
||||
|
||||
#ifdef NDIS_REAP_TIMERS
|
||||
/*
|
||||
* Drivers are sometimes very lax about cancelling all
|
||||
* their timers. Cancel them all ourselves, just to be
|
||||
* safe. We must do this before invoking MiniportHalt(),
|
||||
* since if we wait until after, the memory in which
|
||||
* the timers reside will no longer be valid.
|
||||
*/
|
||||
|
||||
t = sc->ndis_block->nmb_timerlist;
|
||||
while (t != NULL) {
|
||||
KeCancelTimer(&t->nmt_ktimer);
|
||||
n = t;
|
||||
t = t->nmt_nexttimer;
|
||||
n->nmt_nexttimer = NULL;
|
||||
}
|
||||
sc->ndis_block->nmb_timerlist = NULL;
|
||||
if (!cold)
|
||||
KeFlushQueuedDpcs();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Wait for all packets to be returned.
|
||||
*/
|
||||
|
||||
while (1) {
|
||||
KeAcquireSpinLock(&block->nmb_returnlock, &irql);
|
||||
empty = IsListEmpty(&block->nmb_returnlist);
|
||||
KeReleaseSpinLock(&block->nmb_returnlock, irql);
|
||||
if (empty)
|
||||
break;
|
||||
NdisMSleep(1000);
|
||||
}
|
||||
|
||||
NDIS_LOCK(sc);
|
||||
adapter = sc->ndis_block->nmb_miniportadapterctx;
|
||||
@ -1123,7 +1145,6 @@ ndis_halt_nic(arg)
|
||||
return(EIO);
|
||||
}
|
||||
|
||||
sc->ndis_block->nmb_miniportadapterctx = NULL;
|
||||
sc->ndis_block->nmb_devicectx = NULL;
|
||||
|
||||
/*
|
||||
@ -1137,6 +1158,10 @@ ndis_halt_nic(arg)
|
||||
|
||||
MSCALL1(haltfunc, adapter);
|
||||
|
||||
NDIS_LOCK(sc);
|
||||
sc->ndis_block->nmb_miniportadapterctx = NULL;
|
||||
NDIS_UNLOCK(sc);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -1216,7 +1241,7 @@ ndis_init_nic(arg)
|
||||
* expects them to fire before the halt is called.
|
||||
*/
|
||||
|
||||
ndis_thsuspend(curthread->td_proc, NULL, hz);
|
||||
tsleep(curthread->td_proc, PWAIT, "ndwait", hz);
|
||||
|
||||
NDIS_LOCK(sc);
|
||||
sc->ndis_block->nmb_devicectx = sc;
|
||||
@ -1292,33 +1317,26 @@ ndis_isr(arg, ourintr, callhandler)
|
||||
}
|
||||
|
||||
static void
|
||||
ndis_intrhand(dpc, dobj, ip, sc)
|
||||
ndis_intrsetup(dpc, dobj, ip, sc)
|
||||
kdpc *dpc;
|
||||
device_object *dobj;
|
||||
irp *ip;
|
||||
struct ndis_softc *sc;
|
||||
{
|
||||
ndis_handle adapter;
|
||||
ndis_interrupt_handler intrfunc;
|
||||
uint8_t irql;
|
||||
ndis_miniport_interrupt *intr;
|
||||
|
||||
adapter = sc->ndis_block->nmb_miniportadapterctx;
|
||||
intrfunc = sc->ndis_chars->nmc_interrupt_func;
|
||||
intr = sc->ndis_block->nmb_interrupt;
|
||||
|
||||
if (adapter == NULL || intrfunc == NULL)
|
||||
/* Sanity check. */
|
||||
|
||||
if (intr == NULL)
|
||||
return;
|
||||
|
||||
if (NDIS_SERIALIZED(sc->ndis_block))
|
||||
KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
|
||||
|
||||
MSCALL1(intrfunc, adapter);
|
||||
|
||||
/* If there's a MiniportEnableInterrupt() routine, call it. */
|
||||
|
||||
ndis_enable_intr(sc);
|
||||
|
||||
if (NDIS_SERIALIZED(sc->ndis_block))
|
||||
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
|
||||
KeAcquireSpinLockAtDpcLevel(&intr->ni_dpccountlock);
|
||||
KeResetEvent(&intr->ni_dpcevt);
|
||||
if (KeInsertQueueDpc(&intr->ni_dpc, NULL, NULL) == TRUE)
|
||||
intr->ni_dpccnt++;
|
||||
KeReleaseSpinLockFromDpcLevel(&intr->ni_dpccountlock);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1335,32 +1353,29 @@ ndis_get_info(arg, oid, buf, buflen)
|
||||
ndis_handle adapter;
|
||||
ndis_queryinfo_handler queryfunc;
|
||||
uint32_t byteswritten = 0, bytesneeded = 0;
|
||||
int error;
|
||||
uint8_t irql;
|
||||
uint64_t duetime;
|
||||
|
||||
sc = arg;
|
||||
|
||||
KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
|
||||
|
||||
if (sc->ndis_block->nmb_pendingreq != NULL)
|
||||
if (sc->ndis_block->nmb_pendingreq != NULL) {
|
||||
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
|
||||
panic("ndis_get_info() called while other request pending");
|
||||
else
|
||||
} else
|
||||
sc->ndis_block->nmb_pendingreq = (ndis_request *)sc;
|
||||
|
||||
NDIS_LOCK(sc);
|
||||
queryfunc = sc->ndis_chars->nmc_queryinfo_func;
|
||||
adapter = sc->ndis_block->nmb_miniportadapterctx;
|
||||
|
||||
if (adapter == NULL || queryfunc == NULL ||
|
||||
sc->ndis_block->nmb_devicectx == NULL) {
|
||||
sc->ndis_block->nmb_pendingreq = NULL;
|
||||
NDIS_UNLOCK(sc);
|
||||
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
NDIS_UNLOCK(sc);
|
||||
|
||||
rval = MSCALL6(queryfunc, adapter, oid, buf, *buflen,
|
||||
&byteswritten, &bytesneeded);
|
||||
|
||||
@ -1371,11 +1386,11 @@ ndis_get_info(arg, oid, buf, buflen)
|
||||
/* Wait for requests that block. */
|
||||
|
||||
if (rval == NDIS_STATUS_PENDING) {
|
||||
mtx_lock(&ndis_req_mtx);
|
||||
error = msleep(&sc->ndis_block->nmb_getstat,
|
||||
&ndis_req_mtx,
|
||||
curthread->td_priority|PDROP,
|
||||
"ndisget", 5 * hz);
|
||||
/* Wait up to 5 seconds. */
|
||||
duetime = (5 * 1000000) * -10;
|
||||
KeResetEvent(&sc->ndis_block->nmb_getevent);
|
||||
KeWaitForSingleObject(&sc->ndis_block->nmb_getevent,
|
||||
0, 0, FALSE, &duetime);
|
||||
rval = sc->ndis_block->nmb_getstat;
|
||||
}
|
||||
|
||||
@ -1410,6 +1425,17 @@ NdisAddDevice(drv, pdo)
|
||||
ndis_miniport_block *block;
|
||||
struct ndis_softc *sc;
|
||||
uint32_t status;
|
||||
int error;
|
||||
|
||||
sc = device_get_softc(pdo->do_devext);
|
||||
|
||||
if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus) {
|
||||
error = bus_setup_intr(sc->ndis_dev, sc->ndis_irq,
|
||||
INTR_TYPE_NET | INTR_MPSAFE,
|
||||
ntoskrnl_intr, NULL, &sc->ndis_intrhand);
|
||||
if (error)
|
||||
return(NDIS_STATUS_FAILURE);
|
||||
}
|
||||
|
||||
status = IoCreateDevice(drv, sizeof(ndis_miniport_block), NULL,
|
||||
FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);
|
||||
@ -1424,13 +1450,19 @@ NdisAddDevice(drv, pdo)
|
||||
block->nmb_physdeviceobj = pdo;
|
||||
block->nmb_nextdeviceobj = IoAttachDeviceToDeviceStack(fdo, pdo);
|
||||
KeInitializeSpinLock(&block->nmb_lock);
|
||||
KeInitializeSpinLock(&block->nmb_returnlock);
|
||||
KeInitializeEvent(&block->nmb_getevent, EVENT_TYPE_NOTIFY, TRUE);
|
||||
KeInitializeEvent(&block->nmb_setevent, EVENT_TYPE_NOTIFY, TRUE);
|
||||
KeInitializeEvent(&block->nmb_resetevent, EVENT_TYPE_NOTIFY, TRUE);
|
||||
InitializeListHead(&block->nmb_parmlist);
|
||||
InitializeListHead(&block->nmb_returnlist);
|
||||
block->nmb_returnitem = IoAllocateWorkItem(fdo);
|
||||
|
||||
/*
|
||||
* Stash pointers to the miniport block and miniport
|
||||
* characteristics info in the if_ndis softc so the
|
||||
* UNIX wrapper driver can get to them later.
|
||||
*/
|
||||
sc = device_get_softc(pdo->do_devext);
|
||||
sc->ndis_block = block;
|
||||
sc->ndis_chars = IoGetDriverObjectExtension(drv, (void *)1);
|
||||
|
||||
@ -1447,7 +1479,7 @@ NdisAddDevice(drv, pdo)
|
||||
IoDeleteDevice(fdo);
|
||||
return(status);
|
||||
}
|
||||
INIT_LIST_HEAD((&block->nmb_packetlist));
|
||||
InitializeListHead((&block->nmb_packetlist));
|
||||
}
|
||||
|
||||
/* Give interrupt handling priority over timers. */
|
||||
@ -1479,6 +1511,10 @@ ndis_unload_driver(arg)
|
||||
|
||||
sc = arg;
|
||||
|
||||
if (sc->ndis_intrhand)
|
||||
bus_teardown_intr(sc->ndis_dev,
|
||||
sc->ndis_irq, sc->ndis_intrhand);
|
||||
|
||||
if (sc->ndis_block->nmb_rlist != NULL)
|
||||
free(sc->ndis_block->nmb_rlist, M_DEVBUF);
|
||||
|
||||
@ -1489,6 +1525,7 @@ ndis_unload_driver(arg)
|
||||
if (sc->ndis_chars->nmc_transferdata_func != NULL)
|
||||
NdisFreePacketPool(sc->ndis_block->nmb_rxpool);
|
||||
fdo = sc->ndis_block->nmb_deviceobj;
|
||||
IoFreeWorkItem(sc->ndis_block->nmb_returnitem);
|
||||
IoDetachDevice(sc->ndis_block->nmb_nextdeviceobj);
|
||||
IoDeleteDevice(fdo);
|
||||
|
||||
|
@ -137,8 +137,8 @@ windrv_libfini(void)
|
||||
}
|
||||
mtx_unlock(&drvdb_mtx);
|
||||
|
||||
free(fake_pci_driver.dro_drivername.us_buf, M_DEVBUF);
|
||||
free(fake_pccard_driver.dro_drivername.us_buf, M_DEVBUF);
|
||||
RtlFreeUnicodeString(&fake_pci_driver.dro_drivername);
|
||||
RtlFreeUnicodeString(&fake_pccard_driver.dro_drivername);
|
||||
|
||||
mtx_destroy(&drvdb_mtx);
|
||||
|
||||
@ -161,16 +161,16 @@ windrv_lookup(img, name)
|
||||
{
|
||||
struct drvdb_ent *d;
|
||||
unicode_string us;
|
||||
ansi_string as;
|
||||
|
||||
bzero((char *)&us, sizeof(us));
|
||||
|
||||
/* Damn unicode. */
|
||||
|
||||
if (name != NULL) {
|
||||
us.us_len = strlen(name) * 2;
|
||||
us.us_maxlen = strlen(name) * 2;
|
||||
us.us_buf = NULL;
|
||||
ndis_ascii_to_unicode(name, &us.us_buf);
|
||||
RtlInitAnsiString(&as, name);
|
||||
if (RtlAnsiStringToUnicodeString(&us, &as, TRUE))
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
mtx_lock(&drvdb_mtx);
|
||||
@ -187,7 +187,7 @@ windrv_lookup(img, name)
|
||||
mtx_unlock(&drvdb_mtx);
|
||||
|
||||
if (name != NULL)
|
||||
ExFreePool(us.us_buf);
|
||||
RtlFreeUnicodeString(&us);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
@ -230,7 +230,7 @@ windrv_unload(mod, img, len)
|
||||
driver_object *drv;
|
||||
device_object *d, *pdo;
|
||||
device_t dev;
|
||||
list_entry *e, *c;
|
||||
list_entry *e;
|
||||
|
||||
drv = windrv_lookup(img, NULL);
|
||||
|
||||
@ -267,7 +267,7 @@ windrv_unload(mod, img, len)
|
||||
mtx_lock(&drvdb_mtx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STAILQ_FOREACH(db, &drvdb_head, link) {
|
||||
if (db->windrv_object->dro_driverstart == (void *)img) {
|
||||
r = db;
|
||||
@ -280,23 +280,23 @@ windrv_unload(mod, img, len)
|
||||
if (r == NULL)
|
||||
return (ENOENT);
|
||||
|
||||
if (drv == NULL)
|
||||
return(ENOENT);
|
||||
|
||||
/*
|
||||
* Destroy any custom extensions that may have been added.
|
||||
*/
|
||||
drv = r->windrv_object;
|
||||
e = drv->dro_driverext->dre_usrext.nle_flink;
|
||||
while (e != &drv->dro_driverext->dre_usrext) {
|
||||
c = e->nle_flink;
|
||||
REMOVE_LIST_ENTRY(e);
|
||||
while (!IsListEmpty(&drv->dro_driverext->dre_usrext)) {
|
||||
e = RemoveHeadList(&drv->dro_driverext->dre_usrext);
|
||||
ExFreePool(e);
|
||||
e = c;
|
||||
}
|
||||
|
||||
/* Free the driver extension */
|
||||
free(drv->dro_driverext, M_DEVBUF);
|
||||
|
||||
/* Free the driver name */
|
||||
free(drv->dro_drivername.us_buf, M_DEVBUF);
|
||||
RtlFreeUnicodeString(&drv->dro_drivername);
|
||||
|
||||
/* Free driver object */
|
||||
free(drv, M_DEVBUF);
|
||||
@ -330,6 +330,7 @@ windrv_load(mod, img, len, bustype, devlist, regvals)
|
||||
struct driver_object *drv;
|
||||
int status;
|
||||
uint32_t *ptr;
|
||||
ansi_string as;
|
||||
|
||||
/*
|
||||
* First step: try to relocate and dynalink the executable
|
||||
@ -396,16 +397,17 @@ windrv_load(mod, img, len, bustype, devlist, regvals)
|
||||
return(ENOMEM);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD((&drv->dro_driverext->dre_usrext));
|
||||
InitializeListHead((&drv->dro_driverext->dre_usrext));
|
||||
|
||||
drv->dro_driverstart = (void *)img;
|
||||
drv->dro_driversize = len;
|
||||
|
||||
drv->dro_drivername.us_len = strlen(DUMMY_REGISTRY_PATH) * 2;
|
||||
drv->dro_drivername.us_maxlen = strlen(DUMMY_REGISTRY_PATH) * 2;
|
||||
drv->dro_drivername.us_buf = NULL;
|
||||
ndis_ascii_to_unicode(DUMMY_REGISTRY_PATH,
|
||||
&drv->dro_drivername.us_buf);
|
||||
RtlInitAnsiString(&as, DUMMY_REGISTRY_PATH);
|
||||
if (RtlAnsiStringToUnicodeString(&drv->dro_drivername, &as, TRUE)) {
|
||||
free(new, M_DEVBUF);
|
||||
free(drv, M_DEVBUF);
|
||||
return(ENOMEM);
|
||||
}
|
||||
|
||||
new->windrv_object = drv;
|
||||
new->windrv_regvals = regvals;
|
||||
@ -417,7 +419,7 @@ windrv_load(mod, img, len, bustype, devlist, regvals)
|
||||
status = MSCALL2(entry, drv, &drv->dro_drivername);
|
||||
|
||||
if (status != STATUS_SUCCESS) {
|
||||
free(drv->dro_drivername.us_buf, M_DEVBUF);
|
||||
RtlFreeUnicodeString(&drv->dro_drivername);
|
||||
free(drv, M_DEVBUF);
|
||||
free(new, M_DEVBUF);
|
||||
return(ENODEV);
|
||||
@ -517,15 +519,15 @@ windrv_bus_attach(drv, name)
|
||||
char *name;
|
||||
{
|
||||
struct drvdb_ent *new;
|
||||
ansi_string as;
|
||||
|
||||
new = malloc(sizeof(struct drvdb_ent), M_DEVBUF, M_NOWAIT|M_ZERO);
|
||||
if (new == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
drv->dro_drivername.us_len = strlen(name) * 2;
|
||||
drv->dro_drivername.us_maxlen = strlen(name) * 2;
|
||||
drv->dro_drivername.us_buf = NULL;
|
||||
ndis_ascii_to_unicode(name, &drv->dro_drivername.us_buf);
|
||||
RtlInitAnsiString(&as, name);
|
||||
if (RtlAnsiStringToUnicodeString(&drv->dro_drivername, &as, TRUE))
|
||||
return(ENOMEM);
|
||||
|
||||
/*
|
||||
* Set up a fake image pointer to avoid false matches
|
||||
@ -674,7 +676,7 @@ ctxsw_utow(void)
|
||||
* hasn't, we need to do it right now or else things will
|
||||
* explode.
|
||||
*/
|
||||
|
||||
|
||||
if (t->tid_self != t)
|
||||
x86_newldt(NULL);
|
||||
|
||||
|
@ -268,6 +268,31 @@ typedef uint8_t ndis_kirql;
|
||||
#define OID_PNP_WAKE_UP_PATTERN_LIST 0xFD010105
|
||||
#define OID_PNP_ENABLE_WAKE_UP 0xFD010106
|
||||
|
||||
/*
|
||||
* These are the possible power states for
|
||||
* OID_PNP_SET_POWER and OID_PNP_QUERY_POWER.
|
||||
*/
|
||||
#define NDIS_POWERSTATE_UNSPEC 0
|
||||
#define NDIS_POWERSTATE_D0 1
|
||||
#define NDIS_POWERSTATE_D1 2
|
||||
#define NDIS_POWERSTATE_D2 3
|
||||
#define NDIS_POWERSTATE_D3 4
|
||||
|
||||
/*
|
||||
* These are used with the MiniportPnpEventNotify() method.
|
||||
*/
|
||||
|
||||
#define NDIS_POWERPROFILE_BATTERY 0
|
||||
#define NDIS_POWERPROFILE_ACONLINE 1
|
||||
|
||||
#define NDIS_PNP_EVENT_QUERY_REMOVED 0
|
||||
#define NDIS_PNP_EVENT_REMOVED 1
|
||||
#define NDIS_PNP_EVENT_SURPRISE_REMOVED 2
|
||||
#define NDIS_PNP_EVENT_QUERY_STOPPED 3
|
||||
#define NDIS_PNP_EVENT_STOPPED 4
|
||||
#define NDIS_PNP_EVENT_PROFILECHANGED 5
|
||||
|
||||
|
||||
/* PnP/PM Statistics (Optional). */
|
||||
#define OID_PNP_WAKE_UP_OK 0xFD020200
|
||||
#define OID_PNP_WAKE_UP_ERROR 0xFD020201
|
||||
@ -310,12 +335,15 @@ typedef uint8_t ndis_kirql;
|
||||
#define OID_802_11_REMOVE_KEY 0x0D01011E
|
||||
#define OID_802_11_ASSOCIATION_INFORMATION 0x0D01011F
|
||||
#define OID_802_11_TEST 0x0D010120
|
||||
#define OID_802_11_CAPABILITY 0x0D010122
|
||||
#define OID_802_11_PMKID 0x0D010123
|
||||
|
||||
/* structures/definitions for 802.11 */
|
||||
#define NDIS_80211_NETTYPE_11FH 0x00000000
|
||||
#define NDIS_80211_NETTYPE_11DS 0x00000001
|
||||
#define NDIS_80211_NETTYPE_11OFDM5 0x00000002
|
||||
#define NDIS_80211_NETTYPE_11OFDM24 0x00000003
|
||||
#define NDIS_80211_NETTYPE_AUTO 0x00000004
|
||||
|
||||
struct ndis_80211_nettype_list {
|
||||
uint32_t ntl_items;
|
||||
@ -390,6 +418,8 @@ typedef struct ndis_80211_wep ndis_80211_wep;
|
||||
#define NDIS_80211_AUTHMODE_WPA 0x00000003
|
||||
#define NDIS_80211_AUTHMODE_WPAPSK 0x00000004
|
||||
#define NDIS_80211_AUTHMODE_WPANONE 0x00000005
|
||||
#define NDIS_80211_AUTHMODE_WPA2 0x00000006
|
||||
#define NDIS_80211_AUTHMODE_WPA2PSK 0x00000007
|
||||
|
||||
typedef uint8_t ndis_80211_rates[8];
|
||||
typedef uint8_t ndis_80211_rates_ex[16];
|
||||
@ -483,6 +513,7 @@ typedef uint32_t ndis_80211_antenna;
|
||||
#define NDIS_80211_RELOADDEFAULT_WEP 0x00000000
|
||||
|
||||
#define NDIS_80211_STATUSTYPE_AUTH 0x00000000
|
||||
#define NDIS_80211_STATUSTYPE_PMKIDLIST 0x00000001
|
||||
|
||||
struct ndis_80211_status_indication {
|
||||
uint32_t nsi_type;
|
||||
@ -490,6 +521,11 @@ struct ndis_80211_status_indication {
|
||||
|
||||
typedef struct ndis_80211_status_indication ndis_80211_status_indication;
|
||||
|
||||
#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01
|
||||
#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02
|
||||
#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06
|
||||
#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E
|
||||
|
||||
struct ndis_80211_auth_request {
|
||||
uint32_t nar_len;
|
||||
ndis_80211_macaddr nar_bssid;
|
||||
@ -503,8 +539,9 @@ struct ndis_80211_key {
|
||||
uint32_t nk_keyidx;
|
||||
uint32_t nk_keylen;
|
||||
ndis_80211_macaddr nk_bssid;
|
||||
uint8_t nk_pad[6];
|
||||
uint64_t nk_keyrsc;
|
||||
uint8_t nk_keydata[256];
|
||||
uint8_t nk_keydata[32];
|
||||
};
|
||||
|
||||
typedef struct ndis_80211_key ndis_80211_key;
|
||||
@ -573,6 +610,61 @@ struct ndis_80211_test {
|
||||
|
||||
typedef struct ndis_80211_test ndis_80211_test;
|
||||
|
||||
struct ndis_80211_auth_encrypt {
|
||||
uint32_t ne_authmode;
|
||||
uint32_t ne_cryptstat;
|
||||
};
|
||||
|
||||
typedef struct ndis_80211_auth_encrypt ndis_80211_auth_encrypt;
|
||||
|
||||
struct ndis_80211_caps {
|
||||
uint32_t nc_len;
|
||||
uint32_t nc_ver;
|
||||
uint32_t nc_numpmkids;
|
||||
ndis_80211_auth_encrypt nc_authencs[1];
|
||||
};
|
||||
|
||||
typedef struct ndis_80211_caps ndis_80211_caps;
|
||||
|
||||
struct ndis_80211_bssidinfo {
|
||||
ndis_80211_macaddr nb_bssid;
|
||||
uint8_t nb_pmkid[16];
|
||||
};
|
||||
|
||||
typedef struct ndis_80211_bssidinfo ndis_80211_bssidinfo;
|
||||
|
||||
struct ndis_80211_pmkid {
|
||||
uint32_t np_len;
|
||||
uint32_t np_bssidcnt;
|
||||
ndis_80211_bssidinfo np_bssidinfo[1];
|
||||
};
|
||||
|
||||
typedef struct ndis_80211_pmkid ndis_80211_pmkid;
|
||||
|
||||
struct ndis_80211_pmkid_cand {
|
||||
ndis_80211_macaddr npc_bssid;
|
||||
uint32_t npc_flags;
|
||||
};
|
||||
|
||||
typedef struct ndis_80211_pmkid_cand ndis_80211_pmkid_cand;
|
||||
|
||||
#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED (0x01)
|
||||
|
||||
struct ndis_80211_pmkid_candidate_list {
|
||||
uint32_t npcl_version;
|
||||
uint32_t npcl_numcandidates;
|
||||
ndis_80211_pmkid_cand npcl_candidatelist[1];
|
||||
};
|
||||
|
||||
typedef struct ndis_80211_pmkid_candidate_list ndis_80211_pmkid_candidate_list;
|
||||
|
||||
struct ndis_80211_enc_indication {
|
||||
uint32_t nei_statustype;
|
||||
ndis_80211_pmkid_candidate_list nei_pmkidlist;
|
||||
};
|
||||
|
||||
typedef struct ndis_80211_enc_indication ndis_80211_enc_indication;
|
||||
|
||||
/* TCP OIDs. */
|
||||
|
||||
#define OID_TCP_TASK_OFFLOAD 0xFC010201
|
||||
@ -682,6 +774,7 @@ typedef struct ndis_task_ipsec ndis_task_ipsec;
|
||||
* all attributes.
|
||||
*/
|
||||
|
||||
#define NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT 0x00000001
|
||||
#define NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT 0x00000002
|
||||
#define NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS 0x00000004
|
||||
#define NDIS_ATTRIBUTE_BUS_MASTER 0x00000008
|
||||
@ -805,8 +898,20 @@ struct ndis_config_parm {
|
||||
} ncp_parmdata;
|
||||
};
|
||||
|
||||
/*
|
||||
* Not part of Windows NDIS spec; we uses this to keep a
|
||||
* list of ndis_config_parm structures that we've allocated.
|
||||
*/
|
||||
|
||||
typedef struct ndis_config_parm ndis_config_parm;
|
||||
|
||||
struct ndis_parmlist_entry {
|
||||
list_entry np_list;
|
||||
ndis_config_parm np_parm;
|
||||
};
|
||||
|
||||
typedef struct ndis_parmlist_entry ndis_parmlist_entry;
|
||||
|
||||
#ifdef notdef
|
||||
struct ndis_list_entry {
|
||||
struct ndis_list_entry *nle_flink;
|
||||
@ -952,16 +1057,16 @@ typedef struct ndis_request ndis_request;
|
||||
* Filler, not used.
|
||||
*/
|
||||
struct ndis_miniport_interrupt {
|
||||
void *ni_introbj;
|
||||
kinterrupt *ni_introbj;
|
||||
ndis_kspin_lock ni_dpccountlock;
|
||||
void *ni_rsvd;
|
||||
void *ni_isrfunc;
|
||||
void *ni_dpcfunc;
|
||||
struct ndis_kdpc ni_dpc;
|
||||
kdpc ni_dpc;
|
||||
ndis_miniport_block *ni_block;
|
||||
uint8_t ni_dpccnt;
|
||||
uint8_t ni_filler1;
|
||||
struct ndis_kevent ni_dpcsdoneevent;
|
||||
struct nt_kevent ni_dpcevt;
|
||||
uint8_t ni_shared;
|
||||
uint8_t ni_isrreq;
|
||||
};
|
||||
@ -1208,12 +1313,24 @@ struct ndis_packet {
|
||||
void *np_softc;
|
||||
void *np_m0;
|
||||
int np_txidx;
|
||||
kdpc np_dpc;
|
||||
kspin_lock np_lock;
|
||||
list_entry np_list;
|
||||
};
|
||||
|
||||
typedef struct ndis_packet ndis_packet;
|
||||
|
||||
struct ndis_packet_pool {
|
||||
slist_header np_head;
|
||||
int np_dead;
|
||||
nt_kevent np_event;
|
||||
kspin_lock np_lock;
|
||||
int np_cnt;
|
||||
int np_len;
|
||||
int np_protrsvd;
|
||||
void *np_pktmem;
|
||||
};
|
||||
|
||||
typedef struct ndis_packet_pool ndis_packet_pool;
|
||||
|
||||
/* mbuf ext type for NDIS */
|
||||
#define EXT_NDIS 0x999
|
||||
|
||||
@ -1506,13 +1623,18 @@ struct ndis_miniport_block {
|
||||
* End of windows-specific portion of miniport block. Everything
|
||||
* below is BSD-specific.
|
||||
*/
|
||||
uint8_t nmb_dummybuf[128];
|
||||
ndis_config_parm nmb_replyparm;
|
||||
list_entry nmb_parmlist;
|
||||
ndis_resource_list *nmb_rlist;
|
||||
ndis_status nmb_getstat;
|
||||
nt_kevent nmb_getevent;
|
||||
ndis_status nmb_setstat;
|
||||
nt_kevent nmb_setevent;
|
||||
nt_kevent nmb_resetevent;
|
||||
io_workitem *nmb_returnitem;
|
||||
ndis_miniport_timer *nmb_timerlist;
|
||||
ndis_handle nmb_rxpool;
|
||||
list_entry nmb_returnlist;
|
||||
kspin_lock nmb_returnlock;
|
||||
TAILQ_ENTRY(ndis_miniport_block) link;
|
||||
};
|
||||
|
||||
@ -1600,8 +1722,6 @@ extern image_patch_table ndis_functbl[];
|
||||
__BEGIN_DECLS
|
||||
extern int ndis_libinit(void);
|
||||
extern int ndis_libfini(void);
|
||||
extern int ndis_ascii_to_unicode(char *, uint16_t **);
|
||||
extern int ndis_unicode_to_ascii(uint16_t *, int, char **);
|
||||
extern int ndis_load_driver(vm_offset_t, void *);
|
||||
extern int ndis_unload_driver(void *);
|
||||
extern int ndis_mtop(struct mbuf *, ndis_packet **);
|
||||
@ -1629,8 +1749,6 @@ extern int ndis_destroy_dma(void *);
|
||||
extern int ndis_create_sysctls(void *);
|
||||
extern int ndis_add_sysctl(void *, char *, char *, char *, int);
|
||||
extern int ndis_flush_sysctls(void *);
|
||||
extern int ndis_thsuspend(struct proc *, struct mtx *, int);
|
||||
extern void ndis_thresume(struct proc *);
|
||||
extern int ndis_strcasecmp(const char *, const char *);
|
||||
extern int ndis_strncasecmp(const char *, const char *, size_t);
|
||||
|
||||
@ -1645,7 +1763,7 @@ extern void NdisAllocatePacket(ndis_status *,
|
||||
ndis_packet **, ndis_handle);
|
||||
extern void NdisFreePacket(ndis_packet *);
|
||||
extern ndis_status NdisScheduleWorkItem(ndis_work_item *);
|
||||
|
||||
extern void NdisMSleep(uint32_t);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _NDIS_VAR_H_ */
|
||||
|
@ -35,6 +35,8 @@
|
||||
#ifndef _NTOSKRNL_VAR_H_
|
||||
#define _NTOSKRNL_VAR_H_
|
||||
|
||||
#define MTX_NTOSKRNL_SPIN_LOCK "NDIS thread lock"
|
||||
|
||||
/*
|
||||
* us_buf is really a wchar_t *, but it's inconvenient to include
|
||||
* all the necessary header goop needed to define it, and it's a
|
||||
@ -48,6 +50,14 @@ struct unicode_string {
|
||||
|
||||
typedef struct unicode_string unicode_string;
|
||||
|
||||
struct ansi_string {
|
||||
uint16_t as_len;
|
||||
uint16_t as_maxlen;
|
||||
char *as_buf;
|
||||
};
|
||||
|
||||
typedef struct ansi_string ansi_string;
|
||||
|
||||
/*
|
||||
* Windows memory descriptor list. In Windows, it's possible for
|
||||
* buffers to be passed between user and kernel contexts without
|
||||
@ -197,43 +207,54 @@ struct list_entry {
|
||||
|
||||
typedef struct list_entry list_entry;
|
||||
|
||||
#define INIT_LIST_HEAD(l) \
|
||||
#define InitializeListHead(l) \
|
||||
(l)->nle_flink = (l)->nle_blink = (l)
|
||||
|
||||
#define REMOVE_LIST_ENTRY(e) \
|
||||
#define IsListEmpty(h) \
|
||||
((h)->nle_flink == (h))
|
||||
|
||||
#define RemoveEntryList(e) \
|
||||
do { \
|
||||
list_entry *b; \
|
||||
list_entry *f; \
|
||||
\
|
||||
f = e->nle_flink; \
|
||||
b = e->nle_blink; \
|
||||
f = (e)->nle_flink; \
|
||||
b = (e)->nle_blink; \
|
||||
b->nle_flink = f; \
|
||||
f->nle_blink = b; \
|
||||
} while (0)
|
||||
|
||||
#define REMOVE_LIST_HEAD(l) \
|
||||
do { \
|
||||
list_entry *f; \
|
||||
list_entry *e; \
|
||||
\
|
||||
e = l->nle_flink; \
|
||||
f = e->nle_flink; \
|
||||
l->nle_flink = f; \
|
||||
f->nle_blink = l; \
|
||||
} while (0)
|
||||
/* These two have to be inlined since they return things. */
|
||||
|
||||
#define REMOVE_LIST_TAIL(l) \
|
||||
do { \
|
||||
list_entry *b; \
|
||||
list_entry *e; \
|
||||
\
|
||||
e = l->nle_blink; \
|
||||
b = e->nle_blink; \
|
||||
l->nle_blink = b; \
|
||||
b->nle_flink = l; \
|
||||
} while (0)
|
||||
static __inline__ list_entry *
|
||||
RemoveHeadList(list_entry *l)
|
||||
{
|
||||
list_entry *f;
|
||||
list_entry *e;
|
||||
|
||||
#define INSERT_LIST_TAIL(l, e) \
|
||||
e = l->nle_flink;
|
||||
f = e->nle_flink;
|
||||
l->nle_flink = f;
|
||||
f->nle_blink = l;
|
||||
|
||||
return (e);
|
||||
}
|
||||
|
||||
static __inline__ list_entry *
|
||||
RemoveTailList(list_entry *l)
|
||||
{
|
||||
list_entry *b;
|
||||
list_entry *e;
|
||||
|
||||
e = l->nle_blink;
|
||||
b = e->nle_blink;
|
||||
l->nle_blink = b;
|
||||
b->nle_flink = l;
|
||||
|
||||
return (e);
|
||||
}
|
||||
|
||||
#define InsertTailList(l, e) \
|
||||
do { \
|
||||
list_entry *b; \
|
||||
\
|
||||
@ -244,7 +265,7 @@ typedef struct list_entry list_entry;
|
||||
l->nle_blink = (e); \
|
||||
} while (0)
|
||||
|
||||
#define INSERT_LIST_HEAD(l, e) \
|
||||
#define InsertHeadList(l, e) \
|
||||
do { \
|
||||
list_entry *f; \
|
||||
\
|
||||
@ -263,12 +284,24 @@ struct nt_dispatch_header {
|
||||
uint8_t dh_abs;
|
||||
uint8_t dh_size;
|
||||
uint8_t dh_inserted;
|
||||
uint32_t dh_sigstate;
|
||||
int32_t dh_sigstate;
|
||||
list_entry dh_waitlisthead;
|
||||
};
|
||||
|
||||
typedef struct nt_dispatch_header nt_dispatch_header;
|
||||
|
||||
/* Dispatcher object types */
|
||||
|
||||
#define DISP_TYPE_NOTIFICATION_EVENT 0 /* KEVENT */
|
||||
#define DISP_TYPE_SYNCHRONIZATION_EVENT 1 /* KEVENT */
|
||||
#define DISP_TYPE_MUTANT 2 /* KMUTANT/KMUTEX */
|
||||
#define DISP_TYPE_PROCESS 3 /* KPROCESS */
|
||||
#define DISP_TYPE_QUEUE 4 /* KQUEUE */
|
||||
#define DISP_TYPE_SEMAPHORE 5 /* KSEMAPHORE */
|
||||
#define DISP_TYPE_THREAD 6 /* KTHREAD */
|
||||
#define DISP_TYPE_NOTIFICATION_TIMER 8 /* KTIMER */
|
||||
#define DISP_TYPE_SYNCHRONIZATION_TIMER 9 /* KTIMER */
|
||||
|
||||
#define OTYPE_EVENT 0
|
||||
#define OTYPE_MUTEX 1
|
||||
#define OTYPE_THREAD 2
|
||||
@ -334,14 +367,14 @@ struct ktimer {
|
||||
uint64_t k_duetime;
|
||||
union {
|
||||
list_entry k_timerlistentry;
|
||||
struct callout_handle k_handle;
|
||||
struct callout *k_callout;
|
||||
} u;
|
||||
void *k_dpc;
|
||||
uint32_t k_period;
|
||||
};
|
||||
|
||||
#define k_timerlistentry u.k_timerlistentry
|
||||
#define k_handle u.k_handle
|
||||
#define k_callout u.k_callout
|
||||
|
||||
typedef struct ktimer ktimer;
|
||||
|
||||
@ -389,18 +422,12 @@ typedef struct kdpc kdpc;
|
||||
*/
|
||||
struct kmutant {
|
||||
nt_dispatch_header km_header;
|
||||
union {
|
||||
list_entry km_listentry;
|
||||
uint32_t km_acquirecnt;
|
||||
} u;
|
||||
list_entry km_listentry;
|
||||
void *km_ownerthread;
|
||||
uint8_t km_abandoned;
|
||||
uint8_t km_apcdisable;
|
||||
};
|
||||
|
||||
#define km_listentry u.km_listentry
|
||||
#define km_acquirecnt u.km_acquirecnt
|
||||
|
||||
typedef struct kmutant kmutant;
|
||||
|
||||
#define LOOKASIDE_DEPTH 256
|
||||
@ -485,18 +512,28 @@ struct wait_block {
|
||||
void *wb_kthread;
|
||||
nt_dispatch_header *wb_object;
|
||||
struct wait_block *wb_next;
|
||||
#ifdef notdef
|
||||
uint16_t wb_waitkey;
|
||||
uint16_t wb_waittype;
|
||||
#endif
|
||||
uint8_t wb_waitkey;
|
||||
uint8_t wb_waittype;
|
||||
uint8_t wb_awakened;
|
||||
uint8_t wb_oldpri;
|
||||
};
|
||||
|
||||
typedef struct wait_block wait_block;
|
||||
|
||||
#define wb_ext wb_kthread
|
||||
|
||||
#define THREAD_WAIT_OBJECTS 3
|
||||
#define MAX_WAIT_OBJECTS 64
|
||||
|
||||
#define WAITTYPE_ALL 0
|
||||
#define WAITTYPE_ANY 1
|
||||
|
||||
#define WAITKEY_VALID 0x8000
|
||||
|
||||
struct thread_context {
|
||||
void *tc_thrctx;
|
||||
void *tc_thrfunc;
|
||||
@ -532,6 +569,25 @@ struct custom_extension {
|
||||
|
||||
typedef struct custom_extension custom_extension;
|
||||
|
||||
/*
|
||||
* The KINTERRUPT structure in Windows is opaque to drivers.
|
||||
* We define our own custom version with things we need.
|
||||
*/
|
||||
|
||||
struct kinterrupt {
|
||||
list_entry ki_list;
|
||||
device_t ki_dev;
|
||||
int ki_rid;
|
||||
void *ki_cookie;
|
||||
struct resource *ki_irq;
|
||||
kspin_lock ki_lock_priv;
|
||||
kspin_lock *ki_lock;
|
||||
void *ki_svcfunc;
|
||||
void *ki_svcctx;
|
||||
};
|
||||
|
||||
typedef struct kinterrupt kinterrupt;
|
||||
|
||||
/*
|
||||
* In Windows, there are Physical Device Objects (PDOs) and
|
||||
* Functional Device Objects (FDOs). Physical Device Objects are
|
||||
@ -1199,7 +1255,7 @@ typedef struct work_queue_item work_queue_item;
|
||||
do { \
|
||||
(w)->wqi_func = (func); \
|
||||
(w)->wqi_ctx = (ctx); \
|
||||
INIT_LIST_HEAD(&((w)->wqi_entry)); \
|
||||
InitializeListHead(&((w)->wqi_entry)); \
|
||||
} while (0); \
|
||||
|
||||
|
||||
@ -1251,6 +1307,22 @@ extern void ctxsw_wtou(void);
|
||||
|
||||
extern int ntoskrnl_libinit(void);
|
||||
extern int ntoskrnl_libfini(void);
|
||||
|
||||
extern void ntoskrnl_intr(void *);
|
||||
|
||||
extern uint16_t ExQueryDepthSList(slist_header *);
|
||||
extern slist_entry
|
||||
*InterlockedPushEntrySList(slist_header *, slist_entry *);
|
||||
extern slist_entry *InterlockedPopEntrySList(slist_header *);
|
||||
extern uint32_t RtlUnicodeStringToAnsiString(ansi_string *,
|
||||
unicode_string *, uint8_t);
|
||||
extern uint32_t RtlAnsiStringToUnicodeString(unicode_string *,
|
||||
ansi_string *, uint8_t);
|
||||
extern void RtlInitAnsiString(ansi_string *, char *);
|
||||
extern void RtlInitUnicodeString(unicode_string *,
|
||||
uint16_t *);
|
||||
extern void RtlFreeUnicodeString(unicode_string *);
|
||||
extern void RtlFreeAnsiString(ansi_string *);
|
||||
extern void KeInitializeDpc(kdpc *, void *, void *);
|
||||
extern uint8_t KeInsertQueueDpc(kdpc *, void *, void *);
|
||||
extern uint8_t KeRemoveQueueDpc(kdpc *);
|
||||
@ -1264,7 +1336,7 @@ extern uint8_t KeSetTimer(ktimer *, int64_t, kdpc *);
|
||||
extern uint8_t KeSetTimerEx(ktimer *, int64_t, uint32_t, kdpc *);
|
||||
extern uint8_t KeCancelTimer(ktimer *);
|
||||
extern uint8_t KeReadStateTimer(ktimer *);
|
||||
extern uint32_t KeWaitForSingleObject(nt_dispatch_header *, uint32_t,
|
||||
extern uint32_t KeWaitForSingleObject(void *, uint32_t,
|
||||
uint32_t, uint8_t, int64_t *);
|
||||
extern void KeInitializeEvent(nt_kevent *, uint32_t, uint8_t);
|
||||
extern void KeClearEvent(nt_kevent *);
|
||||
@ -1280,10 +1352,20 @@ extern void KeAcquireSpinLockAtDpcLevel(kspin_lock *);
|
||||
extern void KeReleaseSpinLockFromDpcLevel(kspin_lock *);
|
||||
#endif
|
||||
extern void KeInitializeSpinLock(kspin_lock *);
|
||||
extern uint8_t KeAcquireInterruptSpinLock(kinterrupt *);
|
||||
extern void KeReleaseInterruptSpinLock(kinterrupt *, uint8_t);
|
||||
extern uint8_t KeSynchronizeExecution(kinterrupt *, void *, void *);
|
||||
extern uintptr_t InterlockedExchange(volatile uint32_t *,
|
||||
uintptr_t);
|
||||
extern void *ExAllocatePoolWithTag(uint32_t, size_t, uint32_t);
|
||||
extern void ExFreePool(void *);
|
||||
extern uint32_t IoConnectInterrupt(kinterrupt **, void *, void *,
|
||||
kspin_lock *, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t,
|
||||
uint32_t, uint8_t);
|
||||
extern void *MmMapIoSpace(uint64_t, uint32_t, uint32_t);
|
||||
extern void MmUnmapIoSpace(void *, size_t);
|
||||
extern void MmBuildMdlForNonPagedPool(mdl *);
|
||||
extern void IoDisconnectInterrupt(kinterrupt *);
|
||||
extern uint32_t IoAllocateDriverObjectExtension(driver_object *,
|
||||
void *, uint32_t, void **);
|
||||
extern void *IoGetDriverObjectExtension(driver_object *, void *);
|
||||
@ -1317,7 +1399,7 @@ extern void IoQueueWorkItem(io_workitem *, io_workitem_func,
|
||||
#ifdef __i386__
|
||||
#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a)
|
||||
#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b)
|
||||
#define KeRaiseIrql(a) KfRaiseIrql(a)
|
||||
#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a)
|
||||
#define KeLowerIrql(a) KfLowerIrql(a)
|
||||
#define KeAcquireSpinLockAtDpcLevel(a) KefAcquireSpinLockAtDpcLevel(a)
|
||||
#define KeReleaseSpinLockFromDpcLevel(a) KefReleaseSpinLockFromDpcLevel(a)
|
||||
@ -1331,7 +1413,7 @@ extern void IoQueueWorkItem(io_workitem *, io_workitem_func,
|
||||
* These may need to be redefined later;
|
||||
* not sure where they live on amd64 yet.
|
||||
*/
|
||||
#define KeRaiseIrql(a) KfRaiseIrql(a)
|
||||
#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a)
|
||||
#define KeLowerIrql(a) KfLowerIrql(a)
|
||||
#endif /* __amd64__ */
|
||||
|
||||
|
@ -214,6 +214,10 @@ struct image_nt_header {
|
||||
|
||||
typedef struct image_nt_header image_nt_header;
|
||||
|
||||
#define IMAGE_SIZEOF_NT_HEADER(nthdr) \
|
||||
(offsetof(image_nt_header, inh_optionalhdr) + \
|
||||
((image_nt_header *)(nthdr))->inh_filehdr.ifh_optionalhdrlen)
|
||||
|
||||
/* Directory Entries */
|
||||
|
||||
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 /* Export Directory */
|
||||
@ -281,6 +285,11 @@ typedef struct image_section_header image_section_header;
|
||||
|
||||
#define IMAGE_SIZEOF_SECTION_HEADER 40
|
||||
|
||||
#define IMAGE_FIRST_SECTION(nthdr) \
|
||||
((image_section_header *)((vm_offset_t)(nthdr) + \
|
||||
offsetof(image_nt_header, inh_optionalhdr) + \
|
||||
((image_nt_header *)(nthdr))->inh_filehdr.ifh_optionalhdrlen))
|
||||
|
||||
/*
|
||||
* Import format
|
||||
*/
|
||||
|
@ -80,12 +80,18 @@ static void READ_PORT_BUFFER_UCHAR(uint8_t *,
|
||||
static uint64_t KeQueryPerformanceCounter(uint64_t *);
|
||||
static void dummy (void);
|
||||
|
||||
extern struct mtx_pool *ndis_mtxpool;
|
||||
#define NDIS_MAXCPUS 64
|
||||
static struct mtx disp_lock[NDIS_MAXCPUS];
|
||||
|
||||
int
|
||||
hal_libinit()
|
||||
{
|
||||
image_patch_table *patch;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NDIS_MAXCPUS; i++)
|
||||
mtx_init(&disp_lock[i], "HAL preemption lock",
|
||||
"HAL lock", MTX_RECURSE|MTX_DEF);
|
||||
|
||||
patch = hal_functbl;
|
||||
while (patch->ipt_func != NULL) {
|
||||
@ -95,6 +101,7 @@ hal_libinit()
|
||||
patch++;
|
||||
}
|
||||
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -102,6 +109,10 @@ int
|
||||
hal_libfini()
|
||||
{
|
||||
image_patch_table *patch;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NDIS_MAXCPUS; i++)
|
||||
mtx_destroy(&disp_lock[i]);
|
||||
|
||||
patch = hal_functbl;
|
||||
while (patch->ipt_func != NULL) {
|
||||
@ -285,6 +296,72 @@ READ_PORT_BUFFER_UCHAR(port, val, cnt)
|
||||
* KeAcquireSpinLock() must be running at IRQL <= DISPATCH_LEVEL. If
|
||||
* we detect someone trying to acquire a spinlock from DEVICE_LEVEL
|
||||
* or HIGH_LEVEL, we panic.
|
||||
*
|
||||
* Alternate sleep-lock-based spinlock implementation
|
||||
* --------------------------------------------------
|
||||
*
|
||||
* The earlier spinlock implementation was arguably a bit of a hack
|
||||
* and presented several problems. It was basically designed to provide
|
||||
* the functionality of spinlocks without incurring the wrath of
|
||||
* WITNESS. We could get away with using both our spinlock implementation
|
||||
* and FreeBSD sleep locks at the same time, but if WITNESS knew what
|
||||
* we were really up to, it would have spanked us rather severely.
|
||||
*
|
||||
* There's another method we can use based entirely on sleep locks.
|
||||
* First, it's important to realize that everything we're locking
|
||||
* resides inside Project Evil itself: any critical data being locked
|
||||
* by drivers belongs to the drivers, and should not be referenced
|
||||
* by any other OS code outside of the NDISulator. The priority-based
|
||||
* locking scheme has system-wide effects, just like real spinlocks
|
||||
* (blocking preemption affects the whole CPU), but since we keep all
|
||||
* our critical data private, we can use a simpler mechanism that
|
||||
* affects only code/threads directly related to Project Evil.
|
||||
*
|
||||
* The idea is to create a sleep lock mutex for each CPU in the system.
|
||||
* When a CPU running in the NDISulator wants to acquire a spinlock, it
|
||||
* does the following:
|
||||
* - Pin ourselves to the current CPU
|
||||
* - Acquire the mutex for the current CPU
|
||||
* - Spin on the spinlock variable using atomic test and set, just like
|
||||
* a real spinlock.
|
||||
* - Once we have the lock, we execute our critical code
|
||||
*
|
||||
* To give up the lock, we do:
|
||||
* - Clear the spinlock variable with an atomic op
|
||||
* - Release the per-CPU mutex
|
||||
* - Unpin ourselves from the current CPU.
|
||||
*
|
||||
* On a uniprocessor system, this means all threads that access protected
|
||||
* data are serialized through the per-CPU mutex. After one thread
|
||||
* acquires the 'spinlock,' any other thread that uses a spinlock on the
|
||||
* current CPU will block on the per-CPU mutex, which has the same general
|
||||
* effect of blocking pre-emption, but _only_ for those threads that are
|
||||
* running NDISulator code.
|
||||
*
|
||||
* On a multiprocessor system, threads on different CPUs all block on
|
||||
* their respective per-CPU mutex, and the atomic test/set operation
|
||||
* on the spinlock variable provides inter-CPU synchronization, though
|
||||
* only for threads running NDISulator code.
|
||||
*
|
||||
* This method solves an important problem. In Windows, you're allowed
|
||||
* to do an ExAllocatePoolWithTag() with a spinlock held, provided you
|
||||
* allocate from NonPagedPool. This implies an atomic heap allocation
|
||||
* that will not cause the current thread to sleep. (You can't sleep
|
||||
* while holding real spinlock: clowns will eat you.) But in FreeBSD,
|
||||
* malloc(9) _always_ triggers the acquisition of a sleep lock, even
|
||||
* when you use M_NOWAIT. This is not a problem for FreeBSD native
|
||||
* code: you're allowed to sleep in things like interrupt threads. But
|
||||
* it is a problem with the old priority-based spinlock implementation:
|
||||
* even though we get away with it most of the time, we really can't
|
||||
* do a malloc(9) after doing a KeAcquireSpinLock() or KeRaiseIrql().
|
||||
* With the new implementation, it's not a problem: you're allowed to
|
||||
* acquire more than one sleep lock (as long as you avoid lock order
|
||||
* reversals).
|
||||
*
|
||||
* The one drawback to this approach is that now we have a lot of
|
||||
* contention on one per-CPU mutex within the NDISulator code. Whether
|
||||
* or not this is preferable to the expected Windows spinlock behavior
|
||||
* of blocking pre-emption is debatable.
|
||||
*/
|
||||
|
||||
uint8_t
|
||||
@ -297,7 +374,7 @@ KfAcquireSpinLock(lock)
|
||||
if (KeGetCurrentIrql() > DISPATCH_LEVEL)
|
||||
panic("IRQL_NOT_LESS_THAN_OR_EQUAL");
|
||||
|
||||
oldirql = KeRaiseIrql(DISPATCH_LEVEL);
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &oldirql);
|
||||
KeAcquireSpinLockAtDpcLevel(lock);
|
||||
|
||||
return(oldirql);
|
||||
@ -314,10 +391,10 @@ KfReleaseSpinLock(lock, newirql)
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
uint8_t
|
||||
KeGetCurrentIrql()
|
||||
{
|
||||
if (AT_DISPATCH_LEVEL(curthread))
|
||||
if (mtx_owned(&disp_lock[curthread->td_oncpu]))
|
||||
return(DISPATCH_LEVEL);
|
||||
return(PASSIVE_LEVEL);
|
||||
}
|
||||
@ -338,19 +415,14 @@ KfRaiseIrql(irql)
|
||||
{
|
||||
uint8_t oldirql;
|
||||
|
||||
if (irql < KeGetCurrentIrql())
|
||||
oldirql = KeGetCurrentIrql();
|
||||
if (irql < oldirql)
|
||||
panic("IRQL_NOT_LESS_THAN");
|
||||
|
||||
if (KeGetCurrentIrql() == DISPATCH_LEVEL)
|
||||
return(DISPATCH_LEVEL);
|
||||
|
||||
mtx_lock_spin(&sched_lock);
|
||||
oldirql = curthread->td_base_pri;
|
||||
sched_prio(curthread, PI_REALTIME);
|
||||
#if __FreeBSD_version < 600000
|
||||
curthread->td_base_pri = PI_REALTIME;
|
||||
#endif
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
if (oldirql != DISPATCH_LEVEL) {
|
||||
sched_pin();
|
||||
mtx_lock(&disp_lock[curthread->td_oncpu]);
|
||||
}
|
||||
|
||||
return(oldirql);
|
||||
}
|
||||
@ -365,12 +437,8 @@ KfLowerIrql(oldirql)
|
||||
if (KeGetCurrentIrql() != DISPATCH_LEVEL)
|
||||
panic("IRQL_NOT_GREATER_THAN");
|
||||
|
||||
mtx_lock_spin(&sched_lock);
|
||||
#if __FreeBSD_version < 600000
|
||||
curthread->td_base_pri = oldirql;
|
||||
#endif
|
||||
sched_prio(curthread, oldirql);
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
mtx_unlock(&disp_lock[curthread->td_oncpu]);
|
||||
sched_unpin();
|
||||
|
||||
return;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -57,6 +57,7 @@ extern int ndis_strncasecmp(const char *, const char *, size_t);
|
||||
#define strncasecmp(a, b, c) ndis_strncasecmp(a, b, c)
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
@ -142,7 +143,7 @@ pe_get_optional_header(imgbase, hdr)
|
||||
nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
|
||||
|
||||
bcopy ((char *)&nt_hdr->inh_optionalhdr, (char *)hdr,
|
||||
sizeof(image_optional_header));
|
||||
nt_hdr->inh_filehdr.ifh_optionalhdrlen);
|
||||
|
||||
return(0);
|
||||
}
|
||||
@ -169,6 +170,14 @@ pe_get_file_header(imgbase, hdr)
|
||||
dos_hdr = (image_dos_header *)imgbase;
|
||||
nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
|
||||
|
||||
/*
|
||||
* Note: the size of the nt_header is variable since it
|
||||
* can contain optional fields, as indicated by ifh_optionalhdrlen.
|
||||
* However it happens we're only interested in fields in the
|
||||
* non-variant portion of the nt_header structure, so we don't
|
||||
* bother copying the optional parts here.
|
||||
*/
|
||||
|
||||
bcopy ((char *)&nt_hdr->inh_filehdr, (char *)hdr,
|
||||
sizeof(image_file_header));
|
||||
|
||||
@ -197,8 +206,7 @@ pe_get_section_header(imgbase, hdr)
|
||||
|
||||
dos_hdr = (image_dos_header *)imgbase;
|
||||
nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
|
||||
sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +
|
||||
sizeof(image_nt_header));
|
||||
sect_hdr = IMAGE_FIRST_SECTION(nt_hdr);
|
||||
|
||||
bcopy ((char *)sect_hdr, (char *)hdr, sizeof(image_section_header));
|
||||
|
||||
@ -280,8 +288,7 @@ pe_translate_addr(imgbase, rva)
|
||||
|
||||
dos_hdr = (image_dos_header *)imgbase;
|
||||
nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
|
||||
sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +
|
||||
sizeof(image_nt_header));
|
||||
sect_hdr = IMAGE_FIRST_SECTION(nt_hdr);
|
||||
|
||||
/*
|
||||
* The test here is to see if the RVA falls somewhere
|
||||
@ -339,8 +346,7 @@ pe_get_section(imgbase, hdr, name)
|
||||
|
||||
dos_hdr = (image_dos_header *)imgbase;
|
||||
nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
|
||||
sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr +
|
||||
sizeof(image_nt_header));
|
||||
sect_hdr = IMAGE_FIRST_SECTION(nt_hdr);
|
||||
|
||||
for (i = 0; i < sections; i++) {
|
||||
if (!strcmp ((char *)§_hdr->ish_name, name)) {
|
||||
|
@ -82,6 +82,13 @@
|
||||
* we only know the absolute addresses of the thunk and unthunk
|
||||
* routines. So we need to make sure the templates have enough
|
||||
* room in them for the full address.
|
||||
*
|
||||
* Also note that when we call the a thunk/unthunk routine after
|
||||
* invoking a wrapped function, we have to make sure to preserve
|
||||
* the value returned from that function. Most functions return
|
||||
* a 32-bit value in %eax, however some routines return 64-bit
|
||||
* values, which span both %eax and %edx. Consequently, we have
|
||||
* to preserve both registers.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -114,13 +121,16 @@ ENTRY(x86_stdcall_wrap)
|
||||
x86_stdcall_wrap_call:
|
||||
movl $0,%eax
|
||||
call *%eax # jump to routine
|
||||
mov %eax,%esi # preserve return val
|
||||
push %eax # preserve return val
|
||||
push %edx
|
||||
|
||||
movl $ctxsw_utow, %eax
|
||||
call *%eax # thunk
|
||||
|
||||
pop %edx
|
||||
pop %eax # restore return val
|
||||
|
||||
add $64,%esp # clean the stack
|
||||
mov %esi,%eax # restore return val
|
||||
pop %edi
|
||||
pop %esi
|
||||
x86_stdcall_wrap_arg:
|
||||
@ -151,12 +161,14 @@ ENTRY(x86_stdcall_call)
|
||||
call ctxsw_utow # thunk
|
||||
|
||||
call *12(%edi) # branch to stdcall routine
|
||||
mov %eax,%esi # preserve return val
|
||||
push %eax # preserve return val
|
||||
push %edx
|
||||
|
||||
call ctxsw_wtou # unthunk
|
||||
|
||||
pop %edx
|
||||
pop %eax # restore return val
|
||||
mov %edi,%esp # restore stack
|
||||
mov %esi,%eax # restore return val
|
||||
pop %edi # restore %edi
|
||||
pop %esi # and %esi
|
||||
ret
|
||||
@ -188,10 +200,12 @@ x86_fastcall_wrap_call:
|
||||
mov $0,%eax
|
||||
call *%eax # branch to fastcall routine
|
||||
push %eax # preserve return val
|
||||
push %edx
|
||||
|
||||
movl $ctxsw_utow, %eax
|
||||
call *%eax # thunk
|
||||
|
||||
pop %edx
|
||||
pop %eax # restore return val
|
||||
add $12,%esp # clean the stack
|
||||
x86_fastcall_wrap_arg:
|
||||
@ -215,9 +229,11 @@ ENTRY(x86_fastcall_call)
|
||||
mov 16(%esp),%edx
|
||||
call *8(%esp) # branch to fastcall routine
|
||||
push %eax # preserve return val
|
||||
push %edx
|
||||
|
||||
call ctxsw_wtou # unthunk
|
||||
|
||||
pop %edx
|
||||
pop %eax # restore return val
|
||||
add $4,%esp # clean the stack
|
||||
ret
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,6 +35,16 @@
|
||||
#define NDIS_DEFAULT_NODENAME "FreeBSD NDIS node"
|
||||
#define NDIS_NODENAME_LEN 32
|
||||
|
||||
/* For setting/getting OIDs from userspace. */
|
||||
|
||||
struct ndis_oid_data {
|
||||
uint32_t oid;
|
||||
uint32_t len;
|
||||
#ifdef notdef
|
||||
uint8_t data[1];
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ndis_pci_type {
|
||||
uint16_t ndis_vid;
|
||||
uint16_t ndis_did;
|
||||
@ -49,28 +59,52 @@ struct ndis_pccard_type {
|
||||
};
|
||||
|
||||
struct ndis_shmem {
|
||||
list_entry ndis_list;
|
||||
bus_dma_tag_t ndis_stag;
|
||||
bus_dmamap_t ndis_smap;
|
||||
void *ndis_saddr;
|
||||
ndis_physaddr ndis_paddr;
|
||||
struct ndis_shmem *ndis_next;
|
||||
};
|
||||
|
||||
struct ndis_cfglist {
|
||||
ndis_cfg ndis_cfg;
|
||||
struct sysctl_oid *ndis_oid;
|
||||
TAILQ_ENTRY(ndis_cfglist) link;
|
||||
};
|
||||
|
||||
/*
|
||||
* Helper struct to make parsing information
|
||||
* elements easier.
|
||||
*/
|
||||
struct ndis_ie {
|
||||
uint8_t ni_oui[3];
|
||||
uint8_t ni_val;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(nch, ndis_cfglist);
|
||||
|
||||
#define NDIS_INITIALIZED(sc) (sc->ndis_block->nmb_miniportadapterctx != NULL)
|
||||
#define NDIS_INITIALIZED(sc) (sc->ndis_block->nmb_devicectx != NULL)
|
||||
|
||||
#define NDIS_TXPKTS 64
|
||||
#define NDIS_INC(x) \
|
||||
(x)->ndis_txidx = ((x)->ndis_txidx + 1) % (x)->ndis_maxpkts
|
||||
(x)->ndis_txidx = ((x)->ndis_txidx + 1) % NDIS_TXPKTS
|
||||
|
||||
#if __FreeBSD_version < 600007
|
||||
#define arpcom ic.ic_ac
|
||||
#endif
|
||||
|
||||
#define NDIS_EVENTS 4
|
||||
#define NDIS_EVTINC(x) (x) = ((x) + 1) % NDIS_EVENTS
|
||||
|
||||
struct ndis_evt {
|
||||
uint32_t ne_sts;
|
||||
uint32_t ne_len;
|
||||
char *ne_buf;
|
||||
};
|
||||
|
||||
struct ndis_softc {
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com ic; /* interface info */
|
||||
struct ifnet *ifp;
|
||||
struct ifmedia ifmedia; /* media info */
|
||||
u_long ndis_hwassist;
|
||||
uint32_t ndis_v4tx;
|
||||
@ -91,7 +125,8 @@ struct ndis_softc {
|
||||
struct resource *ndis_res_cm; /* common mem (pccard) */
|
||||
struct resource_list ndis_rl;
|
||||
int ndis_rescnt;
|
||||
struct mtx ndis_mtx;
|
||||
kspin_lock ndis_spinlock;
|
||||
uint8_t ndis_irql;
|
||||
device_t ndis_dev;
|
||||
int ndis_unit;
|
||||
ndis_miniport_block *ndis_block;
|
||||
@ -110,6 +145,7 @@ struct ndis_softc {
|
||||
struct nch ndis_cfglist_head;
|
||||
int ndis_80211;
|
||||
int ndis_link;
|
||||
uint32_t ndis_sts;
|
||||
uint32_t ndis_filter;
|
||||
int ndis_if_flags;
|
||||
int ndis_skip;
|
||||
@ -121,18 +157,53 @@ struct ndis_softc {
|
||||
int ndis_devidx;
|
||||
interface_type ndis_iftype;
|
||||
driver_object *ndis_dobj;
|
||||
ndis_work_item ndis_tickitem;
|
||||
ndis_work_item ndis_startitem;
|
||||
ndis_work_item ndis_resetitem;
|
||||
io_workitem *ndis_tickitem;
|
||||
io_workitem *ndis_startitem;
|
||||
io_workitem *ndis_resetitem;
|
||||
io_workitem *ndis_inputitem;
|
||||
kdpc ndis_rxdpc;
|
||||
bus_dma_tag_t ndis_parent_tag;
|
||||
struct ndis_shmem *ndis_shlist;
|
||||
list_entry ndis_shlist;
|
||||
bus_dma_tag_t ndis_mtag;
|
||||
bus_dma_tag_t ndis_ttag;
|
||||
bus_dmamap_t *ndis_mmaps;
|
||||
bus_dmamap_t *ndis_tmaps;
|
||||
int ndis_mmapcnt;
|
||||
struct ndis_evt ndis_evt[NDIS_EVENTS];
|
||||
int ndis_evtpidx;
|
||||
int ndis_evtcidx;
|
||||
struct ifqueue ndis_rxqueue;
|
||||
kspin_lock ndis_rxlock;
|
||||
};
|
||||
|
||||
#define NDIS_LOCK(_sc) mtx_lock(&(_sc)->ndis_mtx)
|
||||
#define NDIS_UNLOCK(_sc) mtx_unlock(&(_sc)->ndis_mtx)
|
||||
#define NDIS_LOCK(_sc) KeAcquireSpinLock(&(_sc)->ndis_spinlock, \
|
||||
&(_sc)->ndis_irql);
|
||||
#define NDIS_UNLOCK(_sc) KeReleaseSpinLock(&(_sc)->ndis_spinlock, \
|
||||
(_sc)->ndis_irql);
|
||||
|
||||
/*
|
||||
* Backwards compatibility defines.
|
||||
*/
|
||||
|
||||
#ifndef IF_ADDR_LOCK
|
||||
#define IF_ADDR_LOCK(x)
|
||||
#define IF_ADDR_UNLOCK(x)
|
||||
#endif
|
||||
|
||||
#ifndef IFF_DRV_OACTIVE
|
||||
#define IFF_DRV_OACTIVE IFF_OACTIVE
|
||||
#define IFF_DRV_RUNNING IFF_RUNNING
|
||||
#define if_drv_flags if_flags
|
||||
#endif
|
||||
|
||||
#ifndef ic_def_txkey
|
||||
#define ic_def_txkey ic_wep_txkey
|
||||
#define wk_keylen wk_len
|
||||
#endif
|
||||
|
||||
#ifndef SIOCGDRVSPEC
|
||||
#define SIOCSDRVSPEC _IOW('i', 123, struct ifreq) /* set driver-specific
|
||||
parameters */
|
||||
#define SIOCGDRVSPEC _IOWR('i', 123, struct ifreq) /* get driver-specific
|
||||
parameters */
|
||||
#endif
|
||||
|
@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
@ -88,8 +89,7 @@ extern const char *__progname;
|
||||
#define SET_HDRS(x) \
|
||||
dos_hdr = (image_dos_header *)x; \
|
||||
nt_hdr = (image_nt_header *)(x + dos_hdr->idh_lfanew); \
|
||||
sect_hdr = (image_section_header *)((vm_offset_t)nt_hdr + \
|
||||
sizeof(image_nt_header));
|
||||
sect_hdr = IMAGE_FIRST_SECTION(nt_hdr);
|
||||
|
||||
static
|
||||
int insert_padding(imgbase, imglen)
|
||||
|
@ -40,6 +40,7 @@
|
||||
NDIS driver distribution
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar /path/to/INF /path/to/SYS
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
@ -57,13 +58,16 @@ compatibility module.
|
||||
The
|
||||
.Nm
|
||||
script is interactive and contains its own help section.
|
||||
The script will prompt the user for the
|
||||
Unless the paths to both files are supplied on the command line,
|
||||
the script will prompt the user for the
|
||||
.Pa .INF
|
||||
and
|
||||
.Pa .SYS
|
||||
files (and any firmware or other external files) needed to generate the
|
||||
files needed to generate the
|
||||
.Fx
|
||||
driver module.
|
||||
The script will also prompt for
|
||||
any firmware or other external files needed.
|
||||
.Sh SEE ALSO
|
||||
.Xr ld 1 ,
|
||||
.Xr objcopy 1 ,
|
||||
|
@ -43,7 +43,7 @@ echo ""
|
||||
|
||||
mainmenu() {
|
||||
header
|
||||
echo " This is script is designed to guide you through the process"
|
||||
echo " This script is designed to guide you through the process"
|
||||
echo " of converting a Windows(r) binary driver module and .INF"
|
||||
echo " specification file into a FreeBSD ELF kernel module for use"
|
||||
echo " with the NDIS compatibility system."
|
||||
@ -57,6 +57,7 @@ echo " 4] Exit"
|
||||
echo ""
|
||||
echo -n " Enter your selection here and press return: "
|
||||
read KEYPRESS
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -78,8 +79,9 @@ echo " you have installed. At this time, the i386 and amd64 architectures"
|
||||
echo " are both supported. Note that you cannot use a Windows/i386 driver"
|
||||
echo " with FreeBSD/amd64: you must obtain a Windows/amd64 driver."
|
||||
echo ""
|
||||
echo -n " Press any key to continue... "
|
||||
echo -n " Press return to continue... "
|
||||
read KEYPRESS
|
||||
return
|
||||
}
|
||||
|
||||
help2() {
|
||||
@ -92,7 +94,7 @@ echo " card which contains Windows(r) drivers. The NDIS compatibility"
|
||||
echo " system is designed to emulate the NDIS API of a couple of different"
|
||||
echo " Windows(r) releases, however it works best with drivers designed"
|
||||
echo " for NDIS 5.0 or later. Drivers distributed for Windows 2000 should"
|
||||
echo " work, however for best results you should use a driver designed"
|
||||
echo " work; however, for best results you should use a driver designed"
|
||||
echo " for Windows XP or Windows Server 2003."
|
||||
echo ""
|
||||
echo " If your card was supplied with your computer, or is a built-in device,"
|
||||
@ -102,8 +104,9 @@ echo ""
|
||||
echo " If you don't have a driver CD, you should be able to find a driver"
|
||||
echo " kit on the card or computer vendor's web site."
|
||||
echo ""
|
||||
echo -n " Press any key to continue... "
|
||||
echo -n " Press return to continue... "
|
||||
read KEYPRESS
|
||||
return
|
||||
}
|
||||
|
||||
help3 () {
|
||||
@ -113,10 +116,10 @@ echo ""
|
||||
echo " In most cases, you will need only two files: a .INF file and a .SYS"
|
||||
echo " file. The .INF file is a text file used by the Windows(r) installer to"
|
||||
echo " perform the driver installation. It contains information that tells"
|
||||
echo " the intaller what devices the driver supports and what registry keys"
|
||||
echo " the installer what devices the driver supports and what registry keys"
|
||||
echo " should be created to control driver configuration. The .SYS file"
|
||||
echo " is the actual driver executable code in Windows(r) Portable Executable"
|
||||
echo " (PE) format. Note that sometimes the .INF file is supplied in unicode"
|
||||
echo " (PE) format. Note that sometimes the .INF file is supplied in Unicode"
|
||||
echo " format. Unicode .INF files must be converted to ASCII form with the"
|
||||
echo " iconv(1) utility before this installer script can use them."
|
||||
echo " Occasionally, a driver may require firmware or register setup"
|
||||
@ -126,8 +129,9 @@ echo " extension, though they can be named almost anything. You will need"
|
||||
echo " these additional files to make your device work with the NDIS"
|
||||
echo " compatibility system as well."
|
||||
echo ""
|
||||
echo -n " Press any key to continue... "
|
||||
echo -n " Press return to continue... "
|
||||
read KEYPRESS
|
||||
return
|
||||
}
|
||||
|
||||
help4 () {
|
||||
@ -150,8 +154,9 @@ echo " static kernel image for those who want/need a fully linked kernel"
|
||||
echo " image (possibly for embedded bootstrap purposes, or just plain old"
|
||||
echo " experimentation)."
|
||||
echo ""
|
||||
echo -n " Press any key to continue... "
|
||||
echo -n " Press return to continue... "
|
||||
read KEYPRESS
|
||||
return
|
||||
}
|
||||
|
||||
help5 () {
|
||||
@ -165,7 +170,7 @@ echo " - The FreeBSD linker, ld(1) (part of the base install)."
|
||||
echo " - The objcopy(1) utility (part of the base install)."
|
||||
echo " - The ndiscvt(1) utility (part of the base install)."
|
||||
echo ""
|
||||
echo " If your happen to end up with a .INF file that's in unicode format,"
|
||||
echo " If you happen to end up with a .INF file that's in Unicode format,"
|
||||
echo " then you'll also need:"
|
||||
echo ""
|
||||
echo " - The iconv(1) utility."
|
||||
@ -174,52 +179,59 @@ echo " If you have installed the X Window system or some sort of desktop"
|
||||
echo " environment, then iconv(1) should already be present. If not, you"
|
||||
echo " will need to install the libiconv package or port."
|
||||
echo ""
|
||||
echo -n " Press any key to continue... "
|
||||
echo -n " Press return to continue... "
|
||||
read KEYPRESS
|
||||
return
|
||||
}
|
||||
|
||||
infconv () {
|
||||
header
|
||||
echo " INF file validation"
|
||||
echo ""
|
||||
echo ""
|
||||
echo " A .INF file is most often provided as an ASCII file, however"
|
||||
echo " files with multilanguage support are provided in Unicode format."
|
||||
echo " Please type in the path to your .INF file now."
|
||||
echo ""
|
||||
echo -n " > "
|
||||
read INFPATH
|
||||
if [ $INFPATH ] && [ -e $INFPATH ];
|
||||
then
|
||||
INFTYPE=`${FILE} ${INFPATH}`
|
||||
|
||||
case ${INFTYPE} in
|
||||
*ASCII*)
|
||||
if [ -z "$INFPATH" ]; then
|
||||
echo ""
|
||||
echo ""
|
||||
echo " A .INF file is most often provided as an ASCII file, however"
|
||||
echo " files with multilanguage support are provided in Unicode format."
|
||||
echo " Please type in the path to your .INF file now."
|
||||
echo ""
|
||||
echo -n " > "
|
||||
read INFPATH
|
||||
fi
|
||||
|
||||
if [ ${INFPATH} ] && [ -e ${INFPATH} ]; then
|
||||
INFTYPE=`${EGREP} -i -c "Signature|.S.i.g.n.a.t.u.r.e" ${INFPATH}`
|
||||
if [ ${INFTYPE} -le 0 ]; then
|
||||
echo ""
|
||||
echo " I don't recognize this file format. It may not be a valid .INF file."
|
||||
echo ""
|
||||
echo -n " Press enter to try again, or ^C to quit. "
|
||||
read KEYPRESS
|
||||
INFPATH=""
|
||||
return
|
||||
fi
|
||||
|
||||
INFTYPE=`${EGREP} -i -c "Class.*=.*Net" ${INFPATH}`
|
||||
if [ ${INFTYPE} -gt 0 ]; then
|
||||
echo ""
|
||||
echo " This .INF file appears to be ASCII."
|
||||
echo ""
|
||||
echo -n " Press any key to continue... "
|
||||
echo -n " Press return to continue... "
|
||||
read KEYPRESS
|
||||
;;
|
||||
*text*)
|
||||
echo ""
|
||||
echo " This .INF file appears to be ASCII."
|
||||
echo ""
|
||||
echo -n " Press any key to continue... "
|
||||
read KEYPRESS
|
||||
;;
|
||||
*nicode*)
|
||||
return
|
||||
fi
|
||||
|
||||
INFTYPE=`${EGREP} -i -c ".C.l.a.s.s.*=.*N.e.t" ${INFPATH}`
|
||||
if [ ${INFTYPE} -gt 0 ]; then
|
||||
echo ""
|
||||
echo " This .INF file appears to be Unicode."
|
||||
if [ -e $ICONVPATH ];
|
||||
then
|
||||
if [ -e ${ICONVPATH} ]; then
|
||||
echo " Trying to convert to ASCII..."
|
||||
${RM} -f /tmp/ascii.inf
|
||||
${ICONVPATH} -f utf-16 -t utf-8 ${INFPATH} > /tmp/ascii.inf
|
||||
INFPATH=/tmp/ascii.inf
|
||||
${ICONVPATH} -f utf-16 -t utf-8 ${INFPATH} > ${INFFILE}
|
||||
INFPATH=${INFFILE}
|
||||
echo " Done."
|
||||
echo ""
|
||||
echo -n " Press any key to continue... "
|
||||
echo -n " Press return to continue... "
|
||||
read KEYPRESS
|
||||
else
|
||||
echo " The iconv(1) utility does not appear to be installed."
|
||||
@ -228,44 +240,47 @@ then
|
||||
echo ""
|
||||
exit
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
echo " I don't recognize this file format. It may not be a valid .INF file."
|
||||
echo ""
|
||||
echo -n " Press enter to try again, or ^C to quit. "
|
||||
read KEYPRESS
|
||||
INFPATH=""
|
||||
;;
|
||||
esac
|
||||
return
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo " I don't recognize this file format. It may not be a valid .INF file."
|
||||
echo ""
|
||||
echo -n " Press enter to try again, or ^C to quit. "
|
||||
read KEYPRESS
|
||||
INFPATH=""
|
||||
else
|
||||
echo ""
|
||||
echo " The file '$INFPATH' was not found."
|
||||
echo " The file '${INFPATH}' was not found."
|
||||
echo ""
|
||||
echo -n " Press enter to try again, or ^C to quit. "
|
||||
read KEYPRESS
|
||||
INFPATH=""
|
||||
fi
|
||||
return
|
||||
}
|
||||
|
||||
sysconv() {
|
||||
header
|
||||
echo " Driver file validation"
|
||||
echo ""
|
||||
echo ""
|
||||
echo " Now you need to specify the name of the Windows(r) driver .SYS"
|
||||
echo " file for your device. Note that if you are running FreeBSD/amd64,"
|
||||
echo " then you must provide a driver that has been compiled for the"
|
||||
echo " 64-bit Windows(r) platform. If a 64-bit driver is not available"
|
||||
echo " for your device, you must install FreeBSD/ia32 and use the"
|
||||
echo " 32-bit driver instead."
|
||||
echo ""
|
||||
echo " Please type in the path to the Windows(r) driver .SYS file now."
|
||||
echo ""
|
||||
echo -n " > "
|
||||
read SYSPATH
|
||||
if [ $SYSPATH ] && [ -e $SYSPATH ];
|
||||
then
|
||||
|
||||
if [ ! -r "$SYSPATH" ]; then
|
||||
echo ""
|
||||
echo ""
|
||||
echo " Now you need to specify the name of the Windows(r) driver .SYS"
|
||||
echo " file for your device. Note that if you are running FreeBSD/amd64,"
|
||||
echo " then you must provide a driver that has been compiled for the"
|
||||
echo " 64-bit Windows(r) platform. If a 64-bit driver is not available"
|
||||
echo " for your device, you must install FreeBSD/i386 and use the"
|
||||
echo " 32-bit driver instead."
|
||||
echo ""
|
||||
echo " Please type in the path to the Windows(r) driver .SYS file now."
|
||||
echo ""
|
||||
echo -n " > "
|
||||
read SYSPATH
|
||||
fi
|
||||
|
||||
if [ ${SYSPATH} ] && [ -e ${SYSPATH} ]; then
|
||||
SYSTYPE=`${FILE} ${SYSPATH}`
|
||||
|
||||
case ${SYSTYPE} in
|
||||
@ -273,9 +288,9 @@ then
|
||||
echo ""
|
||||
echo " This .SYS file appears to be in Windows(r) PE format."
|
||||
echo ""
|
||||
echo -n " Press any key to continue... "
|
||||
echo -n " Press return to continue... "
|
||||
read KEYPRESS
|
||||
SYSBASE=`basename ${SYSPATH} | ${TR} '.' '_'`
|
||||
SYSBASE=`${BASENAME} ${SYSPATH} | ${TR} '.' '_'`
|
||||
;;
|
||||
*)
|
||||
echo ""
|
||||
@ -289,12 +304,13 @@ then
|
||||
esac
|
||||
else
|
||||
echo ""
|
||||
echo " The file '$SYSPATH' was not found."
|
||||
echo " The file '${SYSPATH}' was not found."
|
||||
echo ""
|
||||
echo -n " Press enter to try again, or ^C to quit. "
|
||||
read KEYPRESS
|
||||
SYSPATH=""
|
||||
fi
|
||||
return
|
||||
}
|
||||
|
||||
ndiscvt() {
|
||||
@ -303,7 +319,7 @@ echo " Driver file conversion"
|
||||
echo ""
|
||||
echo " The script will now try to convert the .INF and .SYS files"
|
||||
echo " using the ndiscvt(1) utility. This utility can handle most"
|
||||
echo " .INF files, however occasionally it can fail to parse some files"
|
||||
echo " .INF files; however, occasionally it can fail to parse some files"
|
||||
echo " due to subtle syntax issues: the .INF syntax is very complex,"
|
||||
echo " and the Windows(r) parser will sometimes allow files with small"
|
||||
echo " syntax errors to be processed correctly which ndiscvt(1) will"
|
||||
@ -322,6 +338,7 @@ else
|
||||
echo -n " Press enter to continue... "
|
||||
read KEYPRESS
|
||||
fi
|
||||
return
|
||||
}
|
||||
|
||||
firmcvt() {
|
||||
@ -330,17 +347,17 @@ header
|
||||
echo " Firmware file conversion"
|
||||
echo ""
|
||||
echo " If your driver uses additional firmware files, please list them"
|
||||
echo " below. When you're finished, just press enter to contiue. (If your"
|
||||
echo " below. When you're finished, just press enter to continue. (If your"
|
||||
echo " driver doesn't need any extra firmware files, just press enter"
|
||||
echo " to move to the next step.)"
|
||||
echo ""
|
||||
echo -n " > "
|
||||
read FIRMPATH
|
||||
|
||||
if [ $FIRMPATH ] && [ $FIRMPATH != "" ]; then
|
||||
if [ ! -e $FIRMPATH ]; then
|
||||
if [ ${FIRMPATH} ]; then
|
||||
if [ ! -e ${FIRMPATH} ]; then
|
||||
echo ""
|
||||
echo " The file '$FIRMPATH' was not found"
|
||||
echo " The file '${FIRMPATH}' was not found"
|
||||
echo ""
|
||||
echo -n " Press enter to try again, or ^C to quit. "
|
||||
read KEYPRESS
|
||||
@ -353,7 +370,7 @@ echo ""
|
||||
echo ""
|
||||
echo " Conversion was successful."
|
||||
echo ""
|
||||
FRMBASE=`basename ${FIRMPATH}`
|
||||
FRMBASE=`${BASENAME} ${FIRMPATH}`
|
||||
FRMBASE="${FRMBASE}.o"
|
||||
FRMLIST="${FRMLIST} ${FRMBASE}"
|
||||
fi
|
||||
@ -368,13 +385,14 @@ header
|
||||
echo ""
|
||||
echo " List of files converted firmware files:"
|
||||
echo ""
|
||||
for i in $FRMLIST
|
||||
for i in ${FRMLIST}
|
||||
do
|
||||
echo " "$i
|
||||
done
|
||||
echo ""
|
||||
echo -n " Press enter to continue... "
|
||||
read KEYPRESS
|
||||
return
|
||||
}
|
||||
|
||||
drvgen () {
|
||||
@ -390,57 +408,81 @@ echo " Press enter to compile the stub module and generate the driver"
|
||||
echo -n " module now: "
|
||||
read KEYPRESS
|
||||
echo ""
|
||||
touch bus_if.h
|
||||
touch device_if.h
|
||||
echo -n " Compiling stub... "
|
||||
if ! ${CC} -D_KERNEL -DDRV_DATA_START=${SYSBASE}_drv_data_start -DDRV_NAME=${SYSBASE} -DDRV_DATA_END=${SYSBASE}_drv_data_end -I. ${STUBFILE} -c -o windrv_stub.o; then
|
||||
echo "compilation failed. Exiting."
|
||||
echo -n " Generating Makefile... "
|
||||
echo ".PATH: ${PWD} ${STUBPATH}" > ${MAKEFILE}
|
||||
echo "KMOD= ${SYSBASE}" >> ${MAKEFILE}
|
||||
echo "SRCS+= ${STUBFILE} ${DNAME}.h bus_if.h device_if.h" >> ${MAKEFILE}
|
||||
echo "OBJS+=${FRMLIST} ${DNAME}.o" >> ${MAKEFILE}
|
||||
echo "CFLAGS+= \\" >> ${MAKEFILE}
|
||||
echo " -DDRV_DATA_START=${SYSBASE}_drv_data_start \\" >> ${MAKEFILE}
|
||||
echo " -DDRV_NAME=${SYSBASE} \\" >> ${MAKEFILE}
|
||||
echo " -DDRV_DATA_END=${SYSBASE}_drv_data_end" >> ${MAKEFILE}
|
||||
echo "CLEANFILES+= \\" >> ${MAKEFILE}
|
||||
echo " ${INFFILE} \\" >> ${MAKEFILE}
|
||||
echo " ${DNAME}.h \\" >> ${MAKEFILE}
|
||||
echo " ${DNAME}.o" >> ${MAKEFILE}
|
||||
echo ".include <bsd.kmod.mk>" >> ${MAKEFILE}
|
||||
if [ -f ${MAKEFILE} ]; then
|
||||
echo "done."
|
||||
else
|
||||
echo "generating Makefile failed. Exiting."
|
||||
echo ""
|
||||
exit
|
||||
else
|
||||
echo "done."
|
||||
fi
|
||||
echo -n " Linking loadable kernel module... "
|
||||
if ! ${LD} -Bshareable -d -warn-common -o ${SYSBASE}.ko windrv_stub.o ${FRMLIST} ${DNAME}.o; then
|
||||
echo "linking failed. Exiting."
|
||||
echo -n " Building kernel module... "
|
||||
echo "" > bus_if.h
|
||||
echo "" > device_if.h
|
||||
if ! ${MAKE} -f ${MAKEFILE} depend > /dev/null; then
|
||||
echo "build failed. Exiting."
|
||||
echo ""
|
||||
exit
|
||||
else
|
||||
echo "done."
|
||||
fi
|
||||
echo -n " Linking static kernel module... "
|
||||
if ! ${LD} -r -d -warn-common -o ${SYSBASE}.o windrv_stub.o ${FRMLIST} ${DNAME}.o; then
|
||||
echo "linking failed. Exiting."
|
||||
if ! ${MAKE} -f ${MAKEFILE} all > /dev/null; then
|
||||
echo "build failed. Exiting."
|
||||
echo ""
|
||||
exit
|
||||
else
|
||||
echo "done."
|
||||
if [ -f ${SYSBASE}.ko ]; then
|
||||
${MV} ${SYSBASE}.ko ${SYSBASE}.kmod
|
||||
echo "done."
|
||||
else
|
||||
echo "build failed. Exiting."
|
||||
echo ""
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
echo -n " Cleaning up... "
|
||||
${RM} -f bus_if.h device_if.h windrv_stub.o
|
||||
${RM} -f ${DNAME}.h ${DNAME}.o
|
||||
echo "done."
|
||||
if ! ${MAKE} -f ${MAKEFILE} clean cleandepend > /dev/null; then
|
||||
echo "cleanup failed. Exiting."
|
||||
echo ""
|
||||
exit
|
||||
else
|
||||
echo "done."
|
||||
fi
|
||||
${RM} ${MAKEFILE}
|
||||
${MV} ${SYSBASE}.kmod ${SYSBASE}.ko
|
||||
echo ""
|
||||
echo " The file $SYSBASE.ko has been successfully generated."
|
||||
echo " The file ${SYSBASE}.ko has been successfully generated."
|
||||
echo " You can kldload this module to get started."
|
||||
echo ""
|
||||
echo -n " Press any key to exit. "
|
||||
echo -n " Press return to exit. "
|
||||
read KEYPRESS
|
||||
echo ""
|
||||
echo ""
|
||||
return
|
||||
}
|
||||
|
||||
convert_driver () {
|
||||
while : ; do
|
||||
infconv
|
||||
if [ $INFPATH ] && [ $INFPATH != "" ]; then
|
||||
if [ ${INFPATH} ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
while : ; do
|
||||
sysconv
|
||||
if [ $SYSPATH ] && [ $SYSPATH != "" ]; then
|
||||
if [ ${SYSPATH} ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
@ -448,18 +490,27 @@ convert_driver () {
|
||||
ndiscvt
|
||||
firmcvt
|
||||
drvgen
|
||||
return
|
||||
}
|
||||
|
||||
ICONVPATH=/usr/local/bin/iconv
|
||||
NDISCVT=/usr/sbin/ndiscvt
|
||||
STUBFILE=/usr/share/misc/windrv_stub.c
|
||||
STUBPATH=/usr/share/misc
|
||||
STUBFILE=windrv_stub.c
|
||||
DNAME=windrv
|
||||
OBJCOPY=/usr/bin/objcopy
|
||||
CC=/usr/bin/cc
|
||||
LD=/usr/bin/ld
|
||||
CP=/bin/cp
|
||||
MV=/bin/mv
|
||||
RM=/bin/rm
|
||||
TR=/usr/bin/tr
|
||||
FILE=/usr/bin/file
|
||||
EGREP=/usr/bin/egrep
|
||||
MAKE=/usr/bin/make
|
||||
BASENAME=/usr/bin/basename
|
||||
TOUCH=/usr/bin/touch
|
||||
MKTEMP=/usr/bin/mktemp
|
||||
|
||||
MAKEFILE=`${MKTEMP} /tmp/Makefile.XXXXXX`
|
||||
INFFILE=`${MKTEMP} /tmp/ascii_inf.XXXXXX`
|
||||
|
||||
INFPATH=""
|
||||
FRMLIST=""
|
||||
@ -467,6 +518,13 @@ SYSPATH=""
|
||||
SYSBASE=""
|
||||
FRMBASE=""
|
||||
|
||||
if [ -r "$1" -a -r "$2" ]; then
|
||||
# Looks like the user supplied .INF and .SYS files on the command line
|
||||
INFPATH=$1
|
||||
SYSPATH=$2
|
||||
convert_driver && exit 0
|
||||
fi
|
||||
|
||||
while : ; do
|
||||
mainmenu
|
||||
case ${KEYPRESS} in
|
||||
@ -493,8 +551,9 @@ while : ; do
|
||||
*)
|
||||
header
|
||||
echo ""
|
||||
echo -n " Sorry, I didn't underatand that. Press enter to try again: "
|
||||
echo -n " Sorry, I didn't understand that. Press enter to try again: "
|
||||
read KEYPRESS
|
||||
;;
|
||||
esac
|
||||
done
|
||||
exit
|
||||
|
@ -1,5 +1,5 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SUBDIR= wpa_supplicant wpa_cli hostapd hostapd_cli
|
||||
SUBDIR= wpa_supplicant wpa_cli hostapd hostapd_cli ndis_events
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
@ -6,12 +6,14 @@ WPA_SUPPLICANT_DISTDIR?= ${.CURDIR}/../../../contrib/wpa_supplicant
|
||||
PROG= wpa_supplicant
|
||||
SRCS= config.c eloop.c common.c md5.c rc4.c sha1.c aes_wrap.c \
|
||||
wpa_supplicant.c wpa.c \
|
||||
ctrl_iface.c l2_packet.c drivers.c driver_freebsd.c
|
||||
ctrl_iface.c l2_packet.c drivers.c driver_freebsd.c \
|
||||
driver_ndis.c driver_ndis_.c Packet32.c
|
||||
|
||||
MAN= wpa_supplicant.8 wpa_supplicant.conf.5
|
||||
|
||||
CFLAGS+= -I${.CURDIR} -I${WPA_SUPPLICANT_DISTDIR}
|
||||
CFLAGS+= -DCONFIG_DRIVER_BSD
|
||||
CFLAGS+= -DCONFIG_DRIVER_NDIS
|
||||
CFLAGS+= -DCONFIG_CTRL_IFACE
|
||||
CFLAGS+= -g
|
||||
DPADD+= ${LIBPCAP}
|
||||
|
Loading…
Reference in New Issue
Block a user