|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: acpiutil.c
//
//--------------------------------------------------------------------------
#include "ideport.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(NONPAGE, DeviceQueryACPISettings)
#pragma alloc_text(NONPAGE, DeviceQueryACPISettingsCompletionRoutine)
#pragma alloc_text(NONPAGE, DeviceQueryFirmwareBootSettings)
#pragma alloc_text(NONPAGE, DeviceQueryChannelTimingSettings)
#pragma alloc_text(NONPAGE, ChannelSetACPITimingSettings)
#pragma alloc_text(NONPAGE, ChannelSyncSetACPITimingSettingsCompletionRoutine)
#pragma alloc_text(NONPAGE, ChannelSetACPITimingSettings)
#pragma alloc_text(NONPAGE, ChannelSetACPITimingSettingsCompletionRoutine)
#endif // ALLOC_PRAGMA
NTSTATUS DeviceQueryACPISettings ( IN PDEVICE_EXTENSION_HEADER DoExtension, IN ULONG ControlMethodName, OUT PACPI_EVAL_OUTPUT_BUFFER *QueryResult ) { PIRP irp; PIO_STACK_LOCATION irpSp; IO_STATUS_BLOCK ioStatusBlock; ACPI_EVAL_INPUT_BUFFER cmInputData; PACPI_EVAL_OUTPUT_BUFFER cmOutputData; ULONG cmOutputDataSize; NTSTATUS status; KEVENT event; ULONG retry; ULONG systemBufferLength; PDEVICE_OBJECT targetDeviceObject;
DebugPrint((DBG_ACPI, "ATAPI: ChannelQueryACPISettings for %c%c%c%c\n", ((PUCHAR)&ControlMethodName)[0], ((PUCHAR)&ControlMethodName)[1], ((PUCHAR)&ControlMethodName)[2], ((PUCHAR)&ControlMethodName)[3] ));
RtlZeroMemory ( &cmInputData, sizeof(cmInputData) );
cmInputData.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE; cmInputData.MethodNameAsUlong = ControlMethodName;
//
// get the top of our device stack
//
targetDeviceObject = IoGetAttachedDeviceReference( DoExtension->DeviceObject );
cmOutputDataSize = sizeof(ACPI_EVAL_OUTPUT_BUFFER); irp = NULL;
for (retry=0; retry<2; retry++) {
DebugPrint((DBG_ACPI, "ATAPI: _GTM try %x\n", retry));
cmOutputData = ExAllocatePool ( NonPagedPool, cmOutputDataSize ); if (cmOutputData == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; break; }
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoAllocateIrp(targetDeviceObject->StackSize, FALSE); if (irp == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; break; }
if (sizeof(cmInputData) > cmOutputDataSize) { systemBufferLength = sizeof(cmInputData); } else { systemBufferLength = cmOutputDataSize; }
irp->AssociatedIrp.SystemBuffer = ExAllocatePool( NonPagedPoolCacheAligned, systemBufferLength ); if (irp->AssociatedIrp.SystemBuffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; break; }
ASSERT ((IOCTL_ACPI_ASYNC_EVAL_METHOD & 0x3) == METHOD_BUFFERED); irp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION; irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
irpSp = IoGetNextIrpStackLocation( irp );
irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL; irpSp->Parameters.DeviceIoControl.OutputBufferLength = cmOutputDataSize; irpSp->Parameters.DeviceIoControl.InputBufferLength = sizeof(cmInputData); irpSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_ACPI_ASYNC_EVAL_METHOD;
RtlCopyMemory( irp->AssociatedIrp.SystemBuffer, &cmInputData, sizeof(cmInputData) );
irp->UserBuffer = cmOutputData;
IoSetCompletionRoutine( irp, DeviceQueryACPISettingsCompletionRoutine, &event, TRUE, TRUE, TRUE );
status = IoCallDriver(targetDeviceObject, irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = irp->IoStatus.Status; }
if (NT_SUCCESS(status)) {
//
// should get what we are expecting
//
ASSERT ( cmOutputData->Signature == ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ); if (cmOutputData->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) {
status = STATUS_UNSUCCESSFUL; } }
ExFreePool(irp->AssociatedIrp.SystemBuffer); IoFreeIrp(irp); irp = NULL;
if (!NT_SUCCESS(status)) {
//
// grab the data length in case we need it
//
cmOutputDataSize = cmOutputData->Length;
ExFreePool(cmOutputData); cmOutputData = NULL;
if (status == STATUS_BUFFER_OVERFLOW) {
//
// output buffer too small, try again
//
} else {
//
// got some error, no need to retry
//
break; } } }
//
// Clean up
//
ObDereferenceObject (targetDeviceObject);
if (irp) {
if (irp->AssociatedIrp.SystemBuffer) {
ExFreePool(irp->AssociatedIrp.SystemBuffer); } IoFreeIrp(irp); }
//
// returning
//
*QueryResult = cmOutputData; return status; } // ChannelQueryACPISettings
NTSTATUS DeviceQueryACPISettingsCompletionRoutine ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { PKEVENT event = Context;
if (!NT_ERROR(Irp->IoStatus.Status)) {
//
// Copy the information from the system
// buffer to the caller's buffer.
//
RtlCopyMemory( Irp->UserBuffer, Irp->AssociatedIrp.SystemBuffer, Irp->IoStatus.Information ); }
KeSetEvent( event, EVENT_INCREMENT, FALSE );
return STATUS_MORE_PROCESSING_REQUIRED; } // DeviceQueryACPISettingsCompletionRoutine
NTSTATUS DeviceQueryFirmwareBootSettings ( IN PPDO_EXTENSION PdoExtension, IN OUT PDEVICE_SETTINGS *IdeBiosSettings ) { NTSTATUS status; PACPI_EVAL_OUTPUT_BUFFER queryResult; PDEVICE_SETTINGS ideBiosSettings; ULONG i;
*IdeBiosSettings = NULL;
status = DeviceQueryACPISettings ( (PDEVICE_EXTENSION_HEADER) PdoExtension, ACPI_METHOD_GET_TASK_FILE, &queryResult );
if (NT_SUCCESS(status)) {
if (queryResult->Count != 1) {
ASSERT (queryResult->Count == 1); status = STATUS_UNSUCCESSFUL; } }
if (NT_SUCCESS(status)) {
PACPI_METHOD_ARGUMENT argument;
argument = queryResult->Argument;
//
// looking for buffer type
//
if (argument->Type == ACPI_METHOD_ARGUMENT_BUFFER) {
ULONG numEntries;
ASSERT (!(argument->DataLength % sizeof(ACPI_GTF_IDE_REGISTERS)));
numEntries = argument->DataLength / sizeof(ACPI_GTF_IDE_REGISTERS);
ideBiosSettings = ExAllocatePool ( NonPagedPool, sizeof(DEVICE_SETTINGS) + numEntries * sizeof(IDEREGS) ); if (!ideBiosSettings) {
DebugPrint((DBG_ALWAYS, "ATAPI: ChannelQueryFirmwareBootSettings failed to allocate memory\n")); status = STATUS_INSUFFICIENT_RESOURCES;
} else {
for (i=0; i<numEntries; i++) {
RtlMoveMemory ( ideBiosSettings->FirmwareSettings + i, argument->Data + i * sizeof(ACPI_GTF_IDE_REGISTERS), sizeof(ACPI_GTF_IDE_REGISTERS) );
ideBiosSettings->FirmwareSettings[i].bReserved = 0; }
ideBiosSettings->NumEntries = numEntries;
*IdeBiosSettings = ideBiosSettings;
#if DBG
{ ULONG i; DebugPrint((DBG_ACPI, "ATAPI: _GTF Data:\n")); for (i=0; i<ideBiosSettings->NumEntries; i++) { DebugPrint((DBG_ACPI, "\t")); DebugPrint((DBG_ACPI, " 0x%02x", ideBiosSettings->FirmwareSettings[i].bFeaturesReg)); DebugPrint((DBG_ACPI, " 0x%02x", ideBiosSettings->FirmwareSettings[i].bSectorCountReg)); DebugPrint((DBG_ACPI, " 0x%02x", ideBiosSettings->FirmwareSettings[i].bSectorNumberReg)); DebugPrint((DBG_ACPI, " 0x%02x", ideBiosSettings->FirmwareSettings[i].bCylLowReg)); DebugPrint((DBG_ACPI, " 0x%02x", ideBiosSettings->FirmwareSettings[i].bCylHighReg)); DebugPrint((DBG_ACPI, " 0x%02x", ideBiosSettings->FirmwareSettings[i].bDriveHeadReg)); DebugPrint((DBG_ACPI, " 0x%02x", ideBiosSettings->FirmwareSettings[i].bCommandReg)); DebugPrint((DBG_ACPI, "\n")); } } #endif
} } }
//
// clean up
//
if (queryResult) {
ExFreePool (queryResult); } return status; } // ChannelQueryFirmwareBootSettings
NTSTATUS DeviceQueryChannelTimingSettings ( IN PFDO_EXTENSION FdoExtension, IN OUT PACPI_IDE_TIMING TimimgSettings ) { NTSTATUS status; PACPI_EVAL_OUTPUT_BUFFER queryResult; PACPI_IDE_TIMING timimgSettings; ULONG i;
status = DeviceQueryACPISettings ( (PDEVICE_EXTENSION_HEADER) FdoExtension, ACPI_METHOD_GET_TIMING, &queryResult );
if (NT_SUCCESS(status)) {
if (queryResult->Count != 1) {
ASSERT (queryResult->Count == 1); status = STATUS_UNSUCCESSFUL; } }
if (NT_SUCCESS(status)) {
PACPI_METHOD_ARGUMENT argument;
//
// PIO Speed
//
argument = queryResult->Argument;
ASSERT (argument->Type == ACPI_METHOD_ARGUMENT_BUFFER); if ((argument->Type == ACPI_METHOD_ARGUMENT_BUFFER) && (argument->DataLength >= sizeof (ACPI_IDE_TIMING))) {
RtlCopyMemory ( TimimgSettings, argument->Data, sizeof(ACPI_IDE_TIMING) );
DebugPrint((DBG_ACPI, "ATAPI: _GTM Data:\n")); for (i=0; i<MAX_IDE_DEVICE; i++) { DebugPrint((DBG_ACPI, "\tPIO Speed %d: 0x%0x\n", i, TimimgSettings->Speed[i].Pio)); DebugPrint((DBG_ACPI, "\tDMA Speed %d: 0x%0x\n", i, TimimgSettings->Speed[i].Dma)); } DebugPrint((DBG_ACPI, "\tFlags: 0x%0x\n", TimimgSettings->Flags.AsULong));
//
// The following asserts are bogus. The ACPI spec doesn't say anything about the timing
// information for the slave device in this case
//
//if (!TimimgSettings->Flags.b.IndependentTiming) {
// ASSERT (TimimgSettings->Speed[MAX_IDE_DEVICE - 1].Pio == ACPI_XFER_MODE_NOT_SUPPORT);
// ASSERT (TimimgSettings->Speed[MAX_IDE_DEVICE - 1].Dma == ACPI_XFER_MODE_NOT_SUPPORT);
//}
} else {
status = STATUS_UNSUCCESSFUL; }
}
if (!NT_SUCCESS(status)) {
for (i=0; i<MAX_IDE_DEVICE; i++) {
TimimgSettings->Speed[i].Pio = ACPI_XFER_MODE_NOT_SUPPORT; TimimgSettings->Speed[i].Dma = ACPI_XFER_MODE_NOT_SUPPORT; } }
//
// clean up
//
if (queryResult) {
ExFreePool (queryResult); } return status; } // DeviceQueryChannelTimingSettings
NTSTATUS ChannelSyncSetACPITimingSettings ( IN PFDO_EXTENSION FdoExtension, IN PACPI_IDE_TIMING TimimgSettings, IN PIDENTIFY_DATA AtaIdentifyData[MAX_IDE_DEVICE] ) { SYNC_SET_ACPI_TIMING_CONTEXT context; NTSTATUS status;
KeInitializeEvent(&context.Event, NotificationEvent, FALSE);
status = ChannelSetACPITimingSettings ( FdoExtension, TimimgSettings, AtaIdentifyData, ChannelSyncSetACPITimingSettingsCompletionRoutine, &context );
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&context.Event, Executive, KernelMode, FALSE, NULL); }
return status = context.IrpStatus; }
NTSTATUS ChannelSyncSetACPITimingSettingsCompletionRoutine ( IN PDEVICE_OBJECT DeviceObject, IN NTSTATUS Status, IN PVOID Context ) { PSYNC_SET_ACPI_TIMING_CONTEXT context = Context;
context->IrpStatus = Status;
KeSetEvent( &context->Event, EVENT_INCREMENT, FALSE );
return STATUS_MORE_PROCESSING_REQUIRED; }
NTSTATUS ChannelSetACPITimingSettings ( IN PFDO_EXTENSION FdoExtension, IN PACPI_IDE_TIMING TimimgSettings, IN PIDENTIFY_DATA AtaIdentifyData[MAX_IDE_DEVICE], IN PSET_ACPI_TIMING_COMPLETION_ROUTINE CallerCompletionRoutine, IN PVOID CallerContext ) { ULONG i; PIRP irp; NTSTATUS status; PDEVICE_OBJECT targetDeviceObject;
PACPI_EVAL_INPUT_BUFFER_COMPLEX cmInputData; ULONG cmInputDataSize; PACPI_METHOD_ARGUMENT argument; PASYNC_SET_ACPI_TIMING_CONTEXT context;
PIO_STACK_LOCATION irpSp;
DebugPrint((DBG_ACPI, "ATAPI: ChannelSetACPITimingSettings _STM data\n" )); for (i=0; i<MAX_IDE_DEVICE; i++) { DebugPrint((DBG_ACPI, "\tPIO Speed %d: 0x%0x\n", i, TimimgSettings->Speed[i].Pio)); DebugPrint((DBG_ACPI, "\tDMA Speed %d: 0x%0x\n", i, TimimgSettings->Speed[i].Dma)); } DebugPrint((DBG_ACPI, "\tFlags: 0x%0x\n", TimimgSettings->Flags.AsULong));
cmInputData = NULL; irp = NULL; targetDeviceObject = NULL;
//
// get the memory we need
//
cmInputDataSize = sizeof (ACPI_EVAL_INPUT_BUFFER_COMPLEX) + 3 * sizeof (ACPI_METHOD_ARGUMENT) + sizeof (ACPI_IDE_TIMING) + 2 * sizeof (IDENTIFY_DATA);
cmInputData = ExAllocatePool ( NonPagedPool, cmInputDataSize + sizeof (ASYNC_SET_ACPI_TIMING_CONTEXT) );
if (cmInputData == NULL) { status=STATUS_INSUFFICIENT_RESOURCES; goto getout; }
RtlZeroMemory ( cmInputData, cmInputDataSize + sizeof (ASYNC_SET_ACPI_TIMING_CONTEXT) );
context = (PASYNC_SET_ACPI_TIMING_CONTEXT) (((PUCHAR) cmInputData) + cmInputDataSize); context->FdoExtension = FdoExtension; context->CallerCompletionRoutine = CallerCompletionRoutine; context->CallerContext = CallerContext;
cmInputData->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE; cmInputData->MethodNameAsUlong = ACPI_METHOD_SET_TIMING; cmInputData->Size = cmInputDataSize; cmInputData->ArgumentCount = 3;
//
// first argument
//
argument = cmInputData->Argument;
argument->Type = ACPI_METHOD_ARGUMENT_BUFFER; argument->DataLength = sizeof(ACPI_IDE_TIMING); RtlCopyMemory ( argument->Data, TimimgSettings, sizeof(ACPI_IDE_TIMING) ); argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
//
// second argument
//
argument->Type = ACPI_METHOD_ARGUMENT_BUFFER;
if (AtaIdentifyData[0]) {
argument->DataLength = sizeof(IDENTIFY_DATA); RtlCopyMemory ( argument->Data, AtaIdentifyData[0], sizeof(IDENTIFY_DATA) );
argument = ACPI_METHOD_NEXT_ARGUMENT(argument);
} else {
argument->DataLength = sizeof(IDENTIFY_DATA); RtlZeroMemory ( argument->Data, sizeof(IDENTIFY_DATA) );
argument = ACPI_METHOD_NEXT_ARGUMENT(argument); }
//
// third argument
//
argument->Type = ACPI_METHOD_ARGUMENT_BUFFER; if (AtaIdentifyData[1]) {
argument->DataLength = sizeof(IDENTIFY_DATA); RtlCopyMemory ( argument->Data, AtaIdentifyData[1], sizeof(IDENTIFY_DATA) ); } else {
argument->DataLength = sizeof(IDENTIFY_DATA); RtlZeroMemory ( argument->Data, sizeof(IDENTIFY_DATA) ); }
//
// get the top of our device stack
//
targetDeviceObject = IoGetAttachedDeviceReference( FdoExtension->DeviceObject );
irp = IoAllocateIrp(targetDeviceObject->StackSize, FALSE); if (irp == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto getout; }
irp->AssociatedIrp.SystemBuffer = cmInputData;
ASSERT ((IOCTL_ACPI_ASYNC_EVAL_METHOD & 0x3) == METHOD_BUFFERED); irp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION; irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
irpSp = IoGetNextIrpStackLocation( irp );
irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL; irpSp->Parameters.DeviceIoControl.OutputBufferLength = 0; irpSp->Parameters.DeviceIoControl.InputBufferLength = cmInputDataSize; irpSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_ACPI_ASYNC_EVAL_METHOD;
irp->UserBuffer = NULL;
IoSetCompletionRoutine( irp, ChannelSetACPITimingSettingsCompletionRoutine, context, TRUE, TRUE, TRUE );
IoCallDriver(targetDeviceObject, irp);
status = STATUS_PENDING;
getout: //
// Clean up
//
if (targetDeviceObject) {
ObDereferenceObject (targetDeviceObject); }
if (!NT_SUCCESS(status) && (status != STATUS_PENDING)) {
if (irp) {
IoFreeIrp(irp); }
if (cmInputData) { ExFreePool (cmInputData); } }
//
// returning
//
return status;
} // ChannelSetACPITimingSettings
NTSTATUS ChannelSetACPITimingSettingsCompletionRoutine ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { PASYNC_SET_ACPI_TIMING_CONTEXT context = Context;
if (!NT_SUCCESS(Irp->IoStatus.Status)) {
DebugPrint ((DBG_ALWAYS, "*********************************************\n" "*********************************************\n" "** *\n" "** ACPI Set Timing Failed with status %x *\n" "** Ignore it for now *\n" "** *\n" "*********************************************\n" "*********************************************\n", Irp->IoStatus.Status ));
Irp->IoStatus.Status = STATUS_SUCCESS; }
(*context->CallerCompletionRoutine) ( DeviceObject, Irp->IoStatus.Status, context->CallerContext );
ExFreePool (Irp->AssociatedIrp.SystemBuffer); IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED; }
|