评估不带输入参数的控制方法

若要同步评估不采用输入参数的控制方法,设备的驱动程序应向设备发送 IOCTL_ACPI_EVAL_METHOD 请求或 IOCTL_ACPI_EVAL_METHOD_EX 请求。 同步评估 ACPI 控制方法中介绍了使用这两个请求的常规过程。 使用以下两个请求之间的具体区别如下:

  • 如果控制方法是设备的直接子对象,驱动程序会发送 IOCTL_ACPI_EVAL_METHOD 请求,并提供 ACPI_EVAL_INPUT_BUFFER 输入结构。

  • 如果控制方法是设备 ACPI 命名空间中的子对象,但不是设备的直接子对象,驱动程序会发送 IOCTL_ACPI_EVAL_METHOD_EX 请求,并提供 ACPI_EVAL_INPUT_BUFFER_EX 结构。

本主题中提供的示例 GetAbcData 函数演示了设备驱动程序如何使用 IOCTL_ACPI_EVAL_METHOD 请求,来评估设备支持的名为“ABCD”的控制方法。 “ABCD”控制方法是 ACPI 命名空间中设备的直接子级,并且不采用输入参数或返回输出参数。

如果“ABCD”控制方法不是直接子对象,则此示例代码所需的更改如下所示:

  • 发送 IOCTL_ACPI_EVAL_METHOD_EX 请求,而不是 IOCTL_ACPI_EVAL_METHOD 请求。

  • 提供 ACPI_EVAL_INPUT_BUFFER_EX 结构,而不是 ACPI_EVAL_INPUT_BUFFER 结构。

GetAbcData 首先分配 ACPI_EVAL_INPUT_BUFFER 结构 inputBuffer,将 MethodNameAsUlong 成员设置为控制方法的名称,并将 Signature 成员设置为 ACPI_EVAL_INPUT_BUFFER_SIGNATURE。

    // Fill in the input data
    inputBuffer.MethodNameAsUlong = (ULONG) ('DCBA');
    inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;

GetAbcData 还会分配 ACPI_EVAL_OUTPUT_BUFFER 结构 outputBuffer,但不会设置 outputBuffer 的任何成员。

然后,GetAbcData 会调用名为 SendDownStreamIrp 的驱动程序提供的函数,该函数将执行以下操作:

  1. 调用 IoBuildDeviceIoControlRequest 来生成请求。

  2. 调用 IoCallDriver 来将请求发送到设备堆栈。

  3. 等待 I/O 管理器向驱动程序发出较低级别驱动程序已完成请求的信号。

SendDownStreamIrp 会在 I/O 管理器指示较低级别驱动程序已完成请求后返回。 那么,上述代码示例将执行以下操作:

  1. 如果较低级别驱动程序未返回 STATUS_SUCCESS,则检查请求的状态并返回,而不执行其他处理。

  2. 检查输出参数的有效性。 若要使 outputBuffer 包含有效的输出数据,必须将 Signature 设置为 ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE,并且必须将 Count 设置为大于零。

  3. 处理 ACPI 驱动程序传回驱动程序的输出参数。

尽管此示例代码中不包含此步骤,但驱动程序还应在处理输出数据后调用 IoCompleteRequest,以完成驱动程序发送以评估控制方法的挂起 IOCTL_ACPI_EVAL_METHOD 请求或 IOCTL_ACPI_EVAL_METHOD 请求。

以下示例中使用的 ACPI 数据结构和常量已在 Acpiioct.h 中定义。

NTSTATUS
GetAbcdData(
    IN PDEVICE_OBJECT   Pdo,
    OUT PULONG          ReturnStatus
    )
/*++

Routine Description:
    Evaluates the ABCD method on the device in the ACPI namespace referenced by Pdo

Parameters
    Pdo             - PDO for the device
    ReturnStatus    - Pointer to where the status data is placed

Return Value:
    NT Status of the operation

--*/
{
    ACPI_EVAL_INPUT_BUFFER  inputBuffer;
    ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
    NTSTATUS                status;
    PACPI_METHOD_ARGUMENT   argument;

    .
    .

    ASSERT( ReturnStatus != NULL );
    *ReturnStatus = 0x0;

    // Fill in the input data
    inputBuffer.MethodNameAsUlong = (ULONG) ('DCBA');
    inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;

    // Send the request along
    status = SendDownStreamIrp(
       Pdo,
       IOCTL_ACPI_EVAL_METHOD,
       &inputBuffer,
       sizeof(ACPI_EVAL_INPUT_BUFFER),
       &outputBuffer,
       sizeof(ACPI_EVAL_OUTPUT_BUFFER)
       );

    if (!NT_SUCCESS(status)) {
       return status;
    }

    // Verify the data
    if (outputBuffer != NULL) {
        if ( ( (PACPI_EVAL_OUTPUT_BUFFER) outputBuffer->Signature != 
            ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
            ( (PACPI_EVAL_OUTPUT_BUFFER) outputBuffer->Count == 0) {
            return STATUS_ACPI_INVALID_DATA;
        } 
}

    // Retrieve the output argument
    argument = outputBuffer.Argument;
 
// Process the output argument
 .
.
.
 
    return status;
}