diff options
Diffstat (limited to 'sys/isa/isahint.c')
-rw-r--r-- | sys/isa/isahint.c | 115 |
1 files changed, 76 insertions, 39 deletions
diff --git a/sys/isa/isahint.c b/sys/isa/isahint.c index 01f8823..e2ce6a4 100644 --- a/sys/isa/isahint.c +++ b/sys/isa/isahint.c @@ -33,10 +33,11 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/module.h> #include <isa/isavar.h> +#include <isa/isa_common.h> #include <machine/resource.h> -static void -isahint_add_device(device_t parent, const char *name, int unit) +void +isa_hinted_child(device_t parent, const char *name, int unit) { device_t child; int sensitive, start, count; @@ -82,43 +83,79 @@ isahint_add_device(device_t parent, const char *name, int unit) isa_set_configattr(child, (isa_get_configattr(child)|ISACFGATTR_HINTS)); } -static void -isahint_identify(driver_t *driver, device_t parent) +static int +isa_match_resource_hint(device_t dev, int type, long value) { - int i; - static char buf[] = "isaXXX"; - const char *dname; - int dunit; - - /* - * Add all devices configured to be attached to parent. - */ - sprintf(buf, "isa%d", device_get_unit(parent)); - i = 0; - while (resource_find_match(&i, &dname, &dunit, "at", buf) == 0) - isahint_add_device(parent, dname, dunit); - - /* - * and isa? - */ - i = 0; - while (resource_find_match(&i, &dname, &dunit, "at", "isa") == 0) - isahint_add_device(parent, dname, dunit); + struct isa_device* idev = DEVTOISA(dev); + struct resource_list *rl = &idev->id_resources; + struct resource_list_entry *rle; + + STAILQ_FOREACH(rle, rl, link) { + if (rle->type != type) + continue; + if (rle->start <= value && rle->end >= value) + return (1); + } + return (0); } -static device_method_t isahint_methods[] = { - /* Device interface */ - DEVMETHOD(device_identify, isahint_identify), - - { 0, 0 } -}; - -static driver_t isahint_driver = { - "hint", - isahint_methods, - 1, /* no softc */ -}; - -static devclass_t hint_devclass; - -DRIVER_MODULE(isahint, isa, isahint_driver, hint_devclass, 0, 0); +void +isa_hint_device_unit(device_t bus, device_t child, const char *name, int *unitp) +{ + const char *s; + long value; + int line, matches, unit; + + line = 0; + for (;;) { + if (resource_find_dev(&line, name, &unit, "at", NULL) != 0) + break; + + /* Must have an "at" for isa. */ + resource_string_value(name, unit, "at", &s); + if (!(strcmp(s, device_get_nameunit(bus)) == 0 || + strcmp(s, device_get_name(bus)) == 0)) + continue; + + /* + * Check for matching resources. We must have at least one, + * and all resources specified have to match. + * + * XXX: We may want to revisit this to be more lenient and wire + * as long as it gets one match. + */ + matches = 0; + if (resource_long_value(name, unit, "port", &value) == 0) { + if (isa_match_resource_hint(child, SYS_RES_IOPORT, + value)) + matches++; + else + continue; + } + if (resource_long_value(name, unit, "maddr", &value) == 0) { + if (isa_match_resource_hint(child, SYS_RES_MEMORY, + value)) + matches++; + else + continue; + } + if (resource_long_value(name, unit, "irq", &value) == 0) { + if (isa_match_resource_hint(child, SYS_RES_IRQ, value)) + matches++; + else + continue; + } + if (resource_long_value(name, unit, "drq", &value) == 0) { + if (isa_match_resource_hint(child, SYS_RES_DRQ, value)) + matches++; + else + continue; + } + + if (matches > 0) { + /* We have a winner! */ + *unitp = unit; + break; + } + } +} |