aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>2005-02-16 05:41:18 +0000
committerBill Paul <wpaul@FreeBSD.org>2005-02-16 05:41:18 +0000
commitd8f2dda739fad2bc47249f365a8d5f9de292b965 (patch)
treef3934335c485d66f4991e7d9fc75b2e17460984c /sys
parent5cc540d471f885e245faf92b690fc50d61d16d17 (diff)
Notes
Diffstat (limited to 'sys')
-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
18 files changed, 768 insertions, 259 deletions
diff --git a/sys/compat/ndis/hal_var.h b/sys/compat/ndis/hal_var.h
index 63868956e2231..c2a534e9f217b 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 f93bf4e36fbc2..589742badc60c 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 f298b995c350f..a2279ca702847 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 b4eaf5a179751..7b33a3e3142c1 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 f1c0766cbc777..4c0112a5a719c 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 fa635d4afeb49..47055a8d5f993 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 9386052ccab8b..28f2d62920eed 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 b72613cebe5db..0ec036acb59a5 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 f5b59727aa632..da56c187c63fa 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 f793f2a6f1953..555870581e43f 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 5f37eade203b6..6ac815df36dd6 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 0000000000000..a9428e1b5dd08
--- /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 685cab1cbbba2..0d683988c7c8b 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 8da2f8949a550..7839541ce240f 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 9f94daff46dcd..836a844c74b90 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 6736024a67228..0936aaf7fc23a 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 8b6a2ba95d4ef..a383bbe4df9f2 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 0090a45e03a46..4c622dd2dccd0 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>