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:
parent
ed010cdfa2
commit
074a57f560
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=128045
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user