From d3eb09f083535c8c7d2c2a4f0261dfe4bfdd18f0 Mon Sep 17 00:00:00 2001 From: Bill Paul Date: Sat, 13 Dec 2003 07:41:12 +0000 Subject: [PATCH] subr_ndis.c: - fix ndis_time() so that it returns a time based on the proper epoch (wacky though it may be) - implement NdisInitializeString() and NdisFreeString(), and add stub for NdisMRemoveMiniport() ntoskrnl_var.h: - add missing member to the general_lookaside struct (gl_listentry) subr_ntoskrnl.c: - Fix arguments to the interlocked push/pop routines: 'head' is an slist_header *, not an slist_entry * - Kludge up _fastcall support for the push/pop routines. The _fastcall convention is similar to _stdcall, except the first two available DWORD-sized arguments are passed in %ecx and %edx, respectively. One kludge for this __attribute__ ((regparm(3))), however this isn't entirely right, as it assumes %eax, %ecx and %edx will be used (regparm(2) assumes %eax and %edx). Another kludge is to declare the two fastcall-ed args as local register variables and explicitly assign them to %ecx and %edx, but experimentation showed that gcc would not guard %ecx and %edx against being clobbered. Thus, I came up with a 3rd kludge, which is to use some inline assembly of the form: void *arg1; void *arg2; __asm__("movl %%ecx, %%ecx" : "=c" (arg1)); __asm__("movl %%edx, %%edx" : "=d" (arg2)); This lets gcc know that we're going to reference %ecx and %edx and that it should make an effort not to let it get trampled. This wastes an instruction (movl %reg, %reg is a no-op) but insures proper behavior. It's possible there's a better way to do this though: this is the first time I've used inline assembler in this fashion. The above fixes to ntoskrnl_var.h an subr_ntoskrnl.c make lookaside lists work for the two drivers I have that use them, one of which is an NDIS 5.0 miniport and another which is 5.1. --- sys/compat/ndis/ntoskrnl_var.h | 8 ++++ sys/compat/ndis/subr_ndis.c | 47 ++++++++++++++++++- sys/compat/ndis/subr_ntoskrnl.c | 81 ++++++++++++++++++++------------- 3 files changed, 103 insertions(+), 33 deletions(-) diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h index 236d6fd3610c..68c79bd197eb 100644 --- a/sys/compat/ndis/ntoskrnl_var.h +++ b/sys/compat/ndis/ntoskrnl_var.h @@ -54,6 +54,13 @@ union slist_header { typedef union slist_header slist_header; +struct list_entry { + struct list_entry *nle_flink; + struct list_entry *nle_blink; +}; + +typedef struct list_entry list_entry; + struct general_lookaside { slist_header gl_listhead; uint16_t gl_depth; @@ -73,6 +80,7 @@ struct general_lookaside { uint32_t gl_size; void *gl_allocfunc; void *gl_freefunc; + list_entry gl_listent; uint32_t gl_lasttotallocs; union { uint32_t gl_lastallocmisses; diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index d01866b3cd0f..c6e9a489db8a 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -209,6 +209,9 @@ __stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *, __stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *, void *, void *); __stdcall static void ndis_time(uint64_t *); +__stdcall static void ndis_init_string(ndis_unicode_string **, char *); +__stdcall static void ndis_free_string(ndis_unicode_string *); +__stdcall static ndis_status ndis_remove_miniport(ndis_handle *); __stdcall static void dummy(void); @@ -1851,10 +1854,49 @@ ndis_time(tval) { struct timespec ts; nanotime(&ts); - *tval = (ts.tv_nsec / 100) + (ts.tv_nsec * 10000000); + *tval = (ts.tv_nsec / 100) + (ts.tv_nsec * 10000000); + *tval += 11644473600; return; } +__stdcall static void +ndis_init_string(dst, src) + ndis_unicode_string **dst; + char *src; +{ + ndis_unicode_string *u; + + u = malloc(sizeof(ndis_unicode_string), M_DEVBUF, M_NOWAIT); + if (u == NULL) + return; + u->nus_buf = NULL; + if (ndis_ascii_to_unicode(src, &u->nus_buf)) { + free(u, M_DEVBUF); + return; + } + u->nus_len = u->nus_maxlen = strlen(src) * 2; + return; +} + +__stdcall static void +ndis_free_string(str) + ndis_unicode_string *str; +{ + if (str == NULL) + return; + if (str->nus_buf != NULL) + free(str->nus_buf, M_DEVBUF); + free(str, M_DEVBUF); + return; +} + +__stdcall static ndis_status +ndis_remove_miniport(adapter) + ndis_handle *adapter; +{ + return(NDIS_STATUS_SUCCESS); +} + __stdcall static void dummy() { @@ -1863,6 +1905,9 @@ dummy() } image_patch_table ndis_functbl[] = { + { "NdisMRemoveMiniport", (FUNC)ndis_remove_miniport }, + { "NdisInitializeString", (FUNC)ndis_init_string }, + { "NdisFreeString", (FUNC)ndis_free_string }, { "NdisGetCurrentSystemTime", (FUNC)ndis_time }, { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr }, { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async }, diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c index 3a1d12585e9b..e9fcb3bae2ec 100644 --- a/sys/compat/ndis/subr_ntoskrnl.c +++ b/sys/compat/ndis/subr_ntoskrnl.c @@ -95,11 +95,13 @@ __stdcall static void ntoskrnl_init_nplookaside(npaged_lookaside_list *, lookaside_alloc_func *, lookaside_free_func *, uint32_t, size_t, uint32_t, uint16_t); __stdcall static void ntoskrnl_delete_nplookaside(npaged_lookaside_list *); -static slist_entry *ntoskrnl_push_slist(slist_entry *, slist_entry *); -static slist_entry *ntoskrnl_pop_slist(slist_entry *); -static slist_entry *ntoskrnl_push_slist_ex(slist_entry *, - slist_entry *, kspin_lock *); -static slist_entry *ntoskrnl_pop_slist_ex(slist_entry *, kspin_lock *); +__stdcall static slist_entry *ntoskrnl_push_slist(/*slist_entry *, + slist_entry * */ void); +__stdcall static slist_entry *ntoskrnl_pop_slist(/*slist_entry * */ void); +__stdcall static slist_entry *ntoskrnl_push_slist_ex(/*slist_entry *, + slist_entry *,*/ kspin_lock *); +__stdcall static slist_entry *ntoskrnl_pop_slist_ex(/*slist_entry *, + kspin_lock * */void); __stdcall static void dummy(void); static struct mtx ntoskrnl_interlock; @@ -434,64 +436,79 @@ ntoskrnl_delete_nplookaside(lookaside) /* * Note: the interlocked slist push and pop routines are - * declared to be _fastcall in Windows, which means they - * use the _cdecl calling convention here. + * declared to be _fastcall in Windows. gcc 3.4 is supposed + * to have support for this calling convention, however we + * don't have that version available yet, so we kludge things + * up using some inline assembly. */ -static slist_entry * -ntoskrnl_push_slist(head, entry) - slist_entry *head; - slist_entry *entry; + +__stdcall static slist_entry * +ntoskrnl_push_slist(/*head, entry*/ void) { + slist_header *head; + slist_entry *entry; slist_entry *oldhead; + + __asm__("movl %%ecx, %%ecx" : "=c" (head)); + __asm__("movl %%edx, %%edx" : "=d" (entry)); + mtx_lock(&ntoskrnl_interlock); - oldhead = head->sl_next; - entry->sl_next = head->sl_next; - head->sl_next = entry; + oldhead = head->slh_list.slh_next; + entry->sl_next = head->slh_list.slh_next; + head->slh_list.slh_next = entry; mtx_unlock(&ntoskrnl_interlock); return(oldhead); } -static slist_entry * -ntoskrnl_pop_slist(head) - slist_entry *head; +__stdcall static slist_entry * +ntoskrnl_pop_slist(/*head*/ void) { + slist_header *head; slist_entry *first; + + __asm__("movl %%ecx, %%ecx" : "=c" (head)); + mtx_lock(&ntoskrnl_interlock); - first = head->sl_next; + first = head->slh_list.slh_next; if (first != NULL) - head->sl_next = first->sl_next; + head->slh_list.slh_next = first->sl_next; mtx_unlock(&ntoskrnl_interlock); return(first); } __stdcall static slist_entry * -ntoskrnl_push_slist_ex(head, entry, lock) - slist_entry *head; - slist_entry *entry; +ntoskrnl_push_slist_ex(/*head, entry,*/ lock) kspin_lock *lock; { + slist_header *head; + slist_entry *entry; slist_entry *oldhead; - return(NULL); + + __asm__("movl %%ecx, %%ecx" : "=c" (head)); + __asm__("movl %%edx, %%edx" : "=d" (entry)); + mtx_lock((struct mtx *)*lock); - oldhead = head->sl_next; - entry->sl_next = head->sl_next; - head->sl_next = entry; + oldhead = head->slh_list.slh_next; + entry->sl_next = head->slh_list.slh_next; + head->slh_list.slh_next = entry; mtx_unlock((struct mtx *)*lock); return(oldhead); } __stdcall static slist_entry * -ntoskrnl_pop_slist_ex(head, lock) - slist_entry *head; - kspin_lock *lock; +ntoskrnl_pop_slist_ex(/*head, lock*/ void) { + slist_header *head; + kspin_lock *lock; slist_entry *first; - return(NULL); + __asm__("movl %%ecx, %%ecx" : "=c" (head)); + __asm__("movl %%edx, %%edx" : "=d" (lock)); + mtx_lock((struct mtx *)*lock); - first = head->sl_next; + first = head->slh_list.slh_next; if (first != NULL) - head->sl_next = first->sl_next; + head->slh_list.slh_next = first->sl_next; mtx_unlock((struct mtx *)*lock); return(first); }