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.
This commit is contained in:
Bill Paul 2005-04-24 20:21:22 +00:00
parent 8a399540fa
commit 96b50ea387
19 changed files with 1045 additions and 191 deletions

View File

@ -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>

View File

@ -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;
}

View File

@ -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);

View File

@ -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>

View File

@ -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;
}

View File

@ -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 *,

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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,25 +101,41 @@ 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
static int
ndis_devcompare(t, dev)
struct ndis_pccard_type *t;
device_t dev;
{
const char *prodstr, *vendstr;
int error;
error = pccard_get_product_str(dev, &prodstr);
if (error)
return(FALSE);
error = pccard_get_vendor_str(dev, &vendstr);
if (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);
return(TRUE);
}
t++;
}
return(FALSE);
}
/*
* Probe for an NDIS device. Check the PCI vendor and device
@ -146,33 +145,19 @@ static int
ndis_probe_pccard(dev)
device_t dev;
{
struct ndis_pccard_type *t;
const char *prodstr, *vendstr;
int error;
driver_object *drv;
struct drvdb_ent *db;
drv = windrv_lookup(0, "PCCARD Bus");
if (drv == NULL)
return(ENXIO);
t = ndis_devs;
db = windrv_match((matchfuncptr)ndis_devcompare, dev);
error = pccard_get_product_str(dev, &prodstr);
if (error)
return(error);
error = pccard_get_vendor_str(dev, &vendstr);
if (error)
return(error);
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);
}
t++;
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

View File

@ -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 */

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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 .

500
usr.sbin/ndiscvt/ndisgen.sh Normal file
View File

@ -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

View File

@ -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);
}