tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

new acpi utility functions



Hi!

I want to add two new acpi utility functions
into sys/dev/acpi/acpi.c

They are needed for ACPI drivers I have
in my local tree.

Patch is attached.

Any Comments?

Christoph
# HG changeset patch
# User cegger%powermacg5.local@localhost
# Date 1258456092 -3600
common acpi utility routines
Add acpi_eval_set_integer() and acpi_find_pci_device().

diff -r 1f179103fad5 -r 61825534e7e6 sys/dev/acpi/acpi.c
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -1145,6 +1145,11 @@ acpi_fixed_button_pressed(void *context)
  * ACPI utility routines.
  *****************************************************************************/
 
+static const char * const acpi_pci_bus_ids[] = {
+        "PNP0A??",
+        NULL
+};
+
 /*
  * acpi_eval_integer:
  *
@@ -1163,13 +1168,32 @@ acpi_eval_integer(ACPI_HANDLE handle, co
        buf.Pointer = &param;
        buf.Length = sizeof(param);
 
-       rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, 
ACPI_TYPE_INTEGER);
+       rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf,
+           ACPI_TYPE_INTEGER);
        if (ACPI_SUCCESS(rv))
                *valp = param.Integer.Value;
 
        return rv;
 }
 
+ACPI_STATUS
+acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER arg)
+{
+       ACPI_OBJECT param_arg;
+       ACPI_OBJECT_LIST param_args;
+
+       if (handle == NULL)
+               handle = ACPI_ROOT_OBJECT;
+
+       param_arg.Type = ACPI_TYPE_INTEGER;
+       param_arg.Integer.Value = arg;
+
+       param_args.Count = 1;
+       param_args.Pointer = &param_arg;
+
+       return AcpiEvaluateObject(handle, path, &param_args, NULL);
+}
+
 /*
  * acpi_eval_string:
  *
@@ -1315,6 +1339,156 @@ acpi_match_hid(ACPI_DEVICE_INFO *ad, con
 }
 
 /*
+ * acpi_match_node_with_address:
+ *
+ *      Walker to find the ACPI node having a given address (_ADR).
+ */
+static ACPI_STATUS
+acpi_match_node_with_address(ACPI_HANDLE handle, UINT32 level,
+    void *context, void **retval)
+{
+       ACPI_INTEGER *addrp = context;
+       ACPI_HANDLE *hdlp = retval;
+       ACPI_STATUS rv;
+       ACPI_INTEGER val;
+
+       rv = acpi_eval_integer(handle, "_ADR", &val);
+       if (ACPI_FAILURE(rv))
+               return AE_OK;   /* Continue walk */
+       if (val != *addrp)
+               return AE_OK;   /* Continue walk */
+
+       /* Match found */
+       if (*hdlp != NULL)
+               /* Already found a match */
+               return AE_ALREADY_EXISTS;       /* Stop walk with error */
+
+       *hdlp = handle;
+       return AE_OK;           /* Continue walk to check unicity */
+}
+
+/*
+ * acpi_match_pci_bus:
+ *
+ *      Walker to find the ACPI node corresponding to a given PCI bus number.
+ */
+static ACPI_STATUS
+acpi_match_pci_bus(ACPI_HANDLE handle, UINT32 level,
+    void *context, void **retval)
+{
+       u_int *busp = context;
+       ACPI_HANDLE *hdlp = retval;
+       ACPI_STATUS rv;
+       ACPI_INTEGER bbn;
+       ACPI_HANDLE hdl;
+       ACPI_DEVICE_INFO *info;
+       bool id_match;
+
+       /*
+        * Check whether this is a PCI bus from the device's HID and CIDs.
+        */
+       id_match = false;
+       /* Get device info */
+       rv = AcpiGetObjectInfo(handle, &info);
+       if (ACPI_SUCCESS(rv)) {
+               id_match = acpi_match_hid(info, acpi_pci_bus_ids);
+               ACPI_FREE(info);
+       }
+
+       if (! id_match)
+               return AE_OK;           /* Continue walk */
+
+       /*
+        * We found a PCI bus, let us check whether it is the right number
+        */
+       bbn = 0;                        /* bus number is 0 by default */
+       if (ACPI_SUCCESS(AcpiGetHandle(handle, "_BBN", &hdl))) {
+               if (ACPI_FAILURE(acpi_eval_integer(handle, "_BBN", &bbn)))
+                       return AE_OK;   /* Continue walk */
+       }
+       if (bbn != *busp)
+               return AE_OK;           /* Continue walk */
+
+       /* Match found */
+       if (*hdlp != NULL)
+               /* Already found a match */
+               return AE_ALREADY_EXISTS;       /* Stop walk with error */
+
+       *hdlp = handle;
+       return AE_OK;                   /* Continue walk to check unicity */
+}
+
+/*
+ * acpi_find_pci_device:
+ *
+ *      Finds a PCI device in the ACPI name space.  The PCI device to look for
+ *      is given as a triple (bus, device, function).  The argument handlep
+ *      points to a location where the ACPI handle of the device will be 
written
+ *      if the device is (uniquely) found.
+ *
+ *      There is no straightforward way to match PCI devices.  This function
+ *      looks for an ACPI device that (1) is a descendant of the ACPI device
+ *      that corresponds to the given PCI bus, and (2) has an ACPI address
+ *      (_ADR) that is equal to: (device << 16) | function.  The return status
+ *      is either:
+ *      - AE_NOT_FOUND if no such device was found.
+ *      - AE_OK if one and only one such device was found.
+ *      - AE_ALREADY_EXISTS if multiple such devices were found.
+ */
+ACPI_STATUS
+acpi_find_pci_device(u_int bus, u_int device, u_int function,
+    ACPI_HANDLE *handlep)
+{
+       ACPI_STATUS rv;
+       ACPI_INTEGER addr;
+       ACPI_HANDLE hdl_bus, hdl;
+
+       hdl_bus = NULL;
+       rv = AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 100,
+           acpi_match_pci_bus, &bus, &hdl_bus);
+       if (ACPI_FAILURE(rv)) {
+               printf("%s: failure in ACPI namespace walk: %s\n",
+                   __func__, AcpiFormatException(rv));
+               return rv;
+       }
+
+       if (hdl_bus == NULL) {
+               printf("%s: couldn't find ACPI device for PCI bus: %u\n",
+                   __func__, bus);
+               return AE_NOT_FOUND;
+       }
+
+       addr = (device << 16) | function;
+
+       /*
+        * We walk the ACPI sub-tree of hdl_bus to find the device with address
+        * equal to addr.  Since AcpiWalkNamespace does not walk the given ACPI
+        * handle (only its children and their descendents), we first apply the
+        * walker function to hdl_bus.
+        */
+       hdl = NULL;
+       acpi_match_node_with_address(hdl_bus, 0, &addr, &hdl);
+       rv = AcpiWalkNamespace(ACPI_TYPE_DEVICE, hdl_bus, 100,
+           acpi_match_node_with_address, &addr, &hdl);
+       if (ACPI_FAILURE(rv)) {
+               printf("%s: failure in ACPI namespace walk: %s\n",
+                   __func__, AcpiFormatException(rv));
+               return rv;
+       }
+
+       if (hdl == NULL) {
+               printf("%s: couldn't find ACPI device for PCI: "
+                   "bus %u dev %u fun %u\n",
+                   __func__, bus, device, function);
+               return AE_NOT_FOUND;
+       }
+
+       *handlep = hdl;
+       return AE_OK;
+}
+
+
+/*
  * acpi_wake_gpe_helper
  *
  *     Set/unset GPE as both Runtime and Wake
diff -r 1f179103fad5 -r 61825534e7e6 sys/dev/acpi/acpivar.h
--- a/sys/dev/acpi/acpivar.h
+++ b/sys/dev/acpi/acpivar.h
@@ -267,6 +267,8 @@ void                acpi_set_wake_gpe(ACPI_HANDLE);
 void           acpi_clear_wake_gpe(ACPI_HANDLE);
 
 ACPI_STATUS    acpi_eval_integer(ACPI_HANDLE, const char *, ACPI_INTEGER *);
+ACPI_STATUS    acpi_eval_set_integer(ACPI_HANDLE handle, const char *path,
+                   ACPI_INTEGER arg);
 ACPI_STATUS    acpi_eval_string(ACPI_HANDLE, const char *, char **);
 ACPI_STATUS    acpi_eval_struct(ACPI_HANDLE, const char *, ACPI_BUFFER *);
 
@@ -276,6 +278,9 @@ ACPI_STATUS acpi_get(ACPI_HANDLE, ACPI_B
                    ACPI_STATUS (*)(ACPI_HANDLE, ACPI_BUFFER *));
 const char*    acpi_name(ACPI_HANDLE);
 
+ACPI_STATUS    acpi_find_pci_device(u_int bus, u_int device, u_int function,
+                   ACPI_HANDLE *handlep);
+
 ACPI_STATUS    acpi_resource_parse(device_t, ACPI_HANDLE, const char *,
                    void *, const struct acpi_resource_parse_ops *);
 void           acpi_resource_print(device_t, struct acpi_resources *);


Home | Main Index | Thread Index | Old Index