summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-04-09 06:40:03 +0000
committernjl <njl@FreeBSD.org>2004-04-09 06:40:03 +0000
commitfdef51d350162407b1fd7503b09214a6d4201b40 (patch)
treec67ca9eed3ef6080288b20a150a2891329627e30 /sys/dev
parent34d7e07971263d7e996c84f5971b079f7f476f37 (diff)
downloadFreeBSD-src-fdef51d350162407b1fd7503b09214a6d4201b40.zip
FreeBSD-src-fdef51d350162407b1fd7503b09214a6d4201b40.tar.gz
Add support for packages as the first element of _PRW. This may allow
some machines to enable wake events for more devices although I haven't seen a system yet that uses this form. Also, introduce acpi_GetReference() which retrieves an object reference from various types.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpica/acpi.c59
-rw-r--r--sys/dev/acpica/acpi_package.c31
2 files changed, 64 insertions, 26 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 4b3a45e..83b76a9 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -1983,9 +1983,11 @@ void
acpi_device_enable_wake_event(ACPI_HANDLE h)
{
struct acpi_softc *sc;
+ uint32_t gpe_bit, lowest_wake;
+ ACPI_HANDLE handle;
ACPI_STATUS status;
ACPI_BUFFER prw_buffer;
- ACPI_OBJECT *res;
+ ACPI_OBJECT *res, *res2;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -1994,67 +1996,72 @@ acpi_device_enable_wake_event(ACPI_HANDLE h)
return;
/*
- * _PRW object is only required for devices that have the ability
- * to wake the system from a system sleeping state.
+ * The _PRW object (7.2.9) is only required for devices that have the
+ * ability to wake the system from a sleeping state.
*/
+ prw_buffer.Pointer = NULL;
prw_buffer.Length = ACPI_ALLOCATE_BUFFER;
status = AcpiEvaluateObject(h, "_PRW", NULL, &prw_buffer);
if (ACPI_FAILURE(status))
return;
-
res = (ACPI_OBJECT *)prw_buffer.Pointer;
if (res == NULL)
return;
-
- if ((res->Type != ACPI_TYPE_PACKAGE) || (res->Package.Count < 2)) {
+ if (!ACPI_PKG_VALID(res, 2))
goto out;
- }
/*
- * The element 1 of the _PRW object:
- * The lowest power system sleeping state that can be entered
- * while still providing wake functionality.
- * The sleeping state being entered must be greater or equal to
- * the power state declared in element 1 of the _PRW object.
+ * Element 1 of the _PRW object:
+ * The lowest power system sleeping state that can be entered while still
+ * providing wake functionality. The sleeping state being entered must
+ * be less than (i.e., higher power) or equal to this value.
*/
- if (res->Package.Elements[1].Type != ACPI_TYPE_INTEGER)
+ if (acpi_PkgInt32(res, 1, &lowest_wake) != 0)
goto out;
-
- if (sc->acpi_sstate > res->Package.Elements[1].Integer.Value)
+ if (sc->acpi_sstate > lowest_wake)
goto out;
/*
- * The element 0 of the _PRW object:
+ * Element 0 of the _PRW object:
*/
- switch(res->Package.Elements[0].Type) {
+ switch (res->Package.Elements[0].Type) {
case ACPI_TYPE_INTEGER:
- /*
+ /*
* If the data type of this package element is numeric, then this
* _PRW package element is the bit index in the GPEx_EN, in the
* GPE blocks described in the FADT, of the enable bit that is
* enabled for the wake event.
*/
-
- status = AcpiEnableGpe(NULL, res->Package.Elements[0].Integer.Value,
- ACPI_EVENT_WAKE_ENABLE);
+ gpe_bit = res->Package.Elements[0].Integer.Value;
+ status = AcpiEnableGpe(NULL, gpe_bit, ACPI_EVENT_WAKE_ENABLE);
if (ACPI_FAILURE(status))
- printf("%s: EnableEvent Failed\n", __func__);
+ printf("wake enable: AcpiEnableGpe failed for %u\n",
+ gpe_bit);
break;
case ACPI_TYPE_PACKAGE:
/*
- * XXX TBD
- *
* If the data type of this package element is a package, then this
* _PRW package element is itself a package containing two
- * elements. The first is an object reference to the GPE Block
+ * elements. The first is an object reference to the GPE Block
* device that contains the GPE that will be triggered by the wake
- * event. The second element is numeric and it contains the bit
+ * event. The second element is numeric and it contains the bit
* index in the GPEx_EN, in the GPE Block referenced by the
* first element in the package, of the enable bit that is enabled for
* the wake event.
+ *
* For example, if this field is a package then it is of the form:
* Package() {\_SB.PCI0.ISA.GPE, 2}
*/
+ res2 = &res->Package.Elements[0];
+ if (!ACPI_PKG_VALID(res2, 2))
+ goto out;
+ handle = acpi_GetReference(NULL, &res2->Package.Elements[0]);
+ if (handle == NULL || acpi_PkgInt32(res2, 1, &gpe_bit) != 0)
+ goto out;
+ status = AcpiEnableGpe(handle, gpe_bit, ACPI_EVENT_WAKE_ENABLE);
+ if (ACPI_FAILURE(status))
+ printf("wake enable: AcpiEnableGpe (package) failed for %u\n",
+ gpe_bit);
break;
default:
break;
diff --git a/sys/dev/acpica/acpi_package.c b/sys/dev/acpica/acpi_package.c
index 0011308..41f7581 100644
--- a/sys/dev/acpica/acpi_package.c
+++ b/sys/dev/acpica/acpi_package.c
@@ -123,3 +123,34 @@ acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *rid,
return (0);
}
+
+ACPI_HANDLE
+acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj)
+{
+ ACPI_HANDLE h;
+
+ if (obj == NULL)
+ return (NULL);
+
+ switch (obj->Type) {
+ case ACPI_TYPE_LOCAL_REFERENCE:
+ case ACPI_TYPE_ANY:
+ h = obj->Reference.Handle;
+ break;
+ case ACPI_TYPE_STRING:
+ /*
+ * The String object usually contains a fully-qualified path, so
+ * scope can be NULL.
+ *
+ * XXX This may not always be the case.
+ */
+ if (ACPI_FAILURE(AcpiGetHandle(scope, obj->String.Pointer, &h)))
+ h = NULL;
+ break;
+ default:
+ h = NULL;
+ break;
+ }
+
+ return (h);
+}
OpenPOWER on IntegriCloud