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 = ¶m;
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 = ¶m_arg;
+
+ return AcpiEvaluateObject(handle, path, ¶m_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