diff options
-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 | ||||
-rw-r--r-- | sys/conf/files.amd64 | 1 | ||||
-rw-r--r-- | sys/conf/files.i386 | 1 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis.c | 30 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis_pccard.c | 91 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis_pci.c | 90 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis_usb.c | 29 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndisvar.h | 1 | ||||
-rw-r--r-- | sys/modules/Makefile | 3 | ||||
-rw-r--r-- | sys/modules/if_ndis/Makefile | 3 | ||||
-rw-r--r-- | usr.sbin/ndiscvt/Makefile | 7 | ||||
-rw-r--r-- | usr.sbin/ndiscvt/ndisgen.8 | 82 | ||||
-rw-r--r-- | usr.sbin/ndiscvt/ndisgen.sh | 500 | ||||
-rw-r--r-- | usr.sbin/ndiscvt/windrv_stub.c | 245 |
19 files changed, 1043 insertions, 189 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 *, diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 085108f..6de730c 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -140,6 +140,7 @@ dev/if_ndis/if_ndis.c optional ndis dev/if_ndis/if_ndis_pccard.c optional ndis pccard dev/if_ndis/if_ndis_pci.c optional ndis cardbus dev/if_ndis/if_ndis_pci.c optional ndis pci +dev/if_ndis/if_ndis_usb.c optional ndis usb dev/io/iodev.c optional io dev/fdc/fdc.c optional fdc dev/fdc/fdc_acpi.c optional fdc diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 674de01..3554c30 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -178,6 +178,7 @@ dev/if_ndis/if_ndis.c optional ndis dev/if_ndis/if_ndis_pccard.c optional ndis pccard dev/if_ndis/if_ndis_pci.c optional ndis cardbus dev/if_ndis/if_ndis_pci.c optional ndis pci +dev/if_ndis/if_ndis_usb.c optional ndis usb dev/io/iodev.c optional io dev/kbd/atkbd.c optional atkbd dev/kbd/atkbdc.c optional atkbdc diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index aa0f5c2..cb9e38c 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -76,17 +76,18 @@ __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> -#define NDIS_IMAGE -#define NDIS_REGVALS +MODULE_DEPEND(ndis, ether, 1, 1, 1); +MODULE_DEPEND(ndis, wlan, 1, 1, 1); +MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); -#include "ndis_driver_data.h" +MODULE_VERSION(ndis, 1); int ndis_attach (device_t); int ndis_detach (device_t); @@ -158,8 +159,6 @@ ndisdrv_modevent(mod, cmd, arg) ndisdrv_loaded++; if (ndisdrv_loaded > 1) break; - if (windrv_load(mod, (vm_offset_t)drv_data, 0)) - return(EINVAL); windrv_wrap((funcptr)ndis_rxeof, &ndis_rxeof_wrap, 3, WINDRV_WRAP_STDCALL); windrv_wrap((funcptr)ndis_txeof, &ndis_txeof_wrap, @@ -173,7 +172,6 @@ ndisdrv_modevent(mod, cmd, arg) ndisdrv_loaded--; if (ndisdrv_loaded > 0) break; - windrv_unload(mod, (vm_offset_t)drv_data, 0); windrv_unwrap(ndis_rxeof_wrap); windrv_unwrap(ndis_txeof_wrap); windrv_unwrap(ndis_linksts_wrap); @@ -432,11 +430,9 @@ ndis_attach(dev) { u_char eaddr[ETHER_ADDR_LEN]; struct ndis_softc *sc; - driver_object *drv; driver_object *pdrv; device_object *pdo; struct ifnet *ifp = NULL; - void *img; int error = 0, len; int i; @@ -472,12 +468,10 @@ ndis_attach(dev) } } - sc->ndis_regvals = ndis_regvals; - #if __FreeBSD_version < 502113 sysctl_ctx_init(&sc->ndis_ctx); - #endif + /* Create sysctl registry nodes */ ndis_create_sysctls(sc); @@ -497,17 +491,7 @@ ndis_attach(dev) * for this device instance. */ - img = drv_data; - - drv = windrv_lookup((vm_offset_t)img, NULL); - - if (drv == NULL) { - device_printf(dev, "failed to find driver_object!\n"); - error = ENXIO; - goto fail; - } - - if (NdisAddDevice(drv, pdo) != STATUS_SUCCESS) { + if (NdisAddDevice(sc->ndis_dobj, pdo) != STATUS_SUCCESS) { device_printf(dev, "failed to create FDO!\n"); error = ENXIO; goto fail; diff --git a/sys/dev/if_ndis/if_ndis_pccard.c b/sys/dev/if_ndis/if_ndis_pccard.c index 918e89c..c67941a 100644 --- a/sys/dev/if_ndis/if_ndis_pccard.c +++ b/sys/dev/if_ndis/if_ndis_pccard.c @@ -54,39 +54,22 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_var.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/cfg_var.h> #include <dev/if_ndis/if_ndisvar.h> #include <dev/pccard/pccardvar.h> #include "card_if.h" -#include "ndis_driver_data.h" - -#ifdef NDIS_PCMCIA_DEV_TABLE - MODULE_DEPEND(ndis, pccard, 1, 1, 1); -MODULE_DEPEND(ndis, ether, 1, 1, 1); -MODULE_DEPEND(ndis, wlan, 1, 1, 1); -MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); - -/* - * Various supported device vendors/types and their names. - * These are defined in the ndis_driver_data.h file. - */ -static struct ndis_pccard_type ndis_devs[] = { -#ifdef NDIS_PCMCIA_DEV_TABLE - NDIS_PCMCIA_DEV_TABLE -#endif - { NULL, NULL, NULL } -}; static int ndis_probe_pccard (device_t); static int ndis_attach_pccard (device_t); static struct resource_list *ndis_get_resource_list (device_t, device_t); +static int ndis_devcompare (struct ndis_pccard_type *, device_t); extern int ndisdrv_modevent (module_t, int, void *); extern int ndis_attach (device_t); extern int ndis_shutdown (device_t); @@ -118,63 +101,65 @@ static device_method_t ndis_methods[] = { }; static driver_t ndis_driver = { -#ifdef NDIS_DEVNAME - NDIS_DEVNAME, -#else "ndis", -#endif ndis_methods, sizeof(struct ndis_softc) }; static devclass_t ndis_devclass; -#ifdef NDIS_MODNAME -#define NDIS_MODNAME_OVERRIDE_PCMCIA(x) \ - DRIVER_MODULE(x, pccard, ndis_driver, ndis_devclass, \ - ndisdrv_modevent, 0) -NDIS_MODNAME_OVERRIDE_PCMCIA(NDIS_MODNAME); -#else DRIVER_MODULE(ndis, pccard, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); -#endif -/* - * Probe for an NDIS device. Check the PCI vendor and device - * IDs against our list and return a device name if we find a match. - */ static int -ndis_probe_pccard(dev) +ndis_devcompare(t, dev) + struct ndis_pccard_type *t; device_t dev; { - struct ndis_pccard_type *t; const char *prodstr, *vendstr; int error; - driver_object *drv; - - drv = windrv_lookup(0, "PCCARD Bus"); - if (drv == NULL) - return(ENXIO); - - t = ndis_devs; error = pccard_get_product_str(dev, &prodstr); if (error) - return(error); + return(FALSE); error = pccard_get_vendor_str(dev, &vendstr); if (error) - return(error); + return(FALSE); while(t->ndis_name != NULL) { if (ndis_strcasecmp(vendstr, t->ndis_vid) == 0 && ndis_strcasecmp(prodstr, t->ndis_did) == 0) { device_set_desc(dev, t->ndis_name); - /* Create PDO for this device instance */ - windrv_create_pdo(drv, dev); - return(0); + return(TRUE); } t++; } + return(FALSE); +} + +/* + * Probe for an NDIS device. Check the PCI vendor and device + * IDs against our list and return a device name if we find a match. + */ +static int +ndis_probe_pccard(dev) + device_t dev; +{ + driver_object *drv; + struct drvdb_ent *db; + + drv = windrv_lookup(0, "PCCARD Bus"); + if (drv == NULL) + return(ENXIO); + + db = windrv_match((matchfuncptr)ndis_devcompare, dev); + + if (db != NULL) { + /* Create PDO for this device instance */ + windrv_create_pdo(drv, dev); + return(0); + } + return(ENXIO); } @@ -191,10 +176,16 @@ ndis_attach_pccard(dev) struct ndis_pccard_type *t; int devidx = 0; const char *prodstr, *vendstr; + struct drvdb_ent *db; sc = device_get_softc(dev); unit = device_get_unit(dev); sc->ndis_dev = dev; + + db = windrv_match((matchfuncptr)ndis_devcompare, dev); + if (db == NULL) + return (ENXIO); + resource_list_init(&sc->ndis_rl); sc->ndis_io_rid = 0; @@ -230,7 +221,7 @@ ndis_attach_pccard(dev) /* Figure out exactly which device we matched. */ - t = ndis_devs; + t = db->windrv_devlist; error = pccard_get_product_str(dev, &prodstr); if (error) @@ -266,8 +257,6 @@ ndis_get_resource_list(dev, child) return (&sc->ndis_rl); } -#endif /* NDIS_PCI_DEV_TABLE */ - #define NDIS_AM_RID 3 int diff --git a/sys/dev/if_ndis/if_ndis_pci.c b/sys/dev/if_ndis/if_ndis_pci.c index 08109e6..1c8691b 100644 --- a/sys/dev/if_ndis/if_ndis_pci.c +++ b/sys/dev/if_ndis/if_ndis_pci.c @@ -56,36 +56,19 @@ __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/ndis_var.h> -#include <compat/ndis/cfg_var.h> #include <dev/if_ndis/if_ndisvar.h> -#include "ndis_driver_data.h" - -#ifdef NDIS_PCI_DEV_TABLE - MODULE_DEPEND(ndis, pci, 1, 1, 1); -MODULE_DEPEND(ndis, ether, 1, 1, 1); -MODULE_DEPEND(ndis, wlan, 1, 1, 1); -MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); - -/* - * Various supported device vendors/types and their names. - * These are defined in the ndis_driver_data.h file. - */ -static struct ndis_pci_type ndis_devs[] = { -#ifdef NDIS_PCI_DEV_TABLE - NDIS_PCI_DEV_TABLE -#endif - { 0, 0, 0, NULL } -}; static int ndis_probe_pci (device_t); static int ndis_attach_pci (device_t); static struct resource_list *ndis_get_resource_list (device_t, device_t); +static int ndis_devcompare (struct ndis_pci_type *, device_t); extern int ndisdrv_modevent (module_t, int, void *); extern int ndis_attach (device_t); extern int ndis_shutdown (device_t); @@ -93,8 +76,6 @@ extern int ndis_detach (device_t); extern int ndis_suspend (device_t); extern int ndis_resume (device_t); -extern unsigned char drv_data[]; - static device_method_t ndis_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ndis_probe_pci), @@ -111,29 +92,34 @@ static device_method_t ndis_methods[] = { }; static driver_t ndis_driver = { -#ifdef NDIS_DEVNAME - NDIS_DEVNAME, -#else "ndis", -#endif ndis_methods, sizeof(struct ndis_softc) }; static devclass_t ndis_devclass; -#ifdef NDIS_MODNAME -#define NDIS_MODNAME_OVERRIDE_PCI(x) \ - DRIVER_MODULE(x, pci, ndis_driver, ndis_devclass, ndisdrv_modevent, 0) -#define NDIS_MODNAME_OVERRIDE_CARDBUS(x) \ - DRIVER_MODULE(x, cardbus, ndis_driver, ndis_devclass, \ - ndisdrv_modevent, 0) -NDIS_MODNAME_OVERRIDE_PCI(NDIS_MODNAME); -NDIS_MODNAME_OVERRIDE_CARDBUS(NDIS_MODNAME); -#else DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); DRIVER_MODULE(ndis, cardbus, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); -#endif + +static int +ndis_devcompare(t, dev) + struct ndis_pci_type *t; + device_t dev; +{ + while(t->ndis_name != NULL) { + if ((pci_get_vendor(dev) == t->ndis_vid) && + (pci_get_device(dev) == t->ndis_did) && + ((pci_read_config(dev, PCIR_SUBVEND_0, 4) == + t->ndis_subsys) || t->ndis_subsys == 0)) { + device_set_desc(dev, t->ndis_name); + return(TRUE); + } + t++; + } + + return(FALSE); +} /* * Probe for an NDIS device. Check the PCI vendor and device @@ -143,27 +129,20 @@ static int ndis_probe_pci(dev) device_t dev; { - struct ndis_pci_type *t; driver_object *drv; + struct drvdb_ent *db; - t = ndis_devs; drv = windrv_lookup(0, "PCI Bus"); if (drv == NULL) return(ENXIO); - while(t->ndis_name != NULL) { - if ((pci_get_vendor(dev) == t->ndis_vid) && - (pci_get_device(dev) == t->ndis_did) && - ((pci_read_config(dev, PCIR_SUBVEND_0, 4) == - t->ndis_subsys) || t->ndis_subsys == 0)) { - device_set_desc(dev, t->ndis_name); + db = windrv_match((matchfuncptr)ndis_devcompare, dev); - /* Create PDO for this device instance */ - windrv_create_pdo(drv, dev); - return(0); - } - t++; + if (db != NULL) { + /* Create PDO for this device instance */ + windrv_create_pdo(drv, dev); + return(0); } return(ENXIO); @@ -183,11 +162,18 @@ ndis_attach_pci(dev) int devidx = 0, defidx = 0; struct resource_list *rl; struct resource_list_entry *rle; + struct drvdb_ent *db; sc = device_get_softc(dev); unit = device_get_unit(dev); sc->ndis_dev = dev; + db = windrv_match((matchfuncptr)ndis_devcompare, dev); + if (db == NULL) + return (ENXIO); + sc->ndis_dobj = db->windrv_object; + sc->ndis_regvals = db->windrv_regvals; + /* * Map control/status registers. */ @@ -213,6 +199,7 @@ ndis_attach_pci(dev) error = ENXIO; goto fail; } + pci_enable_io(dev, SYS_RES_IOPORT); break; case SYS_RES_MEMORY: if (sc->ndis_res_altmem != NULL && @@ -250,6 +237,7 @@ ndis_attach_pci(dev) goto fail; } } + pci_enable_io(dev, SYS_RES_MEMORY); break; case SYS_RES_IRQ: rid = rle->rid; @@ -312,7 +300,7 @@ ndis_attach_pci(dev) /* Figure out exactly which device we matched. */ - t = ndis_devs; + t = db->windrv_devlist; while(t->ndis_name != NULL) { if ((pci_get_vendor(dev) == t->ndis_vid) && @@ -329,7 +317,7 @@ ndis_attach_pci(dev) devidx++; } - if (ndis_devs[devidx].ndis_name == NULL) + if (t[devidx].ndis_name == NULL) sc->ndis_devidx = defidx; else sc->ndis_devidx = devidx; @@ -350,5 +338,3 @@ ndis_get_resource_list(dev, child) sc = device_get_softc(dev); return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); } - -#endif /* NDIS_PCI_DEV_TABLE */ diff --git a/sys/dev/if_ndis/if_ndis_usb.c b/sys/dev/if_ndis/if_ndis_usb.c index 8199534..b5a6943 100644 --- a/sys/dev/if_ndis/if_ndis_usb.c +++ b/sys/dev/if_ndis/if_ndis_usb.c @@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/sockio.h> -#include <sys/mbuf.h> +#include <sys/module.h> #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/socket.h> @@ -56,26 +56,18 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/usbdi.h> #include <dev/usb/usbdi_util.h> #include <dev/usb/usbdivar.h> -#include <dev/usb/usbdevs.h> -#include <dev/usb/usb_ethersubr.h> +#include "usbdevs.h" #include <net80211/ieee80211_var.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/cfg_var.h> #include <dev/if_ndis/if_ndisvar.h> MODULE_DEPEND(ndis, usb, 1, 1, 1); -MODULE_DEPEND(ndis, ether, 1, 1, 1); -MODULE_DEPEND(ndis, wlan, 1, 1, 1); -MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); - -#include "ndis_driver_data.h" - -#ifdef NDIS_USB_DEV_TABLE Static int ndisusb_match (device_ptr_t); Static int ndisusb_attach (device_ptr_t); @@ -107,24 +99,14 @@ Static device_method_t ndis_methods[] = { }; Static driver_t ndis_driver = { -#ifdef NDIS_DEVNAME - NDIS_DEVNAME, -#else "ndis", -#endif ndis_methods, sizeof(struct ndis_softc) }; Static devclass_t ndis_devclass; -#ifdef NDIS_MODNAME -#define NDIS_MODNAME_OVERRIDE_USB(x) - DRIVER_MODULE(x, usb, ndis_driver, ndis_devclass, ndisdrv_modevent, 0) -NDIS_MODNAME_OVERRIDE_USB(NDIS_MODNAME); -#else DRIVER_MODULE(ndis, uhub, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); -#endif USB_MATCH(ndisusb) { @@ -147,6 +129,9 @@ USB_ATTACH(ndisusb) sc = (struct ndis_softc *)dummy; + if (uaa->device == NULL) + USB_ATTACH_ERROR_RETURN; + sc->ndis_dev = self; /* Create PDO for this device instance */ @@ -170,5 +155,3 @@ ndis_get_resource_list(dev, child) sc = device_get_softc(dev); return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); } - -#endif /* NDIS_USB_DEV_TABLE */ diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h index 0936aaf..68f30f9 100644 --- a/sys/dev/if_ndis/if_ndisvar.h +++ b/sys/dev/if_ndis/if_ndisvar.h @@ -122,6 +122,7 @@ struct ndis_softc { #endif int ndis_devidx; interface_type ndis_iftype; + driver_object *ndis_dobj; bus_dma_tag_t ndis_parent_tag; struct ndis_shmem *ndis_shlist; diff --git a/sys/modules/Makefile b/sys/modules/Makefile index bfc5438..cc033d9 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -103,6 +103,7 @@ SUBDIR= ${_3dfx} \ if_faith \ if_gif \ if_gre \ + ${_if_ndis} \ if_ppp \ if_sl \ if_stf \ @@ -333,6 +334,7 @@ _hfa= hfa _i2c= i2c _ibcs2= ibcs2 _ie= ie +_if_ndis= if_ndis _io= io _linprocfs= linprocfs _linux= linux @@ -426,6 +428,7 @@ _em= em _ext2fs= ext2fs _i2c= i2c _ida= ida +_if_ndis= if_ndis _iir= iir _io= io _ips= ips diff --git a/sys/modules/if_ndis/Makefile b/sys/modules/if_ndis/Makefile index bce7c96..cbc2ed0 100644 --- a/sys/modules/if_ndis/Makefile +++ b/sys/modules/if_ndis/Makefile @@ -3,7 +3,8 @@ .PATH: ${.CURDIR}/../../dev/if_ndis KMOD= if_ndis -SRCS= if_ndis.c if_ndis_pci.c if_ndis_pccard.c +SRCS= if_ndis.c if_ndis_pci.c if_ndis_pccard.c if_ndis_usb.c SRCS+= opt_bdg.h device_if.h bus_if.h pci_if.h card_if.h pccarddevs.h +SRCS+= opt_usb.h usbdevs.h .include <bsd.kmod.mk> diff --git a/usr.sbin/ndiscvt/Makefile b/usr.sbin/ndiscvt/Makefile index 8004897..90ecebb 100644 --- a/usr.sbin/ndiscvt/Makefile +++ b/usr.sbin/ndiscvt/Makefile @@ -8,6 +8,7 @@ SRCS+= subr_pe.c SRCS+= inf.c inf-token.l inf-parse.y y.tab.h MAN= ndiscvt.8 +MAN+= ndisgen.8 WARNS?= 4 @@ -20,4 +21,10 @@ CFLAGS+=-I. -I${.CURDIR} -I${.CURDIR}/../../sys CLEANFILES= y.output +FILES= windrv_stub.c +FILESNAME= windrv_stub.c +FILESDIR= /usr/share/misc + +SCRIPTS= ndisgen.sh + .include <bsd.prog.mk> diff --git a/usr.sbin/ndiscvt/ndisgen.8 b/usr.sbin/ndiscvt/ndisgen.8 new file mode 100644 index 0000000..d16c34d --- /dev/null +++ b/usr.sbin/ndiscvt/ndisgen.8 @@ -0,0 +1,82 @@ +.\" Copyright (c) 2005 +.\" Bill Paul <wpaul@windriver.com> All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Bill Paul. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +.\" THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd April 24, 2005 +.Dt NDISGEN 8 +.Os +.Sh NAME +.Nm ndisgen +.Nd generate a FreeBSD driver module from a +.Tn Windows\[rg] +NDIS driver distribution +.Fx +.Sh SYNOPSIS +.Nm +.Sh DESCRIPTION +The +.Nm +script uses the +.Xr ndiscvt 8 +utility and other tools to generate a FreeBSD loadable driver module +and a static ELF object module from a +.Tn Windows\[rg] +NDIS driver, for use with the +.Xr ndis 4 +compatibility module. +.Pp +The +.Nm +script is interactive and contains its own help section. The script +will prompt the user for the +.Pa .INF +and +.Pa .SYS +files (and any firmware or other external files) needed to generate +the FreeBSD driver module. +.Sh SEE ALSO +.Xr ld 1 , +.Xr objcopy 1 , +.Xr ndis 4 , +.Xr kldload 8 , +.Xr ndiscvt 8 , +.Xr ndisapi 9 +.Sh HISTORY +The +.Nm +utility first appeared in +.Fx 6.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +utility was written by +.An Bill Paul Aq wpaul@windriver.com . diff --git a/usr.sbin/ndiscvt/ndisgen.sh b/usr.sbin/ndiscvt/ndisgen.sh new file mode 100644 index 0000000..3e31e88 --- /dev/null +++ b/usr.sbin/ndiscvt/ndisgen.sh @@ -0,0 +1,500 @@ +#!/bin/sh +# +# Copyright (c) 2005 +# Bill Paul <wpaul@windriver.com>. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by Bill Paul. +# 4. Neither the name of the author nor the names of any co-contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. +# +# $FreeBSD$ +# + +header () { +clear +echo " ==================================================================" +echo " ------------------ Windows(r) driver converter -------------------" +echo " ==================================================================" +echo "" +} + +mainmenu() { +header +echo " This is script is designed to guide you through the process" +echo " of converting a Windows(r) binary driver module and .INF" +echo " specification file into a FreeBSD ELF kernel module for use" +echo " with the NDIS compatibility system." +echo "" +echo " The following options are available:" +echo "" +echo " 1] Learn about the NDIS compatibility system" +echo " 2] Convert individual firmware files" +echo " 3] Convert driver" +echo " 4] Exit" +echo "" +echo -n " Enter your selection here and press return: " +read KEYPRESS +} + + +help1 () { +header +echo " General information" +echo "" +echo " The NDIS compatibility system is designed to let you use Windows(r)" +echo " binary drivers for networking devices with FreeBSD, in cases where" +echo " a native FreeBSD driver is not available due to hardware manufacturer" +echo " oversight or stupidity. NDIS stands for Network Driver Interface" +echo " Standard, and refers to the programming model used to write Windows(r)" +echo " network drivers. (These are often called \"NDIS miniport\" drivers.)" +echo "" +echo " In order to use your network device in NDIS compatibility mode," +echo " you need the Windows(r) driver that goes with it. Also, the driver" +echo " must be compiled for the same architecture as the release of FreeBSD" +echo " you have installed. At this time, the i386 and amd64 architectures" +echo " are both supported. Note that you cannot use a Windows/i386 driver" +echo " with FreeBSD/amd64: you must obtain a Windows/amd64 driver." +echo "" +echo -n " Press any key to continue... " +read KEYPRESS +} + +help2() { +header +echo " Where to get drivers" +echo "" +echo " If you purchased your network card separately from your computer," +echo " there should have been a driver distribution CD included with the" +echo " card which contains Windows(r) drivers. The NDIS compatibility" +echo " system is designed to emulate the NDIS API of a couple of different" +echo " Windows(r) releases, however it works best with drivers designed" +echo " for NDIS 5.0 or later. Drivers distributed for Windows 2000 should" +echo " work, however for best results you should use a driver designed" +echo " for Windows XP or Windows Server 2003." +echo "" +echo " If your card was supplied with your computer, or is a built-in device," +echo " drivers may have been included on a special driver bundle CD shipped" +echo " with the computer." +echo "" +echo " If you don't have a driver CD, you should be able to find a driver" +echo " kit on the card or computer vendor's web site." +echo "" +echo -n " Press any key to continue... " +read KEYPRESS +} + +help3 () { +header +echo " What files do I need?" +echo "" +echo " In most cases, you will need only two files: a .INF file and a .SYS" +echo " file. The .INF file is a text file used by the Windows(r) installer to" +echo " perform the driver installation. It contains information that tells" +echo " the intaller what devices the driver supports and what registry keys" +echo " should be created to control driver configuration. The .SYS file" +echo " is the actual driver executable code in Windows(r) Portable Executable" +echo " (PE) format. Note that sometimes the .INF file is supplied in unicode" +echo " format. Unicode .INF files must be converted to ASCII form with the" +echo " iconv(1) utility before this installer script can use them." +echo " Occasionally, a driver may require firmware or register setup" +echo " files that are external to the main .SYS file. These are provided" +echo " on the same CD with the driver itself, and sometimes have a .BIN" +echo " extension, though they can be named almost anything. You will need" +echo " these additional files to make your device work with the NDIS" +echo " compatibility system as well." +echo "" +echo -n " Press any key to continue... " +read KEYPRESS +} + +help4 () { +header +echo " How does it all work?" +echo "" +echo " The installer script uses the ndiscvt(1) utility to convert the .INF," +echo " .SYS and optional firmware files into a FreeBSD kernel loadable module" +echo " (.ko) file. This module can be loaded via the kldload(8) utility or" +echo " loaded automatically via the /boot/loader.conf file. The ndiscvt(1)" +echo " utility extracts the device ID information and registry key data" +echo " from the .INF file and converts it into a C header file. It also uses" +echo " the objcopy(1) utility to convert the .SYS file and optional firmware" +echo " files into ELF objects. The header file is compiled into a small C" +echo " stub file which contains a small amount of code to interface with" +echo " the FreeBSD module system. This stub is linked together with the" +echo " converted ELF objects to form a FreeBSD kernel module. A static ELF" +echo " object (.o) file is also created. This file can be linked into a" +echo " static kernel image for those who want/need a fully linked kernel" +echo " image (possibly for embedded bootstrap purposes, or just plain old" +echo " experimentation)." +echo "" +echo -n " Press any key to continue... " +read KEYPRESS +} + +help5 () { +header +echo " Prerequisites" +echo "" +echo " Converting a driver requires the following utilities:" +echo "" +echo " - The FreeBSD C compiler, cc(1) (part of the base install)." +echo " - The FreeBSD linker, ld(1) (part of the base install)." +echo " - The objcopy(1) utility (part of the base install)." +echo " - The ndiscvt(1) utility (part of the base install)." +echo "" +echo " If your happen to end up with a .INF file that's in unicode format," +echo " then you'll also need:" +echo "" +echo " - The iconv(1) utility." +echo "" +echo " If you have installed the X Window system or some sort of desktop" +echo " environment, then iconv(1) should already be present. If not, you" +echo " will need to install the libiconv package or port." +echo "" +echo -n " Press any key to continue... " +read KEYPRESS +} + +infconv () { +header +echo " INF file validation" +echo "" +echo "" +echo " A .INF file is most often provided as an ASCII file, however" +echo " files with multilanguage support are provided in Unicode format." +echo " Please type in the path to your .INF file now." +echo "" +echo -n " > " +read INFPATH +if [ $INFPATH ] && [ -e $INFPATH ]; +then + INFTYPE=`${FILE} ${INFPATH}` + + case ${INFTYPE} in + *ASCII*) + echo "" + echo " This .INF file appears to be ASCII." + echo "" + echo -n " Press any key to continue... " + read KEYPRESS + ;; + *text*) + echo "" + echo " This .INF file appears to be ASCII." + echo "" + echo -n " Press any key to continue... " + read KEYPRESS + ;; + *nicode*) + echo "" + echo " This .INF file appears to be Unicode." + if [ -e $ICONVPATH ]; + then + echo " Trying to convert to ASCII..." + ${RM} -f /tmp/ascii.inf + ${ICONVPATH} -f utf-16 -t utf-8 ${INFPATH} > /tmp/ascii.inf + INFPATH=/tmp/ascii.inf + echo " Done." + echo "" + echo -n " Press any key to continue... " + read KEYPRESS + else + echo " The iconv(1) utility does not appear to be installed." + echo " Please install this utility or convert the .INF file" + echo " to ASCII and run this utility again." + echo "" + exit + fi + ;; + *) + echo "" + echo " I don't recognize this file format. It may not be a valid .INF file." + echo "" + echo -n " Press enter to try again, or ^C to quit. " + read KEYPRESS + INFPATH="" + ;; + esac +else + echo "" + echo " The file '$INFPATH' was not found." + echo "" + echo -n " Press enter to try again, or ^C to quit. " + read KEYPRESS + INFPATH="" +fi +} + +sysconv() { +header +echo " Driver file validation" +echo "" +echo "" +echo " Now you need to specify the name of the Windows(r) driver .SYS" +echo " file for your device. Note that if you are running FreeBSD/amd64," +echo " then you must provide a driver that has been compiled for the" +echo " 64-bit Windows(r) platform. If a 64-bit driver is not available" +echo " for your device, you must install FreeBSD/ia32 and use the" +echo " 32-bit driver instead." +echo "" +echo " Please type in the path to the Windows(r) driver .SYS file now." +echo "" +echo -n " > " +read SYSPATH +if [ $SYSPATH ] && [ -e $SYSPATH ]; +then + SYSTYPE=`${FILE} ${SYSPATH}` + + case ${SYSTYPE} in + *Windows*) + echo "" + echo " This .SYS file appears to be in Windows(r) PE format." + echo "" + echo -n " Press any key to continue... " + read KEYPRESS + SYSBASE=`basename ${SYSPATH} | ${TR} '.' '_'` + ;; + *) + echo "" + echo " I don't recognize this file format. It may not be a valid .SYS file." + echo "" + + echo -n " Press enter to try again, or ^C to quit. " + read KEYPRESS + SYSPATH="" + ;; + esac +else + echo "" + echo " The file '$SYSPATH' was not found." + echo "" + echo -n " Press enter to try again, or ^C to quit. " + read KEYPRESS + SYSPATH="" +fi +} + +ndiscvt() { +header +echo " Driver file conversion" +echo "" +echo " The script will now try to convert the .INF and .SYS files" +echo " using the ndiscvt(1) utility. This utility can handle most" +echo " .INF files, however occasionally it can fail to parse some files" +echo " due to subtle syntax issues: the .INF syntax is very complex," +echo " and the Windows(r) parser will sometimes allow files with small" +echo " syntax errors to be processed correctly which ndiscvt(1) will" +echo " not. If the conversion fails, you may have to edit the .INF" +echo " file by hand to remove the offending lines." +echo "" +echo -n " Press enter to try converting the files now: " +read KEYPRESS +if ! ${NDISCVT} -i ${INFPATH} -s ${SYSPATH} -O -o ${DNAME}.h > /dev/null; then + echo "CONVERSION FAILED" + exit +else + echo "" + echo " Conversion was successful." + echo "" + echo -n " Press enter to continue... " + read KEYPRESS +fi +} + +firmcvt() { + while : ; do +header +echo " Firmware file conversion" +echo "" +echo " If your driver uses additional firmware files, please list them" +echo " below. When you're finished, just press enter to contiue. (If your" +echo " driver doesn't need any extra firmware files, just press enter" +echo " to move to the next step.)" +echo "" + echo -n " > " + read FIRMPATH + + if [ $FIRMPATH ] && [ $FIRMPATH != "" ]; then + if [ ! -e $FIRMPATH ]; then + echo "" + echo " The file '$FIRMPATH' was not found" + echo "" + echo -n " Press enter to try again, or ^C to quit. " + read KEYPRESS + continue + fi + if ! ${NDISCVT} -f ${FIRMPATH} > /dev/null; then + echo "" + echo "CONVERSION FAILED" + else + echo "" + echo " Conversion was successful." + echo "" + FRMBASE=`basename ${FIRMPATH}` + FRMBASE="${FRMBASE}.o" + FRMLIST="${FRMLIST} ${FRMBASE}" + fi + echo -n " Press enter to continue... " + read KEYPRESS + else + break + fi + done + +header +echo "" +echo " List of files converted firmware files:" +echo "" +for i in $FRMLIST +do + echo " "$i +done +echo "" +echo -n " Press enter to continue... " +read KEYPRESS +} + +drvgen () { +header +echo " Kernel module generation" +echo "" +echo "" +echo " The script will now try to generate the kernel driver module." +echo " This is the last step. Once this module is generated, you should" +echo " be able to load it just like any other FreeBSD driver module." +echo "" +echo " Press enter to compile the stub module and generate the driver" +echo -n " module now: " +read KEYPRESS +echo "" +touch bus_if.h +touch device_if.h +echo -n " Compiling stub... " +if ! ${CC} -D_KERNEL -DDRV_DATA_START=${SYSBASE}_drv_data_start -DDRV_NAME=${SYSBASE} -DDRV_DATA_END=${SYSBASE}_drv_data_end -I. ${STUBFILE} -c -o windrv_stub.o; then + echo "compilation failed. Exiting." + echo "" + exit +else + echo "done." +fi +echo -n " Linking loadable kernel module... " +if ! ${LD} -Bshareable -d -warn-common -o ${SYSBASE}.ko windrv_stub.o ${FRMLIST} ${DNAME}.o; then + echo "linking failed. Exiting." + echo "" + exit +else + echo "done." +fi +echo -n " Linking static kernel module... " +if ! ${LD} -r -d -warn-common -o ${SYSBASE}.o windrv_stub.o ${FRMLIST} ${DNAME}.o; then + echo "linking failed. Exiting." + echo "" + exit +else + echo "done." +fi +echo -n " Cleaning up... " +${RM} -f bus_if.h device_if.h windrv_stub.o +${RM} -f ${DNAME}.h ${DNAME}.o +echo "done." +echo "" +echo " The file $SYSBASE.ko has been successfully generated." +echo " You can kldload this module to get started." +echo "" +echo -n " Press any key to exit. " +read KEYPRESS +echo "" +echo "" +} + +convert_driver () { + while : ; do + infconv + if [ $INFPATH ] && [ $INFPATH != "" ]; then + break + fi + done + + while : ; do + sysconv + if [ $SYSPATH ] && [ $SYSPATH != "" ]; then + break + fi + done + + ndiscvt + firmcvt + drvgen +} + +ICONVPATH=/usr/local/bin/iconv +NDISCVT=/usr/sbin/ndiscvt +STUBFILE=/usr/share/misc/windrv_stub.c +DNAME=windrv +OBJCOPY=/usr/bin/objcopy +CC=/usr/bin/cc +LD=/usr/bin/ld +RM=/bin/rm +TR=/usr/bin/tr +FILE=/usr/bin/file + +INFPATH="" +FRMLIST="" +SYSPATH="" +SYSBASE="" +FRMBASE="" + +while : ; do + mainmenu + case ${KEYPRESS} in + 1) + help1 + help2 + help3 + help4 + help5 + ;; + 2) + firmcvt + ;; + 3) + convert_driver + ;; + 4) + header + echo "" + echo " Be seeing you!" + echo "" + exit + ;; + *) + header + echo "" + echo -n " Sorry, I didn't underatand that. Press enter to try again: " + read KEYPRESS + ;; + esac +done diff --git a/usr.sbin/ndiscvt/windrv_stub.c b/usr.sbin/ndiscvt/windrv_stub.c new file mode 100644 index 0000000..2097e50 --- /dev/null +++ b/usr.sbin/ndiscvt/windrv_stub.c @@ -0,0 +1,245 @@ +/*- + * Copyright (c) 2005 + * Bill Paul <wpaul@windriver.com>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/conf.h> + +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/bus.h> + +#define NDIS_REGVALS + +struct ndis_cfg { + char *nc_cfgkey; + char *nc_cfgdesc; + char nc_val[256]; + int nc_idx; +}; + +typedef struct ndis_cfg ndis_cfg; + +#include "windrv.h" + +struct ndis_pci_type { + uint16_t ndis_vid; + uint16_t ndis_did; + uint32_t ndis_subsys; + char *ndis_name; +}; + +struct ndis_pccard_type { + const char *ndis_vid; + const char *ndis_did; + char *ndis_name; +}; + + +#ifdef NDIS_PCI_DEV_TABLE +static struct ndis_pci_type ndis_devs[] = { + NDIS_PCI_DEV_TABLE + { 0, 0, 0, NULL } +}; +#endif + +#ifdef NDIS_PCMCIA_DEV_TABLE +static struct ndis_pccard_type ndis_devs[] = { + NDIS_PCMCIA_DEV_TABLE + { NULL, NULL, NULL } +}; +#endif + +enum interface_type { + InterfaceTypeUndefined = -1, + Internal, + Isa, + Eisa, + MicroChannel, + TurboChannel, + PCIBus, + VMEBus, + NuBus, + PCMCIABus, + CBus, + MPIBus, + MPSABus, + ProcessorInternal, + InternalPowerBus, + PNPISABus, + PNPBus, + MaximumInterfaceType +}; + +typedef enum interface_type interface_type; + +/* + * XXX + * Ordinarily, device_probe_desc is defined in device_if.h, which + * is created from device_if.m. The problem is, the latter file + * is only available if you have the kernel source code installed, + * and not all users choose to install it. I'd like to let people + * load Windows driver modules with the minimal amount of hassle + * and dependencies. <sys/bus.h> wants both device_if.h and bus_if.h + * to be defined, but it turns out the only thing we really need + * to get this module compiled is device_probe_desc, so we define + * that here, and let the build script create empty copies of + * device_if.h and bus_if.h to make the compiler happy. + */ + +extern struct kobjop_desc device_probe_desc; +typedef int device_probe_t(device_t dev); + +extern int windrv_load(module_t, vm_offset_t, size_t, + interface_type, void *, void *); +extern int windrv_unload(module_t, vm_offset_t, size_t); + +#ifndef DRV_DATA_START +#define DRV_DATA_START UNDEF_START +#endif + +#ifndef DRV_DATA_END +#define DRV_DATA_END UNDEF_END +#endif + +#ifndef DRV_NAME +#define DRV_NAME UNDEF_NAME +#endif + +extern uint8_t DRV_DATA_START; +extern uint8_t DRV_DATA_END; + +/* + * The following is stub code that makes it look as though we want + * to be a child device of all the buses that our supported devices + * might want to attach to. Our probe routine always fails. The + * reason we need this code is so that loading an ELF-ified Windows + * driver module will trigger a bus reprobe. + */ + +#define MODULE_DECL(x) \ + MODULE_DEPEND(x, ndisapi, 1, 1, 1); \ + MODULE_DEPEND(x, ndis, 1, 1, 1) + +MODULE_DECL(DRV_NAME); + +static int windrv_probe(device_t); +static int windrv_modevent(module_t, int, void *); +static int windrv_loaded = 0; + +static device_method_t windrv_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, windrv_probe), + + { 0, 0 } +}; + +static driver_t windrv_driver = { + "windrv_stub", + windrv_methods, + 0 +}; + +static devclass_t windrv_devclass; + +#define DRIVER_DECL(x) \ + DRIVER_MODULE(x, pci, windrv_driver, \ + windrv_devclass, windrv_modevent, NULL); \ + DRIVER_MODULE(x, cardbus, windrv_driver, \ + windrv_devclass, windrv_modevent, NULL); \ + DRIVER_MODULE(x, pccard, windrv_driver, \ + windrv_devclass, windrv_modevent, NULL); \ + DRIVER_MODULE(x, uhub, windrv_driver, \ + windrv_devclass, windrv_modevent, NULL); \ + MODULE_VERSION(x, 1) + +DRIVER_DECL(DRV_NAME); + +static int +windrv_probe(dev) + device_t dev; +{ + return (ENXIO); +} + +static int +windrv_modevent(mod, cmd, arg) + module_t mod; + int cmd; + void *arg; +{ + int drv_data_len; + int error = 0; + vm_offset_t drv_data_start; + vm_offset_t drv_data_end; + interface_type drv_type; + +#ifdef NDIS_PCI_DEV_TABLE + drv_type = PCIBus; +#endif + +#ifdef NDIS_PCMCIA_DEV_TABLE + drv_type = PCMCIABus; +#endif + + drv_data_start = (vm_offset_t)&DRV_DATA_START; + drv_data_end = (vm_offset_t)&DRV_DATA_END; + + drv_data_len = drv_data_end - drv_data_start; + switch (cmd) { + case MOD_LOAD: + windrv_loaded++; + if (windrv_loaded > 1) + break; + windrv_load(mod, drv_data_start, drv_data_len, drv_type, + ndis_devs, &ndis_regvals); + break; + case MOD_UNLOAD: + windrv_loaded--; + if (windrv_loaded > 0) + break; + windrv_unload(mod, drv_data_start, drv_data_len); + break; + case MOD_SHUTDOWN: + break; + default: + error = EINVAL; + break; + } + + return (error); +} |