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:
parent
7359dfc0b1
commit
d3eb09f083
@ -54,6 +54,13 @@ union slist_header {
|
|||||||
|
|
||||||
typedef union slist_header 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 {
|
struct general_lookaside {
|
||||||
slist_header gl_listhead;
|
slist_header gl_listhead;
|
||||||
uint16_t gl_depth;
|
uint16_t gl_depth;
|
||||||
@ -73,6 +80,7 @@ struct general_lookaside {
|
|||||||
uint32_t gl_size;
|
uint32_t gl_size;
|
||||||
void *gl_allocfunc;
|
void *gl_allocfunc;
|
||||||
void *gl_freefunc;
|
void *gl_freefunc;
|
||||||
|
list_entry gl_listent;
|
||||||
uint32_t gl_lasttotallocs;
|
uint32_t gl_lasttotallocs;
|
||||||
union {
|
union {
|
||||||
uint32_t gl_lastallocmisses;
|
uint32_t gl_lastallocmisses;
|
||||||
|
@ -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 *,
|
__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
|
||||||
void *, void *);
|
void *, void *);
|
||||||
__stdcall static void ndis_time(uint64_t *);
|
__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);
|
__stdcall static void dummy(void);
|
||||||
|
|
||||||
|
|
||||||
@ -1851,10 +1854,49 @@ ndis_time(tval)
|
|||||||
{
|
{
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
nanotime(&ts);
|
nanotime(&ts);
|
||||||
*tval = (ts.tv_nsec / 100) + (ts.tv_nsec * 10000000);
|
*tval = (ts.tv_nsec / 100) + (ts.tv_nsec * 10000000);
|
||||||
|
*tval += 11644473600;
|
||||||
return;
|
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
|
__stdcall static void
|
||||||
dummy()
|
dummy()
|
||||||
{
|
{
|
||||||
@ -1863,6 +1905,9 @@ dummy()
|
|||||||
}
|
}
|
||||||
|
|
||||||
image_patch_table ndis_functbl[] = {
|
image_patch_table ndis_functbl[] = {
|
||||||
|
{ "NdisMRemoveMiniport", (FUNC)ndis_remove_miniport },
|
||||||
|
{ "NdisInitializeString", (FUNC)ndis_init_string },
|
||||||
|
{ "NdisFreeString", (FUNC)ndis_free_string },
|
||||||
{ "NdisGetCurrentSystemTime", (FUNC)ndis_time },
|
{ "NdisGetCurrentSystemTime", (FUNC)ndis_time },
|
||||||
{ "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
|
{ "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
|
||||||
{ "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
|
{ "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
|
||||||
|
@ -95,11 +95,13 @@ __stdcall static void ntoskrnl_init_nplookaside(npaged_lookaside_list *,
|
|||||||
lookaside_alloc_func *, lookaside_free_func *,
|
lookaside_alloc_func *, lookaside_free_func *,
|
||||||
uint32_t, size_t, uint32_t, uint16_t);
|
uint32_t, size_t, uint32_t, uint16_t);
|
||||||
__stdcall static void ntoskrnl_delete_nplookaside(npaged_lookaside_list *);
|
__stdcall static void ntoskrnl_delete_nplookaside(npaged_lookaside_list *);
|
||||||
static slist_entry *ntoskrnl_push_slist(slist_entry *, slist_entry *);
|
__stdcall static slist_entry *ntoskrnl_push_slist(/*slist_entry *,
|
||||||
static slist_entry *ntoskrnl_pop_slist(slist_entry *);
|
slist_entry * */ void);
|
||||||
static slist_entry *ntoskrnl_push_slist_ex(slist_entry *,
|
__stdcall static slist_entry *ntoskrnl_pop_slist(/*slist_entry * */ void);
|
||||||
slist_entry *, kspin_lock *);
|
__stdcall static slist_entry *ntoskrnl_push_slist_ex(/*slist_entry *,
|
||||||
static slist_entry *ntoskrnl_pop_slist_ex(slist_entry *, kspin_lock *);
|
slist_entry *,*/ kspin_lock *);
|
||||||
|
__stdcall static slist_entry *ntoskrnl_pop_slist_ex(/*slist_entry *,
|
||||||
|
kspin_lock * */void);
|
||||||
__stdcall static void dummy(void);
|
__stdcall static void dummy(void);
|
||||||
|
|
||||||
static struct mtx ntoskrnl_interlock;
|
static struct mtx ntoskrnl_interlock;
|
||||||
@ -434,64 +436,79 @@ ntoskrnl_delete_nplookaside(lookaside)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: the interlocked slist push and pop routines are
|
* Note: the interlocked slist push and pop routines are
|
||||||
* declared to be _fastcall in Windows, which means they
|
* declared to be _fastcall in Windows. gcc 3.4 is supposed
|
||||||
* use the _cdecl calling convention here.
|
* 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)
|
__stdcall static slist_entry *
|
||||||
slist_entry *head;
|
ntoskrnl_push_slist(/*head, entry*/ void)
|
||||||
slist_entry *entry;
|
|
||||||
{
|
{
|
||||||
|
slist_header *head;
|
||||||
|
slist_entry *entry;
|
||||||
slist_entry *oldhead;
|
slist_entry *oldhead;
|
||||||
|
|
||||||
|
__asm__("movl %%ecx, %%ecx" : "=c" (head));
|
||||||
|
__asm__("movl %%edx, %%edx" : "=d" (entry));
|
||||||
|
|
||||||
mtx_lock(&ntoskrnl_interlock);
|
mtx_lock(&ntoskrnl_interlock);
|
||||||
oldhead = head->sl_next;
|
oldhead = head->slh_list.slh_next;
|
||||||
entry->sl_next = head->sl_next;
|
entry->sl_next = head->slh_list.slh_next;
|
||||||
head->sl_next = entry;
|
head->slh_list.slh_next = entry;
|
||||||
mtx_unlock(&ntoskrnl_interlock);
|
mtx_unlock(&ntoskrnl_interlock);
|
||||||
return(oldhead);
|
return(oldhead);
|
||||||
}
|
}
|
||||||
|
|
||||||
static slist_entry *
|
__stdcall static slist_entry *
|
||||||
ntoskrnl_pop_slist(head)
|
ntoskrnl_pop_slist(/*head*/ void)
|
||||||
slist_entry *head;
|
|
||||||
{
|
{
|
||||||
|
slist_header *head;
|
||||||
slist_entry *first;
|
slist_entry *first;
|
||||||
|
|
||||||
|
__asm__("movl %%ecx, %%ecx" : "=c" (head));
|
||||||
|
|
||||||
mtx_lock(&ntoskrnl_interlock);
|
mtx_lock(&ntoskrnl_interlock);
|
||||||
first = head->sl_next;
|
first = head->slh_list.slh_next;
|
||||||
if (first != NULL)
|
if (first != NULL)
|
||||||
head->sl_next = first->sl_next;
|
head->slh_list.slh_next = first->sl_next;
|
||||||
mtx_unlock(&ntoskrnl_interlock);
|
mtx_unlock(&ntoskrnl_interlock);
|
||||||
return(first);
|
return(first);
|
||||||
}
|
}
|
||||||
|
|
||||||
__stdcall static slist_entry *
|
__stdcall static slist_entry *
|
||||||
ntoskrnl_push_slist_ex(head, entry, lock)
|
ntoskrnl_push_slist_ex(/*head, entry,*/ lock)
|
||||||
slist_entry *head;
|
|
||||||
slist_entry *entry;
|
|
||||||
kspin_lock *lock;
|
kspin_lock *lock;
|
||||||
{
|
{
|
||||||
|
slist_header *head;
|
||||||
|
slist_entry *entry;
|
||||||
slist_entry *oldhead;
|
slist_entry *oldhead;
|
||||||
return(NULL);
|
|
||||||
|
__asm__("movl %%ecx, %%ecx" : "=c" (head));
|
||||||
|
__asm__("movl %%edx, %%edx" : "=d" (entry));
|
||||||
|
|
||||||
mtx_lock((struct mtx *)*lock);
|
mtx_lock((struct mtx *)*lock);
|
||||||
oldhead = head->sl_next;
|
oldhead = head->slh_list.slh_next;
|
||||||
entry->sl_next = head->sl_next;
|
entry->sl_next = head->slh_list.slh_next;
|
||||||
head->sl_next = entry;
|
head->slh_list.slh_next = entry;
|
||||||
mtx_unlock((struct mtx *)*lock);
|
mtx_unlock((struct mtx *)*lock);
|
||||||
return(oldhead);
|
return(oldhead);
|
||||||
}
|
}
|
||||||
|
|
||||||
__stdcall static slist_entry *
|
__stdcall static slist_entry *
|
||||||
ntoskrnl_pop_slist_ex(head, lock)
|
ntoskrnl_pop_slist_ex(/*head, lock*/ void)
|
||||||
slist_entry *head;
|
|
||||||
kspin_lock *lock;
|
|
||||||
{
|
{
|
||||||
|
slist_header *head;
|
||||||
|
kspin_lock *lock;
|
||||||
slist_entry *first;
|
slist_entry *first;
|
||||||
|
|
||||||
return(NULL);
|
__asm__("movl %%ecx, %%ecx" : "=c" (head));
|
||||||
|
__asm__("movl %%edx, %%edx" : "=d" (lock));
|
||||||
|
|
||||||
mtx_lock((struct mtx *)*lock);
|
mtx_lock((struct mtx *)*lock);
|
||||||
first = head->sl_next;
|
first = head->slh_list.slh_next;
|
||||||
if (first != NULL)
|
if (first != NULL)
|
||||||
head->sl_next = first->sl_next;
|
head->slh_list.slh_next = first->sl_next;
|
||||||
mtx_unlock((struct mtx *)*lock);
|
mtx_unlock((struct mtx *)*lock);
|
||||||
return(first);
|
return(first);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user