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.
This commit is contained in:
Bill Paul 2003-12-13 07:41:12 +00:00
parent 7359dfc0b1
commit d3eb09f083
3 changed files with 103 additions and 33 deletions

View File

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

View File

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

View File

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