1022 lines
27 KiB
C
1022 lines
27 KiB
C
/*++
|
||
|
||
Copyright (c) 1998 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
ACPI.C
|
||
|
||
Abstract:
|
||
|
||
This module contains code to execute ACPI
|
||
control methods
|
||
|
||
Author:
|
||
|
||
jdunn
|
||
|
||
Environment:
|
||
|
||
kernel mode only
|
||
|
||
Notes:
|
||
|
||
|
||
Revision History:
|
||
|
||
05-13-98 : created
|
||
|
||
--*/
|
||
#include <wdm.h>
|
||
#include <initguid.h>
|
||
#include <wdmguid.h>
|
||
#include <acpiioct.h>
|
||
#include "stdarg.h"
|
||
#include "stdio.h"
|
||
#include "dbci.h"
|
||
#include "dbcacpi.h"
|
||
|
||
|
||
ACPI_INTERFACE_STANDARD AcpiInterfaces;
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
// pagable functions
|
||
#pragma alloc_text(PAGE, DBCACPI_SyncAcpiCall)
|
||
#pragma alloc_text(PAGE, DBCACPI_ReadWriteDBCRegister)
|
||
#endif
|
||
|
||
|
||
NTSTATUS
|
||
DBCACPI_SyncAcpiCall(
|
||
IN PDEVICE_OBJECT Pdo,
|
||
IN ULONG Ioctl,
|
||
IN PVOID InputBuffer,
|
||
IN ULONG InputSize,
|
||
IN PVOID OutputBuffer,
|
||
IN ULONG OutputSize
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Called to send a request to the Pdo
|
||
|
||
Arguments:
|
||
|
||
Pdo - The request is sent to this device object
|
||
Ioctl - the request
|
||
InputBuffer - The incoming request
|
||
InputSize - The size of the incoming request
|
||
OutputBuffer - The answer
|
||
OutputSize - The size of the answer buffer
|
||
|
||
Return Value:
|
||
|
||
NT Status of the operation
|
||
|
||
--*/
|
||
{
|
||
IO_STATUS_BLOCK ioBlock;
|
||
KEVENT event;
|
||
NTSTATUS status;
|
||
PIRP irp;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Initialize an event to wait on
|
||
//
|
||
KeInitializeEvent( &event, SynchronizationEvent, FALSE );
|
||
|
||
//
|
||
// Build the request
|
||
//
|
||
irp = IoBuildDeviceIoControlRequest(
|
||
Ioctl,
|
||
Pdo,
|
||
InputBuffer,
|
||
InputSize,
|
||
OutputBuffer,
|
||
OutputSize,
|
||
FALSE,
|
||
&event,
|
||
&ioBlock
|
||
);
|
||
|
||
if (!irp) {
|
||
DBCACPI_KdPrint ((0, "'failed to allocate Irp\n"));
|
||
TRAP();
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
//
|
||
// Pass request to Pdo, always wait for completion routine
|
||
//
|
||
|
||
|
||
LOGENTRY(LOG_MISC, "ACP>", 0,irp, 0);
|
||
|
||
status = IoCallDriver(Pdo, irp);
|
||
if (status == STATUS_PENDING) {
|
||
|
||
//
|
||
// Wait for the irp to be completed, then grab the real status code
|
||
//
|
||
LOGENTRY(LOG_MISC, "ACPw", 0,irp, 0);
|
||
KeWaitForSingleObject(
|
||
&event,
|
||
Executive,
|
||
KernelMode,
|
||
FALSE,
|
||
NULL
|
||
);
|
||
|
||
status = ioBlock.Status;
|
||
LOGENTRY(LOG_MISC, "ACPk", 0, 0, status);
|
||
}
|
||
|
||
LOGENTRY(LOG_MISC, "ACP<", 0, 0, status);
|
||
//
|
||
// Done
|
||
//
|
||
DBCACPI_KdPrint((2, "'DBCACPI_SyncAcpiCall(%x)\n", status));
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
DBCACPI_BIOSControl(
|
||
PDEVICE_OBJECT DeviceObject,
|
||
BOOLEAN Enable
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Called to read or write a DBC register
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Device Object of DBC controller (FDO)
|
||
|
||
|
||
Return Value:
|
||
|
||
NT Status of the operation
|
||
|
||
--*/
|
||
{
|
||
PACPI_EVAL_INPUT_BUFFER_COMPLEX inputBuffer = NULL;
|
||
PACPI_EVAL_OUTPUT_BUFFER outputBuffer = NULL;
|
||
NTSTATUS ntStatus;
|
||
PACPI_METHOD_ARGUMENT readFlag;
|
||
ULONG inputSize, outputSize;
|
||
PDEVICE_EXTENSION deviceExtension;
|
||
PUCHAR outUChar;
|
||
PUSHORT outUShort;
|
||
PULONG outULong;
|
||
|
||
PAGED_CODE();
|
||
|
||
DBCACPI_KdPrint((2, "'DBCACPI_ControlBIOS\n"));
|
||
|
||
DBCACPI_IncrementIoCount(DeviceObject);
|
||
//
|
||
// Fill in the input data
|
||
//
|
||
|
||
// allow for one arg
|
||
|
||
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
||
inputSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
|
||
sizeof(ACPI_METHOD_ARGUMENT) * 1 ;
|
||
|
||
outputSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
|
||
sizeof(ACPI_EVAL_OUTPUT_BUFFER) * 1 ;
|
||
|
||
inputBuffer = ExAllocatePool(NonPagedPool, inputSize);
|
||
outputBuffer = ExAllocatePool(NonPagedPool, outputSize);
|
||
|
||
//
|
||
// Send the request
|
||
//
|
||
|
||
if ( inputBuffer && outputBuffer) {
|
||
|
||
// set up the input buffer
|
||
inputBuffer->MethodNameAsUlong = DBACPI_BCTR_METHOD;
|
||
|
||
inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
|
||
inputBuffer->ArgumentCount = 1;
|
||
inputBuffer->Size = inputSize; //??
|
||
|
||
// pack up the args
|
||
|
||
readFlag = &inputBuffer->Argument[0];
|
||
readFlag->Type = ACPI_METHOD_ARGUMENT_INTEGER;
|
||
readFlag->DataLength = sizeof(ULONG);
|
||
readFlag->Argument = (ULONG) Enable ? 1 : 0;
|
||
|
||
RtlZeroMemory(outputBuffer, outputSize);
|
||
|
||
#if DBG
|
||
#endif
|
||
|
||
ntStatus = DBCACPI_SyncAcpiCall(
|
||
deviceExtension->TopOfStackDeviceObject,
|
||
IOCTL_ACPI_EVAL_METHOD,
|
||
inputBuffer,
|
||
inputSize,
|
||
outputBuffer,
|
||
outputSize
|
||
);
|
||
|
||
if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) {
|
||
DBCACPI_KdPrint((0, "'method failed\n"));
|
||
TRAP();
|
||
ntStatus = STATUS_UNSUCCESSFUL;
|
||
} else {
|
||
|
||
DBCACPI_KdPrint((2, "'Status = %x Output Buffer: %x\n", ntStatus, outputBuffer));
|
||
DBCACPI_KdPrint((2, "'>Signature %x\n", outputBuffer->Signature));
|
||
DBCACPI_KdPrint((2, "'>Length %x\n", outputBuffer->Length));
|
||
DBCACPI_KdPrint((2, "'>Count %x\n", outputBuffer->Count));
|
||
|
||
DBCACPI_ASSERT(outputBuffer->Count == 1);
|
||
|
||
}
|
||
} else {
|
||
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
DBCACPI_DecrementIoCount(DeviceObject);
|
||
DBCACPI_KdPrint((2, "'DBCACPI_ControlBIOS(%x)\n", ntStatus));
|
||
|
||
return ntStatus;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
DBCACPI_ReadGuidRegister(
|
||
PDEVICE_OBJECT DeviceObject,
|
||
PVOID GuidData,
|
||
USHORT GuidDataLength,
|
||
ULONG Arg0
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Called to read DBC 1394 GUID register
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Device Object of DBC controller (FDO)
|
||
|
||
|
||
Return Value:
|
||
|
||
NT Status of the operation
|
||
|
||
--*/
|
||
{
|
||
PACPI_EVAL_INPUT_BUFFER_COMPLEX inputBuffer = NULL;
|
||
PACPI_EVAL_OUTPUT_BUFFER outputBuffer = NULL;
|
||
NTSTATUS ntStatus;
|
||
PACPI_METHOD_ARGUMENT readFlag;
|
||
ULONG inputSize, outputSize;
|
||
PDEVICE_EXTENSION deviceExtension;
|
||
PUCHAR outUChar;
|
||
PUSHORT outUShort;
|
||
PULONG outULong;
|
||
|
||
PAGED_CODE();
|
||
|
||
DBCACPI_KdPrint((2, "'DBCACPI_ReadGUIDRegister\n"));
|
||
|
||
DBCACPI_IncrementIoCount(DeviceObject);
|
||
//
|
||
// Fill in the input data
|
||
//
|
||
|
||
RtlZeroMemory(GuidData, GuidDataLength);
|
||
|
||
// allow for one arg
|
||
|
||
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
||
inputSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
|
||
sizeof(ACPI_METHOD_ARGUMENT) * 1 + GuidDataLength;
|
||
|
||
outputSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
|
||
sizeof(ACPI_EVAL_OUTPUT_BUFFER) * 1 + GuidDataLength;
|
||
|
||
inputBuffer = ExAllocatePool(NonPagedPool, inputSize);
|
||
outputBuffer = ExAllocatePool(NonPagedPool, outputSize);
|
||
|
||
outULong = GuidData;
|
||
|
||
//
|
||
// Send the request
|
||
//
|
||
|
||
if ( inputBuffer && outputBuffer) {
|
||
|
||
// set up the input buffer
|
||
inputBuffer->MethodNameAsUlong = DBACPI_GUID_METHOD;
|
||
inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
|
||
inputBuffer->ArgumentCount = 1;
|
||
inputBuffer->Size = inputSize; //??
|
||
|
||
// pack up the args
|
||
|
||
readFlag = &inputBuffer->Argument[0];
|
||
readFlag->Type = ACPI_METHOD_ARGUMENT_INTEGER;
|
||
readFlag->DataLength = sizeof(ULONG);
|
||
readFlag->Argument = (ULONG) Arg0;
|
||
|
||
RtlZeroMemory(outputBuffer, outputSize);
|
||
|
||
#if DBG
|
||
#endif
|
||
|
||
ntStatus = DBCACPI_SyncAcpiCall(
|
||
deviceExtension->TopOfStackDeviceObject,
|
||
IOCTL_ACPI_EVAL_METHOD,
|
||
inputBuffer,
|
||
inputSize,
|
||
outputBuffer,
|
||
outputSize
|
||
);
|
||
|
||
if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) {
|
||
DBCACPI_KdPrint((0, "'method failed\n"));
|
||
TRAP();
|
||
ntStatus = STATUS_UNSUCCESSFUL;
|
||
} else {
|
||
|
||
DBCACPI_KdPrint((2, "'Status = %x Output Buffer: %x\n", ntStatus, outputBuffer));
|
||
DBCACPI_KdPrint((2, "'>Signature %x\n", outputBuffer->Signature));
|
||
DBCACPI_KdPrint((2, "'>Length %x\n", outputBuffer->Length));
|
||
DBCACPI_KdPrint((2, "'>Count %x\n", outputBuffer->Count));
|
||
|
||
DBCACPI_ASSERT(outputBuffer->Count == 1);
|
||
|
||
DBCACPI_ASSERT(GuidDataLength == 4);
|
||
|
||
*outULong = outputBuffer->Argument[0].Argument;
|
||
|
||
DBCACPI_KdPrint((1, "'Guid Register (arg0 %d) - [%x]\n",
|
||
Arg0, *outULong));
|
||
|
||
}
|
||
} else {
|
||
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
DBCACPI_DecrementIoCount(DeviceObject);
|
||
DBCACPI_KdPrint((2, "'DBCACPI_ReadGUIDRegister(%x)\n", ntStatus));
|
||
|
||
|
||
return ntStatus;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
DBCACPI_ReadBayMapRegister(
|
||
PDEVICE_OBJECT DeviceObject,
|
||
BOOLEAN Usb,
|
||
PVOID BayData,
|
||
USHORT BayDataLength,
|
||
ULONG BayNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Called to read or write a DBC register
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Device Object of DBC controller (FDO)
|
||
|
||
|
||
Return Value:
|
||
|
||
NT Status of the operation
|
||
|
||
--*/
|
||
{
|
||
PACPI_EVAL_INPUT_BUFFER_COMPLEX inputBuffer = NULL;
|
||
PACPI_EVAL_OUTPUT_BUFFER outputBuffer = NULL;
|
||
NTSTATUS ntStatus;
|
||
PACPI_METHOD_ARGUMENT readFlag;
|
||
ULONG inputSize, outputSize;
|
||
PDEVICE_EXTENSION deviceExtension;
|
||
PUCHAR outUChar;
|
||
PUSHORT outUShort;
|
||
PULONG outULong;
|
||
|
||
PAGED_CODE();
|
||
|
||
DBCACPI_KdPrint((2, "'DBCACPI_ReadBayMapRegister\n"));
|
||
|
||
DBCACPI_IncrementIoCount(DeviceObject);
|
||
//
|
||
// Fill in the input data
|
||
//
|
||
|
||
RtlZeroMemory(BayData, BayDataLength);
|
||
|
||
// allow for one arg
|
||
|
||
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
||
inputSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
|
||
sizeof(ACPI_METHOD_ARGUMENT) * 1 + BayDataLength;
|
||
|
||
outputSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
|
||
sizeof(ACPI_EVAL_OUTPUT_BUFFER) * 1 + BayDataLength;
|
||
|
||
inputBuffer = ExAllocatePool(NonPagedPool, inputSize);
|
||
outputBuffer = ExAllocatePool(NonPagedPool, outputSize);
|
||
|
||
outULong = BayData;
|
||
|
||
//
|
||
// Send the request
|
||
//
|
||
|
||
if ( inputBuffer && outputBuffer) {
|
||
|
||
// set up the input buffer
|
||
if (Usb) {
|
||
inputBuffer->MethodNameAsUlong = DBACPI_BPMU_METHOD;
|
||
} else {
|
||
inputBuffer->MethodNameAsUlong = DBACPI_BPM3_METHOD;
|
||
}
|
||
|
||
inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
|
||
inputBuffer->ArgumentCount = 1;
|
||
inputBuffer->Size = inputSize; //??
|
||
|
||
// pack up the args
|
||
|
||
readFlag = &inputBuffer->Argument[0];
|
||
readFlag->Type = ACPI_METHOD_ARGUMENT_INTEGER;
|
||
readFlag->DataLength = sizeof(ULONG);
|
||
readFlag->Argument = (ULONG) BayNumber;
|
||
|
||
RtlZeroMemory(outputBuffer, outputSize);
|
||
|
||
#if DBG
|
||
#endif
|
||
|
||
ntStatus = DBCACPI_SyncAcpiCall(
|
||
deviceExtension->TopOfStackDeviceObject,
|
||
IOCTL_ACPI_EVAL_METHOD,
|
||
inputBuffer,
|
||
inputSize,
|
||
outputBuffer,
|
||
outputSize
|
||
);
|
||
|
||
if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) {
|
||
DBCACPI_KdPrint((0, "'method failed\n"));
|
||
TRAP();
|
||
ntStatus = STATUS_UNSUCCESSFUL;
|
||
} else {
|
||
|
||
DBCACPI_KdPrint((2, "'Status = %x Output Buffer: %x\n", ntStatus, outputBuffer));
|
||
DBCACPI_KdPrint((2, "'>Signature %x\n", outputBuffer->Signature));
|
||
DBCACPI_KdPrint((2, "'>Length %x\n", outputBuffer->Length));
|
||
DBCACPI_KdPrint((2, "'>Count %x\n", outputBuffer->Count));
|
||
|
||
DBCACPI_ASSERT(outputBuffer->Count == 1);
|
||
|
||
DBCACPI_ASSERT(BayDataLength == 4);
|
||
|
||
*outULong = outputBuffer->Argument[0].Argument;
|
||
|
||
if (Usb) {
|
||
DBCACPI_KdPrint((1, "'USB Bay Map Register (bay %d) - port[%x]\n",
|
||
BayNumber, *outULong));
|
||
} else {
|
||
DBCACPI_KdPrint((1, "'1394 Bay Map Register (bay %d) - port[%x]\n",
|
||
BayNumber, *outULong));
|
||
}
|
||
|
||
}
|
||
} else {
|
||
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
DBCACPI_DecrementIoCount(DeviceObject);
|
||
DBCACPI_KdPrint((2, "'DBCACPI_ReadBayRegister(%x)\n", ntStatus));
|
||
|
||
|
||
return ntStatus;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
DBCACPI_ReadBayReleaseRegister(
|
||
PDEVICE_OBJECT DeviceObject,
|
||
PULONG ReleaseOnShutdown
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Called to read or write a DBC register
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Device Object of DBC controller (FDO)
|
||
|
||
|
||
Return Value:
|
||
|
||
NT Status of the operation
|
||
|
||
--*/
|
||
{
|
||
PACPI_EVAL_INPUT_BUFFER_COMPLEX inputBuffer = NULL;
|
||
PACPI_EVAL_OUTPUT_BUFFER outputBuffer = NULL;
|
||
NTSTATUS ntStatus;
|
||
PACPI_METHOD_ARGUMENT readFlag;
|
||
ULONG inputSize, outputSize;
|
||
PDEVICE_EXTENSION deviceExtension;
|
||
PUCHAR outUChar;
|
||
PUSHORT outUShort;
|
||
PULONG outULong;
|
||
|
||
PAGED_CODE();
|
||
|
||
DBCACPI_KdPrint((2, "'DBCACPI_ReadBayReleaseRegister\n"));
|
||
|
||
DBCACPI_IncrementIoCount(DeviceObject);
|
||
//
|
||
// Fill in the input data
|
||
//
|
||
|
||
// allow for one arg
|
||
|
||
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
||
inputSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
|
||
sizeof(ACPI_METHOD_ARGUMENT) * 0;
|
||
|
||
outputSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
|
||
sizeof(ACPI_EVAL_OUTPUT_BUFFER) * 0;
|
||
|
||
inputBuffer = ExAllocatePool(NonPagedPool, inputSize);
|
||
outputBuffer = ExAllocatePool(NonPagedPool, outputSize);
|
||
|
||
outULong = ReleaseOnShutdown;
|
||
|
||
//
|
||
// Send the request
|
||
//
|
||
|
||
if ( inputBuffer && outputBuffer) {
|
||
|
||
// set up the input buffer
|
||
inputBuffer->MethodNameAsUlong = DBACPI_BREL_METHOD;
|
||
|
||
inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
|
||
inputBuffer->ArgumentCount = 0;
|
||
inputBuffer->Size = inputSize; //??
|
||
|
||
// pack up the args
|
||
|
||
// readFlag = &inputBuffer->Argument[0];
|
||
// readFlag->Type = ACPI_METHOD_ARGUMENT_INTEGER;
|
||
// readFlag->DataLength = sizeof(ULONG);
|
||
// readFlag->Argument = (ULONG) BayNumber;
|
||
|
||
RtlZeroMemory(outputBuffer, outputSize);
|
||
|
||
#if DBG
|
||
#endif
|
||
|
||
ntStatus = DBCACPI_SyncAcpiCall(
|
||
deviceExtension->TopOfStackDeviceObject,
|
||
IOCTL_ACPI_EVAL_METHOD,
|
||
inputBuffer,
|
||
inputSize,
|
||
outputBuffer,
|
||
outputSize
|
||
);
|
||
|
||
if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) {
|
||
DBCACPI_KdPrint((0, "'method failed %x\n"));
|
||
TRAP();
|
||
ntStatus = STATUS_UNSUCCESSFUL;
|
||
} else {
|
||
|
||
DBCACPI_KdPrint((2, "'Status = %x Output Buffer: %x\n", ntStatus, outputBuffer));
|
||
DBCACPI_KdPrint((2, "'>Signature %x\n", outputBuffer->Signature));
|
||
DBCACPI_KdPrint((2, "'>Length %x\n", outputBuffer->Length));
|
||
DBCACPI_KdPrint((2, "'>Count %x\n", outputBuffer->Count));
|
||
|
||
DBCACPI_ASSERT(outputBuffer->Count == 1);
|
||
|
||
*outULong = outputBuffer->Argument[0].Argument;
|
||
|
||
DBCACPI_KdPrint((1, "'BREL = %d\n", outULong));
|
||
|
||
}
|
||
} else {
|
||
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
DBCACPI_DecrementIoCount(DeviceObject);
|
||
DBCACPI_KdPrint((2, "'DBCACPI_ReadBayRegister(%x)\n", ntStatus));
|
||
|
||
|
||
return ntStatus;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
DBCACPI_ReadWriteDBCRegister(
|
||
PDEVICE_OBJECT DeviceObject,
|
||
ULONG RegisterOffset,
|
||
PVOID RegisterData,
|
||
USHORT RegisterDataLength,
|
||
BOOLEAN ReadRegister
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Called to read or write a DBC register
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Device Object of DBC controller (FDO)
|
||
RegisterOffset - offset of the register to read/write
|
||
RegisterData - ptr to register data to read or write
|
||
|
||
|
||
Return Value:
|
||
|
||
NT Status of the operation
|
||
|
||
--*/
|
||
{
|
||
PACPI_EVAL_INPUT_BUFFER_COMPLEX inputBuffer = NULL;
|
||
PACPI_EVAL_OUTPUT_BUFFER outputBuffer = NULL;
|
||
NTSTATUS ntStatus;
|
||
PACPI_METHOD_ARGUMENT readFlag;
|
||
PACPI_METHOD_ARGUMENT offset;
|
||
PACPI_METHOD_ARGUMENT reg;
|
||
ULONG inputSize, outputSize;
|
||
PDEVICE_EXTENSION deviceExtension;
|
||
PUCHAR outUChar;
|
||
PUSHORT outUShort;
|
||
PULONG outULong;
|
||
|
||
PAGED_CODE();
|
||
|
||
DBCACPI_IncrementIoCount(DeviceObject);
|
||
//
|
||
// Fill in the input data
|
||
//
|
||
|
||
if (ReadRegister) {
|
||
RtlZeroMemory(RegisterData, RegisterDataLength);
|
||
}
|
||
|
||
// allow for three args
|
||
|
||
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
||
inputSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
|
||
sizeof(ACPI_METHOD_ARGUMENT) * 2 + RegisterDataLength;
|
||
|
||
outputSize = sizeof(ACPI_EVAL_INPUT_BUFFER_COMPLEX) +
|
||
sizeof(ACPI_EVAL_OUTPUT_BUFFER) * 2 + RegisterDataLength;
|
||
|
||
inputBuffer = ExAllocatePool(NonPagedPool, inputSize);
|
||
outputBuffer = ExAllocatePool(NonPagedPool, outputSize);
|
||
|
||
outUChar = RegisterData;
|
||
outUShort = RegisterData;
|
||
outULong = RegisterData;
|
||
|
||
//
|
||
// Send the request
|
||
//
|
||
|
||
if ( inputBuffer && outputBuffer) {
|
||
|
||
// set up the input buffer
|
||
inputBuffer->MethodNameAsUlong = DBACPI_DBCC_METHOD;
|
||
inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE;
|
||
inputBuffer->ArgumentCount = 3;
|
||
inputBuffer->Size = inputSize; //??
|
||
|
||
// pack up the args
|
||
|
||
readFlag = &inputBuffer->Argument[0];
|
||
readFlag->Type = ACPI_METHOD_ARGUMENT_INTEGER;
|
||
readFlag->DataLength = sizeof(ULONG);
|
||
readFlag->Argument = (ULONG) ReadRegister;
|
||
|
||
offset = &inputBuffer->Argument[1];
|
||
offset->Type = ACPI_METHOD_ARGUMENT_INTEGER;
|
||
offset->DataLength = sizeof(ULONG);
|
||
offset->Argument = (ULONG) RegisterOffset;
|
||
|
||
// reg = &inputBuffer->Argument[2];
|
||
// reg->Type = ACPI_METHOD_ARGUMENT_BUFFER;
|
||
// reg->DataLength = RegisterDataLength;
|
||
// RtlCopyMemory(®->Data[0], RegisterData, RegisterDataLength);
|
||
|
||
// Compaq BIOS expects a ulong
|
||
reg = &inputBuffer->Argument[2];
|
||
reg->Type = ACPI_METHOD_ARGUMENT_INTEGER;
|
||
reg->DataLength = sizeof(ULONG);
|
||
switch (RegisterDataLength) {
|
||
case sizeof(UCHAR):
|
||
reg->Argument = (ULONG) *((UCHAR *) RegisterData);
|
||
break;
|
||
case sizeof(USHORT):
|
||
reg->Argument = (ULONG) *((USHORT *) RegisterData);
|
||
break;
|
||
case sizeof(ULONG):
|
||
reg->Argument = (ULONG) *((ULONG *) RegisterData);
|
||
break;
|
||
default:
|
||
TRAP();
|
||
}
|
||
|
||
RtlZeroMemory(outputBuffer, outputSize);
|
||
|
||
#if DBG
|
||
if (ReadRegister) {
|
||
DBCACPI_KdPrint((2, "'Read reg off %x\n", RegisterOffset));
|
||
} else {
|
||
DBCACPI_KdPrint((2, "'Write reg off 0x%0x val 0x%0x\n",
|
||
RegisterOffset, (ULONG) *((ULONG *) RegisterData)));
|
||
}
|
||
#endif
|
||
ntStatus = DBCACPI_SyncAcpiCall(
|
||
deviceExtension->TopOfStackDeviceObject,
|
||
IOCTL_ACPI_EVAL_METHOD,
|
||
inputBuffer,
|
||
inputSize,
|
||
outputBuffer,
|
||
outputSize
|
||
);
|
||
|
||
if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) {
|
||
DBCACPI_KdPrint((0, "'method failed\n"));
|
||
TRAP();
|
||
ntStatus = STATUS_UNSUCCESSFUL;
|
||
} else {
|
||
|
||
DBCACPI_KdPrint((2, "'Status = %x Output Buffer: %x\n", ntStatus, outputBuffer));
|
||
DBCACPI_KdPrint((2, "'>Signature %x\n", outputBuffer->Signature));
|
||
DBCACPI_KdPrint((2, "'>Length %x\n", outputBuffer->Length));
|
||
DBCACPI_KdPrint((2, "'>Count %x\n", outputBuffer->Count));
|
||
|
||
DBCACPI_ASSERT(outputBuffer->Count == 1);
|
||
|
||
//convert output
|
||
switch (RegisterDataLength) {
|
||
case sizeof(UCHAR):
|
||
*outUChar = (UCHAR) outputBuffer->Argument[0].Argument;
|
||
break;
|
||
case sizeof(USHORT):
|
||
*outUShort = (USHORT) outputBuffer->Argument[0].Argument;
|
||
break;
|
||
case sizeof(ULONG):
|
||
*outULong = outputBuffer->Argument[0].Argument;
|
||
break;
|
||
default:
|
||
TRAP();
|
||
}
|
||
|
||
}
|
||
} else {
|
||
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
DBCACPI_DecrementIoCount(DeviceObject);
|
||
DBCACPI_KdPrint((2, "'DBCACPI_ReadWriteDBCRegister(%x)\n", ntStatus));
|
||
|
||
|
||
return ntStatus;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
DBCACPI_GetAcpiInterfaces(
|
||
IN PDEVICE_OBJECT Pdo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Call ACPI driver to get the direct-call interfaces. It does
|
||
this the first time it is called, no more.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
Status
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||
PIRP irp;
|
||
PIO_STACK_LOCATION irpStack;
|
||
PDEVICE_OBJECT LowerPdo;
|
||
KEVENT event;
|
||
|
||
LowerPdo = IoGetAttachedDeviceReference(Pdo);
|
||
|
||
if (LowerPdo) {
|
||
//
|
||
// Allocate an IRP for below
|
||
//
|
||
irp = IoAllocateIrp (LowerPdo->StackSize, FALSE); // Get stack size from PDO
|
||
|
||
if (!irp) {
|
||
DBCACPI_KdPrint((0, "'Could not allocate Irp!\n"));
|
||
|
||
// decrement reference count
|
||
ObDereferenceObject(LowerPdo);
|
||
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
irpStack = IoGetNextIrpStackLocation(irp);
|
||
|
||
//
|
||
// Use QUERY_INTERFACE to get the address of the direct-call ACPI interfaces.
|
||
//
|
||
irpStack->MajorFunction = IRP_MJ_PNP;
|
||
irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
|
||
|
||
irpStack->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_ACPI_INTERFACE_STANDARD;
|
||
irpStack->Parameters.QueryInterface.Version = 1;
|
||
irpStack->Parameters.QueryInterface.Size = sizeof (AcpiInterfaces);
|
||
irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) &AcpiInterfaces;
|
||
irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
|
||
|
||
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
||
|
||
IoSetCompletionRoutine(irp,
|
||
DBCACPI_DeferIrpCompletion,
|
||
&event,
|
||
TRUE,
|
||
TRUE,
|
||
TRUE);
|
||
|
||
ntStatus = IoCallDriver (LowerPdo, irp);
|
||
|
||
if (ntStatus == STATUS_PENDING) {
|
||
// wait for irp to complete
|
||
|
||
TEST_TRAP(); // first time we hit this
|
||
|
||
KeWaitForSingleObject(
|
||
&event,
|
||
Suspended,
|
||
KernelMode,
|
||
FALSE,
|
||
NULL);
|
||
|
||
ntStatus = irp->IoStatus.Status;
|
||
}
|
||
|
||
IoFreeIrp (irp);
|
||
|
||
if (!NT_SUCCESS(ntStatus)) {
|
||
DBCACPI_KdPrint((0, "'Could not get ACPI interfaces!\n"));
|
||
TRAP();
|
||
}
|
||
} else {
|
||
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
return ntStatus;
|
||
}
|
||
|
||
|
||
VOID
|
||
DBCACPI_NotifyHandler (
|
||
IN PVOID Context,
|
||
IN ULONG NotifyValue
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine fields device notifications from the ACPI driver.
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
PDEVICE_OBJECT fdoDeviceObject = Context;
|
||
KIRQL oldIrql;
|
||
PDEVICE_EXTENSION deviceExtension;
|
||
PDBCACPI_WORKITEM workItem;
|
||
|
||
DBCACPI_KdPrint((0, "'DBC Notification (%x)\n", NotifyValue));
|
||
LOGENTRY(LOG_MISC, "Not+", 0, Context, 0);
|
||
|
||
// do we have a workitem scheduled?
|
||
|
||
deviceExtension = fdoDeviceObject->DeviceExtension;
|
||
DBCACPI_ASSERT_EXT(deviceExtension);
|
||
|
||
KeAcquireSpinLock(&deviceExtension->FlagsSpin, &oldIrql);
|
||
|
||
if (deviceExtension->Flags & DBCACPI_FLAG_WORKITEM_PENDING) {
|
||
// yes, bail
|
||
KeReleaseSpinLock(&deviceExtension->FlagsSpin, oldIrql);
|
||
} else {
|
||
// no, schedule one
|
||
DBCACPI_IncrementIoCount(fdoDeviceObject);
|
||
|
||
workItem = &deviceExtension->WorkItem;
|
||
deviceExtension->Flags |= DBCACPI_FLAG_WORKITEM_PENDING;
|
||
KeReleaseSpinLock(&deviceExtension->FlagsSpin, oldIrql);
|
||
|
||
workItem->Sig = DBC_WORKITEM_SIG;
|
||
|
||
ExInitializeWorkItem(&workItem->WorkQueueItem,
|
||
DBCACPI_NotifyWorker,
|
||
fdoDeviceObject);
|
||
|
||
ExQueueWorkItem(&workItem->WorkQueueItem,
|
||
DelayedWorkQueue);
|
||
}
|
||
|
||
LOGENTRY(LOG_MISC, "Not-", 0, Context, 0);
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
DBCACPI_RegisterWithACPI(
|
||
IN PDEVICE_OBJECT FdoDeviceObject,
|
||
IN BOOLEAN Register
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension;
|
||
NTSTATUS ntStatus = STATUS_SUCCESS;
|
||
|
||
deviceExtension = FdoDeviceObject->DeviceExtension;
|
||
|
||
if (Register) {
|
||
ntStatus = AcpiInterfaces.RegisterForDeviceNotifications (
|
||
|
||
deviceExtension->PhysicalDeviceObject,
|
||
#if 0
|
||
// this is needed on NT5
|
||
AcpiInterfaces.Context,
|
||
#endif
|
||
DBCACPI_NotifyHandler,
|
||
FdoDeviceObject);
|
||
} else {
|
||
AcpiInterfaces.UnregisterForDeviceNotifications (
|
||
deviceExtension->PhysicalDeviceObject,
|
||
|
||
#if 0
|
||
// this is needed on NT5
|
||
AcpiInterfaces.Context,
|
||
#endif
|
||
DBCACPI_NotifyHandler);
|
||
}
|
||
|
||
LOGENTRY(LOG_MISC, "rACP", Register, 0, ntStatus);
|
||
|
||
return ntStatus;
|
||
}
|
||
|
||
|