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:
wpaul 2005-10-27 17:08:57 +00:00
parent 18a30ec710
commit 14b480eac9
18 changed files with 3457 additions and 1697 deletions

View File

@ -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"

View File

@ -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);

View File

@ -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);

View File

@ -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_ */

View File

@ -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__ */

View File

@ -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
*/

View File

@ -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

View File

@ -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 *)&sect_hdr->ish_name, name)) {

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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 ,

View File

@ -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

View File

@ -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>

View File

@ -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}