aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>2005-04-24 20:21:22 +0000
committerBill Paul <wpaul@FreeBSD.org>2005-04-24 20:21:22 +0000
commit96b50ea387181a2e0ceed669e7b065da57602c7b (patch)
treeba1d66e7b03425d40e2969f60b5568a405137f90
parent8a399540fafdfa09a0ef89d20c05e8b6da1da6d6 (diff)
downloadsrc-96b50ea387181a2e0ceed669e7b065da57602c7b.tar.gz
src-96b50ea387181a2e0ceed669e7b065da57602c7b.zip
Throw the switch on the new driver generation/loading mechanism. From
here on in, if_ndis.ko will be pre-built as a module, and can be built into a static kernel (though it's not part of GENERIC). Drivers are created using the new ndisgen(8) script, which uses ndiscvt(8) under the covers, along with a few other tools. The result is a driver module that can be kldloaded into the kernel. A driver with foo.inf and foo.sys files will be converted into foo_sys.ko (and foo_sys.o, for those who want/need to make static kernels). This module contains all of the necessary info from the .INF file and the driver binary image, converted into an ELF module. You can kldload this module (or add it to /boot/loader.conf) to have it loaded automatically. Any required firmware files can be bundled into the module as well (or converted/loaded separately). Also, add a workaround for a problem in NdisMSleep(). During system bootstrap (cold == 1), msleep() always returns 0 without actually sleeping. The Intel 2200BG driver uses NdisMSleep() to wait for the NIC's firmware to come to life, and fails to load if NdisMSleep() doesn't actually delay. As a workaround, if msleep() (and hence ndis_thsuspend()) returns 0, use a hard DELAY() to sleep instead). This is not really the right thing to do, but we can't really do much else. At the very least, this makes the Intel driver happy. There are probably other drivers that fail in this way during bootstrap. Unfortunately, the only workaround for those is to avoid pre-loading them and kldload them once the system is running instead.
Notes
Notes: svn path=/head/; revision=145485
-rw-r--r--sys/compat/ndis/kern_ndis.c2
-rw-r--r--sys/compat/ndis/kern_windrv.c108
-rw-r--r--sys/compat/ndis/ntoskrnl_var.h13
-rw-r--r--sys/compat/ndis/subr_hal.c2
-rw-r--r--sys/compat/ndis/subr_ndis.c19
-rw-r--r--sys/compat/ndis/subr_ntoskrnl.c5
-rw-r--r--sys/conf/files.amd641
-rw-r--r--sys/conf/files.i3861
-rw-r--r--sys/dev/if_ndis/if_ndis.c30
-rw-r--r--sys/dev/if_ndis/if_ndis_pccard.c91
-rw-r--r--sys/dev/if_ndis/if_ndis_pci.c90
-rw-r--r--sys/dev/if_ndis/if_ndis_usb.c29
-rw-r--r--sys/dev/if_ndis/if_ndisvar.h1
-rw-r--r--sys/modules/Makefile3
-rw-r--r--sys/modules/if_ndis/Makefile3
-rw-r--r--usr.sbin/ndiscvt/Makefile7
-rw-r--r--usr.sbin/ndiscvt/ndisgen.882
-rw-r--r--usr.sbin/ndiscvt/ndisgen.sh500
-rw-r--r--usr.sbin/ndiscvt/windrv_stub.c245
19 files changed, 1043 insertions, 189 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
index b7b472a4f009..56832ea3c19d 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 cd631fd36a58..11a582455ba0 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 55e3c1e87930..2ef6915d4db5 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 b4170f4991f5..c992c7e3cb6c 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 992a539bfb52..7c0d4ad2d25d 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 bdb9c8f2f85e..b3b90408f56c 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 085108f56395..6de730c40c70 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 674de0135039..3554c30ded7e 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 aa0f5c2e6a34..cb9e38c49216 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 918e89ccbbb5..c67941a0e22a 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 08109e65f07a..1c8691bd33ad 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 819953419dcd..b5a694337b7e 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 0936aaf7fc23..68f30f9cff1a 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 bfc54383fdad..cc033d9f8d21 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 bce7c969da24..cbc2ed0ee34c 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 8004897e2bed..90ecebbdc552 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 000000000000..d16c34da09bb
--- /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 000000000000..3e31e8805a3a
--- /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 000000000000..2097e50f557f
--- /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);
+}