1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-18 10:35:55 +00:00

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.
This commit is contained in:
Nate Lawson 2004-04-09 06:40:03 +00:00
parent ed010cdfa2
commit 074a57f560
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=128045
2 changed files with 69 additions and 31 deletions

View File

@ -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)) {
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.
*/
if (res->Package.Elements[1].Type != ACPI_TYPE_INTEGER)
goto out;
if (sc->acpi_sstate > res->Package.Elements[1].Integer.Value)
if (!ACPI_PKG_VALID(res, 2))
goto out;
/*
* The element 0 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.
*/
switch(res->Package.Elements[0].Type) {
if (acpi_PkgInt32(res, 1, &lowest_wake) != 0)
goto out;
if (sc->acpi_sstate > lowest_wake)
goto out;
/*
* Element 0 of the _PRW object:
*/
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;

View File

@ -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);
}