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/sched.h>
|
||||||
#include <sys/smp.h>
|
#include <sys/smp.h>
|
||||||
#include <sys/timetc.h>
|
#include <sys/timetc.h>
|
||||||
|
#include <sys/uuid.h>
|
||||||
|
|
||||||
#if defined(__i386__) || defined(__amd64__)
|
#if defined(__i386__) || defined(__amd64__)
|
||||||
#include <machine/clock.h>
|
#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,
|
static ACPI_STATUS acpi_device_eval_obj(device_t bus, device_t dev,
|
||||||
ACPI_STRING pathname, ACPI_OBJECT_LIST *parameters,
|
ACPI_STRING pathname, ACPI_OBJECT_LIST *parameters,
|
||||||
ACPI_BUFFER *ret);
|
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,
|
static ACPI_STATUS acpi_device_scan_cb(ACPI_HANDLE h, UINT32 level,
|
||||||
void *context, void **retval);
|
void *context, void **retval);
|
||||||
static ACPI_STATUS acpi_device_scan_children(device_t bus, device_t dev,
|
static ACPI_STATUS acpi_device_scan_children(device_t bus, device_t dev,
|
||||||
int max_depth, acpi_scan_cb_t user_fn, void *arg);
|
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,
|
static int acpi_isa_pnp_probe(device_t bus, device_t child,
|
||||||
struct isa_pnp_id *ids);
|
struct isa_pnp_id *ids);
|
||||||
static void acpi_platform_osc(device_t dev);
|
static void acpi_platform_osc(device_t dev);
|
||||||
@ -223,6 +227,7 @@ static device_method_t acpi_methods[] = {
|
|||||||
/* ACPI bus */
|
/* ACPI bus */
|
||||||
DEVMETHOD(acpi_id_probe, acpi_device_id_probe),
|
DEVMETHOD(acpi_id_probe, acpi_device_id_probe),
|
||||||
DEVMETHOD(acpi_evaluate_object, acpi_device_eval_obj),
|
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_pwr_for_sleep, acpi_device_pwr_for_sleep),
|
||||||
DEVMETHOD(acpi_scan_children, acpi_device_scan_children),
|
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,
|
SYSCTL_INT(_debug_acpi, OID_AUTO, suspend_bounce, CTLFLAG_RW,
|
||||||
&acpi_susp_bounce, 0, "Don't actually suspend, just test devices.");
|
&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
|
* 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.
|
* 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));
|
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
|
int
|
||||||
acpi_device_pwr_for_sleep(device_t bus, device_t dev, int *dstate)
|
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.
|
* Allocate a buffer with a preset data size.
|
||||||
*/
|
*/
|
||||||
|
@ -121,6 +121,27 @@ METHOD ACPI_STATUS evaluate_object {
|
|||||||
ACPI_BUFFER *ret;
|
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
|
# 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
|
# suspending/resuming. If a bus calls this when suspending a device, it
|
||||||
|
@ -90,6 +90,9 @@ struct acpi_device {
|
|||||||
int ad_flags;
|
int ad_flags;
|
||||||
int ad_cls_class;
|
int ad_cls_class;
|
||||||
|
|
||||||
|
ACPI_BUFFER dsd; /* Device Specific Data */
|
||||||
|
const ACPI_OBJECT *dsd_pkg;
|
||||||
|
|
||||||
/* Resources */
|
/* Resources */
|
||||||
struct resource_list ad_rl;
|
struct resource_list ad_rl;
|
||||||
};
|
};
|
||||||
@ -350,6 +353,8 @@ BOOLEAN acpi_DeviceIsPresent(device_t dev);
|
|||||||
BOOLEAN acpi_BatteryIsPresent(device_t dev);
|
BOOLEAN acpi_BatteryIsPresent(device_t dev);
|
||||||
ACPI_STATUS acpi_GetHandleInScope(ACPI_HANDLE parent, char *path,
|
ACPI_STATUS acpi_GetHandleInScope(ACPI_HANDLE parent, char *path,
|
||||||
ACPI_HANDLE *result);
|
ACPI_HANDLE *result);
|
||||||
|
ACPI_STATUS acpi_GetProperty(device_t dev, ACPI_STRING propname,
|
||||||
|
const ACPI_OBJECT **value);
|
||||||
ACPI_BUFFER *acpi_AllocBuffer(int size);
|
ACPI_BUFFER *acpi_AllocBuffer(int size);
|
||||||
ACPI_STATUS acpi_ConvertBufferToInteger(ACPI_BUFFER *bufp,
|
ACPI_STATUS acpi_ConvertBufferToInteger(ACPI_BUFFER *bufp,
|
||||||
UINT32 *number);
|
UINT32 *number);
|
||||||
@ -396,6 +401,13 @@ int acpi_MatchHid(ACPI_HANDLE h, const char *hid);
|
|||||||
#define ACPI_MATCHHID_HID 1
|
#define ACPI_MATCHHID_HID 1
|
||||||
#define ACPI_MATCHHID_CID 2
|
#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 {
|
struct acpi_parse_resource_set {
|
||||||
void (*set_init)(device_t dev, void *arg, void **context);
|
void (*set_init)(device_t dev, void *arg, void **context);
|
||||||
void (*set_done)(device_t dev, void *context);
|
void (*set_done)(device_t dev, void *context);
|
||||||
|
Loading…
Reference in New Issue
Block a user