diff options
-rw-r--r-- | sys/compat/ndis/kern_ndis.c | 1 | ||||
-rw-r--r-- | sys/compat/ndis/ndis_var.h | 1 | ||||
-rw-r--r-- | sys/compat/ndis/pe_var.h | 101 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ndis.c | 12 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ntoskrnl.c | 66 | ||||
-rw-r--r-- | sys/compat/ndis/subr_pe.c | 101 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis.c | 31 |
7 files changed, 275 insertions, 38 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c index 4e0ce26..4564e95 100644 --- a/sys/compat/ndis/kern_ndis.c +++ b/sys/compat/ndis/kern_ndis.c @@ -1179,6 +1179,7 @@ ndis_load_driver(img, arg) block->nmb_ifp = &sc->arpcom.ac_if; block->nmb_dev = sc->ndis_dev; + block->nmb_img = img; return(0); } diff --git a/sys/compat/ndis/ndis_var.h b/sys/compat/ndis/ndis_var.h index 9dc30a9..3a2f953 100644 --- a/sys/compat/ndis/ndis_var.h +++ b/sys/compat/ndis/ndis_var.h @@ -1280,6 +1280,7 @@ struct ndis_miniport_block { ndis_status nmb_getstat; ndis_status nmb_setstat; struct nte_head nmb_timerlist; + vm_offset_t nmb_img; }; typedef ndis_status (*ndis_init_handler)(ndis_status *, uint32_t *, diff --git a/sys/compat/ndis/pe_var.h b/sys/compat/ndis/pe_var.h index a0a2cc9..4eafc4c 100644 --- a/sys/compat/ndis/pe_var.h +++ b/sys/compat/ndis/pe_var.h @@ -230,6 +230,29 @@ typedef struct image_nt_header image_nt_header; #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 +/* Resource types */ + +#define RT_CURSOR 1 +#define RT_BITMAP 2 +#define RT_ICON 3 +#define RT_MENU 4 +#define RT_DIALOG 5 +#define RT_STRING 6 +#define RT_FONTDIR 7 +#define RT_FONT 8 +#define RT_ACCELERATOR 9 +#define RT_RCDATA 10 +#define RT_MESSAGETABLE 11 +#define RT_GROUP_CURSOR 12 +#define RT_GROUP_ICON 14 +#define RT_VERSION 16 +#define RT_DLGINCLUDE 17 +#define RT_PLUGPLAY 19 +#define RT_VXD 20 +#define RT_ANICURSOR 21 +#define RT_ANIICON 22 +#define RT_HTML 23 + /* * Section header format. */ @@ -303,6 +326,80 @@ typedef struct image_base_reloc image_base_reloc; #define IMAGE_REL_BASED_DIR64 10 #define IMAGE_REL_BASED_HIGH3ADJ 11 +struct image_resource_directory_entry { + uint32_t irde_name; + uint32_t irde_dataoff; +}; + +typedef struct image_resource_directory_entry image_resource_directory_entry; + +#define RESOURCE_NAME_STR 0x80000000 +#define RESOURCE_DIR_FLAG 0x80000000 + +struct image_resource_directory { + uint32_t ird_characteristics; + uint32_t ird_timestamp; + uint16_t ird_majorver; + uint16_t ird_minorver; + uint16_t ird_named_entries; + uint16_t ird_id_entries; +#ifdef notdef + image_resource_directory_entry ird_entries[1]; +#endif +}; + +typedef struct image_resource_directory image_resource_directory; + +struct image_resource_directory_string { + uint16_t irds_len; + char irds_name[1]; +}; + +typedef struct image_resource_directory_string image_resource_directory_string; + +struct image_resource_directory_string_u { + uint16_t irds_len; + char irds_name[1]; +}; + +typedef struct image_resource_directory_string_u + image_resource_directory_string_u; + +struct image_resource_data_entry { + uint32_t irde_offset; + uint32_t irde_size; + uint32_t irde_codepage; + uint32_t irde_rsvd; +}; + +typedef struct image_resource_data_entry image_resource_data_entry; + +struct message_resource_data { + uint32_t mrd_numblocks; +#ifdef notdef + message_resource_block mrd_blocks[1]; +#endif +}; + +typedef struct message_resource_data message_resource_data; + +struct message_resource_block { + uint32_t mrb_lowid; + uint32_t mrb_highid; + uint32_t mrb_entryoff; +}; + +typedef struct message_resource_block message_resource_block; + +struct message_resource_entry { + uint16_t mre_len; + uint16_t mre_flags; + char mre_text[]; +}; + +typedef struct message_resource_entry message_resource_entry; + +#define MESSAGE_RESOURCE_UNICODE 0x0001 struct image_patch_table { char *ipt_name; @@ -325,6 +422,10 @@ 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 *); extern int pe_patch_imports(vm_offset_t, char *, image_patch_table *); +#ifdef _KERNEL +extern int pe_get_messagetable(vm_offset_t, message_resource_data **); +extern int pe_get_message(vm_offset_t, uint32_t, char **, int *); +#endif __END_DECLS #endif /* _PE_VAR_H_ */ diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index 218445a..b25208d 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -796,10 +796,13 @@ ndis_syslog(ndis_handle adapter, ndis_error_code code, ndis_miniport_block *block; va_list ap; int i; + char *str = NULL; block = (ndis_miniport_block *)adapter; - device_printf (block->nmb_dev, "NDIS ERROR: %x\n", code); + pe_get_message(block->nmb_img, code, &str, &i); + device_printf (block->nmb_dev, "NDIS ERROR: %x (%s)\n", code, + str == NULL ? "unknown error" : str); device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors); va_start(ap, numerrors); @@ -1894,7 +1897,14 @@ ndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode) uint8_t shared; ndis_interrupt_mode imode; { + ndis_miniport_block *block; + + block = adapter; + intr->ni_block = adapter; + intr->ni_isrreq = reqisr; + intr->ni_shared = shared; + block->nmb_interrupt = intr; return(NDIS_STATUS_SUCCESS); } diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c index c5f3c31..5278bc2 100644 --- a/sys/compat/ndis/subr_ntoskrnl.c +++ b/sys/compat/ndis/subr_ntoskrnl.c @@ -59,6 +59,8 @@ __FBSDID("$FreeBSD$"); #include <compat/ndis/ntoskrnl_var.h> #define __stdcall __attribute__((__stdcall__)) +#define __regparm __attribute__((regparm(3))) + #define FUNC void(*)(void) __stdcall static uint32_t ntoskrnl_unicode_equal(ndis_unicode_string *, @@ -82,13 +84,13 @@ __stdcall static uint8_t ntoskrnl_readreg_uchar(uint8_t *); __stdcall static int64_t _allmul(int64_t, int64_t); __stdcall static int64_t _alldiv(int64_t, int64_t); __stdcall static int64_t _allrem(int64_t, int64_t); -__stdcall static int64_t _allshr(int64_t, int); -__stdcall static int64_t _allshl(int64_t, int); +__regparm static int64_t _allshr(int64_t, uint8_t); +__regparm static int64_t _allshl(int64_t, uint8_t); __stdcall static uint64_t _aullmul(uint64_t, uint64_t); __stdcall static uint64_t _aulldiv(uint64_t, uint64_t); __stdcall static uint64_t _aullrem(uint64_t, uint64_t); -__stdcall static uint64_t _aullshr(uint64_t, int); -__stdcall static uint64_t _aullshl(uint64_t, int); +__regparm static uint64_t _aullshr(uint64_t, uint8_t); +__regparm static uint64_t _aullshl(uint64_t, uint8_t); __stdcall static void *ntoskrnl_allocfunc(uint32_t, size_t, uint32_t); __stdcall static void ntoskrnl_freefunc(void *); __stdcall static void ntoskrnl_init_lookaside(paged_lookaside_list *, @@ -108,11 +110,13 @@ __stdcall static slist_entry *ntoskrnl_pop_slist_ex(/*slist_entry *, kspin_lock * */void); __stdcall static void ntoskrnl_lock_dpc(/*kspin_lock * */ void); __stdcall static void ntoskrnl_unlock_dpc(/*kspin_lock * */ void); -__stdcall static void ntoskrnl_interlock_inc(/*volatile uint32_t * */ void); -__stdcall static void ntoskrnl_interlock_dec(/*volatile uint32_t * */ void); +__stdcall static uint32_t + ntoskrnl_interlock_inc(/*volatile uint32_t * */ void); +__stdcall static uint32_t + ntoskrnl_interlock_dec(/*volatile uint32_t * */ void); __stdcall static void ntoskrnl_freemdl(ndis_buffer *); __stdcall static void *ntoskrnl_mmaplockedpages(ndis_buffer *, uint8_t); -__stdcall static void ntoskrnl_create_lock(kspin_lock *); +__stdcall static void ntoskrnl_init_lock(kspin_lock *); __stdcall static void dummy(void); __stdcall static size_t ntoskrnl_memcmp(const void *, const void *, size_t); @@ -121,7 +125,7 @@ static struct mtx ntoskrnl_interlock; int ntoskrnl_libinit() { - mtx_init(&ntoskrnl_interlock, "ntoskrnllock", MTX_NETWORK_LOCK, + mtx_init(&ntoskrnl_interlock, "ntoskrnllock", "ntoskrnl interlock", MTX_DEF | MTX_RECURSE); return(0); @@ -333,34 +337,34 @@ _aullrem(a, b) return (a % b); } -__stdcall static int64_t +__regparm static int64_t _allshl(a, b) int64_t a; - int b; + uint8_t b; { return (a << b); } -__stdcall static uint64_t +__regparm static uint64_t _aullshl(a, b) uint64_t a; - int b; + uint8_t b; { return (a << b); } -__stdcall static int64_t +__regparm static int64_t _allshr(a, b) int64_t a; - int b; + uint8_t b; { return (a >> b); } -__stdcall static uint64_t +__regparm static uint64_t _aullshr(a, b) uint64_t a; - int b; + uint8_t b; { return (a >> b); } @@ -567,7 +571,7 @@ ntoskrnl_unlock_dpc(/*lock*/ void) return; } -__stdcall static void +__stdcall static uint32_t ntoskrnl_interlock_inc(/*addend*/ void) { volatile uint32_t *addend; @@ -578,10 +582,10 @@ ntoskrnl_interlock_inc(/*addend*/ void) (*addend)++; mtx_unlock(&ntoskrnl_interlock); - return; + return(*addend); } -__stdcall static void +__stdcall static uint32_t ntoskrnl_interlock_dec(/*addend*/ void) { volatile uint32_t *addend; @@ -592,7 +596,7 @@ ntoskrnl_interlock_dec(/*addend*/ void) (*addend)--; mtx_unlock(&ntoskrnl_interlock); - return; + return(*addend); } __stdcall static void @@ -623,19 +627,19 @@ ntoskrnl_mmaplockedpages(buf, accessmode) return(MDL_VA(buf)); } +/* + * 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. For now, what we do is initialize the lock with + * a pointer to the ntoskrnl interlock mutex. + */ __stdcall static void -ntoskrnl_create_lock(lock) +ntoskrnl_init_lock(lock) kspin_lock *lock; { - struct mtx *mtx; - - mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO); - if (mtx == NULL) - return; - mtx_init(mtx, "ntoslock", "ntoskrnl spinlock", - MTX_DEF | MTX_RECURSE | MTX_DUPOK); - - *lock = (kspin_lock)mtx; + *lock = (kspin_lock)&ntoskrnl_interlock; return; } @@ -715,7 +719,7 @@ image_patch_table ntoskrnl_functbl[] = { { "InterlockedDecrement", (FUNC)ntoskrnl_interlock_dec }, { "IoFreeMdl", (FUNC)ntoskrnl_freemdl }, { "MmMapLockedPages", (FUNC)ntoskrnl_mmaplockedpages }, - { "KeInitializeSpinLock", (FUNC)ntoskrnl_create_lock }, + { "KeInitializeSpinLock", (FUNC)ntoskrnl_init_lock }, /* * This last entry is a catch-all for any function we haven't diff --git a/sys/compat/ndis/subr_pe.c b/sys/compat/ndis/subr_pe.c index 340d669..3151598 100644 --- a/sys/compat/ndis/subr_pe.c +++ b/sys/compat/ndis/subr_pe.c @@ -61,6 +61,15 @@ __FBSDID("$FreeBSD$"); #endif #include <compat/ndis/pe_var.h> +#ifdef _KERNEL +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/bus.h> +#include <sys/rman.h> +#include <compat/ndis/resource_var.h> +#include <compat/ndis/ntoskrnl_var.h> +#include <compat/ndis/ndis_var.h> +#endif static u_int32_t pe_functbl_match(image_patch_table *, char *); @@ -456,6 +465,98 @@ pe_get_import_descriptor(imgbase, desc, module) return (ENOENT); } +#ifdef _KERNEL +int +pe_get_messagetable(imgbase, md) + vm_offset_t imgbase; + message_resource_data **md; +{ + image_resource_directory *rdir, *rtype; + image_resource_directory_entry *dent, *dent2; + image_resource_data_entry *rent; + vm_offset_t offset; + int i; + + if (imgbase == 0) + return(EINVAL); + + offset = pe_directory_offset(imgbase, IMAGE_DIRECTORY_ENTRY_RESOURCE); + if (offset == 0) + return (ENOENT); + + rdir = (image_resource_directory *)offset; + + dent = (image_resource_directory_entry *)(offset + + sizeof(image_resource_directory)); + + for (i = 0; i < rdir->ird_id_entries; i++){ + if (dent->irde_name != RT_MESSAGETABLE) { + dent++; + continue; + } + dent2 = dent; + while (dent2->irde_dataoff & RESOURCE_DIR_FLAG) { + rtype = (image_resource_directory *)(offset + + (dent2->irde_dataoff & ~RESOURCE_DIR_FLAG)); + dent2 = (image_resource_directory_entry *) + ((uintptr_t)rtype + + sizeof(image_resource_directory)); + } + rent = (image_resource_data_entry *)(offset + + dent2->irde_dataoff); + *md = (message_resource_data *)pe_translate_addr(imgbase, + rent->irde_offset); + return(0); + } + + return(ENOENT); +} + +int +pe_get_message(imgbase, id, str, len) + vm_offset_t imgbase; + uint32_t id; + char **str; + int *len; +{ + message_resource_data *md = NULL; + message_resource_block *mb; + message_resource_entry *me; + int i; + char m[1024], *msg; + + pe_get_messagetable(imgbase, &md); + + if (md == NULL) + return(ENOENT); + + mb = (message_resource_block *)((uintptr_t)md + + sizeof(message_resource_data)); + + for (i = 0; i < md->mrd_numblocks; i++) { + if (id >= mb->mrb_lowid && id <= mb->mrb_highid) { + me = (message_resource_entry *)((uintptr_t)md + + mb->mrb_entryoff); + for (i = id - mb->mrb_lowid; i > 0; i--) + me = (message_resource_entry *)((uintptr_t)me + + me->mre_len); + if (me->mre_flags == MESSAGE_RESOURCE_UNICODE) { + msg = m; + ndis_unicode_to_ascii((uint16_t *)me->mre_text, + me->mre_len, &msg); + *str = m; + } else + *str = me->mre_text; + *len = me->mre_len; + return(0); + } + mb++; + } + + return(ENOENT); +} +#endif + /* * Find the function that matches a particular name. This doesn't * need to be particularly speedy since it's only run when loading diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index e4436d3..2870b4d 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -597,11 +597,12 @@ ndis_attach(dev) fail: if (error) ndis_detach(dev); - - /* We're done talking to the NIC for now; halt it. */ - ifp->if_flags |= IFF_UP; - ndis_halt_nic(sc); - ifp->if_flags &= ~IFF_UP; + else { + /* We're done talking to the NIC for now; halt it. */ + ifp->if_flags |= IFF_UP; + ndis_halt_nic(sc); + ifp->if_flags &= ~IFF_UP; + } return(error); } @@ -841,6 +842,9 @@ ndis_intrtask(arg, pending) ifp = &sc->arpcom.ac_if; ndis_intrhand(sc); + mtx_lock(&sc->ndis_intrmtx); + ndis_enable_intr(sc); + mtx_unlock(&sc->ndis_intrmtx); if (ifp->if_snd.ifq_head != NULL) ndis_start(ifp); @@ -864,7 +868,12 @@ ndis_intr(arg) return; mtx_lock(&sc->ndis_intrmtx); - ndis_isr(sc, &is_our_intr, &call_isr); + 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); if (is_our_intr || call_isr) @@ -1098,12 +1107,22 @@ ndis_init(xsc) sc->ndis_txpending = sc->ndis_maxpkts; sc->ndis_link = 0; + ndis_enable_intr(sc); + if (sc->ndis_80211) ndis_setstate_80211(sc); ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; + /* + * Some drivers don't set this value. The NDIS spec says + * the default checkforhang timeout is approximately 2 + * seconds. + */ + if (sc->ndis_block.nmb_checkforhangsecs == 0) + sc->ndis_block.nmb_checkforhangsecs = 2; + if (sc->ndis_chars.nmc_checkhang_func != NULL) sc->ndis_stat_ch = timeout(ndis_tick, sc, hz * sc->ndis_block.nmb_checkforhangsecs); |