2481 lines
58 KiB
C
2481 lines
58 KiB
C
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
root.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the root FDO handler for the NT Driver
|
||
|
||
Author:
|
||
|
||
Stephane Plante (splante)
|
||
|
||
Environment:
|
||
|
||
NT Kernel Model Driver only
|
||
|
||
Revision History:
|
||
|
||
July-09-97 Added support to Unify QueryDeviceRelations from filter.c
|
||
|
||
--*/
|
||
|
||
#include "pch.h"
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE, ACPIRootIrpCancelRemoveOrStopDevice)
|
||
#pragma alloc_text(PAGE, ACPIRootIrpQueryBusRelations)
|
||
#pragma alloc_text(PAGE, ACPIRootIrpQueryCapabilities)
|
||
#pragma alloc_text(PAGE, ACPIRootIrpQueryDeviceRelations)
|
||
#pragma alloc_text(PAGE, ACPIRootIrpQueryRemoveOrStopDevice)
|
||
#pragma alloc_text(PAGE, ACPIRootIrpStartDevice)
|
||
#pragma alloc_text(PAGE, ACPIRootIrpStopDevice)
|
||
#pragma alloc_text(PAGE, ACPIRootIrpQueryInterface)
|
||
#endif
|
||
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpCancelRemoveOrStopDevice(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine transitions the device from the inactive to the
|
||
started state
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - The target
|
||
Irp - The request
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
||
UCHAR minorFunction = irpStack->MinorFunction;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Where we allowed to stop the device? If so, then undo whatever it
|
||
// was we did, otherwise let the world know about the cancel
|
||
//
|
||
|
||
if (!(deviceExtension->Flags & DEV_CAP_NO_STOP) ) {
|
||
|
||
//
|
||
// Check to see if we have placed this device in the inactive state
|
||
//
|
||
if (deviceExtension->DeviceState == Inactive) {
|
||
|
||
//
|
||
// Mark the device state to its previous state
|
||
//
|
||
deviceExtension->DeviceState = deviceExtension->PreviousState;
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
//
|
||
// We are successfull
|
||
//
|
||
Irp->IoStatus.Status = status;
|
||
|
||
//
|
||
// Pass the Irp Along
|
||
//
|
||
Irp->IoStatus.Status = STATUS_SUCCESS ;
|
||
IoSkipCurrentIrpStackLocation( Irp );
|
||
status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
|
||
|
||
//
|
||
// Done
|
||
//
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(%#08lx): %s = %#08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
status
|
||
) );
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpCompleteRoutine(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp,
|
||
IN PVOID Context
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the routine that is called when one of the IRPS that was
|
||
noticed by ACPIRootIrp* and was judged to be an IRP that we need
|
||
to examine later on...
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - A pointer to the Filter Object
|
||
Irp - A pointer to the completed request
|
||
Context - Whatever Irp-dependent information we need to know
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
--*/
|
||
{
|
||
PKEVENT event = (PKEVENT) Context;
|
||
#if DBG
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
||
|
||
if (deviceExtension != NULL) {
|
||
|
||
//
|
||
// Let the world know what we just got...
|
||
//
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(%#08lx): %s = %#08lx (Complete)\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, irpStack->MinorFunction),
|
||
Irp->IoStatus.Status
|
||
) );
|
||
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Signal the event
|
||
//
|
||
KeSetEvent( event, IO_NO_INCREMENT, FALSE );
|
||
|
||
//
|
||
// Always return MORE_PROCESSING_REQUIRED
|
||
//
|
||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpQueryBusRelations(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp,
|
||
OUT PDEVICE_RELATIONS *PdeviceRelations
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is the dispatch point for the IRP_MN_QUERY_DEVICE_RELATIONS
|
||
requests sent to the Root or Filter Device Objects
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to the device object we received the request for
|
||
Irp - Pointer to the request
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS detectStatus;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
||
PNSOBJ acpiObject = NULL;
|
||
UCHAR minorFunction = irpStack->MinorFunction;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// lets look at the ACPIObject that we have and we can see
|
||
// if it is valid
|
||
//
|
||
acpiObject = deviceExtension->AcpiObject;
|
||
ASSERT( acpiObject != NULL );
|
||
if (acpiObject == NULL) {
|
||
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_WARNING,
|
||
deviceExtension,
|
||
"(%#08lx): %s - Invalid ACPI Object %#08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
acpiObject
|
||
) );
|
||
|
||
//
|
||
// Fail the IRP.
|
||
//
|
||
return STATUS_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// Detect which PDOs are missing
|
||
//
|
||
detectStatus = ACPIDetectPdoDevices(
|
||
DeviceObject,
|
||
PdeviceRelations
|
||
);
|
||
|
||
//
|
||
// If something went well along the way, yell a bit
|
||
//
|
||
if ( !NT_SUCCESS(detectStatus) ) {
|
||
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_WARNING,
|
||
deviceExtension,
|
||
"(%#08lx): %s - Enum Failed %#08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
detectStatus
|
||
) );
|
||
|
||
}
|
||
|
||
//
|
||
// Detect which profile providers are missing
|
||
//
|
||
if ( NT_SUCCESS(detectStatus)) {
|
||
|
||
detectStatus = ACPIDetectDockDevices(
|
||
deviceExtension,
|
||
PdeviceRelations
|
||
);
|
||
|
||
//
|
||
// If something went well along the way, yell a bit
|
||
//
|
||
if ( !NT_SUCCESS(detectStatus) ) {
|
||
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_WARNING,
|
||
deviceExtension,
|
||
"(%#08lx): %s - Dock Enum Failed "
|
||
"%#08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
detectStatus
|
||
) );
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// Done
|
||
//
|
||
return detectStatus;
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpQueryCapabilities(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine fills in the capabilities for the root device
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - The object whose capabilities to get
|
||
Irp - The request
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
KEVENT event;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PDEVICE_CAPABILITIES capabilities;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PIO_STACK_LOCATION irpStack;
|
||
UCHAR minorFunction;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Setup the Event so that we are notified of when this done
|
||
//
|
||
KeInitializeEvent( &event, SynchronizationEvent, FALSE );
|
||
|
||
//
|
||
// Copy the stack location
|
||
//
|
||
IoCopyCurrentIrpStackLocationToNext( Irp );
|
||
|
||
//
|
||
// We want our completion routine to fire...
|
||
//
|
||
IoSetCompletionRoutine(
|
||
Irp,
|
||
ACPIRootIrpCompleteRoutine,
|
||
&event,
|
||
TRUE,
|
||
TRUE,
|
||
TRUE
|
||
);
|
||
|
||
//
|
||
// Let the IRP execute
|
||
//
|
||
status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
|
||
if (status == STATUS_PENDING) {
|
||
|
||
//
|
||
// Wait for it
|
||
//
|
||
KeWaitForSingleObject(
|
||
&event,
|
||
Executive,
|
||
KernelMode,
|
||
FALSE,
|
||
NULL
|
||
);
|
||
|
||
//
|
||
// Grab the 'real' status
|
||
//
|
||
status = Irp->IoStatus.Status;
|
||
|
||
}
|
||
|
||
//
|
||
// Look at the current stack location
|
||
//
|
||
irpStack = IoGetCurrentIrpStackLocation( Irp );
|
||
minorFunction = irpStack->MinorFunction;
|
||
|
||
//
|
||
// What happened?
|
||
//
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Failure
|
||
//
|
||
goto ACPIRootIrpQueryCapabilitiesExit;
|
||
|
||
}
|
||
|
||
//
|
||
// Grab a pointer to the capabilitites
|
||
//
|
||
capabilities = irpStack->Parameters.DeviceCapabilities.Capabilities;
|
||
#ifndef HANDLE_BOGUS_CAPS
|
||
if (capabilities->Version < 1) {
|
||
|
||
//
|
||
// do not touch irp!
|
||
//
|
||
goto ACPIRootIrpQueryCapabilitiesExit;
|
||
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Set the capabilities that we know about
|
||
//
|
||
capabilities->LockSupported = FALSE;
|
||
capabilities->EjectSupported = FALSE;
|
||
capabilities->Removable = FALSE;
|
||
capabilities->UINumber = (ULONG) -1;
|
||
capabilities->UniqueID = TRUE;
|
||
capabilities->RawDeviceOK = FALSE;
|
||
capabilities->SurpriseRemovalOK = FALSE;
|
||
capabilities->Address = (ULONG) -1;
|
||
capabilities->DeviceWake = PowerDeviceUnspecified;
|
||
capabilities->SystemWake = PowerDeviceUnspecified;
|
||
|
||
//
|
||
// build the power table properly yet?
|
||
//
|
||
status = ACPISystemPowerInitializeRootMapping(
|
||
deviceExtension,
|
||
capabilities
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_CRITICAL,
|
||
deviceExtension,
|
||
"(0x%08lx): %s - InitializeRootMapping = %08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
status
|
||
) );
|
||
goto ACPIRootIrpQueryCapabilitiesExit;
|
||
|
||
}
|
||
|
||
ACPIRootIrpQueryCapabilitiesExit:
|
||
|
||
//
|
||
// Have happily finished with this irp
|
||
//
|
||
Irp->IoStatus.Status = status;
|
||
|
||
//
|
||
// Complete the Irp
|
||
//
|
||
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
||
|
||
//
|
||
// Done
|
||
//
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(%#08lx): %s = %#08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
status
|
||
) );
|
||
return status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpQueryDeviceRelations(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is the dispatch point for the IRP_MN_QUERY_DEVICE_RELATIONS
|
||
requests sent to the Root or Filter Device Objects
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to the device object we received the request for
|
||
Irp - Pointer to the request
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
BOOLEAN checkForFilters = FALSE;
|
||
KEVENT queryEvent;
|
||
NTSTATUS status;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PDEVICE_RELATIONS deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
|
||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
||
UCHAR minorFunction = irpStack->MinorFunction;
|
||
NTSTATUS detectStatus;
|
||
|
||
PAGED_CODE();
|
||
|
||
switch(irpStack->Parameters.QueryDeviceRelations.Type) {
|
||
|
||
case BusRelations:
|
||
|
||
//
|
||
// Remember to check for filters later on...
|
||
//
|
||
checkForFilters = TRUE;
|
||
|
||
//
|
||
// Get the real bus relations
|
||
//
|
||
status = ACPIRootIrpQueryBusRelations(
|
||
DeviceObject,
|
||
Irp,
|
||
&deviceRelations
|
||
);
|
||
break ;
|
||
|
||
default:
|
||
status = STATUS_NOT_SUPPORTED ;
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_WARNING,
|
||
deviceExtension,
|
||
"(%#08lx): %s - Unhandled Type %d\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
irpStack->Parameters.QueryDeviceRelations.Type
|
||
) );
|
||
break ;
|
||
}
|
||
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(%#08lx): %s (d) = %#08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
status
|
||
) );
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Pass the IRP status along
|
||
//
|
||
Irp->IoStatus.Status = status;
|
||
Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
|
||
|
||
} else if ((status != STATUS_NOT_SUPPORTED) && (deviceRelations == NULL)) {
|
||
|
||
//
|
||
// If we haven't succeed the irp, then we can also fail it
|
||
//
|
||
Irp->IoStatus.Status = status;
|
||
Irp->IoStatus.Information = (ULONG_PTR) NULL;
|
||
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
||
return status;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Either someone above us added an entry or we did not have anything
|
||
// to add. Therefore, we do not touch this IRP, but simply pass it down.
|
||
//
|
||
}
|
||
|
||
//
|
||
// Initialize an event so that we can block
|
||
//
|
||
KeInitializeEvent( &queryEvent, SynchronizationEvent, FALSE );
|
||
|
||
//
|
||
// If we succeeded, then we must set a completion routine so that we
|
||
// can do some post-processing
|
||
//
|
||
IoCopyCurrentIrpStackLocationToNext( Irp );
|
||
IoSetCompletionRoutine(
|
||
Irp,
|
||
ACPIRootIrpCompleteRoutine,
|
||
&queryEvent,
|
||
TRUE,
|
||
TRUE,
|
||
TRUE
|
||
);
|
||
|
||
//
|
||
// Pass the irp along
|
||
//
|
||
status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
|
||
|
||
//
|
||
// Wait for it to come back...
|
||
//
|
||
if (status == STATUS_PENDING) {
|
||
|
||
KeWaitForSingleObject(
|
||
&queryEvent,
|
||
Executive,
|
||
KernelMode,
|
||
FALSE,
|
||
NULL
|
||
);
|
||
|
||
//
|
||
// Grab the 'real' status
|
||
//
|
||
status = Irp->IoStatus.Status;
|
||
|
||
}
|
||
|
||
//
|
||
// Read back the device relations (they may have changed)
|
||
//
|
||
deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
|
||
|
||
//
|
||
// If we succeeded, then we should try to load the filters
|
||
//
|
||
if ( (NT_SUCCESS(status) || (status == STATUS_NOT_SUPPORTED) ) &&
|
||
checkForFilters == TRUE) {
|
||
|
||
//
|
||
// Grab the device relations
|
||
//
|
||
detectStatus = ACPIDetectFilterDevices(
|
||
DeviceObject,
|
||
deviceRelations
|
||
);
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(0x%08lx): %s (u) = %#08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
detectStatus
|
||
) );
|
||
|
||
}
|
||
|
||
//
|
||
// Done with the IRP
|
||
//
|
||
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
||
|
||
//
|
||
// Done
|
||
//
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpQueryInterface(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles IRP_MN_QUERY_INTERFACE requests for the ACPI FDO.
|
||
It will eject an arbiter interface for interrupts.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to the device object we received the request for
|
||
Irp - Pointer to the request
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
ARBITER_INTERFACE ArbiterTable;
|
||
CM_RESOURCE_TYPE resource;
|
||
NTSTATUS status;
|
||
GUID *interfaceType;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
||
ULONG count;
|
||
UCHAR minorFunction = irpStack->MinorFunction;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Obtain the info we will need from the irp
|
||
//
|
||
resource = (CM_RESOURCE_TYPE)
|
||
PtrToUlong(irpStack->Parameters.QueryInterface.InterfaceSpecificData);
|
||
interfaceType = (LPGUID) irpStack->Parameters.QueryInterface.InterfaceType;
|
||
|
||
#if DBG
|
||
{
|
||
NTSTATUS status2;
|
||
UNICODE_STRING guidString;
|
||
|
||
status2 = RtlStringFromGUID( interfaceType, &guidString );
|
||
if (NT_SUCCESS(status2)) {
|
||
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(0x%08lx): %s - Res %x Type = %wZ\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, irpStack->MinorFunction),
|
||
resource,
|
||
&guidString
|
||
) );
|
||
|
||
RtlFreeUnicodeString( &guidString );
|
||
|
||
}
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// *Only* Handle the Guids that we know about. Do Not Ever touch
|
||
// any other GUID
|
||
//
|
||
if ((CompareGuid(interfaceType, (PVOID) &GUID_ARBITER_INTERFACE_STANDARD)) &&
|
||
(resource == CmResourceTypeInterrupt)){
|
||
|
||
//
|
||
// Only copy up to current size of the ARBITER_INTERFACE structure
|
||
//
|
||
if (irpStack->Parameters.QueryInterface.Size >
|
||
sizeof (ARBITER_INTERFACE) ) {
|
||
|
||
count = sizeof (ARBITER_INTERFACE);
|
||
|
||
} else {
|
||
|
||
count = irpStack->Parameters.QueryInterface.Size;
|
||
}
|
||
|
||
ArbiterTable.Size = sizeof(ARBITER_INTERFACE);
|
||
ArbiterTable.Version = 1;
|
||
ArbiterTable.InterfaceReference = AcpiNullReference;
|
||
ArbiterTable.InterfaceDereference = AcpiNullReference;
|
||
ArbiterTable.ArbiterHandler = &ArbArbiterHandler;
|
||
ArbiterTable.Context = &AcpiArbiter.ArbiterState;
|
||
ArbiterTable.Flags = 0; // Do not set ARBITER_PARTIAL here
|
||
|
||
//
|
||
// Copy the arbiter table.
|
||
//
|
||
RtlCopyMemory(irpStack->Parameters.QueryInterface.Interface,
|
||
&ArbiterTable,
|
||
count);
|
||
|
||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// Done
|
||
//
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(%#08lx): %s = %#08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
Irp->IoStatus.Status
|
||
) );
|
||
|
||
return ACPIDispatchForwardIrp( DeviceObject, Irp );
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpQueryPower(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles the QUERY_POWER sent to the root FDO. It succeeds
|
||
the query if ACPI supports the listed system state
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - The Target
|
||
Irp - The Request
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
BOOLEAN passDown = TRUE;
|
||
NTSTATUS status = Irp->IoStatus.Status;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PIO_STACK_LOCATION irpSp;
|
||
PNSOBJ object;
|
||
SYSTEM_POWER_STATE systemState;
|
||
ULONG objectName;
|
||
|
||
//
|
||
// Get the Current stack location to determine if we are a system
|
||
// irp or a device irp. We ignore device irps here.
|
||
//
|
||
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
if (irpSp->Parameters.Power.Type != SystemPowerState) {
|
||
|
||
//
|
||
// We don't handle this irp
|
||
//
|
||
goto ACPIRootIrpQueryPowerExit;
|
||
|
||
}
|
||
if (irpSp->Parameters.Power.ShutdownType == PowerActionWarmEject) {
|
||
|
||
//
|
||
// We definately don't allow the ejection of this node
|
||
//
|
||
passDown = FALSE;
|
||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||
goto ACPIRootIrpQueryPowerExit;
|
||
|
||
}
|
||
|
||
//
|
||
// What system state are we looking at?
|
||
//
|
||
systemState = irpSp->Parameters.Power.State.SystemState;
|
||
switch (systemState) {
|
||
case PowerSystemWorking: objectName = PACKED_S0; break;
|
||
case PowerSystemSleeping1: objectName = PACKED_S1; break;
|
||
case PowerSystemSleeping2: objectName = PACKED_S2; break;
|
||
case PowerSystemSleeping3: objectName = PACKED_S3; break;
|
||
case PowerSystemHibernate:
|
||
case PowerSystemShutdown:
|
||
|
||
status = STATUS_SUCCESS;
|
||
goto ACPIRootIrpQueryPowerExit;
|
||
|
||
default:
|
||
|
||
//
|
||
// We don't handle this IRP
|
||
//
|
||
passDown = FALSE;
|
||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||
goto ACPIRootIrpQueryPowerExit;
|
||
}
|
||
|
||
//
|
||
// Does the object exist?
|
||
//
|
||
object = ACPIAmliGetNamedChild(
|
||
deviceExtension->AcpiObject->pnsParent,
|
||
objectName
|
||
);
|
||
if (object != NULL) {
|
||
|
||
status = STATUS_SUCCESS;
|
||
|
||
} else {
|
||
|
||
passDown = FALSE;
|
||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||
|
||
}
|
||
|
||
ACPIRootIrpQueryPowerExit:
|
||
|
||
//
|
||
// Let the system know what we support and what we don't
|
||
//
|
||
Irp->IoStatus.Status = status;
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(0x%08lx): ACPIRootIrpQueryPower = %08lx\n",
|
||
Irp,
|
||
status
|
||
) );
|
||
|
||
//
|
||
// Should we pass the irp down or fail it?
|
||
//
|
||
if (passDown) {
|
||
|
||
//
|
||
// If we support the request then pass it down and give someone else a
|
||
// chance to veto it
|
||
//
|
||
return ACPIDispatchForwardPowerIrp( DeviceObject, Irp );
|
||
|
||
} else {
|
||
|
||
//
|
||
// If we failed the irp for whatever reason, the we should just complete
|
||
// the request now and continue along
|
||
//
|
||
PoStartNextPowerIrp( Irp );
|
||
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
||
return status;
|
||
|
||
}
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpQueryRemoveOrStopDevice(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine transitions the device to the inactive state
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - The target
|
||
Irp - The Request
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
||
UCHAR minorFunction = irpStack->MinorFunction;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Are we allowed to stop the device?
|
||
//
|
||
if (deviceExtension->Flags & DEV_CAP_NO_STOP) {
|
||
|
||
//
|
||
// No, then fail the irp
|
||
//
|
||
Irp->IoStatus.Status = status = STATUS_INVALID_DEVICE_REQUEST;
|
||
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
||
|
||
} else {
|
||
|
||
//
|
||
// Mark the device state as inactive...
|
||
//
|
||
deviceExtension->PreviousState = deviceExtension->DeviceState;
|
||
deviceExtension->DeviceState = Inactive;
|
||
|
||
//
|
||
// Pass the Irp Along
|
||
//
|
||
IoSkipCurrentIrpStackLocation( Irp );
|
||
status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
|
||
|
||
|
||
}
|
||
|
||
//
|
||
// Done
|
||
//
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(%#08lx): %s = %#08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
status
|
||
) );
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpRemoveDevice(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called when a filter object must remove itself...
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - The DeviceObject that must be removed
|
||
Irp - The request to remove ourselves
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
{
|
||
LONG oldReferenceCount;
|
||
KIRQL oldIrql;
|
||
NTSTATUS status;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PDEVICE_OBJECT targetObject;
|
||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
||
UCHAR minorFunction = irpStack->MinorFunction;
|
||
|
||
//
|
||
// Set the device state as 'removed' ...
|
||
//
|
||
deviceExtension->DeviceState = Removed;
|
||
|
||
//
|
||
// Send on the remove IRP
|
||
//
|
||
IoSkipCurrentIrpStackLocation( Irp );
|
||
status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
|
||
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(%#08lx): %s = %#08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
status
|
||
) );
|
||
|
||
//
|
||
// Attempt to stop the device (if possible)
|
||
//
|
||
ACPIInitStopACPI( DeviceObject );
|
||
|
||
|
||
//
|
||
// Unregister WMI
|
||
//
|
||
#ifdef WMI_TRACING
|
||
ACPIWmiUnRegisterLog(DeviceObject);
|
||
#endif // WMI_TRACING
|
||
|
||
//
|
||
// Delete the useless set of resources
|
||
//
|
||
if (deviceExtension->ResourceList != NULL) {
|
||
|
||
ExFreePool( deviceExtension->ResourceList );
|
||
|
||
}
|
||
|
||
//
|
||
// Update the device extension ---
|
||
// we need to hold the lock for this
|
||
//
|
||
KeAcquireSpinLock( &AcpiDeviceTreeLock, &oldIrql );
|
||
|
||
//
|
||
// Step one is to zero out the things that we no longer care
|
||
// about
|
||
//
|
||
DeviceObject->DeviceExtension = NULL;
|
||
targetObject = deviceExtension->TargetDeviceObject;
|
||
deviceExtension->TargetDeviceObject = NULL;
|
||
deviceExtension->PhysicalDeviceObject = NULL;
|
||
deviceExtension->DeviceObject = NULL;
|
||
|
||
//
|
||
// Mark the node as being fresh and untouched
|
||
//
|
||
ACPIInternalUpdateFlags( &(deviceExtension->Flags), DEV_MASK_TYPE, TRUE );
|
||
ACPIInternalUpdateFlags( &(deviceExtension->Flags), DEV_TYPE_NOT_FOUND, FALSE );
|
||
ACPIInternalUpdateFlags( &(deviceExtension->Flags), DEV_TYPE_REMOVED, FALSE );
|
||
|
||
//
|
||
// The reference count should have value >= 1
|
||
//
|
||
oldReferenceCount = InterlockedDecrement(
|
||
&(deviceExtension->ReferenceCount)
|
||
);
|
||
|
||
ASSERT( oldReferenceCount >= 0 );
|
||
|
||
//
|
||
// Do we have to delete the node?
|
||
//
|
||
if (oldReferenceCount == 0) {
|
||
|
||
//
|
||
// Delete the extension
|
||
//
|
||
ACPIInitDeleteDeviceExtension( deviceExtension );
|
||
|
||
}
|
||
|
||
//
|
||
// Done with the lock
|
||
//
|
||
KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
|
||
|
||
//
|
||
// Detach the device and delete the object
|
||
//
|
||
ASSERT( targetObject );
|
||
IoDetachDevice( targetObject );
|
||
IoDeleteDevice( DeviceObject );
|
||
|
||
//
|
||
// done
|
||
//
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpSetPower (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to tell the Root device that the system is
|
||
going to sleep
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Device which represents the root of the ACPI tree
|
||
Irp - The request in question
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
KIRQL oldIrql;
|
||
NTSTATUS status;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PIO_STACK_LOCATION irpSp;
|
||
|
||
//
|
||
// See if we need to bugcheck
|
||
//
|
||
if (AcpiSystemInitialized == FALSE) {
|
||
|
||
ACPIInternalError( ACPI_ROOT );
|
||
|
||
}
|
||
|
||
//
|
||
// Get the Current stack location to determine if we are a system
|
||
// irp or a device irp. We ignore device irps here.
|
||
//
|
||
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
if (irpSp->Parameters.Power.Type != SystemPowerState) {
|
||
|
||
//
|
||
// We don't handle this irp
|
||
//
|
||
return ACPIDispatchForwardPowerIrp( DeviceObject, Irp );
|
||
|
||
}
|
||
|
||
//
|
||
// We are going to work on the Irp, so mark it as being SUCCESS
|
||
// for now
|
||
//
|
||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(0x%08lx): ACPIRootIrpSetPower - S%d\n",
|
||
Irp,
|
||
irpSp->Parameters.Power.State.SystemState - PowerSystemWorking
|
||
) );
|
||
|
||
//
|
||
// Mark the irp as pending, and increment the irp count because a
|
||
// completion is going to be set
|
||
//
|
||
IoMarkIrpPending( Irp );
|
||
InterlockedIncrement( &(deviceExtension->OutstandingIrpCount) );
|
||
|
||
//
|
||
// Queue the request
|
||
//
|
||
status = ACPIDeviceIrpSystemRequest(
|
||
DeviceObject,
|
||
Irp,
|
||
ACPIDeviceIrpForwardRequest
|
||
);
|
||
|
||
//
|
||
// Did we return STATUS_MORE_PROCESSING_REQUIRED (which we used if
|
||
// we overloaded STATUS_PENDING)
|
||
//
|
||
if (status == STATUS_MORE_PROCESSING_REQUIRED) {
|
||
|
||
status = STATUS_PENDING;
|
||
|
||
}
|
||
|
||
//
|
||
// Done. Note: the callback function always gets called, so we don't
|
||
// have to worry about doing clean-up work here.
|
||
//
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpStartDevice(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is the dispatch point for the IRP_MN_START_DEVICE requests sent
|
||
to the Root (or FDO, take your pick, they are the same thing) device object
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to the device object we received the request for
|
||
Irp - Pointer to the request
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
KEVENT event;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PIO_STACK_LOCATION irpStack;
|
||
UCHAR minorFunction;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Request to start the device. The rule is that we must pass
|
||
// this down to the PDO before we can start the device ourselves
|
||
//
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(0x%08lx): ACPIRootIrpStartDevice\n",
|
||
Irp
|
||
) );
|
||
|
||
//
|
||
// Setup the Event so that we are notified of when this done
|
||
//
|
||
KeInitializeEvent( &event, SynchronizationEvent, FALSE );
|
||
|
||
//
|
||
// Copy the stack location
|
||
//
|
||
IoCopyCurrentIrpStackLocationToNext( Irp );
|
||
|
||
//
|
||
// We want our completion routine to fire...
|
||
//
|
||
IoSetCompletionRoutine(
|
||
Irp,
|
||
ACPIRootIrpCompleteRoutine,
|
||
&event,
|
||
TRUE,
|
||
TRUE,
|
||
TRUE
|
||
);
|
||
|
||
//
|
||
// Let the IRP execute
|
||
//
|
||
status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
|
||
|
||
if (status == STATUS_PENDING) {
|
||
|
||
//
|
||
// Wait for it
|
||
//
|
||
KeWaitForSingleObject(
|
||
&event,
|
||
Executive,
|
||
KernelMode,
|
||
FALSE,
|
||
NULL
|
||
);
|
||
|
||
//
|
||
// Grab the 'real' status
|
||
//
|
||
status = Irp->IoStatus.Status;
|
||
|
||
}
|
||
|
||
//
|
||
// Get the current irp stack location
|
||
//
|
||
irpStack = IoGetCurrentIrpStackLocation( Irp );
|
||
minorFunction = irpStack->MinorFunction;
|
||
|
||
//
|
||
// What happened?
|
||
//
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Failure
|
||
//
|
||
goto ACPIRootIrpStartDeviceExit;
|
||
|
||
}
|
||
|
||
//
|
||
// Grab the translatted resource allocated for this device
|
||
//
|
||
deviceExtension->ResourceList =
|
||
(irpStack->Parameters.StartDevice.AllocatedResourcesTranslated ==
|
||
NULL) ? NULL:
|
||
RtlDuplicateCmResourceList(
|
||
NonPagedPool,
|
||
irpStack->Parameters.StartDevice.AllocatedResourcesTranslated,
|
||
ACPI_RESOURCE_POOLTAG
|
||
);
|
||
if (deviceExtension->ResourceList == NULL) {
|
||
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_CRITICAL,
|
||
deviceExtension,
|
||
" - Did not find a resource list!\n"
|
||
) );
|
||
KeBugCheckEx(
|
||
ACPI_BIOS_ERROR,
|
||
ACPI_ROOT_RESOURCES_FAILURE,
|
||
(ULONG_PTR) deviceExtension,
|
||
0,
|
||
0
|
||
);
|
||
|
||
}
|
||
|
||
//
|
||
// Start ACPI
|
||
//
|
||
status = ACPIInitStartACPI( DeviceObject );
|
||
|
||
//
|
||
// Update the status of the device
|
||
//
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
deviceExtension->DeviceState = Started;
|
||
|
||
}
|
||
|
||
#if 0
|
||
status = ACPIRootUpdateRootResourcesWithHalResources();
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_CRITICAL,
|
||
deviceExtension,
|
||
"(0x%08lx): ACPIRootUpdateRootResourcesWithHalResources = %08lx\n",
|
||
Irp,
|
||
status
|
||
) );
|
||
|
||
}
|
||
#endif
|
||
|
||
ACPIRootIrpStartDeviceExit:
|
||
|
||
//
|
||
// Store and return the result
|
||
//
|
||
Irp->IoStatus.Status = status;
|
||
|
||
//
|
||
// Complete the Irp
|
||
//
|
||
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
||
|
||
//
|
||
// Done
|
||
//
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(%#08lx): %s = %#08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
status
|
||
) );
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpStopDevice(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This handles a request to stop the device
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - The device to stop
|
||
Irp - The request to tell us how to do it...
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
|
||
NTSTATUS status;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
||
UCHAR minorFunction = irpStack->MinorFunction;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Note: we can only stop a device from within the Inactive state...
|
||
//
|
||
if (deviceExtension->DeviceState != Inactive) {
|
||
|
||
ASSERT( deviceExtension->DeviceState == Inactive );
|
||
Irp->IoStatus.Status = status = STATUS_INVALID_DEVICE_REQUEST;
|
||
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
||
goto ACPIRootIrpStopDeviceExit;
|
||
|
||
}
|
||
|
||
//
|
||
// Set the device as 'Stopped'
|
||
deviceExtension->DeviceState = Stopped;
|
||
|
||
//
|
||
// Send on the Stop IRP
|
||
//
|
||
IoSkipCurrentIrpStackLocation( Irp );
|
||
status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
|
||
|
||
//
|
||
// Attempt to stop the device (if possible)
|
||
//
|
||
#if 1
|
||
ACPIInitStopACPI( DeviceObject );
|
||
#endif
|
||
|
||
ACPIRootIrpStopDeviceExit:
|
||
|
||
//
|
||
// done
|
||
//
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_IRP,
|
||
deviceExtension,
|
||
"(%#08lx): %s = %#08lx\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
|
||
status
|
||
) );
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootIrpUnhandled(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is the dispatch point for the unhandled requests sent to a filter
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to the device object we received the request for
|
||
Irp - Pointer to the request
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status;
|
||
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
|
||
|
||
//
|
||
// Let the debugger know
|
||
//
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_WARNING,
|
||
deviceExtension,
|
||
"(%#08lx): %s - Unhandled\n",
|
||
Irp,
|
||
ACPIDebugGetIrpText(IRP_MJ_PNP, irpStack->MinorFunction)
|
||
) );
|
||
|
||
//
|
||
// Skip current stack location
|
||
//
|
||
IoSkipCurrentIrpStackLocation( Irp );
|
||
|
||
//
|
||
// Call the driver below us
|
||
//
|
||
status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
|
||
|
||
//
|
||
// Done
|
||
//
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// Some data structures used by the AML interpreter. We need to be able
|
||
// to read/write these globals to keep track of the number of contexts
|
||
// allocated by the interpreter...
|
||
//
|
||
extern ULONG gdwcCTObjsMax;
|
||
extern ULONG AMLIMaxCTObjs;
|
||
extern KSPIN_LOCK gdwGContextSpinLock;
|
||
|
||
VOID
|
||
ACPIRootPowerCallBack(
|
||
IN PVOID CallBackContext,
|
||
IN PVOID Argument1,
|
||
IN PVOID Argument2
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called when the system changes power states
|
||
|
||
Arguments:
|
||
|
||
CallBackContext - The device extension for the root device
|
||
Argument1
|
||
|
||
--*/
|
||
{
|
||
HANDLE pKey;
|
||
HANDLE wKey;
|
||
KIRQL oldIrql;
|
||
NTSTATUS status;
|
||
ULONG action = PtrToUlong( Argument1 );
|
||
ULONG value = PtrToUlong( Argument2 );
|
||
ULONG num;
|
||
|
||
//
|
||
// We are looking for a PO_CB_SYSTEM_STATE_LOCK
|
||
//
|
||
if (action != PO_CB_SYSTEM_STATE_LOCK) {
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
//
|
||
// We need to remember if we are going to S0 or we are leaving S0
|
||
//
|
||
KeAcquireSpinLock( &GpeTableLock, &oldIrql );
|
||
AcpiPowerLeavingS0 = (value != 1);
|
||
KeReleaseSpinLock( &GpeTableLock, oldIrql );
|
||
|
||
//
|
||
// We have to update the GPE masks now. Before we can do that, we need
|
||
// to hold the cancel spinlock and the power lock to make sure that
|
||
// everything is synchronized okay
|
||
//
|
||
IoAcquireCancelSpinLock( &oldIrql );
|
||
KeAcquireSpinLockAtDpcLevel( &AcpiPowerLock );
|
||
|
||
//
|
||
// Update the GPE masks
|
||
//
|
||
ACPIWakeRemoveDevicesAndUpdate( NULL, NULL );
|
||
|
||
//
|
||
// Done with the locks
|
||
//
|
||
KeReleaseSpinLockFromDpcLevel( &AcpiPowerLock );
|
||
IoReleaseCancelSpinLock( oldIrql );
|
||
|
||
if (value == 0) {
|
||
|
||
//
|
||
// We need to reset the max number of context objects allocated
|
||
//
|
||
KeAcquireSpinLock( &gdwGContextSpinLock, &oldIrql );
|
||
gdwcCTObjsMax = 0;
|
||
KeReleaseSpinLock( &gdwGContextSpinLock, oldIrql );
|
||
|
||
//
|
||
// Return now otherwise we will execute that we normally
|
||
// would execute on wake-up
|
||
//
|
||
return;
|
||
|
||
}
|
||
|
||
//
|
||
// Open the correct handle to the registry
|
||
//
|
||
status = OSCreateHandle(ACPI_PARAMETERS_REGISTRY_KEY, NULL, &pKey);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
//
|
||
// Grab the max number of contexts allocated and write it to
|
||
// the registry, but only if it exceeds the last value store
|
||
// in the registry
|
||
//
|
||
KeAcquireSpinLock( &gdwGContextSpinLock, &oldIrql );
|
||
if (gdwcCTObjsMax > AMLIMaxCTObjs) {
|
||
|
||
AMLIMaxCTObjs = gdwcCTObjsMax;
|
||
|
||
}
|
||
num = AMLIMaxCTObjs;
|
||
KeReleaseSpinLock( &gdwGContextSpinLock, oldIrql );
|
||
OSWriteRegValue(
|
||
"AMLIMaxCTObjs",
|
||
pKey,
|
||
&num,
|
||
sizeof(num)
|
||
);
|
||
|
||
//
|
||
// If we are leaving the sleep state, and re-entering the running
|
||
// state, then we had better write to the registery that we think
|
||
// woke up the computer
|
||
//
|
||
status = OSCreateHandle("WakeUp",pKey,&wKey);
|
||
OSCloseHandle(pKey);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
OSCloseHandle(pKey);
|
||
return;
|
||
|
||
}
|
||
|
||
|
||
//
|
||
// Store the PM1 Fixed Register Mask
|
||
//
|
||
OSWriteRegValue(
|
||
"FixedEventMask",
|
||
wKey,
|
||
&(AcpiInformation->pm1_wake_mask),
|
||
sizeof(AcpiInformation->pm1_wake_mask)
|
||
);
|
||
|
||
//
|
||
// Store the PM1 Fixed Register Status
|
||
//
|
||
OSWriteRegValue(
|
||
"FixedEventStatus",
|
||
wKey,
|
||
&(AcpiInformation->pm1_wake_status),
|
||
sizeof(AcpiInformation->pm1_wake_status)
|
||
);
|
||
|
||
//
|
||
// Store the GPE Mask
|
||
//
|
||
OSWriteRegValue(
|
||
"GenericEventMask",
|
||
wKey,
|
||
GpeSavedWakeMask,
|
||
AcpiInformation->GpeSize
|
||
);
|
||
|
||
//
|
||
// Store the GPE Status
|
||
//
|
||
OSWriteRegValue(
|
||
"GenericEventStatus",
|
||
wKey,
|
||
GpeSavedWakeStatus,
|
||
AcpiInformation->GpeSize
|
||
);
|
||
|
||
//
|
||
// Done with the key
|
||
//
|
||
OSCloseHandle( wKey );
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootUpdateRootResourcesWithBusResources(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called when ACPI is started. Its purpose is to change
|
||
the resources reported to ACPI for its own use to include those resources
|
||
used by direct childs which are not buses. In other words, it updates
|
||
its resource list so that buses do not prevent direct children from
|
||
starting.
|
||
|
||
This is black magic
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
KIRQL oldIrql;
|
||
LONG oldReferenceCount;
|
||
NTSTATUS status;
|
||
PCM_RESOURCE_LIST cmList;
|
||
PDEVICE_EXTENSION deviceExtension;
|
||
PDEVICE_EXTENSION oldExtension;
|
||
PIO_RESOURCE_REQUIREMENTS_LIST currentList = NULL;
|
||
PIO_RESOURCE_REQUIREMENTS_LIST globalList = NULL;
|
||
PUCHAR crsBuf;
|
||
|
||
//
|
||
// First take the ACPI CM Res List and turn *that* into an Io ResList. This
|
||
// is the list that we will add things to
|
||
//
|
||
status = PnpCmResourceListToIoResourceList(
|
||
RootDeviceExtension->ResourceList,
|
||
&globalList
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Oops
|
||
//
|
||
return status;
|
||
|
||
}
|
||
|
||
//
|
||
// We must walk the tree at Dispatch level <sigh>
|
||
//
|
||
KeAcquireSpinLock( &AcpiDeviceTreeLock, &oldIrql );
|
||
|
||
//
|
||
// Is the list empty?
|
||
//
|
||
if (IsListEmpty( &(RootDeviceExtension->ChildDeviceList) ) ) {
|
||
|
||
//
|
||
// We have nothing to do here
|
||
//
|
||
KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
|
||
ExFreePool( globalList );
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
//
|
||
// Get the first child
|
||
//
|
||
deviceExtension = CONTAINING_RECORD(
|
||
RootDeviceExtension->ChildDeviceList.Flink,
|
||
DEVICE_EXTENSION,
|
||
SiblingDeviceList
|
||
);
|
||
|
||
//
|
||
// Always update the reference count to make sure that one will ever
|
||
// delete the node without our knowing about it
|
||
//
|
||
InterlockedIncrement( &(deviceExtension->ReferenceCount) );
|
||
|
||
//
|
||
// Release the lock
|
||
//
|
||
KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
|
||
|
||
//
|
||
// loop until we get to the parent
|
||
//
|
||
while (deviceExtension != NULL ) {
|
||
|
||
//
|
||
// Check to see if we are a bus, and if we are, we will skip this
|
||
// node
|
||
//
|
||
if (!(deviceExtension->Flags & DEV_MASK_BUS) &&
|
||
!(deviceExtension->Flags & DEV_PROP_NO_OBJECT) ) {
|
||
|
||
//
|
||
// At this point, see if there is a _CRS
|
||
//
|
||
ACPIGetBufferSync(
|
||
deviceExtension,
|
||
PACKED_CRS,
|
||
&crsBuf,
|
||
NULL
|
||
);
|
||
if (crsBuf != NULL) {
|
||
|
||
//
|
||
// Try to turn the crs into an IO_RESOURCE_REQUIREMENTS_LIST
|
||
//
|
||
status = PnpBiosResourcesToNtResources(
|
||
crsBuf,
|
||
0,
|
||
¤tList
|
||
);
|
||
|
||
//
|
||
// If we didn't succeed, then we skip the list
|
||
//
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Add this list to the global list
|
||
//
|
||
status = ACPIRangeAdd(
|
||
&globalList,
|
||
currentList
|
||
);
|
||
|
||
//
|
||
// We are done with the local IO res list
|
||
//
|
||
ExFreePool( currentList );
|
||
|
||
}
|
||
|
||
ACPIDevPrint( (
|
||
ACPI_PRINT_RESOURCES_1,
|
||
deviceExtension,
|
||
"ACPIRootUpdateResources = %08lx\n",
|
||
status
|
||
) );
|
||
|
||
//
|
||
// Done with local crs
|
||
//
|
||
ExFreePool( crsBuf );
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// We need the lock to walk the next resource in the tree
|
||
//
|
||
KeAcquireSpinLock( &AcpiDeviceTreeLock, &oldIrql );
|
||
|
||
//
|
||
// Remember the old extension
|
||
//
|
||
oldExtension = deviceExtension;
|
||
|
||
//
|
||
// Get the next device extension
|
||
//
|
||
if (deviceExtension->SiblingDeviceList.Flink !=
|
||
&(RootDeviceExtension->ChildDeviceList) ) {
|
||
|
||
//
|
||
// Next Element
|
||
//
|
||
deviceExtension = CONTAINING_RECORD(
|
||
deviceExtension->SiblingDeviceList.Flink,
|
||
DEVICE_EXTENSION,
|
||
SiblingDeviceList
|
||
);
|
||
|
||
//
|
||
// Reference count the device
|
||
//
|
||
InterlockedIncrement( &(deviceExtension->ReferenceCount) );
|
||
|
||
} else {
|
||
|
||
deviceExtension = NULL;
|
||
|
||
}
|
||
|
||
//
|
||
// Decrement the reference count on this node
|
||
//
|
||
oldReferenceCount = InterlockedDecrement(
|
||
&(oldExtension->ReferenceCount)
|
||
);
|
||
|
||
//
|
||
// Is this the last reference?
|
||
//
|
||
if (oldReferenceCount == 0) {
|
||
|
||
//
|
||
// Free the memory allocated by the extension
|
||
//
|
||
ACPIInitDeleteDeviceExtension( oldExtension );
|
||
}
|
||
|
||
//
|
||
// Done with the lock
|
||
//
|
||
KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
|
||
|
||
}
|
||
|
||
//
|
||
// Do we have any resources that we care to update?
|
||
//
|
||
if (globalList == NULL) {
|
||
|
||
//
|
||
// No, then we are done
|
||
//
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
//
|
||
// Turn the global list into a CM_RES_LIST
|
||
//
|
||
status = PnpIoResourceListToCmResourceList( globalList, &cmList );
|
||
|
||
//
|
||
// No matter what, we are done with the global list
|
||
//
|
||
ExFreePool( globalList );
|
||
|
||
//
|
||
// Check to see if we succeeded
|
||
//
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Oops
|
||
//
|
||
return status;
|
||
|
||
}
|
||
|
||
//
|
||
// Now, set this as the resources consumed by ACPI. The previous list
|
||
// was created by the system manager, so freeing it is bad.
|
||
//
|
||
RootDeviceExtension->ResourceList = cmList;
|
||
|
||
//
|
||
// Done
|
||
//
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
ACPIRootUpdateRootResourcesWithHalResources(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine will read from the registry the resources that cannot
|
||
be allocated by ACPI and store them in the resourceList for PnP0C08
|
||
|
||
This is black magic
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS
|
||
|
||
--*/
|
||
{
|
||
HANDLE classKeyHandle;
|
||
HANDLE driverKeyHandle;
|
||
HANDLE resourceMap;
|
||
NTSTATUS status;
|
||
OBJECT_ATTRIBUTES resourceObject;
|
||
PCM_FULL_RESOURCE_DESCRIPTOR cmFullResList;
|
||
PCM_RESOURCE_LIST globalResList;
|
||
PCM_RESOURCE_LIST cmResList;
|
||
PUCHAR lastAddr;
|
||
ULONG bufferSize;
|
||
ULONG busTranslatedLength;
|
||
ULONG classKeyIndex;
|
||
ULONG driverKeyIndex;
|
||
ULONG driverValueIndex;
|
||
ULONG i;
|
||
ULONG j;
|
||
ULONG length;
|
||
ULONG temp;
|
||
ULONG translatedLength;
|
||
union {
|
||
PVOID buffer;
|
||
PKEY_BASIC_INFORMATION keyBasicInf;
|
||
PKEY_FULL_INFORMATION keyFullInf;
|
||
PKEY_VALUE_FULL_INFORMATION valueKeyFullInf;
|
||
} u;
|
||
UNICODE_STRING keyName;
|
||
WCHAR rgzTranslated[] = L".Translated";
|
||
WCHAR rgzBusTranslated[] = L".Bus.Translated";
|
||
WCHAR rgzResourceMap[] =
|
||
L"\\REGISTRY\\MACHINE\\HARDWARE\\RESOURCEMAP";
|
||
|
||
#define INVALID_HANDLE (HANDLE) -1
|
||
|
||
//
|
||
// Start out with one page of buffer
|
||
//
|
||
bufferSize = PAGE_SIZE;
|
||
|
||
//
|
||
// Allocate this buffer
|
||
//
|
||
u.buffer = ExAllocatePoolWithTag(
|
||
PagedPool,
|
||
bufferSize,
|
||
ACPI_MISC_POOLTAG
|
||
);
|
||
if (u.buffer == NULL) {
|
||
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
|
||
}
|
||
|
||
//
|
||
// Add the current global res list to the working list
|
||
//
|
||
globalResList = NULL;
|
||
status = ACPIRangeAddCmList(
|
||
&globalResList,
|
||
RootDeviceExtension->ResourceList
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
ExFreePool( u.buffer );
|
||
return status;
|
||
|
||
}
|
||
ExFreePool( RootDeviceExtension->ResourceList );
|
||
RootDeviceExtension->ResourceList = NULL;
|
||
|
||
//
|
||
// count the constant string lengths
|
||
//
|
||
for (translatedLength = 0;
|
||
rgzTranslated[translatedLength];
|
||
translatedLength++);
|
||
for (busTranslatedLength = 0;
|
||
rgzBusTranslated[busTranslatedLength];
|
||
busTranslatedLength++);
|
||
translatedLength *= sizeof(WCHAR);
|
||
busTranslatedLength *= sizeof(WCHAR);
|
||
|
||
//
|
||
// Initialize the registry path information
|
||
//
|
||
RtlInitUnicodeString( &keyName, rgzResourceMap );
|
||
|
||
//
|
||
// Open the registry key for this information
|
||
//
|
||
InitializeObjectAttributes(
|
||
&resourceObject,
|
||
&keyName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
status = ZwOpenKey(
|
||
&resourceMap,
|
||
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
|
||
&resourceObject
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Failed:
|
||
//
|
||
ACPIPrint( (
|
||
ACPI_PRINT_CRITICAL,
|
||
"ACPIRootUpdateRootResourcesWithHalResources: ZwOpenKey = 0x%08lx\n",
|
||
status
|
||
) );
|
||
ExFreePool( u.buffer );
|
||
return status;
|
||
|
||
}
|
||
|
||
//
|
||
// Walk resource map and collect any in-use resources
|
||
//
|
||
classKeyIndex = 0;
|
||
classKeyHandle = INVALID_HANDLE;
|
||
driverKeyHandle = INVALID_HANDLE;
|
||
status = STATUS_SUCCESS;
|
||
|
||
//
|
||
// loop until failure
|
||
//
|
||
while (NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Get the class information
|
||
//
|
||
status = ZwEnumerateKey(
|
||
resourceMap,
|
||
classKeyIndex++,
|
||
KeyBasicInformation,
|
||
u.keyBasicInf,
|
||
bufferSize,
|
||
&temp
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Create a unicode string using the counted string passed back to
|
||
// us in the information structure, and open the class key
|
||
//
|
||
keyName.Buffer = (PWSTR) u.keyBasicInf->Name;
|
||
keyName.Length = (USHORT) u.keyBasicInf->NameLength;
|
||
keyName.MaximumLength = (USHORT) u.keyBasicInf->NameLength;
|
||
InitializeObjectAttributes(
|
||
&resourceObject,
|
||
&keyName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
resourceMap,
|
||
NULL
|
||
);
|
||
status = ZwOpenKey(
|
||
&classKeyHandle,
|
||
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
|
||
&resourceObject
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Loop until failure
|
||
//
|
||
driverKeyIndex = 0;
|
||
while (NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Get the class information
|
||
//
|
||
status = ZwEnumerateKey(
|
||
classKeyHandle,
|
||
driverKeyIndex++,
|
||
KeyBasicInformation,
|
||
u.keyBasicInf,
|
||
bufferSize,
|
||
&temp
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Create a unicode string using the counted string passed back
|
||
// to us in the information structure, and open the class key
|
||
//
|
||
keyName.Buffer = (PWSTR) u.keyBasicInf->Name;
|
||
keyName.Length = (USHORT) u.keyBasicInf->NameLength;
|
||
keyName.MaximumLength = (USHORT) u.keyBasicInf->NameLength;
|
||
InitializeObjectAttributes(
|
||
&resourceObject,
|
||
&keyName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
classKeyHandle,
|
||
NULL
|
||
);
|
||
status = ZwOpenKey(
|
||
&driverKeyHandle,
|
||
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
|
||
&resourceObject
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Get full information for that key so we can get the information
|
||
// about the data stored in the key
|
||
//
|
||
status = ZwQueryKey(
|
||
driverKeyHandle,
|
||
KeyFullInformation,
|
||
u.keyFullInf,
|
||
bufferSize,
|
||
&temp
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// How long is the key?
|
||
//
|
||
length = sizeof( KEY_VALUE_FULL_INFORMATION) +
|
||
u.keyFullInf->MaxValueNameLen +
|
||
u.keyFullInf->MaxValueDataLen +
|
||
sizeof(UNICODE_NULL);
|
||
if (length > bufferSize) {
|
||
|
||
PVOID tempBuffer;
|
||
|
||
//
|
||
// Grow the buffer
|
||
//
|
||
tempBuffer = ExAllocatePoolWithTag(
|
||
PagedPool,
|
||
length,
|
||
ACPI_MISC_POOLTAG
|
||
);
|
||
if (tempBuffer == NULL) {
|
||
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
break;
|
||
|
||
}
|
||
ExFreePool( u.buffer );
|
||
u.buffer = tempBuffer;
|
||
bufferSize = length;
|
||
|
||
}
|
||
|
||
//
|
||
// Look at all the values
|
||
//
|
||
driverValueIndex = 0;
|
||
for(;;) {
|
||
|
||
PCM_RESOURCE_LIST tempCmList;
|
||
|
||
status = ZwEnumerateValueKey(
|
||
driverKeyHandle,
|
||
driverValueIndex++,
|
||
KeyValueFullInformation,
|
||
u.valueKeyFullInf,
|
||
bufferSize,
|
||
&temp
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// If this is not a translated resource list, skip it
|
||
//
|
||
i = u.valueKeyFullInf->NameLength;
|
||
if (i < translatedLength ||
|
||
RtlCompareMemory(
|
||
((PUCHAR) u.valueKeyFullInf->Name) + i - translatedLength,
|
||
rgzTranslated,
|
||
translatedLength) != translatedLength
|
||
) {
|
||
|
||
//
|
||
// Does not end in rgzTranslated
|
||
//
|
||
continue;
|
||
|
||
}
|
||
|
||
//
|
||
// Is this a bus translated resource list???
|
||
//
|
||
if (i >= busTranslatedLength &&
|
||
RtlCompareMemory(
|
||
((PUCHAR) u.valueKeyFullInf->Name) + i - busTranslatedLength,
|
||
rgzBusTranslated,
|
||
busTranslatedLength) != busTranslatedLength
|
||
) {
|
||
|
||
//
|
||
// Ends in rgzBusTranslated
|
||
//
|
||
continue;
|
||
|
||
}
|
||
|
||
//
|
||
// we now have a pointer to the cm resource list
|
||
//
|
||
cmResList = (PCM_RESOURCE_LIST) ( (PUCHAR) u.valueKeyFullInf +
|
||
u.valueKeyFullInf->DataOffset);
|
||
lastAddr = (PUCHAR) cmResList + u.valueKeyFullInf->DataLength;
|
||
|
||
//
|
||
// We must flatten this list down to one level, so lets
|
||
// figure out how many descriptors we need
|
||
//
|
||
cmFullResList = cmResList->List;
|
||
for (temp = i = 0; i < cmResList->Count; i++) {
|
||
|
||
if ( (PUCHAR) cmFullResList > lastAddr) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
temp += cmFullResList->PartialResourceList.Count;
|
||
|
||
//
|
||
// next CM_FULL_RESOURCE_DESCRIPTOR
|
||
//
|
||
cmFullResList =
|
||
(PCM_FULL_RESOURCE_DESCRIPTOR) ( (PUCHAR) cmFullResList
|
||
+ sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
|
||
(cmFullResList->PartialResourceList.Count - 1) *
|
||
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) );
|
||
|
||
}
|
||
|
||
//
|
||
// Now that we have the number of descriptors, allocate this
|
||
// much space
|
||
//
|
||
tempCmList = ExAllocatePool(
|
||
PagedPool,
|
||
sizeof(CM_RESOURCE_LIST) + (temp - 1) *
|
||
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
|
||
);
|
||
if (tempCmList == NULL) {
|
||
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Now, fill up the flatened list
|
||
//
|
||
RtlCopyMemory(
|
||
tempCmList,
|
||
cmResList,
|
||
sizeof(CM_RESOURCE_LIST) -
|
||
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
|
||
);
|
||
tempCmList->Count = 1;
|
||
tempCmList->List->PartialResourceList.Count = temp;
|
||
|
||
//
|
||
// This is a brute force approach
|
||
//
|
||
cmFullResList = cmResList->List;
|
||
for (temp = i = 0; i < cmResList->Count; i++) {
|
||
|
||
if ( (PUCHAR) cmFullResList > lastAddr) {
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Copy the current descriptors over
|
||
//
|
||
RtlCopyMemory(
|
||
&(tempCmList->List->PartialResourceList.PartialDescriptors[temp]),
|
||
cmFullResList->PartialResourceList.PartialDescriptors,
|
||
cmFullResList->PartialResourceList.Count *
|
||
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
|
||
);
|
||
|
||
|
||
temp += cmFullResList->PartialResourceList.Count;
|
||
|
||
//
|
||
// next CM_FULL_RESOURCE_DESCRIPTOR
|
||
//
|
||
cmFullResList =
|
||
(PCM_FULL_RESOURCE_DESCRIPTOR) ( (PUCHAR) cmFullResList
|
||
+ sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
|
||
(cmFullResList->PartialResourceList.Count - 1) *
|
||
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) );
|
||
|
||
}
|
||
|
||
//
|
||
// Add it to the global list
|
||
//
|
||
status = ACPIRangeAddCmList(
|
||
&globalResList,
|
||
tempCmList
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
ACPIPrint( (
|
||
ACPI_PRINT_CRITICAL,
|
||
"ACPIRootUpdateRootResourcesWithHalResources: "
|
||
"ACPIRangeAddCmList = 0x%08lx\n",
|
||
status
|
||
) );
|
||
ExFreePool( tempCmList );
|
||
break;
|
||
|
||
}
|
||
ExFreePool( tempCmList );
|
||
|
||
} // for -- Next driverValueIndex
|
||
|
||
if (driverKeyHandle != INVALID_HANDLE) {
|
||
|
||
ZwClose( driverKeyHandle);
|
||
driverKeyHandle = INVALID_HANDLE;
|
||
|
||
}
|
||
|
||
if (status == STATUS_NO_MORE_ENTRIES) {
|
||
|
||
status = STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
} // while -- Next driverKeyIndex
|
||
|
||
if (classKeyHandle != INVALID_HANDLE) {
|
||
|
||
ZwClose( classKeyHandle );
|
||
classKeyHandle = INVALID_HANDLE;
|
||
|
||
}
|
||
|
||
if (status == STATUS_NO_MORE_ENTRIES) {
|
||
|
||
status = STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
} // while -- next classKeyIndex
|
||
|
||
if (status == STATUS_NO_MORE_ENTRIES) {
|
||
|
||
status = STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
ZwClose( resourceMap );
|
||
ExFreePool( u.buffer );
|
||
|
||
//
|
||
// Remember the new global list
|
||
//
|
||
RootDeviceExtension->ResourceList = globalResList;
|
||
|
||
return status;
|
||
}
|
||
|