git: fd08253cdcec - stable/13 - acpica: add ACPI_GET_PROPERTY to access Device Specific Data (DSD)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 29 Mar 2022 22:59:53 UTC
The branch stable/13 has been updated by mw: URL: https://cgit.FreeBSD.org/src/commit/?id=fd08253cdcec12ed4fd6cd47be69d978efc2f214 commit fd08253cdcec12ed4fd6cd47be69d978efc2f214 Author: Bartlomiej Grzesik <bag@semihalf.com> AuthorDate: 2021-07-27 12:39:31 +0000 Commit: Marcin Wojtas <mw@FreeBSD.org> CommitDate: 2022-03-29 22:24:25 +0000 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 (cherry picked from commit b91fc6c43a81d3b760fb570c8439a922e536d7e6) --- sys/dev/acpica/acpi.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ sys/dev/acpica/acpi_if.m | 21 ++++++++++ sys/dev/acpica/acpivar.h | 12 ++++++ 3 files changed, 132 insertions(+) diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index c1b79fb15727..8cbd916634b0 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -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. @@ -1733,6 +1747,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) { @@ -2405,6 +2495,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. */ diff --git a/sys/dev/acpica/acpi_if.m b/sys/dev/acpica/acpi_if.m index 6e36f398411e..e0ed4d72e899 100644 --- a/sys/dev/acpica/acpi_if.m +++ b/sys/dev/acpica/acpi_if.m @@ -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 diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index fb568169cf28..f53adaa1d834 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -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);