summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/compat/ndis/kern_ndis.c1
-rw-r--r--sys/compat/ndis/ndis_var.h1
-rw-r--r--sys/compat/ndis/pe_var.h101
-rw-r--r--sys/compat/ndis/subr_ndis.c12
-rw-r--r--sys/compat/ndis/subr_ntoskrnl.c66
-rw-r--r--sys/compat/ndis/subr_pe.c101
-rw-r--r--sys/dev/if_ndis/if_ndis.c31
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);
OpenPOWER on IntegriCloud