summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-11-18 21:01:54 +0000
committerjhb <jhb@FreeBSD.org>2008-11-18 21:01:54 +0000
commitc2251260be90b098d300f1452cc5cb46c5032282 (patch)
tree9f64d56b3288179bc04a3f77b610240093f70345 /sys/dev/acpica
parent7a676b30d156207340caf73e0c93ff42db650ffb (diff)
downloadFreeBSD-src-c2251260be90b098d300f1452cc5cb46c5032282.zip
FreeBSD-src-c2251260be90b098d300f1452cc5cb46c5032282.tar.gz
Allow device hints to wire the unit numbers of devices.
- An "at" hint now reserves a device name. - A new BUS_HINT_DEVICE_UNIT method is added to the bus interface. When determining the unit number of a device, this method is invoked to let the bus driver specify the unit of a device given a specific devclass. This is the only way a device can be given a name reserved via an "at" hint. - Implement BUS_HINT_DEVICE_UNIT() for the acpi(4) and isa(4) bus drivers. Both of these busses implement this by comparing the resources for a given hint device with the resources enumerated by ACPI/PnPBIOS and wire a unit if the hint resources are a subset of the "real" resources. - Use bus_hinted_children() for adding hinted devices on isa(4) busses now instead of doing it by hand. - Remove the unit kludging from sio(4) as it is no longer necessary. Prodding from: peter, imp OK'd by: marcel MFC after: 1 month
Diffstat (limited to 'sys/dev/acpica')
-rw-r--r--sys/dev/acpica/acpi.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index a345f29..8271917 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -158,6 +158,8 @@ static int acpi_child_pnpinfo_str_method(device_t acdev, device_t child,
#if defined(__i386__) || defined(__amd64__)
static void acpi_enable_pcie(void);
#endif
+static void acpi_hint_device_unit(device_t acdev, device_t child,
+ const char *name, int *unitp);
static device_method_t acpi_methods[] = {
/* Device interface */
@@ -187,6 +189,7 @@ static device_method_t acpi_methods[] = {
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_hint_device_unit, acpi_hint_device_unit),
/* ACPI bus */
DEVMETHOD(acpi_id_probe, acpi_device_id_probe),
@@ -949,6 +952,89 @@ acpi_get_rlist(device_t dev, device_t child)
return (&ad->ad_rl);
}
+static int
+acpi_match_resource_hint(device_t dev, int type, long value)
+{
+ struct acpi_device *ad = device_get_ivars(dev);
+ struct resource_list *rl = &ad->ad_rl;
+ 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);
+}
+
+/*
+ * Wire device unit numbers based on resource matches in hints.
+ */
+static void
+acpi_hint_device_unit(device_t acdev, device_t child, const char *name,
+ int *unitp)
+{
+ const char *s;
+ long value;
+ int line, matches, unit;
+
+ /*
+ * Iterate over all the hints for the devices with the specified
+ * name to see if one's resources are a subset of this device.
+ */
+ line = 0;
+ for (;;) {
+ if (resource_find_dev(&line, name, &unit, "at", NULL) != 0)
+ break;
+
+ /* Must have an "at" for acpi or isa. */
+ resource_string_value(name, unit, "at", &s);
+ if (!(strcmp(s, "acpi0") == 0 || strcmp(s, "acpi") == 0 ||
+ strcmp(s, "isa0") == 0 || strcmp(s, "isa") == 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 (acpi_match_resource_hint(child, SYS_RES_IOPORT, value))
+ matches++;
+ else
+ continue;
+ }
+ if (resource_long_value(name, unit, "maddr", &value) == 0) {
+ if (acpi_match_resource_hint(child, SYS_RES_MEMORY, value))
+ matches++;
+ else
+ continue;
+ }
+ if (resource_long_value(name, unit, "irq", &value) == 0) {
+ if (acpi_match_resource_hint(child, SYS_RES_IRQ, value))
+ matches++;
+ else
+ continue;
+ }
+ if (resource_long_value(name, unit, "drq", &value) == 0) {
+ if (acpi_match_resource_hint(child, SYS_RES_DRQ, value))
+ matches++;
+ else
+ continue;
+ }
+
+ if (matches > 0) {
+ /* We have a winner! */
+ *unitp = unit;
+ break;
+ }
+ }
+}
+
/*
* Pre-allocate/manage all memory and IO resources. Since rman can't handle
* duplicates, we merge any in the sysresource attach routine.
OpenPOWER on IntegriCloud