summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica/acpi_resource.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/acpica/acpi_resource.c')
-rw-r--r--sys/dev/acpica/acpi_resource.c128
1 files changed, 91 insertions, 37 deletions
diff --git a/sys/dev/acpica/acpi_resource.c b/sys/dev/acpica/acpi_resource.c
index ffc2c98..06bf29b 100644
--- a/sys/dev/acpica/acpi_resource.c
+++ b/sys/dev/acpica/acpi_resource.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/bus.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <machine/bus.h>
@@ -537,72 +538,125 @@ acpi_res_set_end_dependant(device_t dev, void *context)
}
/*
- * Resource-owning placeholders.
+ * Resource-owning placeholders for IO and memory pseudo-devices.
*
- * This code "owns" system resource objects that aren't
- * otherwise useful to devices, and which shouldn't be
- * considered "free".
- *
- * Note that some systems claim *all* of the physical address space
- * with a PNP0C01 device, so we cannot correctly "own" system memory
- * here (must be done in the SMAP handler on x86 systems, for
- * example).
+ * This code allocates system resource objects that will be owned by ACPI
+ * child devices. Really, the acpi parent device should have the resources
+ * but this would significantly affect the device probe code.
*/
-static int acpi_sysresource_probe(device_t dev);
-static int acpi_sysresource_attach(device_t dev);
+static int acpi_sysres_probe(device_t dev);
+static int acpi_sysres_attach(device_t dev);
-static device_method_t acpi_sysresource_methods[] = {
+static device_method_t acpi_sysres_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, acpi_sysresource_probe),
- DEVMETHOD(device_attach, acpi_sysresource_attach),
+ DEVMETHOD(device_probe, acpi_sysres_probe),
+ DEVMETHOD(device_attach, acpi_sysres_attach),
{0, 0}
};
-static driver_t acpi_sysresource_driver = {
+static driver_t acpi_sysres_driver = {
"acpi_sysresource",
- acpi_sysresource_methods,
+ acpi_sysres_methods,
0,
};
-static devclass_t acpi_sysresource_devclass;
-DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver,
- acpi_sysresource_devclass, 0, 0);
+static devclass_t acpi_sysres_devclass;
+DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysres_driver, acpi_sysres_devclass,
+ 0, 0);
MODULE_DEPEND(acpi_sysresource, acpi, 1, 1, 1);
static int
-acpi_sysresource_probe(device_t dev)
+acpi_sysres_probe(device_t dev)
{
- if (!acpi_disabled("sysresource") && acpi_MatchHid(dev, "PNP0C02"))
- device_set_desc(dev, "System Resource");
- else
+ ACPI_HANDLE h;
+
+ h = acpi_get_handle(dev);
+ if (acpi_disabled("sysresource") ||
+ (!acpi_MatchHid(h, "PNP0C01") && !acpi_MatchHid(h, "PNP0C02")))
return (ENXIO);
+ device_set_desc(dev, "System Resource");
device_quiet(dev);
return (-100);
}
static int
-acpi_sysresource_attach(device_t dev)
+acpi_sysres_attach(device_t dev)
{
- struct resource *res;
- int i, rid;
+ device_t gparent;
+ struct resource *res;
+ struct rman *rm;
+ struct resource_list_entry *rle;
+ struct resource_list *rl;
/*
- * Suck up all the resources that might have been assigned to us.
- * Note that it's impossible to tell the difference between a
- * resource that someone else has claimed, and one that doesn't
- * exist.
+ * Pre-allocate/manage all memory and IO resources. We detect duplicates
+ * by setting rle->res to the resource we got from the parent. We can't
+ * ignore them since rman can't handle duplicates.
*/
- for (i = 0; i < 100; i++) {
- rid = i;
- res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, 0);
- rid = i;
- res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0);
- rid = i;
- res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE);
+ rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
+ SLIST_FOREACH(rle, rl, link) {
+ if (rle->res != NULL) {
+ device_printf(dev, "duplicate resource for %lx\n", rle->start);
+ continue;
+ }
+
+ /* Only memory and IO resources are valid here. */
+ switch (rle->type) {
+ case SYS_RES_IOPORT:
+ rm = &acpi_rman_io;
+ break;
+ case SYS_RES_MEMORY:
+ rm = &acpi_rman_mem;
+ break;
+ default:
+ continue;
+ }
+
+ /* Pre-allocate resource and add to our rman pool. */
+ gparent = device_get_parent(device_get_parent(dev));
+ res = BUS_ALLOC_RESOURCE(gparent, dev, rle->type, &rle->rid,
+ rle->start, rle->start + rle->count - 1, rle->count, 0);
+ if (res != NULL) {
+ rman_manage_region(rm, rman_get_start(res), rman_get_end(res));
+ rle->res = res;
+ }
}
return (0);
}
+
+struct resource_list_entry *
+acpi_sysres_find(int type, u_long addr)
+{
+ device_t *devs;
+ int i, numdevs;
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+
+ /* We only consider IO and memory resources for our pool. */
+ rle = NULL;
+ if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY)
+ return (rle);
+
+ /* Find all the sysresource devices. */
+ if (devclass_get_devices(acpi_sysres_devclass, &devs, &numdevs) != 0)
+ return (rle);
+
+ /* Check each device for a resource that contains "addr". */
+ for (i = 0; i < numdevs && rle == NULL; i++) {
+ rl = BUS_GET_RESOURCE_LIST(device_get_parent(devs[i]), devs[i]);
+ if (rl == NULL)
+ continue;
+ SLIST_FOREACH(rle, rl, link) {
+ if (type == rle->type && addr >= rle->start &&
+ addr < rle->start + rle->count)
+ break;
+ }
+ }
+
+ free(devs, M_TEMP);
+ return (rle);
+}
OpenPOWER on IntegriCloud