The branch stable/13 has been updated by mw:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=fd08253cdcec12ed4fd6cd47be69d978efc2f214

commit fd08253cdcec12ed4fd6cd47be69d978efc2f214
Author:     Bartlomiej Grzesik <b...@semihalf.com>
AuthorDate: 2021-07-27 12:39:31 +0000
Commit:     Marcin Wojtas <m...@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);

Reply via email to