Add support to ACPI to manage its own resources. Previously, resource
allocation was passed up to nexus. Now, we probe sysresource objects and manage the resources they describe in a local rman pool. This helps devices which attach/detach varying resources (like the _CST object) and module loads/unloads. The allocation/release routines now check to see if the resource is described in a child sysresource object and if so, allocate from the local rman. Sysresource objects add their resources to the pool and reserve them upon boot. This means sysresources need to be probed before other ACPI devices. Changes include: * Add ordering to the child device probe. The current order is: system resource objects, embedded controllers, then everything else. * Make acpi_MatchHid take a handle instead of a device_t arg. * Replace acpi_{get,set}_resource with the generic equivalents.
This commit is contained in:
parent
a10ab60930
commit
9123341378
@ -81,6 +81,9 @@ static struct cdevsw acpi_cdevsw = {
|
||||
struct mtx acpi_mutex;
|
||||
#endif
|
||||
|
||||
/* Local pools for managing system resources for ACPI child devices. */
|
||||
struct rman acpi_rman_io, acpi_rman_mem;
|
||||
|
||||
struct acpi_quirks {
|
||||
char *OemId;
|
||||
uint32_t OemRevision;
|
||||
@ -111,10 +114,7 @@ static int acpi_read_ivar(device_t dev, device_t child, int index,
|
||||
uintptr_t *result);
|
||||
static int acpi_write_ivar(device_t dev, device_t child, int index,
|
||||
uintptr_t value);
|
||||
static int acpi_set_resource(device_t dev, device_t child, int type,
|
||||
int rid, u_long start, u_long count);
|
||||
static int acpi_get_resource(device_t dev, device_t child, int type,
|
||||
int rid, u_long *startp, u_long *countp);
|
||||
static struct resource_list *acpi_get_rlist(device_t dev, device_t child);
|
||||
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);
|
||||
@ -162,8 +162,9 @@ static device_method_t acpi_methods[] = {
|
||||
DEVMETHOD(bus_print_child, acpi_print_child),
|
||||
DEVMETHOD(bus_read_ivar, acpi_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, acpi_write_ivar),
|
||||
DEVMETHOD(bus_set_resource, acpi_set_resource),
|
||||
DEVMETHOD(bus_get_resource, acpi_get_resource),
|
||||
DEVMETHOD(bus_get_resource_list, acpi_get_rlist),
|
||||
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
DEVMETHOD(bus_alloc_resource, acpi_alloc_resource),
|
||||
DEVMETHOD(bus_release_resource, acpi_release_resource),
|
||||
DEVMETHOD(bus_child_pnpinfo_str, acpi_child_pnpinfo_str_method),
|
||||
@ -395,6 +396,20 @@ acpi_attach(device_t dev)
|
||||
bzero(sc, sizeof(*sc));
|
||||
sc->acpi_dev = dev;
|
||||
|
||||
/* Initialize resource manager. */
|
||||
acpi_rman_io.rm_type = RMAN_ARRAY;
|
||||
acpi_rman_io.rm_start = 0;
|
||||
acpi_rman_io.rm_end = 0xffff;
|
||||
acpi_rman_io.rm_descr = "I/O ports";
|
||||
if (rman_init(&acpi_rman_io) != 0)
|
||||
panic("acpi rman_init IO ports failed");
|
||||
acpi_rman_mem.rm_type = RMAN_ARRAY;
|
||||
acpi_rman_mem.rm_start = 0;
|
||||
acpi_rman_mem.rm_end = ~0ul;
|
||||
acpi_rman_mem.rm_descr = "I/O memory addresses";
|
||||
if (rman_init(&acpi_rman_mem) != 0)
|
||||
panic("acpi rman_init memory failed");
|
||||
|
||||
#ifdef ACPI_DEBUGGER
|
||||
debugpoint = getenv("debug.acpi.debugger");
|
||||
if (debugpoint) {
|
||||
@ -824,56 +839,102 @@ acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
|
||||
/*
|
||||
* Handle child resource allocation/removal
|
||||
*/
|
||||
static int
|
||||
acpi_set_resource(device_t dev, device_t child, int type, int rid,
|
||||
u_long start, u_long count)
|
||||
static struct resource_list *
|
||||
acpi_get_rlist(device_t dev, device_t child)
|
||||
{
|
||||
struct acpi_device *ad = device_get_ivars(child);
|
||||
struct resource_list *rl = &ad->ad_rl;
|
||||
struct acpi_device *ad;
|
||||
|
||||
resource_list_add(rl, type, rid, start, start + count -1, count);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_get_resource(device_t dev, device_t child, int type, int rid,
|
||||
u_long *startp, u_long *countp)
|
||||
{
|
||||
struct acpi_device *ad = device_get_ivars(child);
|
||||
struct resource_list *rl = &ad->ad_rl;
|
||||
struct resource_list_entry *rle;
|
||||
|
||||
rle = resource_list_find(rl, type, rid);
|
||||
if (!rle)
|
||||
return(ENOENT);
|
||||
|
||||
if (startp)
|
||||
*startp = rle->start;
|
||||
if (countp)
|
||||
*countp = rle->count;
|
||||
|
||||
return (0);
|
||||
ad = device_get_ivars(child);
|
||||
return (&ad->ad_rl);
|
||||
}
|
||||
|
||||
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)
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
struct acpi_device *ad = device_get_ivars(child);
|
||||
struct resource_list *rl = &ad->ad_rl;
|
||||
struct resource_list_entry *rle;
|
||||
struct resource *res;
|
||||
struct rman *rm;
|
||||
int needactivate;
|
||||
|
||||
return (resource_list_alloc(rl, bus, child, type, rid, start, end, count,
|
||||
flags));
|
||||
/*
|
||||
* If this is an allocation of the "default" range for a given RID, and
|
||||
* we know what the resources for this device are (i.e., they're on the
|
||||
* child's resource list), use those start/end values.
|
||||
*/
|
||||
if (start == 0UL && end == ~0UL) {
|
||||
rle = resource_list_find(rl, type, *rid);
|
||||
if (rle == NULL)
|
||||
return (NULL);
|
||||
start = rle->start;
|
||||
end = rle->end;
|
||||
count = rle->count;
|
||||
}
|
||||
|
||||
/* If we don't manage this address, pass the request up to the parent. */
|
||||
rle = acpi_sysres_find(type, start);
|
||||
if (rle == NULL) {
|
||||
return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, rid,
|
||||
start, end, count, flags));
|
||||
}
|
||||
|
||||
/* We only handle memory and IO resources through rman. */
|
||||
switch (type) {
|
||||
case SYS_RES_IOPORT:
|
||||
rm = &acpi_rman_io;
|
||||
break;
|
||||
case SYS_RES_MEMORY:
|
||||
rm = &acpi_rman_mem;
|
||||
break;
|
||||
default:
|
||||
panic("acpi_alloc_resource: invalid res type %d", type);
|
||||
}
|
||||
|
||||
/* If we do know it, allocate it from the local pool. */
|
||||
needactivate = flags & RF_ACTIVE;
|
||||
flags &= ~RF_ACTIVE;
|
||||
res = rman_reserve_resource(rm, start, end, count, flags, child);
|
||||
if (res == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* Copy the bus tag from the pre-allocated resource. */
|
||||
rman_set_bustag(res, rman_get_bustag(rle->res));
|
||||
if (type == SYS_RES_IOPORT)
|
||||
rman_set_bushandle(res, res->r_start);
|
||||
|
||||
/* If requested, activate the resource using the parent's method. */
|
||||
if (needactivate)
|
||||
if (bus_activate_resource(child, type, *rid, res) != 0) {
|
||||
rman_release_resource(res);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r)
|
||||
acpi_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
{
|
||||
struct acpi_device *ad = device_get_ivars(child);
|
||||
struct resource_list *rl = &ad->ad_rl;
|
||||
int ret;
|
||||
|
||||
return (resource_list_release(rl, bus, child, type, rid, r));
|
||||
/*
|
||||
* If we know about this address, deactivate it and release it to the
|
||||
* local pool. If we don't, pass this request up to the parent.
|
||||
*/
|
||||
if (acpi_sysres_find(type, rman_get_start(r)) == NULL) {
|
||||
if (rman_get_flags(r) & RF_ACTIVE) {
|
||||
ret = bus_deactivate_resource(child, type, rid, r);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
}
|
||||
ret = rman_release_resource(r);
|
||||
} else
|
||||
ret = BUS_RELEASE_RESOURCE(device_get_parent(bus), child, type, rid, r);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* Allocate an IO port or memory resource, given its GAS. */
|
||||
@ -1043,8 +1104,8 @@ acpi_probe_children(device_t bus)
|
||||
{
|
||||
ACPI_HANDLE parent;
|
||||
ACPI_STATUS status;
|
||||
static char *scopes[] = {"\\_PR_", "\\_TZ_", "\\_SI", "\\_SB_", NULL};
|
||||
int i;
|
||||
static char *scopes[] = {"\\_PR_", "\\_TZ_", "\\_SI", "\\_SB_", NULL};
|
||||
|
||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
|
||||
ACPI_ASSERTLOCK;
|
||||
@ -1091,6 +1152,28 @@ acpi_probe_children(device_t bus)
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_probe_order(ACPI_HANDLE handle, int level, int *order)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
/* IO port and memory system resource holders are first. */
|
||||
if (acpi_MatchHid(handle, "PNP0C01") || acpi_MatchHid(handle, "PNP0C02")) {
|
||||
*order = 1;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
/* The embedded controller is needed to handle accesses early. */
|
||||
if (acpi_MatchHid(handle, "PNP0C09")) {
|
||||
*order = 2;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
*order = (level + 1) * 10;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate a child device and determine whether we might attach a device to
|
||||
* it.
|
||||
@ -1099,7 +1182,8 @@ static ACPI_STATUS
|
||||
acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
|
||||
{
|
||||
ACPI_OBJECT_TYPE type;
|
||||
device_t child, bus = (device_t)context;
|
||||
device_t child, bus;
|
||||
int order, probe_now;
|
||||
|
||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
|
||||
|
||||
@ -1107,6 +1191,7 @@ acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
|
||||
if (acpi_avoid(handle))
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
|
||||
bus = (device_t)context;
|
||||
if (ACPI_SUCCESS(AcpiGetType(handle, &type))) {
|
||||
switch(type) {
|
||||
case ACPI_TYPE_DEVICE:
|
||||
@ -1122,7 +1207,8 @@ 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);
|
||||
probe_now = acpi_probe_order(handle, level, &order);
|
||||
child = BUS_ADD_CHILD(bus, order, NULL, -1);
|
||||
if (child == NULL)
|
||||
break;
|
||||
|
||||
@ -1154,6 +1240,8 @@ acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
|
||||
acpi_parse_resources(child, handle, &acpi_res_parse_set, NULL);
|
||||
|
||||
/* If we're debugging, probe/attach now rather than later */
|
||||
if (probe_now)
|
||||
device_probe_and_attach(child);
|
||||
ACPI_DEBUG_EXEC(device_probe_and_attach(child));
|
||||
break;
|
||||
}
|
||||
@ -1342,13 +1430,12 @@ acpi_BatteryIsPresent(device_t dev)
|
||||
}
|
||||
|
||||
/*
|
||||
* Match a HID string against a device
|
||||
* Match a HID string against a handle
|
||||
*/
|
||||
BOOLEAN
|
||||
acpi_MatchHid(device_t dev, char *hid)
|
||||
acpi_MatchHid(ACPI_HANDLE h, char *hid)
|
||||
{
|
||||
ACPI_DEVICE_INFO *devinfo;
|
||||
ACPI_HANDLE h;
|
||||
ACPI_BUFFER buf;
|
||||
ACPI_STATUS error;
|
||||
int ret, i;
|
||||
@ -1356,15 +1443,13 @@ acpi_MatchHid(device_t dev, char *hid)
|
||||
ACPI_ASSERTLOCK;
|
||||
|
||||
ret = FALSE;
|
||||
if (hid == NULL)
|
||||
return (FALSE);
|
||||
if ((h = acpi_get_handle(dev)) == NULL)
|
||||
return (FALSE);
|
||||
if (hid == NULL || h == NULL)
|
||||
return (ret);
|
||||
buf.Pointer = NULL;
|
||||
buf.Length = ACPI_ALLOCATE_BUFFER;
|
||||
error = AcpiGetObjectInfo(h, &buf);
|
||||
if (ACPI_FAILURE(error))
|
||||
return (FALSE);
|
||||
return (ret);
|
||||
devinfo = (ACPI_DEVICE_INFO *)buf.Pointer;
|
||||
|
||||
if ((devinfo->Valid & ACPI_VALID_HID) != 0 &&
|
||||
|
@ -137,7 +137,7 @@ static int
|
||||
acpi_acad_probe(device_t dev)
|
||||
{
|
||||
if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("acad") &&
|
||||
acpi_MatchHid(dev, "ACPI0003")) {
|
||||
acpi_MatchHid(acpi_get_handle(dev), "ACPI0003")) {
|
||||
device_set_desc(dev, "AC Adapter");
|
||||
return (0);
|
||||
}
|
||||
|
@ -90,24 +90,26 @@ static int
|
||||
acpi_button_probe(device_t dev)
|
||||
{
|
||||
struct acpi_button_softc *sc;
|
||||
ACPI_HANDLE h;
|
||||
int ret = ENXIO;
|
||||
|
||||
h = acpi_get_handle(dev);
|
||||
sc = device_get_softc(dev);
|
||||
if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("button")) {
|
||||
if (acpi_MatchHid(dev, "PNP0C0C")) {
|
||||
if (acpi_MatchHid(h, "PNP0C0C")) {
|
||||
device_set_desc(dev, "Power Button");
|
||||
sc->button_type = ACPI_POWER_BUTTON;
|
||||
ret = 0;
|
||||
} else if (acpi_MatchHid(dev, "ACPI_FPB")) {
|
||||
} else if (acpi_MatchHid(h, "ACPI_FPB")) {
|
||||
device_set_desc(dev, "Power Button (fixed)");
|
||||
sc->button_type = ACPI_POWER_BUTTON;
|
||||
sc->fixed = 1;
|
||||
ret = 0;
|
||||
} else if (acpi_MatchHid(dev, "PNP0C0E")) {
|
||||
} else if (acpi_MatchHid(h, "PNP0C0E")) {
|
||||
device_set_desc(dev, "Sleep Button");
|
||||
sc->button_type = ACPI_SLEEP_BUTTON;
|
||||
ret = 0;
|
||||
} else if (acpi_MatchHid(dev, "ACPI_FSB")) {
|
||||
} else if (acpi_MatchHid(h, "ACPI_FSB")) {
|
||||
device_set_desc(dev, "Sleep Button (fixed)");
|
||||
sc->button_type = ACPI_SLEEP_BUTTON;
|
||||
sc->fixed = 1;
|
||||
|
@ -291,8 +291,8 @@ acpi_cmbat_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
|
||||
static int
|
||||
acpi_cmbat_probe(device_t dev)
|
||||
{
|
||||
if (acpi_get_type(dev) == ACPI_TYPE_DEVICE &&
|
||||
!acpi_disabled("cmbat") && acpi_MatchHid(dev, "PNP0C0A")) {
|
||||
if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("cmbat")
|
||||
&& acpi_MatchHid(acpi_get_handle(dev), "PNP0C0A")) {
|
||||
|
||||
device_set_desc(dev, "Control Method Battery");
|
||||
return (0);
|
||||
|
@ -454,7 +454,7 @@ acpi_ec_probe(device_t dev)
|
||||
if (DEV_ECDT(dev)) {
|
||||
params = acpi_get_private(dev);
|
||||
ret = 0;
|
||||
} else if (acpi_MatchHid(dev, "PNP0C09")) {
|
||||
} else if (acpi_MatchHid(acpi_get_handle(dev), "PNP0C09")) {
|
||||
params = malloc(sizeof(struct acpi_ec_params), M_TEMP,
|
||||
M_WAITOK | M_ZERO);
|
||||
h = acpi_get_handle(dev);
|
||||
|
@ -90,11 +90,13 @@ MODULE_DEPEND(acpi_isab, acpi, 1, 1, 1);
|
||||
static int
|
||||
acpi_isab_probe(device_t dev)
|
||||
{
|
||||
ACPI_HANDLE h;
|
||||
|
||||
h = acpi_get_handle(dev);
|
||||
if (acpi_get_type(dev) == ACPI_TYPE_DEVICE &&
|
||||
!acpi_disabled("isa") &&
|
||||
devclass_get_device(isab_devclass, 0) == dev &&
|
||||
(acpi_MatchHid(dev, "PNP0A05") || acpi_MatchHid(dev, "PNP0A06"))) {
|
||||
(acpi_MatchHid(h, "PNP0A05") || acpi_MatchHid(h, "PNP0A06"))) {
|
||||
device_set_desc(dev, "ACPI Generic ISA bridge");
|
||||
return (0);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ static int
|
||||
acpi_lid_probe(device_t dev)
|
||||
{
|
||||
if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("lid") &&
|
||||
acpi_MatchHid(dev, "PNP0C0D")) {
|
||||
acpi_MatchHid(acpi_get_handle(dev), "PNP0C0D")) {
|
||||
|
||||
device_set_desc(dev, "Control Method Lid Switch");
|
||||
return (0);
|
||||
|
@ -117,7 +117,7 @@ acpi_pcib_acpi_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("pci") &&
|
||||
acpi_MatchHid(dev, "PNP0A03")) {
|
||||
acpi_MatchHid(acpi_get_handle(dev), "PNP0A03")) {
|
||||
|
||||
if (pci_cfgregopen() == 0)
|
||||
return (ENXIO);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ void acpi_EnterDebugger(void);
|
||||
#define ACPI_DEVINFO_PRESENT(x) (((x) & 0x9) == 9)
|
||||
BOOLEAN acpi_DeviceIsPresent(device_t dev);
|
||||
BOOLEAN acpi_BatteryIsPresent(device_t dev);
|
||||
BOOLEAN acpi_MatchHid(device_t dev, char *hid);
|
||||
BOOLEAN acpi_MatchHid(ACPI_HANDLE h, char *hid);
|
||||
ACPI_STATUS acpi_GetHandleInScope(ACPI_HANDLE parent, char *path,
|
||||
ACPI_HANDLE *result);
|
||||
uint32_t acpi_TimerDelta(uint32_t end, uint32_t start);
|
||||
@ -270,6 +270,8 @@ struct acpi_parse_resource_set {
|
||||
extern struct acpi_parse_resource_set acpi_res_parse_set;
|
||||
ACPI_STATUS acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
|
||||
struct acpi_parse_resource_set *set, void *arg);
|
||||
extern struct rman acpi_rman_io, acpi_rman_mem;
|
||||
struct resource_list_entry *acpi_sysres_find(int type, u_long addr);
|
||||
|
||||
/* ACPI event handling */
|
||||
UINT32 acpi_event_power_button_sleep(void *context);
|
||||
|
Loading…
x
Reference in New Issue
Block a user