windows-nt/Source/XPSP1/NT/base/busdrv/acpi/driver/nt/idevice.c

416 lines
8.7 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
bus.c
Abstract:
This module contains the bus dispatcher for the ACPI driver, NT version
Author:
Stephane Plante (splante)
Environment:
NT Kernel Model Driver only
--*/
#include "pch.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, ACPIInternalDeviceClockIrpStartDevice)
#pragma alloc_text(PAGE, ACPIInternalDeviceQueryCapabilities)
#pragma alloc_text(PAGE, ACPIInternalDeviceQueryDeviceRelations)
#endif
NTSTATUS
ACPIInternalDeviceClockIrpStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This function is called to start the Real-Time Clock in the system. This
is similar to starting all the other devices in the system, except that
in this case, we send a WAIT_WAKE irp to the device
Arguments:
DeviceObject - The real-time clock object
Irp - The start request
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
PAGED_CODE();
//
// Start the device
//
status = ACPIInitStartDevice(
DeviceObject,
NULL,
ACPIInternalDeviceClockIrpStartDeviceCompletion,
Irp,
Irp
);
if (NT_SUCCESS(status)) {
return STATUS_PENDING;
} else {
return status;
}
}
VOID
ACPIInternalDeviceClockIrpStartDeviceCompletion(
IN PDEVICE_EXTENSION DeviceExtension,
IN PVOID Context,
IN NTSTATUS Status
)
/*++
Routine Description:
This is the callback routine that is invoked when we have finished
programming the resources
Arguments:
DeviceExtension - Extension of the device that was started
Context - The Irp
Status - The Result
Return Value:
None
--*/
{
KIRQL oldIrql;
IO_STATUS_BLOCK ioStatus;
PIRP irp = (PIRP) Context;
POWER_STATE state;
irp->IoStatus.Status = Status;
if (NT_SUCCESS(Status)) {
//
// Remember that the device is started
//
DeviceExtension->DeviceState = Started;
//
// If the device doesn't support Wakeup, then we don't have to
// anything else here
//
if ( !(DeviceExtension->Flags & DEV_CAP_WAKE) ) {
goto ACPIInternalDeviceClockIrpStartDeviceCompletionExit;
}
//
// Make sure that we are holding the power lock
//
KeAcquireSpinLock( &AcpiPowerLock, &oldIrql );
//
// Remember the maximum state that the clock can wake the system
//
state.SystemState = DeviceExtension->PowerInfo.SystemWakeLevel;
//
// Done with the lock
//
KeReleaseSpinLock( &AcpiPowerLock, oldIrql );
//
// Initialize the IO_STATUS_BLOCK that we will use to start the wait
// wake loop
//
ioStatus.Status = STATUS_SUCCESS;
ioStatus.Information = 0;
//
// Start the wait wake loop
//
Status = ACPIInternalWaitWakeLoop(
DeviceExtension->DeviceObject,
IRP_MN_WAIT_WAKE,
state,
NULL,
&ioStatus
);
if (!NT_SUCCESS(Status)) {
irp->IoStatus.Status = Status;
goto ACPIInternalDeviceClockIrpStartDeviceCompletionExit;
}
}
ACPIInternalDeviceClockIrpStartDeviceCompletionExit:
//
// Complete the irp
//
IoCompleteRequest( irp, IO_NO_INCREMENT );
}
NTSTATUS
ACPIInternalDeviceQueryCapabilities(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the dispatch point for the IRP_MN_QUERY_CAPABILITIES requests sent
to the PDO
Arguments:
DeviceObject - Pointer to the device object we received the request for
Irp - Pointer to the request
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CAPABILITIES capabilities;
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
PAGED_CODE();
//
// Grab a pointer to the capabilities
//
capabilities = irpStack->Parameters.DeviceCapabilities.Capabilities;
#ifndef HANDLE_BOGUS_CAPS
if (capabilities->Version < 1) {
//
// do not touch irp!
//
status = Irp->IoStatus.Status;
goto ACPIInternalDeviceQueryCapabilitiesExit;
}
#endif
//
// Set the current flags for the capabilities
//
capabilities->UniqueID = (deviceExtension->InstanceID == NULL ?
FALSE : TRUE);
capabilities->RawDeviceOK = (deviceExtension->Flags & DEV_CAP_RAW) ?
TRUE : FALSE;
capabilities->SilentInstall = TRUE;
//
// Do the power capabilities
//
status = ACPISystemPowerQueryDeviceCapabilities(
deviceExtension,
capabilities
);
if (!NT_SUCCESS(status)) {
ACPIDevPrint( (
ACPI_PRINT_CRITICAL,
deviceExtension,
" - Could query device capabilities - %08lx",
status
) );
goto ACPIInternalDeviceQueryCapabilitiesExit;
}
ACPIInternalDeviceQueryCapabilitiesExit:
//
// Done...
//
Irp->IoStatus.Status = status;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return status;
}
NTSTATUS
ACPIInternalDeviceQueryDeviceRelations(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the dispatch point for the IRP_MN_QUERY_DEVICE_RELATION
PNP minor function
Arguments:
DeviceObject - The object that we care about
Irp - The request in question
Return Value:
NTSTATUS
--*/
{
NTSTATUS status ;
PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
PDEVICE_RELATIONS deviceRelations = NULL;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
UCHAR minorFunction = irpStack->MinorFunction;
PAGED_CODE();
switch(irpStack->Parameters.QueryDeviceRelations.Type) {
case TargetDeviceRelation:
status = ACPIBusIrpQueryTargetRelation(
DeviceObject,
Irp,
&deviceRelations
);
break ;
default:
status = STATUS_NOT_SUPPORTED;
ACPIDevPrint( (
ACPI_PRINT_IRP,
deviceExtension,
"(0x%08lx): %s - Unhandled Type %d\n",
Irp,
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
irpStack->Parameters.QueryDeviceRelations.Type
) );
break ;
}
//
// If we succeeds, then we can always write to the irp
//
if (NT_SUCCESS(status)) {
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
} else if (status != STATUS_NOT_SUPPORTED) {
//
// If we haven't succeed the irp, then we can also fail it
//
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = (ULONG_PTR) NULL;
} else {
//
// Grab our status from what is already present
//
status = Irp->IoStatus.Status;
}
//
// Done with the irp
//
IoCompleteRequest( Irp, IO_NO_INCREMENT );
//
// Done
//
ACPIDevPrint( (
ACPI_PRINT_IRP,
deviceExtension,
"(0x%08lx): %s = 0x%08lx\n",
Irp,
ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
status
) );
return status;
}
NTSTATUS
ACPIInternalWaitWakeLoop(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
This routine is called after the WAIT_WAKE on the RTC has been completed
Arguments:
DeviceObject - The RTC PDO
MinorFunction - IRP_MN_WAIT_WAKE
PowerState - The Sleep state that it could wake from
Context - NOT USED
IoStatus - The status of the request
Return Value:
NTSTATUS
--*/
{
if (!NT_SUCCESS(IoStatus->Status)) {
return IoStatus->Status;
}
//
// In this case, we just cause the same thing to happen again
//
PoRequestPowerIrp(
DeviceObject,
MinorFunction,
PowerState,
ACPIInternalWaitWakeLoop,
Context,
NULL
);
//
// Done
//
return STATUS_SUCCESS;
}