diff options
Diffstat (limited to 'sys/compat/ndis')
-rw-r--r-- | sys/compat/ndis/kern_ndis.c | 2 | ||||
-rw-r--r-- | sys/compat/ndis/kern_windrv.c | 108 | ||||
-rw-r--r-- | sys/compat/ndis/ntoskrnl_var.h | 13 | ||||
-rw-r--r-- | sys/compat/ndis/subr_hal.c | 2 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ndis.c | 19 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ntoskrnl.c | 5 |
6 files changed, 110 insertions, 39 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c index b7b472a..56832ea 100644 --- a/sys/compat/ndis/kern_ndis.c +++ b/sys/compat/ndis/kern_ndis.c @@ -66,11 +66,11 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_ioctl.h> #include <compat/ndis/pe_var.h> +#include <compat/ndis/cfg_var.h> #include <compat/ndis/resource_var.h> #include <compat/ndis/ntoskrnl_var.h> #include <compat/ndis/ndis_var.h> #include <compat/ndis/hal_var.h> -#include <compat/ndis/cfg_var.h> #include <compat/ndis/usbd_var.h> #include <dev/if_ndis/if_ndisvar.h> diff --git a/sys/compat/ndis/kern_windrv.c b/sys/compat/ndis/kern_windrv.c index cd631fd..11a5824 100644 --- a/sys/compat/ndis/kern_windrv.c +++ b/sys/compat/ndis/kern_windrv.c @@ -64,22 +64,6 @@ __FBSDID("$FreeBSD$"); #include <compat/ndis/hal_var.h> #include <compat/ndis/usbd_var.h> -struct windrv_type { - uint16_t windrv_vid; /* for PCI or USB */ - uint16_t windrv_did; /* for PCI or USB */ - uint32_t windrv_subsys; /* for PCI */ - char *windrv_vname; /* for pccard */ - char *windrv_dname; /* for pccard */ - char *windrv_name; /* for pccard, PCI or USB */ -}; - -struct drvdb_ent { - driver_object *windrv_object; - struct windrv_type *windrv_devlist; - ndis_cfg *windrv_regvals; - STAILQ_ENTRY(drvdb_ent) link; -}; - struct mtx drvdb_mtx; static STAILQ_HEAD(drvdb, drvdb_ent) drvdb_head; @@ -208,6 +192,29 @@ windrv_lookup(img, name) return(NULL); } +struct drvdb_ent * +windrv_match(matchfunc, ctx) + matchfuncptr matchfunc; + void *ctx; +{ + struct drvdb_ent *d; + int match; + + mtx_lock(&drvdb_mtx); + STAILQ_FOREACH(d, &drvdb_head, link) { + if (d->windrv_devlist == NULL) + continue; + match = matchfunc(d->windrv_devlist, ctx); + if (match == TRUE) { + mtx_unlock(&drvdb_mtx); + return(d); + } + } + mtx_unlock(&drvdb_mtx); + + return(NULL); +} + /* * Remove a driver_object from our datatabase and destroy it. Throw * away any custom driver extension info that may have been added. @@ -219,15 +226,52 @@ windrv_unload(mod, img, len) vm_offset_t img; int len; { - struct drvdb_ent *d, *r = NULL; + struct drvdb_ent *db, *r = NULL; driver_object *drv; + device_object *d, *pdo; + device_t dev; list_entry *e, *c; + drv = windrv_lookup(img, NULL); + + /* + * When we unload a driver image, we need to force a + * detach of any devices that might be using it. We + * need the PDOs of all attached devices for this. + * Getting at them is a little hard. We basically + * have to walk the device lists of all our bus + * drivers. + */ + mtx_lock(&drvdb_mtx); - STAILQ_FOREACH(d, &drvdb_head, link) { - if (d->windrv_object->dro_driverstart == (void *)img) { - r = d; - STAILQ_REMOVE(&drvdb_head, d, drvdb_ent, link); + STAILQ_FOREACH(db, &drvdb_head, link) { + /* + * Fake bus drivers have no devlist info. + * If this driver has devlist info, it's + * a loaded Windows driver and has no PDOs, + * so skip it. + */ + if (db->windrv_devlist != NULL) + continue; + pdo = db->windrv_object->dro_devobj; + while (pdo != NULL) { + d = pdo->do_attacheddev; + if (d->do_drvobj != drv) { + pdo = pdo->do_nextdev; + continue; + } + dev = pdo->do_devext; + pdo = pdo->do_nextdev; + mtx_unlock(&drvdb_mtx); + device_detach(dev); + mtx_lock(&drvdb_mtx); + } + } + + STAILQ_FOREACH(db, &drvdb_head, link) { + if (db->windrv_object->dro_driverstart == (void *)img) { + r = db; + STAILQ_REMOVE(&drvdb_head, db, drvdb_ent, link); break; } } @@ -269,10 +313,13 @@ windrv_unload(mod, img, len) */ int -windrv_load(mod, img, len) +windrv_load(mod, img, len, bustype, devlist, regvals) module_t mod; vm_offset_t img; int len; + interface_type bustype; + void *devlist; + ndis_cfg *regvals; { image_import_descriptor imp_desc; image_optional_header opt_hdr; @@ -350,6 +397,9 @@ windrv_load(mod, img, len) &drv->dro_drivername.us_buf); new->windrv_object = drv; + new->windrv_regvals = regvals; + new->windrv_devlist = devlist; + new->windrv_bustype = bustype; /* Now call the DriverEntry() function. */ @@ -433,13 +483,16 @@ windrv_find_pdo(drv, bsddev) mtx_lock(&drvdb_mtx); pdo = drv->dro_devobj; - if (pdo->do_devext != bsddev) { - mtx_unlock(&drvdb_mtx); - panic("PDO wasn't first device in list"); + while (pdo != NULL) { + if (pdo->do_devext == bsddev) { + mtx_unlock(&drvdb_mtx); + return(pdo); + } + pdo = pdo->do_nextdev; } mtx_unlock(&drvdb_mtx); - return(pdo); + return(NULL); } /* @@ -628,9 +681,8 @@ ctxsw_wtou(void) #ifdef EXTRA_SANITY if (t->tid_cpu != curthread->td_oncpu) - panic("ctxswGOT MOVED TO OTHER CPU!"); + panic("ctxsw GOT MOVED TO OTHER CPU!"); #endif - return; } diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h index 55e3c1e..2ef6915 100644 --- a/sys/compat/ndis/ntoskrnl_var.h +++ b/sys/compat/ndis/ntoskrnl_var.h @@ -1162,14 +1162,25 @@ typedef struct driver_object driver_object; #define WINDRV_WRAP_CDECL 4 #define WINDRV_WRAP_AMD64 5 +struct drvdb_ent { + driver_object *windrv_object; + void *windrv_devlist; + ndis_cfg *windrv_regvals; + interface_type windrv_bustype; + STAILQ_ENTRY(drvdb_ent) link; +}; + extern image_patch_table ntoskrnl_functbl[]; typedef void (*funcptr)(void); +typedef int (*matchfuncptr)(void *, void *); __BEGIN_DECLS extern int windrv_libinit(void); extern int windrv_libfini(void); extern driver_object *windrv_lookup(vm_offset_t, char *); -extern int windrv_load(module_t, vm_offset_t, int); +extern struct drvdb_ent *windrv_match(matchfuncptr, void *); +extern int windrv_load(module_t, vm_offset_t, int, interface_type, + void *, ndis_cfg *); extern int windrv_unload(module_t, vm_offset_t, int); extern int windrv_create_pdo(driver_object *, device_t); extern void windrv_destroy_pdo(driver_object *, device_t); diff --git a/sys/compat/ndis/subr_hal.c b/sys/compat/ndis/subr_hal.c index b4170f4..c992c7e 100644 --- a/sys/compat/ndis/subr_hal.c +++ b/sys/compat/ndis/subr_hal.c @@ -55,6 +55,8 @@ __FBSDID("$FreeBSD$"); #include <sys/rman.h> #include <compat/ndis/pe_var.h> +#include <compat/ndis/resource_var.h> +#include <compat/ndis/cfg_var.h> #include <compat/ndis/ntoskrnl_var.h> #include <compat/ndis/hal_var.h> diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index 992a539..7c0d4ad 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -99,11 +99,11 @@ __FBSDID("$FreeBSD$"); #include <dev/pci/pcivar.h> #include <compat/ndis/pe_var.h> +#include <compat/ndis/cfg_var.h> #include <compat/ndis/resource_var.h> #include <compat/ndis/ntoskrnl_var.h> #include <compat/ndis/hal_var.h> #include <compat/ndis/ndis_var.h> -#include <compat/ndis/cfg_var.h> #include <dev/if_ndis/if_ndisvar.h> static char ndis_filepath[MAXPATHLEN]; @@ -1014,7 +1014,7 @@ NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code, block = (ndis_miniport_block *)adapter; dev = block->nmb_physdeviceobj->do_devext; - drv = block->nmb_physdeviceobj->do_drvobj; + drv = block->nmb_deviceobj->do_drvobj; error = pe_get_message((vm_offset_t)drv->dro_driverstart, code, &str, &i, &flags); @@ -1262,7 +1262,6 @@ NdisMCancelTimer(timer, cancelled) uint8_t *cancelled; { *cancelled = KeCancelTimer(&timer->nt_ktimer); - return; } @@ -2346,10 +2345,18 @@ NdisMSleep(usecs) { struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = usecs; + /* + * During system bootstrap, (i.e. cold == 1), we aren't + * allowed to msleep(), so calling ndis_thsuspend() here + * will return 0, and we won't actually have delayed. This + * is a problem because some drivers expect NdisMSleep() + * to always wait, and might fail if the expected delay + * period does not in fact elapse. As a workaround, if the + * attempt to sleep delay fails, we do a hard DELAY() instead. + */ - ndis_thsuspend(curthread->td_proc, NULL, tvtohz(&tv)); + if (ndis_thsuspend(curthread->td_proc, NULL, tvtohz(&tv)) == 0) + DELAY(usecs); return; } diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c index bdb9c8f..b3b9040 100644 --- a/sys/compat/ndis/subr_ntoskrnl.c +++ b/sys/compat/ndis/subr_ntoskrnl.c @@ -68,13 +68,12 @@ __FBSDID("$FreeBSD$"); #include <vm/uma.h> #include <compat/ndis/pe_var.h> +#include <compat/ndis/cfg_var.h> +#include <compat/ndis/resource_var.h> #include <compat/ndis/ntoskrnl_var.h> #include <compat/ndis/hal_var.h> -#include <compat/ndis/resource_var.h> #include <compat/ndis/ndis_var.h> -#define __regparm __attribute__((regparm(3))) - static uint8_t RtlEqualUnicodeString(ndis_unicode_string *, ndis_unicode_string *, uint8_t); static void RtlCopyUnicodeString(ndis_unicode_string *, |