Compartilhar via


Avaliando um método de controle sem argumentos de entrada

Para avaliar de forma síncrona um método de controle que não usa argumentos de entrada, um driver para um dispositivo envia uma solicitação IOCTL_ACPI_EVAL_METHOD ou uma solicitação de IOCTL_ACPI_EVAL_METHOD_EX para o dispositivo. O procedimento geral para usar essas duas solicitações é descrito em Avaliando métodos de controle ACPI de forma síncrona. A diferença específica entre o uso dessas duas solicitações é a seguinte:

  • Se o método de controle for um objeto filho imediato do dispositivo, o driver enviará uma solicitação IOCTL_ACPI_EVAL_METHOD e fornecerá uma estrutura de entrada ACPI_EVAL_INPUT_BUFFER .

  • Se o método de controle for um objeto filho no namespace ACPI do dispositivo, mas não for um objeto filho imediato do dispositivo, o driver enviará uma solicitação IOCTL_ACPI_EVAL_METHOD_EX e fornecerá uma estrutura ACPI_EVAL_INPUT_BUFFER_EX .

A função GetAbcData de exemplo fornecida neste tópico mostra como um driver para um dispositivo pode usar uma solicitação IOCTL_ACPI_EVAL_METHOD para avaliar um método de controle chamado "ABCD" compatível com o dispositivo. O método de controle 'ABCD' é um filho imediato do dispositivo no namespace ACPI e não aceita argumentos de entrada ou retorna argumentos de saída.

Se o método de controle 'ABCD' não for um objeto filho imediato, as alterações necessárias neste código de exemplo serão as seguintes:

  • Envie uma solicitação de IOCTL_ACPI_EVAL_METHOD_EX em vez de uma solicitação de IOCTL_ACPI_EVAL_METHOD.

  • Forneça uma estrutura ACPI_EVAL_INPUT_BUFFER_EX em vez de uma estrutura ACPI_EVAL_INPUT_BUFFER.

GetAbcData primeiro aloca um ACPI_EVAL_INPUT_BUFFER inputBuffer da estrutura e define o membro MethodNameAsUlong como o nome do método de controle e define o membro Signature como ACPI_EVAL_INPUT_BUFFER_SIGNATURE.

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

GetAbcData também aloca um ACPI_EVAL_OUTPUT_BUFFERde estrutura outputBuffer, mas não define nenhum dos membros do outputBuffer.

GetAbcData chama uma função fornecida pelo driver chamada SendDownStreamIrp que executa o seguinte:

  1. Chama IoBuildDeviceIoControlRequest para compilar a solicitação.

  2. Chama IoCallDriver para enviar a solicitação para baixo na pilha do dispositivo.

  3. Aguarda o gerente de E/S sinalizar ao driver que os drivers de nível inferior concluíram a solicitação.

SendDownStreamIrp retorna depois que o gerente de E/S sinaliza que os drivers de nível inferior concluíram a solicitação. O exemplo de código mencionado anteriormente executa o seguinte:

  1. Verifica o status da solicitação e retorna sem processamento adicional se os drivers de nível inferior não retornaram STATUS_SUCCESS.

  2. Verifica a validade dos argumentos de saída. Para que o outputBuffer contenha dados de saída válidos, a assinatura deve ser definida como ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE e Count deve ser definida como maior que zero.

  3. Processa os argumentos de saída que o driver ACPI passou de volta para o driver.

Embora essa etapa não esteja incluída no código de exemplo, o driver também deve chamar IoCompleteRequest depois de processar os dados de saída para concluir a solicitação de IOCTL_ACPI_EVAL_METHOD pendente ou IOCTL_ACPI_EVAL_METHOD solicitação que o driver enviou para avaliar um método de controle.

As estruturas de dados e as constantes de ACPI usadas no exemplo a seguir são definidas em 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;
}