summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2005-02-16 05:41:18 +0000
committerwpaul <wpaul@FreeBSD.org>2005-02-16 05:41:18 +0000
commit07b632956a99a773db5488fdd2ffd5f209d38dea (patch)
treef3934335c485d66f4991e7d9fc75b2e17460984c
parent41238cc6d19537d94771e20dbde35067d8d8f618 (diff)
downloadFreeBSD-src-07b632956a99a773db5488fdd2ffd5f209d38dea.zip
FreeBSD-src-07b632956a99a773db5488fdd2ffd5f209d38dea.tar.gz
Add support for Windows/x86-64 binaries to Project Evil.
Ville-Pertti Keinonen (will at exomi dot comohmygodnospampleasekthx) deserves a big thanks for submitting initial patches to make it work. I have mangled his contributions appropriately. The main gotcha with Windows/x86-64 is that Microsoft uses a different calling convention than everyone else. The standard ABI requires using 6 registers for argument passing, with other arguments on the stack. Microsoft uses only 4 registers, and requires the caller to leave room on the stack for the register arguments incase the callee needs to spill them. Unlike x86, where Microsoft uses a mix of _cdecl, _stdcall and _fastcall, all routines on Windows/x86-64 uses the same convention. This unfortunately means that all the functions we export to the driver require an intermediate translation wrapper. Similarly, we have to wrap all calls back into the driver binary itself. The original patches provided macros to wrap every single routine at compile time, providing a secondary jump table with a customized wrapper for each exported routine. I decided to use a different approach: the call wrapper for each function is created from a template at runtime, and the routine to jump to is patched into the wrapper as it is created. The subr_pe module has been modified to patch in the wrapped function instead of the original. (On x86, the wrapping routine is a no-op.) There are some minor API differences that had to be accounted for: - KeAcquireSpinLock() is a real function on amd64, not a macro wrapper around KfAcquireSpinLock() - NdisFreeBuffer() is actually IoFreeMdl(). I had to change the whole NDIS_BUFFER API a bit to accomodate this. Bugs fixed along the way: - IoAllocateMdl() always returned NULL - kern_windrv.c:windrv_unload() wasn't releasing private driver object extensions correctly (found thanks to memguard) This has only been tested with the driver for the Broadcom 802.11g chipset, which was the only Windows/x86-64 driver I could find.
-rw-r--r--sys/compat/ndis/hal_var.h2
-rw-r--r--sys/compat/ndis/kern_ndis.c114
-rw-r--r--sys/compat/ndis/kern_windrv.c60
-rw-r--r--sys/compat/ndis/ndis_var.h26
-rw-r--r--sys/compat/ndis/ntoskrnl_var.h19
-rw-r--r--sys/compat/ndis/pe_var.h98
-rw-r--r--sys/compat/ndis/resource_var.h46
-rw-r--r--sys/compat/ndis/subr_hal.c33
-rw-r--r--sys/compat/ndis/subr_ndis.c206
-rw-r--r--sys/compat/ndis/subr_ntoskrnl.c115
-rw-r--r--sys/compat/ndis/subr_pe.c26
-rw-r--r--sys/compat/ndis/winx64_wrap.S191
-rw-r--r--sys/conf/files.amd6414
-rw-r--r--sys/conf/options.amd642
-rw-r--r--sys/dev/if_ndis/if_ndis.c66
-rw-r--r--sys/dev/if_ndis/if_ndisvar.h3
-rw-r--r--sys/modules/Makefile2
-rw-r--r--sys/modules/ndis/Makefile4
-rw-r--r--usr.sbin/ndiscvt/inf.c19
19 files changed, 782 insertions, 264 deletions
diff --git a/sys/compat/ndis/hal_var.h b/sys/compat/ndis/hal_var.h
index 6386895..c2a534e 100644
--- a/sys/compat/ndis/hal_var.h
+++ b/sys/compat/ndis/hal_var.h
@@ -46,6 +46,8 @@
extern image_patch_table hal_functbl[];
__BEGIN_DECLS
+extern int hal_libinit(void);
+extern int hal_libfini(void);
__fastcall extern uint8_t KfAcquireSpinLock(REGARGS1(kspin_lock *lock));
__fastcall void KfReleaseSpinLock(REGARGS2(kspin_lock *lock, uint8_t newirql));
__fastcall extern uint8_t KfRaiseIrql(REGARGS1(uint8_t irql));
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
index f93bf4e..589742b 100644
--- a/sys/compat/ndis/kern_ndis.c
+++ b/sys/compat/ndis/kern_ndis.c
@@ -85,6 +85,17 @@ __stdcall static void ndis_getdone_func(ndis_handle, ndis_status);
__stdcall static void ndis_resetdone_func(ndis_handle, ndis_status, uint8_t);
__stdcall static void ndis_sendrsrcavail_func(ndis_handle);
+static image_patch_table kernndis_functbl[] = {
+ IMPORT_FUNC(ndis_status_func),
+ IMPORT_FUNC(ndis_statusdone_func),
+ IMPORT_FUNC(ndis_setdone_func),
+ IMPORT_FUNC(ndis_getdone_func),
+ IMPORT_FUNC(ndis_resetdone_func),
+ IMPORT_FUNC(ndis_sendrsrcavail_func),
+
+ { NULL, NULL, NULL }
+};
+
struct nd_head ndis_devhead;
struct ndis_req {
@@ -108,12 +119,12 @@ static int ndis_enlarge_thrqueue(int);
static int ndis_shrink_thrqueue(int);
static void ndis_runq(void *);
-static uma_zone_t ndis_packet_zone, ndis_buffer_zone;
+static uma_zone_t ndis_buffer_zone;
struct mtx ndis_thr_mtx;
struct mtx ndis_req_mtx;
static STAILQ_HEAD(ndisqhead, ndis_req) ndis_ttodo;
-struct ndisqhead ndis_itodo;
-struct ndisqhead ndis_free;
+static struct ndisqhead ndis_itodo;
+static struct ndisqhead ndis_free;
static int ndis_jobs = 32;
static struct ndisproc ndis_tproc;
@@ -130,21 +141,27 @@ static int
ndis_modevent(module_t mod, int cmd, void *arg)
{
int error = 0;
+ image_patch_table *patch;
switch (cmd) {
case MOD_LOAD:
/* Initialize subsystems */
windrv_libinit();
+ hal_libinit();
ndis_libinit();
ntoskrnl_libinit();
+ patch = kernndis_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_wrap((funcptr)patch->ipt_func,
+ (funcptr *)&patch->ipt_wrap);
+ patch++;
+ }
+
/* Initialize TX buffer UMA zone. */
- ndis_packet_zone = uma_zcreate("NDIS packet",
- sizeof(ndis_packet), NULL, NULL, NULL,
- NULL, UMA_ALIGN_PTR, 0);
ndis_buffer_zone = uma_zcreate("NDIS buffer",
- sizeof(ndis_buffer), NULL, NULL, NULL,
- NULL, UMA_ALIGN_PTR, 0);
+ sizeof(struct mdl) + (sizeof(vm_offset_t *) * 16),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
ndis_create_kthreads();
@@ -156,11 +173,18 @@ ndis_modevent(module_t mod, int cmd, void *arg)
ndis_destroy_kthreads();
if (TAILQ_FIRST(&ndis_devhead) == NULL) {
/* Shut down subsystems */
+ hal_libfini();
ndis_libfini();
ntoskrnl_libfini();
+ windrv_libfini();
+
+ patch = kernndis_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_unwrap(patch->ipt_wrap);
+ patch++;
+ }
/* Remove zones */
- uma_zdestroy(ndis_packet_zone);
uma_zdestroy(ndis_buffer_zone);
}
break;
@@ -169,12 +193,18 @@ ndis_modevent(module_t mod, int cmd, void *arg)
ndis_destroy_kthreads();
/* Shut down subsystems */
+ hal_libfini();
ndis_libfini();
ntoskrnl_libfini();
windrv_libfini();
+ patch = kernndis_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_unwrap(patch->ipt_wrap);
+ patch++;
+ }
+
/* Remove zones */
- uma_zdestroy(ndis_packet_zone);
uma_zdestroy(ndis_buffer_zone);
break;
default:
@@ -803,7 +833,7 @@ ndis_return(arg)
returnfunc = sc->ndis_chars->nmc_return_packet_func;
irql = KeRaiseIrql(DISPATCH_LEVEL);
- returnfunc(adapter, p);
+ MSCALL2(returnfunc, adapter, p);
KeLowerIrql(irql);
return;
@@ -859,7 +889,7 @@ ndis_free_packet(p)
return;
ndis_free_bufs(p->np_private.npp_head);
- uma_zfree(ndis_packet_zone, p);
+ NdisFreePacket(p);
return;
}
@@ -1057,21 +1087,11 @@ ndis_mtop(m0, p)
ndis_buffer *buf = NULL, *prev = NULL;
ndis_packet_private *priv;
- if (p == NULL || m0 == NULL)
+ if (p == NULL || *p == NULL || m0 == NULL)
return(EINVAL);
- /* If caller didn't supply a packet, make one. */
- if (*p == NULL) {
- *p = uma_zalloc(ndis_packet_zone, M_NOWAIT|M_ZERO);
-
- if (*p == NULL)
- return(ENOMEM);
- }
-
priv = &(*p)->np_private;
priv->npp_totlen = m0->m_pkthdr.len;
- priv->npp_packetooboffset = offsetof(ndis_packet, np_oob);
- priv->npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
for (m = m0; m != NULL; m = m->m_next) {
if (m->m_len == 0)
@@ -1153,7 +1173,7 @@ ndis_set_info(arg, oid, buf, buflen)
return(ENXIO);
KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
- rval = setfunc(adapter, oid, buf, *buflen,
+ rval = MSCALL6(setfunc, adapter, oid, buf, *buflen,
&byteswritten, &bytesneeded);
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
@@ -1210,7 +1230,7 @@ ndis_send_packets(arg, packets, cnt)
sendfunc = sc->ndis_chars->nmc_sendmulti_func;
senddonefunc = sc->ndis_block->nmb_senddone_func;
irql = KeRaiseIrql(DISPATCH_LEVEL);
- sendfunc(adapter, packets, cnt);
+ MSCALL3(sendfunc, adapter, packets, cnt);
KeLowerIrql(irql);
for (i = 0; i < cnt; i++) {
@@ -1223,7 +1243,7 @@ ndis_send_packets(arg, packets, cnt)
*/
if (p == NULL || p->np_oob.npo_status == NDIS_STATUS_PENDING)
continue;
- senddonefunc(sc->ndis_block, p, p->np_oob.npo_status);
+ MSCALL3(senddonefunc, sc->ndis_block, p, p->np_oob.npo_status);
}
return(0);
@@ -1249,13 +1269,14 @@ ndis_send_packet(arg, packet)
senddonefunc = sc->ndis_block->nmb_senddone_func;
irql = KeRaiseIrql(DISPATCH_LEVEL);
- status = sendfunc(adapter, packet, packet->np_private.npp_flags);
+ status = MSCALL3(sendfunc, adapter, packet,
+ packet->np_private.npp_flags);
KeLowerIrql(irql);
if (status == NDIS_STATUS_PENDING)
return(0);
- senddonefunc(sc->ndis_block, packet, status);
+ MSCALL3(senddonefunc, sc->ndis_block, packet, status);
return(0);
}
@@ -1338,7 +1359,7 @@ ndis_reset_nic(arg)
return(EIO);
irql = KeRaiseIrql(DISPATCH_LEVEL);
- rval = resetfunc(&addressing_reset, adapter);
+ rval = MSCALL2(resetfunc, &addressing_reset, adapter);
KeLowerIrql(irql);
if (rval == NDIS_STATUS_PENDING) {
@@ -1378,7 +1399,7 @@ ndis_halt_nic(arg)
haltfunc = sc->ndis_chars->nmc_halt_func;
NDIS_UNLOCK(sc);
- haltfunc(adapter);
+ MSCALL1(haltfunc, adapter);
NDIS_LOCK(sc);
sc->ndis_block->nmb_miniportadapterctx = NULL;
@@ -1404,9 +1425,9 @@ ndis_shutdown_nic(arg)
return(EIO);
if (sc->ndis_chars->nmc_rsvd0 == NULL)
- shutdownfunc(adapter);
+ MSCALL1(shutdownfunc, adapter);
else
- shutdownfunc(sc->ndis_chars->nmc_rsvd0);
+ MSCALL1(shutdownfunc, sc->ndis_chars->nmc_rsvd0);
ndis_shrink_thrqueue(8);
TAILQ_REMOVE(&ndis_devhead, sc->ndis_block, link);
@@ -1434,12 +1455,10 @@ ndis_init_nic(arg)
initfunc = sc->ndis_chars->nmc_init_func;
NDIS_UNLOCK(sc);
- TAILQ_INIT(&block->nmb_timerlist);
-
for (i = 0; i < NdisMediumMax; i++)
mediumarray[i] = i;
- status = initfunc(&openstatus, &chosenmedium,
+ status = MSCALL6(initfunc, &openstatus, &chosenmedium,
mediumarray, NdisMediumMax, block, block);
/*
@@ -1470,7 +1489,7 @@ ndis_enable_intr(arg)
intrenbfunc = sc->ndis_chars->nmc_enable_interrupts_func;
if (adapter == NULL || intrenbfunc == NULL)
return;
- intrenbfunc(adapter);
+ MSCALL1(intrenbfunc, adapter);
return;
}
@@ -1488,7 +1507,7 @@ ndis_disable_intr(arg)
intrdisfunc = sc->ndis_chars->nmc_disable_interrupts_func;
if (adapter == NULL || intrdisfunc == NULL)
return;
- intrdisfunc(adapter);
+ MSCALL1(intrdisfunc, adapter);
return;
}
@@ -1513,7 +1532,7 @@ ndis_isr(arg, ourintr, callhandler)
if (adapter == NULL || isrfunc == NULL)
return(ENXIO);
- isrfunc(&accepted, &queue, adapter);
+ MSCALL3(isrfunc, &accepted, &queue, adapter);
*ourintr = accepted;
*callhandler = queue;
@@ -1539,7 +1558,7 @@ ndis_intrhand(arg)
if (adapter == NULL || intrfunc == NULL)
return(EINVAL);
- intrfunc(adapter);
+ MSCALL1(intrfunc, adapter);
return(0);
}
@@ -1569,7 +1588,7 @@ ndis_get_info(arg, oid, buf, buflen)
return(ENXIO);
KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
- rval = queryfunc(adapter, oid, buf, *buflen,
+ rval = MSCALL6(queryfunc, adapter, oid, buf, *buflen,
&byteswritten, &bytesneeded);
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
@@ -1633,20 +1652,19 @@ NdisAddDevice(drv, pdo)
* 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);
-
+
/* Finish up BSD-specific setup. */
block->nmb_signature = (void *)0xcafebabe;
- block->nmb_setdone_func = ndis_setdone_func;
- block->nmb_querydone_func = ndis_getdone_func;
- block->nmb_status_func = ndis_status_func;
- block->nmb_statusdone_func = ndis_statusdone_func;
- block->nmb_resetdone_func = ndis_resetdone_func;
- block->nmb_sendrsrc_func = ndis_sendrsrcavail_func;
+ block->nmb_status_func = kernndis_functbl[0].ipt_wrap;
+ block->nmb_statusdone_func = kernndis_functbl[1].ipt_wrap;
+ block->nmb_setdone_func = kernndis_functbl[2].ipt_wrap;
+ block->nmb_querydone_func = kernndis_functbl[3].ipt_wrap;
+ block->nmb_resetdone_func = kernndis_functbl[4].ipt_wrap;
+ block->nmb_sendrsrc_func = kernndis_functbl[5].ipt_wrap;
ndis_enlarge_thrqueue(8);
diff --git a/sys/compat/ndis/kern_windrv.c b/sys/compat/ndis/kern_windrv.c
index f298b99..a2279ca 100644
--- a/sys/compat/ndis/kern_windrv.c
+++ b/sys/compat/ndis/kern_windrv.c
@@ -182,9 +182,9 @@ windrv_unload(mod, img, len)
e = drv->dro_driverext->dre_usrext.nle_flink;
while (e != &drv->dro_driverext->dre_usrext) {
c = e->nle_flink;
- REMOVE_LIST_HEAD((&drv->dro_driverext->dre_usrext));
+ REMOVE_LIST_ENTRY(e);
ExFreePool(c);
- e = e->nle_flink;
+ e = c;
}
/* Free the driver extension */
@@ -294,7 +294,7 @@ windrv_load(mod, img, len)
/* Now call the DriverEntry() function. */
- status = entry(dobj, &dobj->dro_drivername);
+ status = MSCALL2(entry, dobj, &dobj->dro_drivername);
if (status != STATUS_SUCCESS) {
free(dobj->dro_drivername.us_buf, M_DEVBUF);
@@ -414,3 +414,57 @@ windrv_bus_attach(drv, name)
return(0);
}
+
+#ifdef __amd64__
+
+extern void x86_64_wrap(void);
+extern void x86_64_wrap_call(void);
+extern void x86_64_wrap_end(void);
+
+#endif /* __amd64__ */
+
+int
+windrv_wrap(func, wrap)
+ funcptr func;
+ funcptr *wrap;
+{
+#ifdef __amd64__
+ funcptr p;
+ vm_offset_t *calladdr;
+ vm_offset_t wrapstart, wrapend, wrapcall;
+
+ wrapstart = (vm_offset_t)&x86_64_wrap;
+ wrapend = (vm_offset_t)&x86_64_wrap_end;
+ wrapcall = (vm_offset_t)&x86_64_wrap_call;
+
+ /* Allocate a new wrapper instance. */
+
+ p = malloc((wrapend - wrapstart), M_DEVBUF, M_NOWAIT);
+ if (p == NULL)
+ return(ENOMEM);
+
+ /* Copy over the code. */
+
+ bcopy((char *)wrapstart, p, (wrapend - wrapstart));
+
+ /* Insert the function address into the new wrapper instance. */
+
+ calladdr = (uint64_t *)((char *)p + (wrapcall - wrapstart) + 2);
+ *calladdr = (vm_offset_t)func;
+
+ *wrap = p;
+#else /* __amd64__ */
+ *wrap = func;
+#endif /* __amd64__ */
+ return(0);
+}
+
+int
+windrv_unwrap(func)
+ funcptr func;
+{
+#ifdef __amd64__
+ free(func, M_DEVBUF);
+#endif /* __amd64__ */
+ return(0);
+}
diff --git a/sys/compat/ndis/ndis_var.h b/sys/compat/ndis/ndis_var.h
index b4eaf5a..7b33a3e 100644
--- a/sys/compat/ndis/ndis_var.h
+++ b/sys/compat/ndis/ndis_var.h
@@ -733,15 +733,24 @@ typedef enum ndis_media_state ndis_media_state;
#define NDIS_DMA_32BITS 0x01
#define NDIS_DMA_64BITS 0x02
+/*
struct ndis_physaddr {
+#ifdef __i386__
uint64_t np_quad;
+#endif
+#ifdef __amd64__
+ uint32_t np_low;
+ uint32_t np_high;
+#define np_quad np_low
+#endif
#ifdef notdef
uint32_t np_low;
uint32_t np_high;
#endif
};
+*/
-typedef struct ndis_physaddr ndis_physaddr;
+typedef struct physaddr ndis_physaddr;
struct ndis_ansi_string {
uint16_t nas_len;
@@ -1136,6 +1145,7 @@ struct ndis_packet {
} np_macrsvd;
} u;
uint32_t *np_rsvd[2];
+ uint8_t nm_protocolreserved[1];
/*
* This next part is probably wrong, but we need some place
@@ -1155,6 +1165,8 @@ struct ndis_packet {
typedef struct ndis_packet ndis_packet;
+#define PROTOCOL_RESERVED_SIZE_IN_PACKET (4 * sizeof(void *))
+
/* mbuf ext type for NDIS */
#define EXT_NDIS 0x999
@@ -1453,7 +1465,6 @@ struct ndis_miniport_block {
ndis_resource_list *nmb_rlist;
ndis_status nmb_getstat;
ndis_status nmb_setstat;
- struct nte_head nmb_timerlist;
vm_offset_t nmb_img;
TAILQ_ENTRY(ndis_miniport_block) link;
};
@@ -1531,7 +1542,18 @@ extern int ndis_thsuspend(struct proc *, 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);
+
__stdcall extern uint32_t NdisAddDevice(driver_object *, device_object *);
+__stdcall extern void NdisAllocatePacketPool(ndis_status *,
+ ndis_handle *, uint32_t, uint32_t);
+__stdcall extern void NdisAllocatePacketPoolEx(ndis_status *,
+ ndis_handle *, uint32_t, uint32_t, uint32_t);
+__stdcall extern uint32_t NdisPacketPoolUsage(ndis_handle);
+__stdcall extern void NdisFreePacketPool(ndis_handle);
+__stdcall extern void NdisAllocatePacket(ndis_status *,
+ ndis_packet **, ndis_handle);
+__stdcall extern void NdisFreePacket(ndis_packet *);
+
__END_DECLS
#endif /* _NDIS_VAR_H_ */
diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h
index f1c0766..4c0112a 100644
--- a/sys/compat/ndis/ntoskrnl_var.h
+++ b/sys/compat/ndis/ntoskrnl_var.h
@@ -1068,6 +1068,7 @@ typedef struct driver_object driver_object;
#define NDIS_KSTACK_PAGES 8
extern image_patch_table ntoskrnl_functbl[];
+typedef void (*funcptr)(void);
__BEGIN_DECLS
extern int windrv_libinit(void);
@@ -1079,6 +1080,8 @@ extern int windrv_create_pdo(driver_object *, device_t);
extern void windrv_destroy_pdo(driver_object *, device_t);
extern device_object *windrv_find_pdo(driver_object *, device_t);
extern int windrv_bus_attach(driver_object *, char *);
+extern int windrv_wrap(funcptr, funcptr *);
+extern int windrv_unwrap(funcptr);
extern int ntoskrnl_libinit(void);
extern int ntoskrnl_libfini(void);
@@ -1100,6 +1103,8 @@ __stdcall extern uint32_t KeSetEvent(nt_kevent *, uint32_t, uint8_t);
__stdcall extern uint32_t KeResetEvent(nt_kevent *);
__fastcall extern void KefAcquireSpinLockAtDpcLevel(REGARGS1(kspin_lock *));
__fastcall extern void KefReleaseSpinLockFromDpcLevel(REGARGS1(kspin_lock *));
+__stdcall extern uint8_t KeAcquireSpinLockRaiseToDpc(kspin_lock *);
+__stdcall extern void KeReleaseSpinLock(kspin_lock *, uint8_t);
__stdcall extern void KeInitializeSpinLock(kspin_lock *);
__stdcall extern void *ExAllocatePoolWithTag(uint32_t, size_t, uint32_t);
__stdcall extern void ExFreePool(void *);
@@ -1115,6 +1120,8 @@ __fastcall extern void IofCompleteRequest(REGARGS2(irp *, uint8_t));
__stdcall extern void IoDetachDevice(device_object *);
__stdcall extern device_object *IoAttachDeviceToDeviceStack(device_object *,
device_object *);
+__stdcall mdl *IoAllocateMdl(void *, uint32_t, uint8_t, uint8_t, irp *);
+__stdcall void IoFreeMdl(mdl *);
#define IoCallDriver(a, b) FASTCALL2(IofCallDriver, a, b)
#define IoCompleteRequest(a, b) FASTCALL2(IofCompleteRequest, a, b)
@@ -1129,6 +1136,18 @@ __stdcall extern device_object *IoAttachDeviceToDeviceStack(device_object *,
#define KeRaiseIrql(a) FASTCALL1(KfRaiseIrql, a)
#define KeLowerIrql(a) FASTCALL1(KfLowerIrql, a)
#endif /* __i386__ */
+
+#ifdef __amd64__
+#define KeAcquireSpinLock(a, b) *(b) = KeAcquireSpinLockRaiseToDpc(a)
+
+/*
+ * These may need to be redefined later;
+ * not sure where they live on amd64 yet.
+ */
+#define KeRaiseIrql(a) KfRaiseIrql(a)
+#define KeLowerIrql(a) KfLowerIrql(a)
+#endif /* __amd64__ */
+
__END_DECLS
#endif /* _NTOSKRNL_VAR_H_ */
diff --git a/sys/compat/ndis/pe_var.h b/sys/compat/ndis/pe_var.h
index fa635d4..47055a8 100644
--- a/sys/compat/ndis/pe_var.h
+++ b/sys/compat/ndis/pe_var.h
@@ -39,11 +39,11 @@
* Image Format
*/
-#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
-#define IMAGE_OS2_SIGNATURE 0x454E /* NE */
-#define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */
-#define IMAGE_VXD_SIGNATURE 0x454C /* LE */
-#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
+#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
+#define IMAGE_OS2_SIGNATURE 0x454E /* NE */
+#define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */
+#define IMAGE_VXD_SIGNATURE 0x454C /* LE */
+#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
/*
* All PE files have one of these, just so if you attempt to
@@ -174,11 +174,13 @@ struct image_optional_header {
uint32_t ioh_bsssize;
uint32_t ioh_entryaddr;
uint32_t ioh_codebaseaddr;
+#ifndef __amd64__
uint32_t ioh_databaseaddr;
+#endif
/* NT-specific fields */
- uint32_t ioh_imagebase;
+ uintptr_t ioh_imagebase;
uint32_t ioh_sectalign;
uint32_t ioh_filealign;
uint16_t ioh_osver_major;
@@ -193,10 +195,10 @@ struct image_optional_header {
uint32_t ioh_csum;
uint16_t ioh_subsys;
uint16_t ioh_dll_characteristics;
- uint32_t ioh_stackreservesize;
- uint32_t ioh_stackcommitsize;
- uint32_t ioh_heapreservesize;
- uint32_t ioh_heapcommitsize;
+ uintptr_t ioh_stackreservesize;
+ uintptr_t ioh_stackcommitsize;
+ uintptr_t ioh_heapreservesize;
+ uintptr_t ioh_heapcommitsize;
uint16_t ioh_loaderflags;
uint32_t ioh_rva_size_cnt;
image_data_directory ioh_datadir[IMAGE_DIRECTORY_ENTRIES_MAX];
@@ -404,6 +406,7 @@ typedef struct message_resource_entry message_resource_entry;
struct image_patch_table {
char *ipt_name;
void (*ipt_func)(void);
+ void (*ipt_wrap)(void);
};
typedef struct image_patch_table image_patch_table;
@@ -476,9 +479,78 @@ fastcall3(fcall3 f, uint32_t a, uint32_t b, uint32_t c)
#define FASTCALL3(f, a, b, c) (f)((a), (b), (c))
#endif /* __i386__ */
+
+/*
+ * AMD64 support. Microsoft uses a different calling convention
+ * than everyone else on the amd64 platform. Sadly, gcc has no
+ * built-in support for it (yet).
+ *
+ * The three major differences we're concerned with are:
+ *
+ * - The first 4 register-sized arguments are passed in the
+ * %rcx, %rdx, %r8 and %r9 registers, and the rest are pushed
+ * onto the stack. (The ELF ABI uses 6 registers, not 4).
+ *
+ * - The caller must reserve space on the stack for the 4
+ * register arguments in case the callee has to spill them.
+ *
+ * - The stack myst be 16-byte aligned by the time the callee
+ * executes. A call instruction implicitly pushes an 8 byte
+ * return address onto the stack. We have to make sure that
+ * the amount of space we consume, plus the return address,
+ * is a multiple of 16 bytes in size. This means that in
+ * some cases, we may need to chew up an extra 8 bytes on
+ * the stack that will be unused.
+ *
+ * On the bright side, Microsoft seems to be using just the one
+ * calling convention for all functions on amd64, unlike x86 where
+ * they use a mix of _stdcall, _fastcall and _cdecl.
+ */
+
+#ifdef __amd64__
+
+extern uint64_t x86_64_call1(void *, uint64_t);
+extern uint64_t x86_64_call2(void *, uint64_t, uint64_t);
+extern uint64_t x86_64_call3(void *, uint64_t, uint64_t, uint64_t);
+extern uint64_t x86_64_call4(void *, uint64_t, uint64_t, uint64_t, uint64_t);
+extern uint64_t x86_64_call5(void *, uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t);
+extern uint64_t x86_64_call6(void *, uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t, uint64_t);
+
+
+#define MSCALL1(fn, a) \
+ x86_64_call1((fn), (uint64_t)(a))
+#define MSCALL2(fn, a, b) \
+ x86_64_call2((fn), (uint64_t)(a), (uint64_t)(b))
+#define MSCALL3(fn, a, b, c) \
+ x86_64_call3((fn), (uint64_t)(a), (uint64_t)(b), \
+ (uint64_t)(c))
+#define MSCALL4(fn, a, b, c, d) \
+ x86_64_call4((fn), (uint64_t)(a), (uint64_t)(b), \
+ (uint64_t)(c), (uint64_t)(d))
+#define MSCALL5(fn, a, b, c, d, e) \
+ x86_64_call5((fn), (uint64_t)(a), (uint64_t)(b), \
+ (uint64_t)(c), (uint64_t)(d), (uint64_t)(e))
+#define MSCALL6(fn, a, b, c, d, e, f) \
+ x86_64_call6((fn), (uint64_t)(a), (uint64_t)(b), \
+ (uint64_t)(c), (uint64_t)(d), (uint64_t)(e), (uint64_t)(f))
+
+#else /* __amd64__ */
+
+#define MSCALL1(fn, a) (fn)((a))
+#define MSCALL2(fn, a, b) (fn)((a), (b))
+#define MSCALL3(fn, a, b, c) (fn)((a), (b), (c))
+#define MSCALL4(fn, a, b, c, d) (fn)((a), (b), (c), (d))
+#define MSCALL5(fn, a, b, c, d, e) (fn)((a), (b), (c), (d), (e))
+#define MSCALL6(fn, a, b, c, d, e, f) (fn)((a), (b), (c), (d), (e), (f))
+
+#endif /* __amd64__ */
+
+
#define FUNC void(*)(void)
-#define IMPORT_FUNC(x) { #x, (FUNC)x }
-#define IMPORT_FUNC_MAP(x, y) { #x, (FUNC)y }
+#define IMPORT_FUNC(x) { #x, (FUNC)x, NULL }
+#define IMPORT_FUNC_MAP(x, y) { #x, (FUNC)y, NULL }
__BEGIN_DECLS
extern int pe_get_dos_header(vm_offset_t, image_dos_header *);
@@ -489,7 +561,7 @@ extern int pe_get_section_header(vm_offset_t, image_section_header *);
extern int pe_numsections(vm_offset_t);
extern vm_offset_t pe_imagebase(vm_offset_t);
extern vm_offset_t pe_directory_offset(vm_offset_t, uint32_t);
-extern vm_offset_t pe_translate_addr (vm_offset_t, uint32_t);
+extern vm_offset_t pe_translate_addr (vm_offset_t, vm_offset_t);
extern int pe_get_section(vm_offset_t, image_section_header *, const char *);
extern int pe_relocate(vm_offset_t);
extern int pe_get_import_descriptor(vm_offset_t, image_import_descriptor *, char *);
diff --git a/sys/compat/ndis/resource_var.h b/sys/compat/ndis/resource_var.h
index 9386052..28f2d62 100644
--- a/sys/compat/ndis/resource_var.h
+++ b/sys/compat/ndis/resource_var.h
@@ -1,12 +1,48 @@
-
-/*
+/*-
+ * Copyright (c) 2005
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
* $FreeBSD$
*/
+#ifndef _RESOURCE_VAR_H_
+#define _RESOURCE_VAR_H_
+
typedef int cm_resource_type;
struct physaddr {
- uint64_t np_quad;
+ uint64_t np_quad;
+#ifdef notdef
+ uint32_t np_low;
+ uint32_t np_high;
+#endif
};
typedef struct physaddr physaddr;
@@ -129,7 +165,7 @@ struct cm_partial_resource_desc {
uint32_t cprd_rsvd1;
uint32_t cprd_rsvd2;
} cprd_devspec;
- } u;
+ } u __attribute__((packed));
};
typedef struct cm_partial_resource_desc cm_partial_resource_desc;
@@ -159,3 +195,5 @@ struct cm_resource_list {
typedef struct cm_resource_list cm_resource_list;
typedef cm_partial_resource_list ndis_resource_list;
+
+#endif /* _RESOURCE_VAR_H_ */
diff --git a/sys/compat/ndis/subr_hal.c b/sys/compat/ndis/subr_hal.c
index b72613c..0ec036a 100644
--- a/sys/compat/ndis/subr_hal.c
+++ b/sys/compat/ndis/subr_hal.c
@@ -82,6 +82,35 @@ __stdcall static void dummy (void);
extern struct mtx_pool *ndis_mtxpool;
+int
+hal_libinit()
+{
+ image_patch_table *patch;
+
+ patch = hal_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_wrap((funcptr)patch->ipt_func,
+ (funcptr *)&patch->ipt_wrap);
+ patch++;
+ }
+
+ return(0);
+}
+
+int
+hal_libfini()
+{
+ image_patch_table *patch;
+
+ patch = hal_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_unwrap(patch->ipt_wrap);
+ patch++;
+ }
+
+ return(0);
+}
+
__stdcall static void
KeStallExecutionProcessor(usecs)
uint32_t usecs;
@@ -375,9 +404,9 @@ image_patch_table hal_functbl[] = {
* in this table.
*/
- { NULL, (FUNC)dummy },
+ { NULL, (FUNC)dummy, NULL },
/* End of list. */
- { NULL, NULL },
+ { NULL, NULL, NULL }
};
diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c
index f5b5972..da56c18 100644
--- a/sys/compat/ndis/subr_ndis.c
+++ b/sys/compat/ndis/subr_ndis.c
@@ -188,15 +188,6 @@ __stdcall static uint32_t NdisGetCacheFillSize(void);
__stdcall static uint32_t NdisMGetDmaAlignment(ndis_handle);
__stdcall static ndis_status NdisMInitializeScatterGatherDma(ndis_handle,
uint8_t, uint32_t);
-__stdcall static void NdisAllocatePacketPool(ndis_status *,
- ndis_handle *, uint32_t, uint32_t);
-__stdcall static void NdisAllocatePacketPoolEx(ndis_status *,
- ndis_handle *, uint32_t, uint32_t, uint32_t);
-__stdcall static uint32_t NdisPacketPoolUsage(ndis_handle);
-__stdcall static void NdisFreePacketPool(ndis_handle);
-__stdcall static void NdisAllocatePacket(ndis_status *,
- ndis_packet **, ndis_handle);
-__stdcall static void NdisFreePacket(ndis_packet *);
__stdcall static void NdisUnchainBufferAtFront(ndis_packet *, ndis_buffer **);
__stdcall static void NdisUnchainBufferAtBack(ndis_packet *, ndis_buffer **);
__stdcall static void NdisAllocateBufferPool(ndis_status *,
@@ -306,13 +297,31 @@ __stdcall static void dummy(void);
int
ndis_libinit()
{
+ image_patch_table *patch;
+
strcpy(ndis_filepath, "/compat/ndis");
+
+ patch = ndis_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_wrap((funcptr)patch->ipt_func,
+ (funcptr *)&patch->ipt_wrap);
+ patch++;
+ }
+
return(0);
}
int
ndis_libfini()
{
+ image_patch_table *patch;
+
+ patch = ndis_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_unwrap(patch->ipt_wrap);
+ patch++;
+ }
+
return(0);
}
@@ -460,6 +469,7 @@ NdisAllocateMemoryWithTag(vaddr, len, tag)
{
void *mem;
+
mem = ExAllocatePoolWithTag(NonPagedPool, len, tag);
if (mem == NULL)
return(NDIS_STATUS_RESOURCES);
@@ -528,6 +538,7 @@ NdisOpenConfiguration(status, cfg, wrapctx)
ndis_handle *cfg;
ndis_handle wrapctx;
{
+
*cfg = wrapctx;
*status = NDIS_STATUS_SUCCESS;
@@ -676,7 +687,6 @@ NdisReadConfiguration(status, parm, cfg, key, type)
}
ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr);
-
*parm = &block->nmb_replyparm;
bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
unicode = (uint16_t *)&block->nmb_dummybuf;
@@ -960,11 +970,14 @@ NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code,
uint16_t flags;
char msgbuf[ERRMSGLEN];
device_t dev;
+ driver_object *drv;
block = (ndis_miniport_block *)adapter;
dev = block->nmb_physdeviceobj->do_devext;
+ drv = block->nmb_physdeviceobj->do_drvobj;
- error = pe_get_message(block->nmb_img, code, &str, &i, &flags);
+ error = pe_get_message((vm_offset_t)drv->dro_driverstart,
+ code, &str, &i, &flags);
if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) {
ustr = msgbuf;
ndis_unicode_to_ascii((uint16_t *)str,
@@ -1194,6 +1207,7 @@ NdisMQueryAdapterResources(status, adapter, list, buflen)
bcopy((char *)block->nmb_rlist, (char *)list, rsclen);
*status = NDIS_STATUS_SUCCESS;
+
return;
}
@@ -1381,11 +1395,11 @@ NdisMAllocateSharedMemory(adapter, len, cached, vaddr, paddr)
* At least one device/driver combination (Linksys Instant
* Wireless PCI Card V2.7, Broadcom 802.11b) seems to have
* problems with performing DMA operations with physical
- * that lie above the 1GB mark. I don't know if this is a
- * hardware limitation or if the addresses are being truncated
- * within the driver, but this seems to be the only way to
- * make these cards work reliably in systems with more than
- * 1GB of physical memory.
+ * addresses that lie above the 1GB mark. I don't know if this
+ * is a hardware limitation or if the addresses are being
+ * truncated within the driver, but this seems to be the only
+ * way to make these cards work reliably in systems with more
+ * than 1GB of physical memory.
*/
error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
@@ -1452,7 +1466,7 @@ ndis_asyncmem_complete(arg)
donefunc = sc->ndis_chars->nmc_allocate_complete_func;
NdisMAllocateSharedMemory(w->na_adapter, w->na_len,
w->na_cached, &vaddr, &paddr);
- donefunc(w->na_adapter, vaddr, &paddr, w->na_len, w->na_ctx);
+ MSCALL5(donefunc, w->na_adapter, vaddr, &paddr, w->na_len, w->na_ctx);
free(arg, M_DEVBUF);
@@ -1626,7 +1640,7 @@ NdisMInitializeScatterGatherDma(adapter, is64, maxphysmap)
return(NDIS_STATUS_SUCCESS);
}
-__stdcall static void
+__stdcall void
NdisAllocatePacketPool(status, pool, descnum, protrsvdlen)
ndis_status *status;
ndis_handle *pool;
@@ -1636,7 +1650,7 @@ NdisAllocatePacketPool(status, pool, descnum, protrsvdlen)
ndis_packet *cur;
int i;
- *pool = malloc(sizeof(ndis_packet) *
+ *pool = malloc((sizeof(ndis_packet) + protrsvdlen) *
((descnum + NDIS_POOL_EXTRA) + 1),
M_DEVBUF, M_NOWAIT|M_ZERO);
@@ -1657,7 +1671,7 @@ NdisAllocatePacketPool(status, pool, descnum, protrsvdlen)
return;
}
-__stdcall static void
+__stdcall void
NdisAllocatePacketPoolEx(status, pool, descnum, oflowdescnum, protrsvdlen)
ndis_status *status;
ndis_handle *pool;
@@ -1669,7 +1683,7 @@ NdisAllocatePacketPoolEx(status, pool, descnum, oflowdescnum, protrsvdlen)
descnum + oflowdescnum, protrsvdlen));
}
-__stdcall static uint32_t
+__stdcall uint32_t
NdisPacketPoolUsage(pool)
ndis_handle pool;
{
@@ -1680,7 +1694,7 @@ NdisPacketPoolUsage(pool)
return(head->np_private.npp_count);
}
-__stdcall static void
+__stdcall void
NdisFreePacketPool(pool)
ndis_handle pool;
{
@@ -1702,7 +1716,7 @@ NdisFreePacketPool(pool)
return;
}
-__stdcall static void
+__stdcall void
NdisAllocatePacket(status, packet, pool)
ndis_status *status;
ndis_packet **packet;
@@ -1747,7 +1761,8 @@ NdisAllocatePacket(status, packet, pool)
/*
* We must initialize the packet flags correctly in order
* for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
- * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() to work correctly.
+ * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() macros to work
+ * correctly.
*/
pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
@@ -1755,10 +1770,11 @@ NdisAllocatePacket(status, packet, pool)
head->np_private.npp_count++;
*status = NDIS_STATUS_SUCCESS;
+
return;
}
-__stdcall static void
+__stdcall void
NdisFreePacket(packet)
ndis_packet *packet;
{
@@ -1842,12 +1858,16 @@ NdisUnchainBufferAtBack(packet, buf)
}
/*
- * The NDIS "buffer" manipulation functions are somewhat misnamed.
- * They don't really allocate buffers: they allocate buffer mappings.
- * The idea is you reserve a chunk of DMA-able memory using
- * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
- * to obtain the virtual address of the DMA-able region.
- * NdisAllocateBufferPool() is analagous to bus_dma_tag_create().
+ * The NDIS "buffer" is really an MDL (memory descriptor list)
+ * which is used to describe a buffer in a way that allows it
+ * to mapped into different contexts. We have to be careful how
+ * we handle them: in some versions of Windows, the NdisFreeBuffer()
+ * routine is an actual function in the NDIS API, but in others
+ * it's just a macro wrapper around IoFreeMdl(). There's really
+ * no way to use the 'descnum' parameter to count how many
+ * "buffers" are allocated since in order to use IoFreeMdl() to
+ * dispose of a buffer, we have to use IoAllocateMdl() to allocate
+ * them, and IoAllocateMdl() just grabs them out of the heap.
*/
__stdcall static void
@@ -1856,27 +1876,13 @@ NdisAllocateBufferPool(status, pool, descnum)
ndis_handle *pool;
uint32_t descnum;
{
- ndis_buffer *cur;
- int i;
-
- *pool = malloc(sizeof(ndis_buffer) *
- ((descnum + NDIS_POOL_EXTRA) + 1),
- M_DEVBUF, M_NOWAIT|M_ZERO);
-
- if (*pool == NULL) {
- *status = NDIS_STATUS_RESOURCES;
- return;
- }
-
- cur = (ndis_buffer *)*pool;
- cur->mdl_flags = 0x1; /* mark the head of the list */
- MmGetMdlByteCount(cur) = 0; /* init usage count */
- MmGetMdlByteOffset(cur) = 0; /* init deletetion flag */
- for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
- cur->mdl_next = cur + 1;
- cur++;
- }
+ /*
+ * The only thing we can really do here is verify that descnum
+ * is a reasonable value, but I really don't know what to check
+ * it against.
+ */
+ *pool = NonPagedPool;
*status = NDIS_STATUS_SUCCESS;
return;
}
@@ -1885,26 +1891,9 @@ __stdcall static void
NdisFreeBufferPool(pool)
ndis_handle pool;
{
- ndis_buffer *head;
-
- head = pool;
-
- /* Mark this pool as 'going away.' */
-
- MmGetMdlByteOffset(head) = 1;
-
- /* If there are no buffers loaned out, destroy the pool. */
- if (MmGetMdlByteCount(head) == 0)
- free(pool, M_DEVBUF);
- else
- printf("NDIS: buggy driver deleting active buffer pool!\n");
-
return;
}
-/*
- * This maps to a bus_dmamap_create() and bus_dmamap_load().
- */
__stdcall static void
NdisAllocateBuffer(status, buffer, pool, vaddr, len)
ndis_status *status;
@@ -1913,45 +1902,17 @@ NdisAllocateBuffer(status, buffer, pool, vaddr, len)
void *vaddr;
uint32_t len;
{
- ndis_buffer *head, *buf;
-
- head = (ndis_buffer *)pool;
- if (head->mdl_flags != 0x1) {
- *status = NDIS_STATUS_FAILURE;
- return;
- }
-
- /*
- * If this pool is marked as 'going away' don't allocate any
- * more buffers out of it.
- */
-
- if (MmGetMdlByteOffset(head)) {
- *status = NDIS_STATUS_FAILURE;
- return;
- }
-
- buf = head->mdl_next;
+ ndis_buffer *buf;
+ buf = IoAllocateMdl(vaddr, len, FALSE, FALSE, NULL);
if (buf == NULL) {
*status = NDIS_STATUS_RESOURCES;
return;
}
- head->mdl_next = buf->mdl_next;
-
- /* Save pointer to the pool. */
- buf->mdl_process = head;
-
- MmInitializeMdl(buf, vaddr, len);
-
*buffer = buf;
-
- /* Increment count of busy buffers. */
-
- MmGetMdlByteCount(head)++;
-
*status = NDIS_STATUS_SUCCESS;
+
return;
}
@@ -1959,31 +1920,7 @@ __stdcall static void
NdisFreeBuffer(buf)
ndis_buffer *buf;
{
- ndis_buffer *head;
-
- if (buf == NULL || buf->mdl_process == NULL)
- return;
-
- head = buf->mdl_process;
-
- if (head->mdl_flags != 0x1)
- return;
-
- buf->mdl_next = head->mdl_next;
- head->mdl_next = buf;
-
- /* Decrement count of busy buffers. */
-
- MmGetMdlByteCount(head)--;
-
- /*
- * If the pool has been marked for deletion and there are
- * no more buffers outstanding, nuke the pool.
- */
-
- if (MmGetMdlByteOffset(head) && MmGetMdlByteCount(head) == 0)
- free(head, M_DEVBUF);
-
+ IoFreeMdl(buf);
return;
}
@@ -2194,6 +2131,8 @@ NdisMRegisterInterrupt(intr, adapter, ivec, ilevel, reqisr, shared, imode)
intr->ni_shared = shared;
block->nmb_interrupt = intr;
+ KeInitializeSpinLock(&intr->ni_dpccountlock);
+
return(NDIS_STATUS_SUCCESS);
}
@@ -2423,18 +2362,17 @@ NdisMSynchronizeWithInterrupt(intr, syncfunc, syncctx)
void *syncfunc;
void *syncctx;
{
- struct ndis_softc *sc;
__stdcall uint8_t (*sync)(void *);
uint8_t rval;
+ uint8_t irql;
if (syncfunc == NULL || syncctx == NULL)
return(0);
- sc = device_get_softc(intr->ni_block->nmb_physdeviceobj->do_devext);
sync = syncfunc;
- mtx_lock(&sc->ndis_intrmtx);
- rval = sync(syncctx);
- mtx_unlock(&sc->ndis_intrmtx);
+ KeAcquireSpinLock(&intr->ni_dpccountlock, &irql);
+ rval = MSCALL1(sync, syncctx);
+ KeReleaseSpinLock(&intr->ni_dpccountlock, irql);
return(rval);
}
@@ -2901,7 +2839,7 @@ NdisMIndicateStatusComplete(adapter)
block = (ndis_miniport_block *)adapter;
statusdonefunc = block->nmb_statusdone_func;
- statusdonefunc(adapter);
+ MSCALL1(statusdonefunc, adapter);
return;
}
@@ -2918,7 +2856,7 @@ NdisMIndicateStatus(adapter, status, sbuf, slen)
block = (ndis_miniport_block *)adapter;
statusfunc = block->nmb_status_func;
- statusfunc(adapter, status, sbuf, slen);
+ MSCALL4(statusfunc, adapter, status, sbuf, slen);
return;
}
@@ -2931,7 +2869,7 @@ ndis_workfunc(ctx)
work = ctx;
workfunc = work->nwi_func;
- workfunc(work, work->nwi_ctx);
+ MSCALL2(workfunc, work, work->nwi_ctx);
return;
}
@@ -3230,9 +3168,9 @@ image_patch_table ndis_functbl[] = {
* in this table.
*/
- { NULL, (FUNC)dummy },
+ { NULL, (FUNC)dummy, NULL },
/* End of list. */
- { NULL, NULL },
+ { NULL, NULL, NULL }
};
diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c
index f793f2a..5558705 100644
--- a/sys/compat/ndis/subr_ntoskrnl.c
+++ b/sys/compat/ndis/subr_ntoskrnl.c
@@ -143,8 +143,6 @@ __fastcall static uint32_t
InterlockedDecrement(REGARGS1(volatile uint32_t *addend));
__fastcall static void
ExInterlockedAddLargeStatistic(REGARGS2(uint64_t *addend, uint32_t));
-__stdcall static mdl *IoAllocateMdl(void *, uint32_t, uint8_t, uint8_t, irp *);
-__stdcall static void IoFreeMdl(mdl *);
__stdcall static uint32_t MmSizeOfMdl(void *, size_t);
__stdcall static void MmBuildMdlForNonPagedPool(mdl *);
__stdcall static void *MmMapLockedPages(mdl *, uint8_t);
@@ -178,6 +176,7 @@ __stdcall static ndis_status ObReferenceObjectByHandle(ndis_handle,
uint32_t, void *, uint8_t, void **, void **);
__fastcall static void ObfDereferenceObject(REGARGS1(void *object));
__stdcall static uint32_t ZwClose(ndis_handle);
+static void *ntoskrnl_memset(void *, int, size_t);
static uint32_t DbgPrint(char *, ...);
__stdcall static void DbgBreakPoint(void);
__stdcall static void dummy(void);
@@ -190,20 +189,51 @@ static struct nt_objref_head ntoskrnl_reflist;
int
ntoskrnl_libinit()
{
+ image_patch_table *patch;
+
mtx_init(&ntoskrnl_dispatchlock,
"ntoskrnl dispatch lock", MTX_NDIS_LOCK, MTX_DEF);
KeInitializeSpinLock(&ntoskrnl_global);
TAILQ_INIT(&ntoskrnl_reflist);
+
+ patch = ntoskrnl_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_wrap((funcptr)patch->ipt_func,
+ (funcptr *)&patch->ipt_wrap);
+ patch++;
+ }
+
return(0);
}
int
ntoskrnl_libfini()
{
+ image_patch_table *patch;
mtx_destroy(&ntoskrnl_dispatchlock);
+
+ patch = ntoskrnl_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_unwrap(patch->ipt_wrap);
+ patch++;
+ }
+
return(0);
}
+/*
+ * We need to be able to reference this externally from the wrapper;
+ * GCC only generates a local implementation of memset.
+ */
+static void *
+ntoskrnl_memset(buf, ch, size)
+ void *buf;
+ int ch;
+ size_t size;
+{
+ return(memset(buf, ch, size));
+}
+
__stdcall static uint8_t
RtlEqualUnicodeString(str1, str2, caseinsensitive)
ndis_unicode_string *str1;
@@ -680,7 +710,7 @@ IofCompleteRequest(REGARGS2(irp *ip, uint8_t prioboost))
masterirp = ip->irp_assoc.irp_master;
masterirpcnt = FASTCALL1(InterlockedDecrement,
- masterirp->irp_assoc.irp_irpcnt);
+ &masterirp->irp_assoc.irp_irpcnt);
while ((m = ip->irp_mdl) != NULL) {
ip->irp_mdl = m->mdl_next;
@@ -1323,7 +1353,7 @@ ExDeletePagedLookasideList(lookaside)
freefunc = lookaside->nll_l.gl_freefunc;
while((buf = ntoskrnl_popsl(&lookaside->nll_l.gl_listhead)) != NULL)
- freefunc(buf);
+ MSCALL1(freefunc, buf);
return;
}
@@ -1373,7 +1403,7 @@ ExDeleteNPagedLookasideList(lookaside)
freefunc = lookaside->nll_l.gl_freefunc;
while((buf = ntoskrnl_popsl(&lookaside->nll_l.gl_listhead)) != NULL)
- freefunc(buf);
+ MSCALL1(freefunc, buf);
return;
}
@@ -1435,6 +1465,22 @@ ExInterlockedPopEntrySList(REGARGS2(slist_header *head, kspin_lock *lock))
return(first);
}
+/*
+ * The KeInitializeSpinLock(), KefAcquireSpinLockAtDpcLevel()
+ * and KefReleaseSpinLockFromDpcLevel() appear to be analagous
+ * to splnet()/splx() in their use. We can't create a new mutex
+ * lock here because there is no complimentary KeFreeSpinLock()
+ * function. Instead, we grab a mutex from the mutex pool.
+ */
+__stdcall void
+KeInitializeSpinLock(lock)
+ kspin_lock *lock;
+{
+ *lock = 0;
+
+ return;
+}
+
__fastcall void
KefAcquireSpinLockAtDpcLevel(REGARGS1(kspin_lock *lock))
{
@@ -1452,6 +1498,27 @@ KefReleaseSpinLockFromDpcLevel(REGARGS1(kspin_lock *lock))
return;
}
+__stdcall uint8_t
+KeAcquireSpinLockRaiseToDpc(lock)
+ kspin_lock *lock;
+{
+ uint8_t oldirql;
+
+ oldirql = FASTCALL1(KfAcquireSpinLock, lock);
+ return(oldirql);
+}
+
+#ifndef __i386__
+__stdcall void
+KeReleaseSpinLock(lock, irql)
+ kspin_lock *lock;
+ uint8_t irql;
+{
+ FASTCALL2(KfReleaseSpinLock, lock, irql);
+ return;
+}
+#endif
+
__fastcall static uint32_t
InterlockedIncrement(REGARGS1(volatile uint32_t *addend))
{
@@ -1478,7 +1545,7 @@ ExInterlockedAddLargeStatistic(REGARGS2(uint64_t *addend, uint32_t inc))
return;
};
-__stdcall static mdl *
+__stdcall mdl *
IoAllocateMdl(vaddr, len, secondarybuf, chargequota, iopkt)
void *vaddr;
uint32_t len;
@@ -1510,10 +1577,10 @@ IoAllocateMdl(vaddr, len, secondarybuf, chargequota, iopkt)
}
}
- return (NULL);
+ return (m);
}
-__stdcall static void
+__stdcall void
IoFreeMdl(m)
mdl *m;
{
@@ -1599,22 +1666,6 @@ MmUnmapLockedPages(vaddr, buf)
return;
}
-/*
- * The KeInitializeSpinLock(), KefAcquireSpinLockAtDpcLevel()
- * and KefReleaseSpinLockFromDpcLevel() appear to be analagous
- * to splnet()/splx() in their use. We can't create a new mutex
- * lock here because there is no complimentary KeFreeSpinLock()
- * function. Instead, we grab a mutex from the mutex pool.
- */
-__stdcall void
-KeInitializeSpinLock(lock)
- kspin_lock *lock;
-{
- *lock = 0;
-
- return;
-}
-
__stdcall static size_t
RtlCompareMemory(s1, s2, len)
const void *s1;
@@ -1987,7 +2038,7 @@ ntoskrnl_thrfunc(arg)
tctx = thrctx->tc_thrctx;
free(thrctx, M_TEMP);
- rval = tfunc(tctx);
+ rval = MSCALL1(tfunc, tctx);
PsTerminateSystemThread(rval);
return; /* notreached */
@@ -2167,7 +2218,8 @@ ntoskrnl_run_dpc(arg)
dpc = arg;
dpcfunc = dpc->k_deferedfunc;
irql = KeRaiseIrql(DISPATCH_LEVEL);
- dpcfunc(dpc, dpc->k_deferredctx, dpc->k_sysarg1, dpc->k_sysarg2);
+ MSCALL4(dpcfunc, dpc, dpc->k_deferredctx,
+ dpc->k_sysarg1, dpc->k_sysarg2);
KeLowerIrql(irql);
return;
@@ -2322,6 +2374,7 @@ image_patch_table ntoskrnl_functbl[] = {
IMPORT_FUNC(RtlUnicodeStringToAnsiString),
IMPORT_FUNC(RtlAnsiStringToUnicodeString),
IMPORT_FUNC(RtlInitAnsiString),
+ IMPORT_FUNC_MAP(RtlInitString, RtlInitAnsiString),
IMPORT_FUNC(RtlInitUnicodeString),
IMPORT_FUNC(RtlFreeAnsiString),
IMPORT_FUNC(RtlFreeUnicodeString),
@@ -2338,8 +2391,8 @@ image_patch_table ntoskrnl_functbl[] = {
IMPORT_FUNC(strcpy),
IMPORT_FUNC(strlen),
IMPORT_FUNC(memcpy),
- IMPORT_FUNC_MAP(memmove, memset),
- IMPORT_FUNC(memset),
+ IMPORT_FUNC_MAP(memmove, ntoskrnl_memset),
+ IMPORT_FUNC(ntoskrnl_memset),
IMPORT_FUNC(IoAllocateDriverObjectExtension),
IMPORT_FUNC(IoGetDriverObjectExtension),
IMPORT_FUNC(IofCallDriver),
@@ -2389,6 +2442,8 @@ image_patch_table ntoskrnl_functbl[] = {
IMPORT_FUNC(ExInterlockedPushEntrySList),
IMPORT_FUNC(KefAcquireSpinLockAtDpcLevel),
IMPORT_FUNC(KefReleaseSpinLockFromDpcLevel),
+ IMPORT_FUNC(KeAcquireSpinLockRaiseToDpc),
+ IMPORT_FUNC(KeReleaseSpinLock),
IMPORT_FUNC(InterlockedIncrement),
IMPORT_FUNC(InterlockedDecrement),
IMPORT_FUNC(ExInterlockedAddLargeStatistic),
@@ -2432,9 +2487,9 @@ image_patch_table ntoskrnl_functbl[] = {
* in this table.
*/
- { NULL, (FUNC)dummy },
+ { NULL, (FUNC)dummy, NULL },
/* End of list. */
- { NULL, NULL },
+ { NULL, NULL, NULL }
};
diff --git a/sys/compat/ndis/subr_pe.c b/sys/compat/ndis/subr_pe.c
index 5f37ead..6ac815d 100644
--- a/sys/compat/ndis/subr_pe.c
+++ b/sys/compat/ndis/subr_pe.c
@@ -263,7 +263,7 @@ pe_directory_offset(imgbase, diridx)
vm_offset_t
pe_translate_addr(imgbase, rva)
vm_offset_t imgbase;
- uint32_t rva;
+ vm_offset_t rva;
{
image_optional_header opt_hdr;
image_section_header *sect_hdr;
@@ -366,7 +366,10 @@ pe_relocate(imgbase)
image_section_header sect;
image_base_reloc *relhdr;
uint16_t rel, *sloc;
- uint32_t base, delta, *lloc;
+ vm_offset_t base;
+ vm_size_t delta;
+ uint32_t *lloc;
+ uint64_t *qloc;
int i, count;
vm_offset_t txt;
@@ -403,6 +406,13 @@ pe_relocate(imgbase)
relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
*sloc += (delta & 0xFFFF);
break;
+ case IMAGE_REL_BASED_DIR64:
+ qloc = (uint64_t *)pe_translate_addr(imgbase,
+ relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
+ *qloc = pe_translate_addr(imgbase,
+ (*qloc - base));
+ break;
+
default:
printf ("[%d]reloc type: %d\n",i,
IMR_RELTYPE(rel));
@@ -561,11 +571,19 @@ pe_functbl_match(functbl, name)
while (p->ipt_name != NULL) {
if (!strcmp(p->ipt_name, name))
- return((vm_offset_t)p->ipt_func);
+ return((vm_offset_t)p->ipt_wrap);
p++;
}
printf ("no match for %s\n", name);
- return((vm_offset_t)p->ipt_func);
+
+ /*
+ * Return the wrapper pointer for this routine.
+ * For x86, this is the same as the funcptr.
+ * For amd64, this points to a wrapper routine
+ * that does calling convention translation and
+ * then invokes the underlying routine.
+ */
+ return((vm_offset_t)p->ipt_wrap);
}
/*
diff --git a/sys/compat/ndis/winx64_wrap.S b/sys/compat/ndis/winx64_wrap.S
new file mode 100644
index 0000000..a9428e1
--- /dev/null
+++ b/sys/compat/ndis/winx64_wrap.S
@@ -0,0 +1,191 @@
+/*-
+ * Copyright (c) 2005
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The x86_64 callback routines were written and graciously submitted
+ * by Ville-Pertti Keinonen <will@exomi.com>.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asmacros.h>
+
+/*
+ * Wrapper for handling up to 16 arguments. We can't really
+ * know how many arguments the caller will pass us. I'm taking an
+ * educated guess that we'll never get over 16. Handling too
+ * few arguments is bad. Handling too many is inefficient, but
+ * not fatal. If someone can think of a way to handle an arbitrary
+ * number of arguments with more elegant code, freel free to let
+ * me know.
+ *
+ * Standard amd64 calling conventions specify the following registers
+ * to be used for passing the first 6 arguments:
+ *
+ * %rdi, %rsi, %rdx, %rcx, %r8, %r9
+ *
+ * Further arguments are passed on the stack (the 7th argument is
+ * located immediately after the return address).
+ *
+ * Windows x86_64 calling conventions only pass the first 4
+ * arguments in registers:
+ *
+ * %rcx, %rdx, %r8, %r9
+ *
+ * Even when arguments are passed in registers, the stack must have
+ * space reserved for those arguments. Thus the 5th argument (the
+ * first non-register argument) is placed 32 bytes after the return
+ * address. Additionally, %rdi and %rsi must be preserved. (These
+ * two registers are not scratch registers in the standard convention.)
+ *
+ * Note that in this template, we load a contrived 64 bit address into
+ * %r11 to represent our jump address. This is to guarantee that the
+ * assembler leaves enough room to patch in an absolute 64-bit address
+ * later. The idea behind this code is that we want to avoid having to
+ * manually create all the wrapper functions at compile time with
+ * a bunch of macros. This is doable, but a) messy and b) requires
+ * us to maintain two separate tables (one for the UNIX function
+ * pointers and another with the wrappers). This means I'd have to
+ * update two different tables each time I added a function.
+ *
+ * To avoid this, we create the wrappers at runtime instead. The
+ * image patch tables now contain two pointers: one two the normal
+ * routine, and a blank one for the wrapper. To construct a wrapper,
+ * we allocate some memory and copy the template function into it,
+ * then patch the function pointer for the routine we want to wrap
+ * into the newly created wrapper. The subr_pe module can then
+ * simply patch the wrapper routine into the jump table into the
+ * windows image. As a bonus, the wrapper pointer not only serves
+ * as the wrapper entry point address, it's also a data pointer
+ * that we can pass to free() later when we unload the module.
+ */
+
+ .globl x86_64_wrap_call
+ .globl x86_64_wrap_end
+
+ENTRY(x86_64_wrap)
+x86_64_wrap:
+ subq $96,%rsp
+ mov %rsi,96-8(%rsp)
+ mov %rdi,96-16(%rsp)
+ mov %rcx,%rdi
+ mov %rdx,%rsi
+ mov %r8,%rdx
+ mov %r9,%rcx
+ mov 96+40(%rsp),%r8
+ mov 96+48(%rsp),%r9
+ mov 96+56(%rsp),%rax
+ mov %rax,(%rsp)
+ mov 96+64(%rsp),%rax
+ mov %rax,8(%rsp)
+ mov 96+72(%rsp),%rax
+ mov %rax,16(%rsp)
+ mov 96+80(%rsp),%rax
+ mov %rax,24(%rsp)
+ mov 96+88(%rsp),%rax
+ mov %rax,32(%rsp)
+ mov 96+96(%rsp),%rax
+ mov %rax,40(%rsp)
+ mov 96+104(%rsp),%rax
+ mov %rax,48(%rsp)
+ mov 96+112(%rsp),%rax
+ mov %rax,56(%rsp)
+ mov 96+120(%rsp),%rax
+ mov %rax,64(%rsp)
+ mov 96+128(%rsp),%rax
+ mov %rax,72(%rsp)
+ xor %rax,%rax
+x86_64_wrap_call:
+ mov $0xFF00FF00FF00FF00,%r11
+ callq *%r11
+ mov 96-16(%rsp),%rdi
+ mov 96-8(%rsp),%rsi
+ addq $96,%rsp
+ ret
+x86_64_wrap_end:
+
+/*
+ * Functions for invoking x86_64 callbacks. In each case, the first
+ * argument is a pointer to the function.
+ */
+
+ENTRY(x86_64_call1)
+ subq $8,%rsp
+ mov %rsi,%rcx
+ call *%rdi
+ addq $8,%rsp
+ ret
+
+ENTRY(x86_64_call2)
+ subq $24,%rsp
+ mov %rsi,%rcx
+ /* %rdx is already correct */
+ call *%rdi
+ addq $24,%rsp
+ ret
+
+ENTRY(x86_64_call3)
+ subq $24,%rsp
+ mov %rcx,%r8
+ mov %rsi,%rcx
+ call *%rdi
+ addq $24,%rsp
+ ret
+
+ENTRY(x86_64_call4)
+ subq $40,%rsp
+ mov %r8,%r9
+ mov %rcx,%r8
+ mov %rsi,%rcx
+ call *%rdi
+ addq $40,%rsp
+ ret
+
+ENTRY(x86_64_call5)
+ subq $40,%rsp
+ mov %r9,32(%rsp)
+ mov %r8,%r9
+ mov %rcx,%r8
+ mov %rsi,%rcx
+ call *%rdi
+ addq $40,%rsp
+ ret
+
+ENTRY(x86_64_call6)
+ subq $56,%rsp
+ mov 56+8(%rsp),%rax
+ mov %r9,32(%rsp)
+ mov %rax,40(%rsp)
+ mov %r8,%r9
+ mov %rcx,%r8
+ mov %rsi,%rcx
+ call *%rdi
+ addq $56,%rsp
+ ret
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 685cab1..0d68398 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -125,6 +125,10 @@ dev/fb/fb.c optional fb
dev/fb/fb.c optional vga
dev/fb/splash.c optional splash
dev/fb/vga.c optional vga
+dev/if_ndis/if_ndis.c optional ndis
+dev/if_ndis/if_ndis_pccard.c optional ndis pccard
+dev/if_ndis/if_ndis_pci.c optional ndis cardbus
+dev/if_ndis/if_ndis_pci.c optional ndis pci
dev/io/iodev.c optional io
dev/fdc/fdc.c optional fdc
dev/fdc/fdc_acpi.c optional fdc
@@ -196,3 +200,13 @@ compat/linux/linux_stats.c optional compat_linux32
compat/linux/linux_sysctl.c optional compat_linux32
compat/linux/linux_uid16.c optional compat_linux32
compat/linux/linux_util.c optional compat_linux32
+#
+# Windows NDIS driver support
+#
+compat/ndis/kern_ndis.c optional ndisapi pci
+compat/ndis/kern_windrv.c optional ndisapi pci
+compat/ndis/subr_hal.c optional ndisapi pci
+compat/ndis/subr_ndis.c optional ndisapi pci
+compat/ndis/subr_ntoskrnl.c optional ndisapi pci
+compat/ndis/subr_pe.c optional ndisapi pci
+compat/ndis/winx64_wrap.S optional ndisapi pci
diff --git a/sys/conf/options.amd64 b/sys/conf/options.amd64
index 8da2f89..7839541 100644
--- a/sys/conf/options.amd64
+++ b/sys/conf/options.amd64
@@ -17,7 +17,7 @@ COMPAT_IA32 opt_compat.h
COMPAT_LINUX32 opt_compat.h
#COMPAT_SVR4 opt_dontuse.h
#DEBUG_SVR4 opt_svr4.h
-#NDISAPI opt_dontuse.h
+NDISAPI opt_dontuse.h
CLK_CALIBRATION_LOOP opt_clock.h
CLK_USE_I8254_CALIBRATION opt_clock.h
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c
index 9f94daf..836a844 100644
--- a/sys/dev/if_ndis/if_ndis.c
+++ b/sys/dev/if_ndis/if_ndis.c
@@ -101,6 +101,13 @@ static __stdcall void ndis_linksts (ndis_handle,
ndis_status, void *, uint32_t);
static __stdcall void ndis_linksts_done (ndis_handle);
+/* We need to wrap these functions for amd64. */
+
+static funcptr ndis_txeof_wrap;
+static funcptr ndis_rxeof_wrap;
+static funcptr ndis_linksts_wrap;
+static funcptr ndis_linksts_done_wrap;
+
static void ndis_intr (void *);
static void ndis_intrtask (void *);
static void ndis_tick (void *);
@@ -151,14 +158,27 @@ ndisdrv_modevent(mod, cmd, arg)
if (ndisdrv_loaded > 1)
break;
windrv_load(mod, (vm_offset_t)drv_data, 0);
+ windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap);
+ windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap);
+ windrv_wrap((funcptr)ndis_linksts, &ndis_linksts_wrap);
+ windrv_wrap((funcptr)ndis_linksts_done,
+ &ndis_linksts_done_wrap);
break;
case MOD_UNLOAD:
ndisdrv_loaded--;
if (ndisdrv_loaded > 0)
break;
windrv_unload(mod, (vm_offset_t)drv_data, 0);
+ windrv_unwrap(ndis_rxeof_wrap);
+ windrv_unwrap(ndis_txeof_wrap);
+ windrv_unwrap(ndis_linksts_wrap);
+ windrv_unwrap(ndis_linksts_done_wrap);
break;
case MOD_SHUTDOWN:
+ windrv_unwrap(ndis_rxeof_wrap);
+ windrv_unwrap(ndis_txeof_wrap);
+ windrv_unwrap(ndis_linksts_wrap);
+ windrv_unwrap(ndis_linksts_done_wrap);
break;
default:
error = EINVAL;
@@ -418,8 +438,6 @@ ndis_attach(dev)
mtx_init(&sc->ndis_mtx, "ndis softc lock",
MTX_NETWORK_LOCK, MTX_DEF);
- mtx_init(&sc->ndis_intrmtx,
- "ndis irq lock", MTX_NETWORK_LOCK, MTX_DEF);
/*
* Hook interrupt early, since calling the driver's
@@ -476,8 +494,8 @@ ndis_attach(dev)
ndis_convert_res(sc);
/* Install our RX and TX interrupt handlers. */
- sc->ndis_block->nmb_senddone_func = ndis_txeof;
- sc->ndis_block->nmb_pktind_func = ndis_rxeof;
+ sc->ndis_block->nmb_senddone_func = ndis_txeof_wrap;
+ sc->ndis_block->nmb_pktind_func = ndis_rxeof_wrap;
/* Call driver's init routine. */
if (ndis_init_nic(sc)) {
@@ -511,6 +529,18 @@ ndis_attach(dev)
sc->ndis_txarray = malloc(sizeof(ndis_packet *) *
sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO);
+ /* Allocate a pool of ndis_packets for TX encapsulation. */
+
+ NdisAllocatePacketPool(&i, &sc->ndis_txpool,
+ sc->ndis_maxpkts, PROTOCOL_RESERVED_SIZE_IN_PACKET);
+
+ if (i != NDIS_STATUS_SUCCESS) {
+ sc->ndis_txpool = NULL;
+ device_printf(dev, "failed to allocate TX packet pool");
+ error = ENOMEM;
+ goto fail;
+ }
+
sc->ndis_txpending = sc->ndis_maxpkts;
sc->ndis_oidcnt = 0;
@@ -748,8 +778,8 @@ nonettypes:
}
/* Override the status handler so we can detect link changes. */
- sc->ndis_block->nmb_status_func = ndis_linksts;
- sc->ndis_block->nmb_statusdone_func = ndis_linksts_done;
+ sc->ndis_block->nmb_status_func = ndis_linksts_wrap;
+ sc->ndis_block->nmb_statusdone_func = ndis_linksts_done_wrap;
fail:
if (error)
ndis_detach(dev);
@@ -778,8 +808,6 @@ ndis_detach(dev)
sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->ndis_mtx),
("ndis mutex not initialized"));
- KASSERT(mtx_initialized(&sc->ndis_intrmtx),
- ("ndis interrupt mutex not initialized"));
NDIS_LOCK(sc);
ifp = &sc->arpcom.ac_if;
ifp->if_flags &= ~IFF_UP;
@@ -822,6 +850,9 @@ ndis_detach(dev)
if (!sc->ndis_80211)
ifmedia_removeall(&sc->ifmedia);
+ if (sc->ndis_txpool != NULL)
+ NdisFreePacketPool(sc->ndis_txpool);
+
ndis_unload_driver(sc);
/* Destroy the PDO for this device. */
@@ -839,7 +870,6 @@ ndis_detach(dev)
#endif
mtx_destroy(&sc->ndis_mtx);
- mtx_destroy(&sc->ndis_intrmtx);
return(0);
}
@@ -1083,9 +1113,8 @@ ndis_intrtask(arg)
irql = KeRaiseIrql(DISPATCH_LEVEL);
ndis_intrhand(sc);
KeLowerIrql(irql);
- mtx_lock(&sc->ndis_intrmtx);
+
ndis_enable_intr(sc);
- mtx_unlock(&sc->ndis_intrmtx);
return;
}
@@ -1098,21 +1127,24 @@ ndis_intr(arg)
struct ifnet *ifp;
int is_our_intr = 0;
int call_isr = 0;
+ uint8_t irql;
+ ndis_miniport_interrupt *intr;
sc = arg;
ifp = &sc->arpcom.ac_if;
+ intr = sc->ndis_block->nmb_interrupt;
if (sc->ndis_block->nmb_miniportadapterctx == NULL)
return;
- mtx_lock(&sc->ndis_intrmtx);
+ KeAcquireSpinLock(&intr->ni_dpccountlock, &irql);
if (sc->ndis_block->nmb_interrupt->ni_isrreq == TRUE)
ndis_isr(sc, &is_our_intr, &call_isr);
else {
ndis_disable_intr(sc);
call_isr = 1;
}
- mtx_unlock(&sc->ndis_intrmtx);
+ KeReleaseSpinLock(&intr->ni_dpccountlock, irql);
if ((is_our_intr || call_isr))
ndis_sched(ndis_intrtask, ifp->if_softc, NDIS_SWI);
@@ -1258,7 +1290,7 @@ ndis_start(ifp)
struct mbuf *m = NULL;
ndis_packet **p0 = NULL, *p = NULL;
ndis_tcpip_csum *csum;
- int pcnt = 0;
+ int pcnt = 0, status;
sc = ifp->if_softc;
@@ -1280,7 +1312,11 @@ ndis_start(ifp)
if (m == NULL)
break;
- sc->ndis_txarray[sc->ndis_txidx] = NULL;
+ NdisAllocatePacket(&status,
+ &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
+
+ if (status != NDIS_STATUS_SUCCESS)
+ break;
if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
#if __FreeBSD_version >= 502114
diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h
index 6736024..0936aaf 100644
--- a/sys/dev/if_ndis/if_ndisvar.h
+++ b/sys/dev/if_ndis/if_ndisvar.h
@@ -94,7 +94,6 @@ struct ndis_softc {
struct resource_list ndis_rl;
int ndis_rescnt;
struct mtx ndis_mtx;
- struct mtx ndis_intrmtx;
device_t ndis_dev;
int ndis_unit;
ndis_miniport_block *ndis_block;
@@ -107,6 +106,7 @@ struct ndis_softc {
int ndis_txidx;
int ndis_txpending;
ndis_packet **ndis_txarray;
+ ndis_handle ndis_txpool;
int ndis_sc;
ndis_cfg *ndis_regvals;
struct nch ndis_cfglist_head;
@@ -130,7 +130,6 @@ struct ndis_softc {
bus_dmamap_t *ndis_mmaps;
bus_dmamap_t *ndis_tmaps;
int ndis_mmapcnt;
- device_object *ndis_pdo;
};
#define NDIS_LOCK(_sc) mtx_lock(&(_sc)->ndis_mtx)
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 8b6a2ba..a383bbe 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -413,7 +413,7 @@ _io= io
_ips= ips
#_lnc= lnc
_mly= mly
-#_ndis= ndis
+_ndis= ndis
_safe= safe
_scsi_low= scsi_low
_smbfs= smbfs
diff --git a/sys/modules/ndis/Makefile b/sys/modules/ndis/Makefile
index 0090a45..4c622dd 100644
--- a/sys/modules/ndis/Makefile
+++ b/sys/modules/ndis/Makefile
@@ -7,4 +7,8 @@ SRCS= subr_pe.c subr_ndis.c subr_hal.c subr_ntoskrnl.c kern_ndis.c
SRCS+= kern_windrv.c
SRCS+= opt_bdg.h device_if.h bus_if.h pci_if.h vnode_if.h
+.if ${MACHINE_ARCH} == "amd64"
+SRCS+= winx64_wrap.S
+.endif
+
.include <bsd.kmod.mk>
diff --git a/usr.sbin/ndiscvt/inf.c b/usr.sbin/ndiscvt/inf.c
index de6c342..e6389fc 100644
--- a/usr.sbin/ndiscvt/inf.c
+++ b/usr.sbin/ndiscvt/inf.c
@@ -61,7 +61,7 @@ static void dump_deviceids_pci (void);
static void dump_deviceids_pcmcia (void);
static void dump_pci_id (const char *);
static void dump_pcmcia_id (const char *);
-static void dump_regvals (void);
+/*static*/ void dump_regvals (void);
static void dump_paramreg (const struct section *,
const struct reg *, int);
@@ -246,7 +246,8 @@ dump_deviceids_pci()
if (manf->vals[1] != NULL &&
(strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
strcasecmp(manf->vals[1], "NTx86") == 0 ||
- strcasecmp(manf->vals[1], "NTx86.5.1") == 0)) {
+ strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
+ strcasecmp(manf->vals[1], "NTamd64") == 0)) {
/* Handle Windows XP INF files. */
snprintf(xpsec, sizeof(xpsec), "%s.%s",
manf->vals[0], manf->vals[1]);
@@ -325,7 +326,8 @@ dump_deviceids_pcmcia()
if (manf->vals[1] != NULL &&
(strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
strcasecmp(manf->vals[1], "NTx86") == 0 ||
- strcasecmp(manf->vals[1], "NTx86.5.1") == 0)) {
+ strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
+ strcasecmp(manf->vals[1], "NTamd64") == 0)) {
/* Handle Windows XP INF files. */
snprintf(xpsec, sizeof(xpsec), "%s.%s",
manf->vals[0], manf->vals[1]);
@@ -557,7 +559,7 @@ dump_paramreg(const struct section *s, const struct reg *r, int devidx)
return;
}
-static void
+/*static*/ void
dump_regvals(void)
{
struct assign *manf, *dev;
@@ -578,7 +580,8 @@ dump_regvals(void)
if (manf->vals[1] != NULL &&
(strcasecmp(manf->vals[1], "NT.5.1") == 0 ||
strcasecmp(manf->vals[1], "NTx86") == 0 ||
- strcasecmp(manf->vals[1], "NTx86.5.1") == 0)) {
+ strcasecmp(manf->vals[1], "NTx86.5.1") == 0 ||
+ strcasecmp(manf->vals[1], "NTamd64") == 0)) {
is_winxp++;
/* Handle Windows XP INF files. */
snprintf(sname, sizeof(sname), "%s.%s",
@@ -600,9 +603,15 @@ retry:
* Look for section names with .NT, unless
* this is a WinXP .INF file.
*/
+
if (is_winxp) {
sprintf(sname, "%s.NTx86", assign->vals[0]);
dev = find_assign(sname, "AddReg");
+ if (dev == NULL) {
+ sprintf(sname, "%s.NT",
+ assign->vals[0]);
+ dev = find_assign(sname, "AddReg");
+ }
if (dev == NULL)
dev = find_assign(assign->vals[0],
"AddReg");
OpenPOWER on IntegriCloud