summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica/acpi.c
diff options
context:
space:
mode:
authormsmith <msmith@FreeBSD.org>2001-08-30 00:50:58 +0000
committermsmith <msmith@FreeBSD.org>2001-08-30 00:50:58 +0000
commitd83b514457efc8cbd5a3d69492b202cb45f203da (patch)
treec44d7d26893717cc8dbf9ef4f119203178813e3a /sys/dev/acpica/acpi.c
parent48c2759e11457275a7eef2586aee62e452ec0533 (diff)
downloadFreeBSD-src-d83b514457efc8cbd5a3d69492b202cb45f203da.zip
FreeBSD-src-d83b514457efc8cbd5a3d69492b202cb45f203da.tar.gz
Add support for attaching PnP-aware ISA drivers to ACPI.
Always parse ACPI device resource settings (current resources only) and attach the resources to the device before probe/attaching.
Diffstat (limited to 'sys/dev/acpica/acpi.c')
-rw-r--r--sys/dev/acpica/acpi.c75
1 files changed, 74 insertions, 1 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 83c0393..b1e92b6 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -44,9 +44,10 @@
#include <sys/ctype.h>
#include <machine/clock.h>
-
#include <machine/resource.h>
+#include <isa/isavar.h>
+
#include "acpi.h"
#include <dev/acpica/acpivar.h>
@@ -110,6 +111,7 @@ static int acpi_get_resource(device_t dev, device_t child, int type, int rid, u_
static struct resource *acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags);
static int acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r);
+static int acpi_isa_pnp_probe(device_t bus, device_t child, struct isa_pnp_id *ids);
static void acpi_probe_children(device_t bus);
static ACPI_STATUS acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status);
@@ -147,6 +149,9 @@ static device_method_t acpi_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ /* ISA emulation */
+ DEVMETHOD(isa_pnp_probe, acpi_isa_pnp_probe),
+
{0, 0}
};
@@ -594,6 +599,60 @@ acpi_release_resource(device_t bus, device_t child, int type, int rid, struct re
}
/*
+ * Handle ISA-like devices probing for a PnP ID to match.
+ */
+#define PNP_EISAID(s) \
+ ((((s[0] - '@') & 0x1f) << 2) \
+ | (((s[1] - '@') & 0x18) >> 3) \
+ | (((s[1] - '@') & 0x07) << 13) \
+ | (((s[2] - '@') & 0x1f) << 8) \
+ | (PNP_HEXTONUM(s[4]) << 16) \
+ | (PNP_HEXTONUM(s[3]) << 20) \
+ | (PNP_HEXTONUM(s[6]) << 24) \
+ | (PNP_HEXTONUM(s[5]) << 28))
+
+int
+acpi_isa_pnp_probe(device_t bus, device_t child, struct isa_pnp_id *ids)
+{
+ ACPI_HANDLE h;
+ ACPI_DEVICE_INFO devinfo;
+ ACPI_STATUS error;
+ u_int32_t pnpid;
+ int result;
+
+ FUNCTION_TRACE(__func__);
+
+ /*
+ * ISA-style drivers attached to ACPI may persist and
+ * probe manually if we return ENOENT. We never want
+ * that to happen, so don't ever return it.
+ */
+ result = ENXIO;
+ ACPI_LOCK;
+
+ /* fetch and validate the HID */
+ if ((h = acpi_get_handle(child)) == NULL)
+ goto out;
+ if ((error = AcpiGetObjectInfo(h, &devinfo)) != AE_OK)
+ goto out;
+ if (!(devinfo.Valid & ACPI_VALID_HID))
+ goto out;
+
+ /* scan the supplied IDs for a match */
+ pnpid = PNP_EISAID(devinfo.HardwareId);
+ while (ids && ids->ip_id) {
+ if (pnpid == ids->ip_id) {
+ result = 0;
+ goto out;
+ }
+ ids++;
+ }
+ out:
+ ACPI_UNLOCK;
+ return_VALUE(result);
+}
+
+/*
* Scan relevant portions of the ACPI namespace and attach child devices.
*
* Note that we only expect to find devices in the \_PR_, \_TZ_, \_SI_ and \_SB_ scopes,
@@ -642,6 +701,7 @@ acpi_probe_children(device_t bus)
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "second bus_generic_attach\n"));
bus_generic_attach(bus);
+ ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "done attaching children\n"));
return_VOID;
}
@@ -677,7 +737,20 @@ acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
*/
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "scanning '%s'\n", acpi_name(handle)));
child = BUS_ADD_CHILD(bus, level * 10, NULL, -1);
+ if (child == NULL)
+ break;
acpi_set_handle(child, handle);
+
+ /*
+ * Get the device's resource settings and attach them.
+ * Note that if the device has _PRS but no _CRS, we need
+ * to decide when it's appropriate to try to configure the
+ * device. Ignore the return value here; it's OK for the
+ * device not to have any resources.
+ */
+ acpi_parse_resources(child, handle, &acpi_res_parse_set);
+
+ /* if we're debugging, probe/attach now rather than later */
DEBUG_EXEC(device_probe_and_attach(child));
break;
}
OpenPOWER on IntegriCloud