aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/acpica/acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/acpica/acpi.c')
-rw-r--r--sys/dev/acpica/acpi.c198
1 files changed, 123 insertions, 75 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 2899929c8e6b..9cd809761b8e 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -126,11 +126,16 @@ static bus_child_deleted_t acpi_child_deleted;
static bus_read_ivar_t acpi_read_ivar;
static bus_write_ivar_t acpi_write_ivar;
static bus_get_resource_list_t acpi_get_rlist;
+static bus_get_rman_t acpi_get_rman;
static bus_set_resource_t acpi_set_resource;
static bus_alloc_resource_t acpi_alloc_resource;
static bus_adjust_resource_t acpi_adjust_resource;
static bus_release_resource_t acpi_release_resource;
static bus_delete_resource_t acpi_delete_resource;
+static bus_activate_resource_t acpi_activate_resource;
+static bus_deactivate_resource_t acpi_deactivate_resource;
+static bus_map_resource_t acpi_map_resource;
+static bus_unmap_resource_t acpi_unmap_resource;
static bus_child_pnpinfo_t acpi_child_pnpinfo_method;
static bus_child_location_t acpi_child_location_method;
static bus_hint_device_unit_t acpi_hint_device_unit;
@@ -196,16 +201,19 @@ static device_method_t acpi_methods[] = {
DEVMETHOD(bus_read_ivar, acpi_read_ivar),
DEVMETHOD(bus_write_ivar, acpi_write_ivar),
DEVMETHOD(bus_get_resource_list, acpi_get_rlist),
+ DEVMETHOD(bus_get_rman, acpi_get_rman),
DEVMETHOD(bus_set_resource, acpi_set_resource),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_alloc_resource, acpi_alloc_resource),
DEVMETHOD(bus_adjust_resource, acpi_adjust_resource),
DEVMETHOD(bus_release_resource, acpi_release_resource),
DEVMETHOD(bus_delete_resource, acpi_delete_resource),
+ DEVMETHOD(bus_activate_resource, acpi_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, acpi_deactivate_resource),
+ DEVMETHOD(bus_map_resource, acpi_map_resource),
+ DEVMETHOD(bus_unmap_resource, acpi_unmap_resource),
DEVMETHOD(bus_child_pnpinfo, acpi_child_pnpinfo_method),
DEVMETHOD(bus_child_location, acpi_child_location_method),
- DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
- 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),
@@ -479,6 +487,8 @@ acpi_attach(device_t dev)
if (rman_init(&acpi_rman_mem) != 0)
panic("acpi rman_init memory failed");
+ resource_list_init(&sc->sysres_rl);
+
/* Initialise the ACPI mutex */
mtx_init(&acpi_mutex, "ACPI global lock", NULL, MTX_DEF);
@@ -1294,6 +1304,20 @@ acpi_get_domain(device_t dev, device_t child, int *domain)
return (bus_generic_get_domain(dev, child, domain));
}
+static struct rman *
+acpi_get_rman(device_t bus, int type, u_int flags)
+{
+ /* Only memory and IO resources are managed. */
+ switch (type) {
+ case SYS_RES_IOPORT:
+ return (&acpi_rman_io);
+ case SYS_RES_MEMORY:
+ return (&acpi_rman_mem);
+ default:
+ return (NULL);
+ }
+}
+
/*
* Pre-allocate/manage all memory and IO resources. Since rman can't handle
* duplicates, we merge any in the sysresource attach routine.
@@ -1301,8 +1325,8 @@ acpi_get_domain(device_t dev, device_t child, int *domain)
static int
acpi_sysres_alloc(device_t dev)
{
+ struct acpi_softc *sc = device_get_softc(dev);
struct resource *res;
- struct resource_list *rl;
struct resource_list_entry *rle;
struct rman *rm;
device_t *children;
@@ -1320,28 +1344,21 @@ acpi_sysres_alloc(device_t dev)
}
free(children, M_TEMP);
- rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
- STAILQ_FOREACH(rle, rl, link) {
+ STAILQ_FOREACH(rle, &sc->sysres_rl, link) {
if (rle->res != NULL) {
device_printf(dev, "duplicate resource for %jx\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:
+ rm = acpi_get_rman(dev, rle->type, 0);
+ if (rm == NULL)
continue;
- }
/* Pre-allocate resource and add to our rman pool. */
- res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, rle->type,
- &rle->rid, rle->start, rle->start + rle->count - 1, rle->count, 0);
+ res = bus_alloc_resource(dev, rle->type,
+ &rle->rid, rle->start, rle->start + rle->count - 1, rle->count,
+ RF_ACTIVE | RF_UNMAPPED);
if (res != NULL) {
rman_manage_region(rm, rman_get_start(res), rman_get_end(res));
rle->res = res;
@@ -1542,63 +1559,39 @@ acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
* from our system resource regions.
*/
if (res == NULL && start + count - 1 == end)
- res = acpi_alloc_sysres(child, type, rid, start, end, count, flags);
+ res = bus_generic_rman_alloc_resource(bus, child, type, rid, start, end,
+ count, flags);
return (res);
}
-/*
- * Attempt to allocate a specific resource range from the system
- * resource ranges. Note that we only handle memory and I/O port
- * system resources.
- */
-struct resource *
-acpi_alloc_sysres(device_t child, int type, int *rid, rman_res_t start,
- rman_res_t end, rman_res_t count, u_int flags)
+static bool
+acpi_is_resource_managed(device_t bus, int type, struct resource *r)
{
- struct rman *rm;
- struct resource *res;
-
- switch (type) {
- case SYS_RES_IOPORT:
- rm = &acpi_rman_io;
- break;
- case SYS_RES_MEMORY:
- rm = &acpi_rman_mem;
- break;
- default:
- return (NULL);
- }
+ struct rman *rm;
- KASSERT(start + count - 1 == end, ("wildcard resource range"));
- res = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE,
- child);
- if (res == NULL)
- return (NULL);
-
- rman_set_rid(res, *rid);
-
- /* If requested, activate the resource using the parent's method. */
- if (flags & RF_ACTIVE)
- if (bus_activate_resource(child, type, *rid, res) != 0) {
- rman_release_resource(res);
- return (NULL);
- }
-
- return (res);
+ rm = acpi_get_rman(bus, type, 0);
+ if (rm == NULL)
+ return (false);
+ return (rman_is_region_manager(r, rm));
}
-static int
-acpi_is_resource_managed(int type, struct resource *r)
+static struct resource *
+acpi_managed_resource(device_t bus, int type, struct resource *r)
{
+ struct acpi_softc *sc = device_get_softc(bus);
+ struct resource_list_entry *rle;
- /* We only handle memory and IO resources through rman. */
- switch (type) {
- case SYS_RES_IOPORT:
- return (rman_is_region_manager(r, &acpi_rman_io));
- case SYS_RES_MEMORY:
- return (rman_is_region_manager(r, &acpi_rman_mem));
- }
- return (0);
+ KASSERT(acpi_is_resource_managed(bus, type, r),
+ ("resource %p is not suballocated", r));
+
+ STAILQ_FOREACH(rle, &sc->sysres_rl, link) {
+ if (rle->type != type || rle->res == NULL)
+ continue;
+ if (rman_get_start(r) >= rman_get_start(rle->res) &&
+ rman_get_end(r) <= rman_get_end(rle->res))
+ return (rle->res);
+ }
+ return (NULL);
}
static int
@@ -1606,7 +1599,7 @@ acpi_adjust_resource(device_t bus, device_t child, int type, struct resource *r,
rman_res_t start, rman_res_t end)
{
- if (acpi_is_resource_managed(type, r))
+ if (acpi_is_resource_managed(bus, type, r))
return (rman_adjust_resource(r, start, end));
return (bus_generic_adjust_resource(bus, child, type, r, start, end));
}
@@ -1615,20 +1608,12 @@ static int
acpi_release_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
- int ret;
-
/*
* If this resource belongs to one of our internal managers,
* deactivate it and release it to the local pool.
*/
- if (acpi_is_resource_managed(type, r)) {
- if (rman_get_flags(r) & RF_ACTIVE) {
- ret = bus_deactivate_resource(child, type, rid, r);
- if (ret != 0)
- return (ret);
- }
- return (rman_release_resource(r));
- }
+ if (acpi_is_resource_managed(bus, type, r))
+ return (bus_generic_rman_release_resource(bus, child, type, rid, r));
return (bus_generic_rl_release_resource(bus, child, type, rid, r));
}
@@ -1648,6 +1633,69 @@ acpi_delete_resource(device_t bus, device_t child, int type, int rid)
resource_list_delete(rl, type, rid);
}
+static int
+acpi_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ if (acpi_is_resource_managed(bus, type, r))
+ return (bus_generic_rman_activate_resource(bus, child, type,
+ rid, r));
+ return (bus_generic_activate_resource(bus, child, type, rid, r));
+}
+
+static int
+acpi_deactivate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+ if (acpi_is_resource_managed(bus, type, r))
+ return (bus_generic_rman_deactivate_resource(bus, child, type,
+ rid, r));
+ return (bus_generic_deactivate_resource(bus, child, type, rid, r));
+}
+
+static int
+acpi_map_resource(device_t bus, device_t child, int type, struct resource *r,
+ struct resource_map_request *argsp, struct resource_map *map)
+{
+ struct resource_map_request args;
+ struct resource *sysres;
+ rman_res_t length, start;
+ int error;
+
+ if (!acpi_is_resource_managed(bus, type, r))
+ return (bus_generic_map_resource(bus, child, type, r, argsp,
+ map));
+
+ /* Resources must be active to be mapped. */
+ if (!(rman_get_flags(r) & RF_ACTIVE))
+ return (ENXIO);
+
+ resource_init_map_request(&args);
+ error = resource_validate_map_request(r, argsp, &args, &start, &length);
+ if (error)
+ return (error);
+
+ sysres = acpi_managed_resource(bus, type, r);
+ if (sysres == NULL)
+ return (ENOENT);
+
+ args.offset = start - rman_get_start(sysres);
+ args.length = length;
+ return (bus_generic_map_resource(bus, child, type, sysres, &args, map));
+}
+
+static int
+acpi_unmap_resource(device_t bus, device_t child, int type, struct resource *r,
+ struct resource_map *map)
+{
+ if (acpi_is_resource_managed(bus, type, r)) {
+ r = acpi_managed_resource(bus, type, r);
+ if (r == NULL)
+ return (ENOENT);
+ }
+ return (bus_generic_unmap_resource(bus, child, type, r, map));
+}
+
/* Allocate an IO port or memory resource, given its GAS. */
int
acpi_bus_alloc_gas(device_t dev, int *type, int *rid, ACPI_GENERIC_ADDRESS *gas,