acpica: add ACPI_GET_PROPERTY to access Device Specific Data (DSD)
Add lazy acquiring of DSD package, which allows accessing Device Specific Data. Reviewed by: manu, mw Sponsored by: Semihalf Differential revision: https://reviews.freebsd.org/D31596
This commit is contained in:
parent
34b1efcea1
commit
b91fc6c43a
@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sched.h>
|
||||
#include <sys/smp.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/uuid.h>
|
||||
|
||||
#if defined(__i386__) || defined(__amd64__)
|
||||
#include <machine/clock.h>
|
||||
@ -147,10 +148,13 @@ static int acpi_device_id_probe(device_t bus, device_t dev, char **ids, char **m
|
||||
static ACPI_STATUS acpi_device_eval_obj(device_t bus, device_t dev,
|
||||
ACPI_STRING pathname, ACPI_OBJECT_LIST *parameters,
|
||||
ACPI_BUFFER *ret);
|
||||
static ACPI_STATUS acpi_device_get_prop(device_t bus, device_t dev,
|
||||
ACPI_STRING propname, const ACPI_OBJECT **value);
|
||||
static ACPI_STATUS acpi_device_scan_cb(ACPI_HANDLE h, UINT32 level,
|
||||
void *context, void **retval);
|
||||
static ACPI_STATUS acpi_device_scan_children(device_t bus, device_t dev,
|
||||
int max_depth, acpi_scan_cb_t user_fn, void *arg);
|
||||
static ACPI_STATUS acpi_find_dsd(device_t bus, device_t dev);
|
||||
static int acpi_isa_pnp_probe(device_t bus, device_t child,
|
||||
struct isa_pnp_id *ids);
|
||||
static void acpi_platform_osc(device_t dev);
|
||||
@ -223,6 +227,7 @@ static device_method_t acpi_methods[] = {
|
||||
/* ACPI bus */
|
||||
DEVMETHOD(acpi_id_probe, acpi_device_id_probe),
|
||||
DEVMETHOD(acpi_evaluate_object, acpi_device_eval_obj),
|
||||
DEVMETHOD(acpi_get_property, acpi_device_get_prop),
|
||||
DEVMETHOD(acpi_pwr_for_sleep, acpi_device_pwr_for_sleep),
|
||||
DEVMETHOD(acpi_scan_children, acpi_device_scan_children),
|
||||
|
||||
@ -296,6 +301,15 @@ int acpi_susp_bounce;
|
||||
SYSCTL_INT(_debug_acpi, OID_AUTO, suspend_bounce, CTLFLAG_RW,
|
||||
&acpi_susp_bounce, 0, "Don't actually suspend, just test devices.");
|
||||
|
||||
/*
|
||||
* ACPI standard UUID for Device Specific Data Package
|
||||
* "Device Properties UUID for _DSD" Rev. 2.0
|
||||
*/
|
||||
static const struct uuid acpi_dsd_uuid = {
|
||||
0xdaffd814, 0x6eba, 0x4d8c, 0x8a, 0x91,
|
||||
{ 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 }
|
||||
};
|
||||
|
||||
/*
|
||||
* ACPI can only be loaded as a module by the loader; activating it after
|
||||
* system bootstrap time is not useful, and can be fatal to the system.
|
||||
@ -1727,6 +1741,82 @@ acpi_device_eval_obj(device_t bus, device_t dev, ACPI_STRING pathname,
|
||||
return (AcpiEvaluateObject(h, pathname, parameters, ret));
|
||||
}
|
||||
|
||||
static ACPI_STATUS
|
||||
acpi_device_get_prop(device_t bus, device_t dev, ACPI_STRING propname,
|
||||
const ACPI_OBJECT **value)
|
||||
{
|
||||
const ACPI_OBJECT *pkg, *name, *val;
|
||||
struct acpi_device *ad;
|
||||
ACPI_STATUS status;
|
||||
int i;
|
||||
|
||||
ad = device_get_ivars(dev);
|
||||
|
||||
if (ad == NULL || propname == NULL)
|
||||
return (AE_BAD_PARAMETER);
|
||||
if (ad->dsd_pkg == NULL) {
|
||||
if (ad->dsd.Pointer == NULL) {
|
||||
status = acpi_find_dsd(bus, dev);
|
||||
if (ACPI_FAILURE(status))
|
||||
return (status);
|
||||
} else {
|
||||
return (AE_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ad->dsd_pkg->Package.Count; i ++) {
|
||||
pkg = &ad->dsd_pkg->Package.Elements[i];
|
||||
if (pkg->Type != ACPI_TYPE_PACKAGE || pkg->Package.Count != 2)
|
||||
continue;
|
||||
|
||||
name = &pkg->Package.Elements[0];
|
||||
val = &pkg->Package.Elements[1];
|
||||
if (name->Type != ACPI_TYPE_STRING)
|
||||
continue;
|
||||
if (strncmp(propname, name->String.Pointer, name->String.Length) == 0) {
|
||||
if (value != NULL)
|
||||
*value = val;
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
}
|
||||
|
||||
return (AE_NOT_FOUND);
|
||||
}
|
||||
|
||||
static ACPI_STATUS
|
||||
acpi_find_dsd(device_t bus, device_t dev)
|
||||
{
|
||||
const ACPI_OBJECT *dsd, *guid, *pkg;
|
||||
struct acpi_device *ad;
|
||||
ACPI_STATUS status;
|
||||
|
||||
ad = device_get_ivars(dev);
|
||||
ad->dsd.Length = ACPI_ALLOCATE_BUFFER;
|
||||
ad->dsd.Pointer = NULL;
|
||||
ad->dsd_pkg = NULL;
|
||||
|
||||
status = ACPI_EVALUATE_OBJECT(bus, dev, "_DSD", NULL, &ad->dsd);
|
||||
if (ACPI_FAILURE(status))
|
||||
return (status);
|
||||
|
||||
dsd = ad->dsd.Pointer;
|
||||
guid = &dsd->Package.Elements[0];
|
||||
pkg = &dsd->Package.Elements[1];
|
||||
|
||||
if (guid->Type != ACPI_TYPE_BUFFER || pkg->Type != ACPI_TYPE_PACKAGE ||
|
||||
guid->Buffer.Length != sizeof(acpi_dsd_uuid))
|
||||
return (AE_NOT_FOUND);
|
||||
if (memcmp(guid->Buffer.Pointer, &acpi_dsd_uuid,
|
||||
sizeof(acpi_dsd_uuid)) == 0) {
|
||||
|
||||
ad->dsd_pkg = pkg;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
return (AE_NOT_FOUND);
|
||||
}
|
||||
|
||||
int
|
||||
acpi_device_pwr_for_sleep(device_t bus, device_t dev, int *dstate)
|
||||
{
|
||||
@ -2399,6 +2489,15 @@ acpi_GetHandleInScope(ACPI_HANDLE parent, char *path, ACPI_HANDLE *result)
|
||||
}
|
||||
}
|
||||
|
||||
ACPI_STATUS
|
||||
acpi_GetProperty(device_t dev, ACPI_STRING propname,
|
||||
const ACPI_OBJECT **value)
|
||||
{
|
||||
device_t bus = device_get_parent(dev);
|
||||
|
||||
return (ACPI_GET_PROPERTY(bus, dev, propname, value));
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a buffer with a preset data size.
|
||||
*/
|
||||
|
@ -121,6 +121,27 @@ METHOD ACPI_STATUS evaluate_object {
|
||||
ACPI_BUFFER *ret;
|
||||
};
|
||||
|
||||
#
|
||||
# Get property value from Device Specific Data
|
||||
#
|
||||
# device_t bus: parent bus for the device
|
||||
#
|
||||
# device_t dev: find property for this device's handle.
|
||||
#
|
||||
# const ACPI_STRING propname: name of the property
|
||||
#
|
||||
# const ACPI_OBJECT **value: property value output
|
||||
# Specify NULL if ignored
|
||||
#
|
||||
# Returns: AE_OK or an error value
|
||||
#
|
||||
METHOD ACPI_STATUS get_property {
|
||||
device_t bus;
|
||||
device_t dev;
|
||||
ACPI_STRING propname;
|
||||
const ACPI_OBJECT **value;
|
||||
};
|
||||
|
||||
#
|
||||
# Get the highest power state (D0-D3) that is usable for a device when
|
||||
# suspending/resuming. If a bus calls this when suspending a device, it
|
||||
|
@ -90,6 +90,9 @@ struct acpi_device {
|
||||
int ad_flags;
|
||||
int ad_cls_class;
|
||||
|
||||
ACPI_BUFFER dsd; /* Device Specific Data */
|
||||
const ACPI_OBJECT *dsd_pkg;
|
||||
|
||||
/* Resources */
|
||||
struct resource_list ad_rl;
|
||||
};
|
||||
@ -350,6 +353,8 @@ BOOLEAN acpi_DeviceIsPresent(device_t dev);
|
||||
BOOLEAN acpi_BatteryIsPresent(device_t dev);
|
||||
ACPI_STATUS acpi_GetHandleInScope(ACPI_HANDLE parent, char *path,
|
||||
ACPI_HANDLE *result);
|
||||
ACPI_STATUS acpi_GetProperty(device_t dev, ACPI_STRING propname,
|
||||
const ACPI_OBJECT **value);
|
||||
ACPI_BUFFER *acpi_AllocBuffer(int size);
|
||||
ACPI_STATUS acpi_ConvertBufferToInteger(ACPI_BUFFER *bufp,
|
||||
UINT32 *number);
|
||||
@ -396,6 +401,13 @@ int acpi_MatchHid(ACPI_HANDLE h, const char *hid);
|
||||
#define ACPI_MATCHHID_HID 1
|
||||
#define ACPI_MATCHHID_CID 2
|
||||
|
||||
static __inline bool
|
||||
acpi_HasProperty(device_t dev, ACPI_STRING propname)
|
||||
{
|
||||
|
||||
return ACPI_SUCCESS(acpi_GetProperty(dev, propname, NULL));
|
||||
}
|
||||
|
||||
struct acpi_parse_resource_set {
|
||||
void (*set_init)(device_t dev, void *arg, void **context);
|
||||
void (*set_done)(device_t dev, void *context);
|
||||
|
Loading…
Reference in New Issue
Block a user