diff options
author | njl <njl@FreeBSD.org> | 2004-04-09 06:40:03 +0000 |
---|---|---|
committer | njl <njl@FreeBSD.org> | 2004-04-09 06:40:03 +0000 |
commit | fdef51d350162407b1fd7503b09214a6d4201b40 (patch) | |
tree | c67ca9eed3ef6080288b20a150a2891329627e30 /sys/dev/acpica | |
parent | 34d7e07971263d7e996c84f5971b079f7f476f37 (diff) | |
download | FreeBSD-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/acpica')
-rw-r--r-- | sys/dev/acpica/acpi.c | 59 | ||||
-rw-r--r-- | sys/dev/acpica/acpi_package.c | 31 |
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); +} |