Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2140 lines
52 KiB

/*++
Copyright (c) 2000-2001 Microsoft Corporation
Module Name:
dispatch.c
Abstract:
ACPI BIOS Simulator / Generic 3rd Party Operation Region Provider
Pnp / Power handler module
Author(s):
Vincent Geglia
Michael T. Murphy
Chris Burgess
Environment:
Kernel mode
Notes:
Revision History:
--*/
//
// General includes
//
#include "ntddk.h"
//
// Specific includes
//
#include "acpisim.h"
#include "dispatch.h"
#include "util.h"
//
// Private function prototypes
//
NTSTATUS
AcpisimPnpStartDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimPnpStopDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimPnpQueryStopDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimPnpCancelStopDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimPnpRemoveDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimPnpQueryRemoveDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimPnpCancelRemoveDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimPnpSurpriseRemoval
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimPnpQueryCapabilities
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimPowerQueryPower
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimPowerSetPower
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimPowerSIrp
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimQueryPowerDIrp
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimSetPowerDIrp
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimCompletionRoutine
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
AcpisimForwardIrpAndWait
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
AcpisimIssuePowerDIrp
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS
AcpisimCompleteSIrp
(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
);
NTSTATUS
AcpisimD0Completion
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
VOID
AcpisimInitDevPowerStateTable
(
IN PDEVICE_OBJECT DeviceObject
);
//
// Pnp minor dispatch table
//
IRP_DISPATCH_TABLE PnpDispatchTable[] = {
IRP_MN_START_DEVICE, "Pnp/START_DEVICE", AcpisimPnpStartDevice,
IRP_MN_STOP_DEVICE, "Pnp/STOP_DEVICE", AcpisimPnpStopDevice,
IRP_MN_QUERY_STOP_DEVICE, "Pnp/QUERY_STOP_DEVICE", AcpisimPnpQueryStopDevice,
IRP_MN_CANCEL_STOP_DEVICE, "Pnp/CANCEL_STOP_DEVICE", AcpisimPnpCancelStopDevice,
IRP_MN_REMOVE_DEVICE, "Pnp/REMOVE_DEVICE", AcpisimPnpRemoveDevice,
IRP_MN_QUERY_REMOVE_DEVICE, "Pnp/QUERY_REMOVE_DEVICE", AcpisimPnpQueryRemoveDevice,
IRP_MN_CANCEL_REMOVE_DEVICE,"Pnp/CANCEL_REMOVE_DEVICE", AcpisimPnpCancelRemoveDevice,
IRP_MN_SURPRISE_REMOVAL, "Pnp/SURPRISE_REMOVAL", AcpisimPnpSurpriseRemoval,
IRP_MN_QUERY_CAPABILITIES, "Pnp/QUERY_CAPABILITIIES", AcpisimPnpQueryCapabilities
};
//
// Power minor dispatch table
//
IRP_DISPATCH_TABLE PowerDispatchTable[] = {
IRP_MN_QUERY_POWER, "Power/QUERY_POWER", AcpisimPowerQueryPower,
IRP_MN_SET_POWER, "Power/SET_POWER", AcpisimPowerSetPower
};
NTSTATUS
AcpisimDispatchPnp
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the pnp IRP handler. It checks the minor code,
and passes on to the appropriate minor handler.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
result of IRP processing
--*/
{
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG count = 0;
DBG_PRINT (DBG_INFO, "Entering AcpisimDispatchPnp.\n");
while (count < sizeof (PnpDispatchTable) / sizeof (IRP_DISPATCH_TABLE)) {
if (irpsp->MinorFunction == PnpDispatchTable[count].IrpFunction) {
DBG_PRINT (DBG_INFO,
"Recognized PnP IRP 0x%x '%s'.\n",
irpsp->MinorFunction,
PnpDispatchTable[count].IrpName);
status = PnpDispatchTable[count].IrpHandler (DeviceObject, Irp);
goto EndAcpisimDispatchPnp;
}
count ++;
}
DBG_PRINT (DBG_INFO, "Unrecognized PnP IRP 0x%x, pass it on.\n", irpsp->MinorFunction);
IoSkipCurrentIrpStackLocation (Irp);
status = IoCallDriver (deviceextension->NextDevice, Irp);
EndAcpisimDispatchPnp:
DBG_PRINT (DBG_INFO, "Exiting AcpisimDispatchPnp.\n");
return status;
}
NTSTATUS
AcpisimDispatchPower
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the power IRP handler. It checks the minor code,
and passes on to the appropriate minor handler.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
result of IRP processing
--*/
{
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG count = 0;
DBG_PRINT (DBG_INFO, "Entering AcpisimDispatchPower.\n");
while (count < sizeof (PowerDispatchTable) / sizeof (IRP_DISPATCH_TABLE)) {
if (irpsp->MinorFunction == PowerDispatchTable[count].IrpFunction) {
DBG_PRINT (DBG_INFO,
"Recognized Power IRP 0x%x '%s'.\n",
irpsp->MinorFunction,
PowerDispatchTable[count].IrpName);
status = PowerDispatchTable[count].IrpHandler (DeviceObject, Irp);
goto EndAcpisimDispatchPower;
}
count ++;
}
DBG_PRINT (DBG_INFO, "Unrecognized Power IRP 0x%x, pass it on.\n", irpsp->MinorFunction);
PoStartNextPowerIrp (Irp);
IoSkipCurrentIrpStackLocation (Irp);
status = PoCallDriver (deviceextension->NextDevice, Irp);
EndAcpisimDispatchPower:
DBG_PRINT (DBG_INFO, "Exiting AcpisimDispatchPower.\n");
return status;
}
NTSTATUS
AcpisimPnpStartDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the Pnp Start Device handler. It enables the device interface
and registers the operation region handler.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
result of IRP_MN_START_DEVICE processing
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
KIRQL oldirql;
DBG_PRINT (DBG_INFO,
"Entering AcpisimPnpStartDevice.\n");
//
// We handle this IRP on the way back up.
//
status = AcpisimForwardIrpAndWait (DeviceObject, Irp);
ASSERT (NT_SUCCESS (status));
if ((status != STATUS_SUCCESS && status != STATUS_PENDING) || !NT_SUCCESS (Irp->IoStatus.Status)) {
DBG_PRINT (DBG_ERROR,
"Error processing, or lower driver failed start IRP. IoCallDriver = %lx, Irp->IoStatus.Status = %lx\n",
status,
Irp->IoStatus.Status);
goto EndAcpisimPnpStartDevice;
}
//
// Check to see if we are already started. If we are,
// just return success since we aren't using resources
// anyway.
//
if (deviceextension->PnpState == PNP_STATE_STARTED) {
status = STATUS_SUCCESS;
goto EndAcpisimPnpStartDevice;
}
//
// Enable our device interface
//
status = AcpisimEnableDisableDeviceInterface (DeviceObject, TRUE);
ASSERT (NT_SUCCESS (status));
if (!NT_SUCCESS (status)) {
DBG_PRINT (DBG_ERROR,
"Error enabling device interface. Fail the start. Status = %lx.\n",
status);
Irp->IoStatus.Status = status;
goto EndAcpisimPnpStartDevice;
}
AcpisimSetDevExtFlags (DeviceObject, DE_FLAG_INTERFACE_ENABLED);
//
// Typically, we would check the state of our hardware, and
// set our internal power state to reflect the current state
// of the hardware. However, in this case we are a virtual
// device, and it is safe to assume we are in D0 when we
// receive IRP_MN_START_DEVICE.
//
AcpisimUpdatePowerState (DeviceObject, POWER_STATE_WORKING);
AcpisimUpdateDevicePowerState (DeviceObject, PowerDeviceD0);
//
// Finally, we can register our operation region handler.
//
status = AcpisimRegisterOpRegionHandler (DeviceObject);
ASSERT (NT_SUCCESS (status));
if (!NT_SUCCESS (status)) {
DBG_PRINT (DBG_ERROR,
"Couldn't register op region handler (%lx). Fail start IRP.\n",
status);
goto EndAcpisimPnpStartDevice;
}
AcpisimSetDevExtFlags (DeviceObject, DE_FLAG_OPREGION_REGISTERED);
EndAcpisimPnpStartDevice:
//
// If we completed the start successfully, change our pnp state
// to PNP_STARTED
//
if (NT_SUCCESS (status)) {
AcpisimUpdatePnpState (DeviceObject, PNP_STATE_STARTED);
} else {
AcpisimUpdatePnpState (DeviceObject, PNP_STATE_STOPPED);
}
//
// Because we are handling this IRP "on the way up", we need
// to complete it when we are done working with it.
//
IoCompleteRequest (Irp, IO_NO_INCREMENT);
DBG_PRINT (DBG_INFO,
"Exiting AcpisimPnpStartDevice.\n");
return status;
}
NTSTATUS
AcpisimPnpStopDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the Pnp Stop Device handler. It checks to see if
there are any outstanding requests, and fails the stop IRP
if there are.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
result of IRP_MN_STOP_DEVICE processing
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
DBG_PRINT (DBG_INFO,
"Entering AcpisimPnpStopDevice.\n");
//
// BUGBUG - We currently don't handle the case where
// there is still an outstanding request at stop
// time. If we were to do things correctly, we'd
// complete any outstanding requests in the driver
// with an appropriate error code. In this
// particular case, if a request happened to squeak
// by our check at QUERY STOP time, it is likely
// the request would not be completed at all.
//
//
// Oh, and we had better not have LESS then 2 count
// or we've got a bug somewhere.
//
if (deviceextension->OutstandingIrpCount < 2) {
DBG_PRINT (DBG_WARN,
"Possible internal consistency error - OutstandingIrpCount too low.\n");
}
ASSERT (deviceextension->OutstandingIrpCount == 2);
IoSkipCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
status = IoCallDriver (deviceextension->NextDevice, Irp);
ASSERT (NT_SUCCESS (status));
if (!NT_SUCCESS (status)) {
DBG_PRINT (DBG_ERROR,
"IRP_MN_STOP forwarding failed (%lx).\n",
status);
goto EndAcpisimPnpStopDevice;
}
AcpisimUpdatePnpState (DeviceObject, PNP_STATE_STOPPED);
EndAcpisimPnpStopDevice:
DBG_PRINT (DBG_INFO,
"Exiting AcpisimPnpStopDevice.\n");
return status;
}
NTSTATUS
AcpisimPnpQueryStopDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the Pnp Query Stop Device handler. If there are any
outstanding requests, it vetos the IRP.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
result of IRP_MN_QUERY_STOP_DEVICE processing
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
DBG_PRINT (DBG_INFO,
"Entering AcpisimPnpQueryStopDevice.\n");
//
// Let existing IRPs in the driver complete before we say OK.
// But to do this, we need to get the OutstandingIrpsCount
// right. Subtract 2 since we are biased to 1, and we have an
// additional 1 for the QUERY_STOP IRP.
//
AcpisimDecrementIrpCount (DeviceObject);
AcpisimDecrementIrpCount (DeviceObject);
status = KeWaitForSingleObject (&deviceextension->IrpsCompleted,
Executive,
KernelMode,
FALSE,
0);
InterlockedIncrement (&deviceextension->OutstandingIrpCount);
InterlockedIncrement (&deviceextension->OutstandingIrpCount);
KeResetEvent (&deviceextension->IrpsCompleted);
ASSERT (NT_SUCCESS (status));
if (!NT_SUCCESS (status)) {
DBG_PRINT (DBG_ERROR,
"KeWaitForSingleObject failed (%lx). IRP_MN_QUERY_STOP failed.\n",
status);
IoSkipCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
status = IoCallDriver (deviceextension->NextDevice, Irp);
ASSERT (NT_SUCCESS (status));
goto EndPnpQueryStopDevice;
}
//
// We can stop - change our state to stopping, and pass it on.
//
IoSkipCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
status = IoCallDriver (deviceextension->NextDevice, Irp);
AcpisimUpdatePnpState (DeviceObject, PNP_STATE_STOP_PENDING);
EndPnpQueryStopDevice:
DBG_PRINT (DBG_INFO,
"Exiting AcpisimPnpQueryStopDevice.\n");
return status;
}
NTSTATUS
AcpisimPnpCancelStopDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the Pnp Cancel Stop Device handler. It does nothing
more then returns the pnp state to started. This is a virtual
device so there is no work to do.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
STATUS_SUCCESS
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
DBG_PRINT (DBG_INFO,
"Entering AcpisimPnpCancelStopDevice.\n");
status = AcpisimForwardIrpAndWait (DeviceObject, Irp);
ASSERT (NT_SUCCESS (status));
if (!NT_SUCCESS (status)) {
DBG_PRINT (DBG_ERROR,
"IRP_MN_CANCEL_STOP forwarding failed (%lx).\n",
status);
goto EndPnpCancelStopDevice;
}
status = STATUS_SUCCESS;
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, 0);
AcpisimUpdatePnpState (DeviceObject, PNP_STATE_STARTED);
EndPnpCancelStopDevice:
DBG_PRINT (DBG_INFO,
"Exiting AcpisimPnpCancelStopDevice.\n");
return status;
}
NTSTATUS
AcpisimPnpRemoveDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the Pnp Remove Device handler. It de-registers the
operation region handler, detaches the device object, and
deletes it if all goes well.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
status of removal operation
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
PDEVICE_OBJECT nextdevice = deviceextension->NextDevice;
DBG_PRINT (DBG_INFO,
"Entering AcpisimPnpRemoveDevice.\n");
//
// BUGBUG - We currently don't handle the case where
// there is still an outstanding request at remove
// time. If we were to do things correctly, we'd
// complete any outstanding requests in the driver
// with an appropriate error code. In this
// particular case, if a request happened to squeak
// by our check at QUERY REMOVE time, it is likely
// the request would not be completed at all.
//
//
// Our OutstandingIrpCount logic is biased to 1. So
// if we are processing a remove IRP, and there are
// no other requests in the driver, OustandingIrpCount
// had better be 2.
if (deviceextension->OutstandingIrpCount < 2) {
DBG_PRINT (DBG_WARN,
"Possible internal consistency error - OutstandingIrpCount too low.\n");
}
ASSERT (deviceextension->OutstandingIrpCount == 2);
//
// Ok, we are ready to remove the device. Shut down the
// interface, deregister the opregion handler, and
// delete the device object.
//
status = AcpisimEnableDisableDeviceInterface (DeviceObject, FALSE);
ASSERT (NT_SUCCESS (status));
if (NT_SUCCESS (status)) {
AcpisimClearDevExtFlags (DeviceObject, DE_FLAG_INTERFACE_ENABLED);
}
status = AcpisimUnRegisterOpRegionHandler (DeviceObject);
ASSERT (NT_SUCCESS (status));
if (NT_SUCCESS (status)) {
AcpisimClearDevExtFlags (DeviceObject, DE_FLAG_OPREGION_REGISTERED);
}
RtlFreeUnicodeString (&deviceextension->InterfaceString);
IoDetachDevice (deviceextension->NextDevice);
IoDeleteDevice (DeviceObject);
//
// Now, pass it on...
//
IoSkipCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
status = IoCallDriver (nextdevice, Irp);
ASSERT (NT_SUCCESS (status));
if (!NT_SUCCESS (status)) {
DBG_PRINT (DBG_ERROR,
"Passing remove IRP onto next driver failed for some reason (%lx).\n",
status);
}
DBG_PRINT (DBG_INFO,
"Exiting AcpisimPnpRemoveDevice.\n");
return status;
}
NTSTATUS
AcpisimPnpQueryRemoveDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the Pnp Query Remove Device handler. It waits for
existing requests in the driver to finish, and then completes
the IRP successfully.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
Status of query remove device operation
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
DBG_PRINT (DBG_INFO,
"Entering AcpisimPnpQueryRemoveDevice.\n");
//
// Make sure our state is correct
//
ASSERT (deviceextension->OutstandingIrpCount >= 2);
//
// Let existing IRPs in the driver complete before we say OK.
// But to do this, we need to get the OutstandingIrpsCount
// right. Subtract 2 since we are biased to 1, and we have an
// additional 1 for the QUERY_STOP IRP.
//
AcpisimDecrementIrpCount (DeviceObject);
AcpisimDecrementIrpCount (DeviceObject);
status = KeWaitForSingleObject (&deviceextension->IrpsCompleted,
Executive,
KernelMode,
FALSE,
0);
InterlockedIncrement (&deviceextension->OutstandingIrpCount);
InterlockedIncrement (&deviceextension->OutstandingIrpCount);
KeResetEvent (&deviceextension->IrpsCompleted);
ASSERT (NT_SUCCESS (status));
if (!NT_SUCCESS (status)) {
DBG_PRINT (DBG_ERROR,
"KeWaitForSingleObject failed (%lx). IRP_MN_QUERY_REMOVE failed.\n",
status);
IoSkipCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
status = IoCallDriver (deviceextension->NextDevice, Irp);
ASSERT (NT_SUCCESS (status));
goto EndPnpQueryRemoveDevice;
}
//
// We can remove - change our state to remove pending, and pass it on.
//
IoSkipCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
status = IoCallDriver (deviceextension->NextDevice, Irp);
AcpisimUpdatePnpState (DeviceObject, PNP_STATE_REMOVE_PENDING);
EndPnpQueryRemoveDevice:
DBG_PRINT (DBG_INFO,
"Exiting AcpisimPnpQueryRemoveDevice.\n");
return status;
}
NTSTATUS
AcpisimPnpCancelRemoveDevice
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the Pnp Cancel Remove Device handler. It does nothing
more then returns the pnp state to started. This is a virtual
device so there is no work to do.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
STATUS_SUCCESS
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
DBG_PRINT (DBG_INFO,
"Entering AcpisimPnpCancelRemoveDevice.\n");
status = AcpisimForwardIrpAndWait (DeviceObject, Irp);
ASSERT (NT_SUCCESS (status));
if (!NT_SUCCESS (status)) {
DBG_PRINT (DBG_ERROR,
"IRP_MN_CANCEL_REMOVE forwarding failed (%lx).\n",
status);
goto EndPnpCancelRemoveDevice;
}
status = STATUS_SUCCESS;
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, 0);
AcpisimUpdatePnpState (DeviceObject, PNP_STATE_STARTED);
EndPnpCancelRemoveDevice:
DBG_PRINT (DBG_INFO,
"Exiting AcpisimPnpCancelRemoveDevice.\n");
return status;
}
NTSTATUS
AcpisimPnpSurpriseRemoval
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the Pnp Surprise Remove handler. It basically updates
the state, and passes the IRP on.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
STATUS_SUCCESS
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
DBG_PRINT (DBG_INFO,
"Entering AcpisimPnpSurpriseRemoval.\n");
//
// Again, because we are a virtual device, handling
// surprise remove is really a no-op. Just update
// our state, and succeed the IRP.
//
AcpisimUpdatePnpState (DeviceObject, PNP_STATE_SURPRISE_REMOVAL);
IoSkipCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
status = IoCallDriver (deviceextension->NextDevice, Irp);
ASSERT (NT_SUCCESS (status));
DBG_PRINT (DBG_INFO,
"Exiting AcpisimPnpSurpriseRemoval.\n");
return status;
}
NTSTATUS
AcpisimPnpQueryCapabilities
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine handles IRP_MN_QUERY_CAPABILITIES. We need this
information to build our power state table correctly. All
we do here is set a completion routine, as we need to gather this
data after the PDO has filled out DeviceState.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
Status of operation
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
PIO_STACK_LOCATION irpsp;
UCHAR count = 0;
DBG_PRINT (DBG_INFO,
"Entering AcpisimPnpQueryCapabilities.\n");
//
// Fill out the power mapping table with a default
//
AcpisimInitDevPowerStateTable (DeviceObject);
//
// Handle this IRP after the PDO has filled out the structure
//
status = AcpisimForwardIrpAndWait (DeviceObject, Irp);
if (!NT_SUCCESS (status)) {
DBG_PRINT (DBG_ERROR, "Somebody failed the QUERY_CAPABILITIES IRP...\n");
goto EndAcpisimPnpQueryCapabilities;
}
irpsp = IoGetCurrentIrpStackLocation (Irp);
//
// Update our power mappings with what we found in the device
// capabilities structure. We only use valid mappings, e.g.
// PowerDeviceUnspecified is ignored.
//
DBG_PRINT (DBG_INFO, "Device mappings:\n");
for (count = 0; count < 6; count ++) {
if (irpsp->Parameters.DeviceCapabilities.Capabilities->DeviceState[count + 1] != PowerDeviceUnspecified) {
deviceextension->PowerMappings[count] = irpsp->Parameters.DeviceCapabilities.Capabilities->DeviceState [count + 1];
}
DBG_PRINT (DBG_INFO, "S%d --> D%d\n", count, deviceextension->PowerMappings[count] - 1);
}
status = STATUS_SUCCESS;
Irp->IoStatus.Status = status;
EndAcpisimPnpQueryCapabilities:
IoCompleteRequest (Irp, IO_NO_INCREMENT);
DBG_PRINT (DBG_INFO,
"Exiting AcpisimPnpQueryCapabilities.\n");
return status;
}
NTSTATUS
AcpisimPowerQueryPower
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the QUERY Power handler. It determines if the power
IRP is an S or D IRP, and passes it on to the proper handler.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
Status returned from power handler
--*/
{
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
NTSTATUS status = STATUS_UNSUCCESSFUL;
DBG_PRINT (DBG_INFO,
"Entering AcpisimPowerQueryPower.\n");
switch (irpsp->Parameters.Power.Type) {
case SystemPowerState:
status = AcpisimPowerSIrp (DeviceObject, Irp);
break;
case DevicePowerState:
status = AcpisimQueryPowerDIrp (DeviceObject, Irp);
break;
default:
DBG_PRINT (DBG_ERROR,
"Undefined QUERY Power IRP type. Ignoring.\n");
IoSkipCurrentIrpStackLocation (Irp);
status = IoCallDriver (deviceextension->NextDevice, Irp);
}
DBG_PRINT (DBG_INFO,
"Exiting AcpisimPowerQueryPower.\n");
return status;
}
NTSTATUS
AcpisimPowerSetPower
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the SET Power handler. It determines if the power
IRP is an S or D IRP, and passes it on to the proper handler.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
Status returned from power handler
--*/
{
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
NTSTATUS status = STATUS_UNSUCCESSFUL;
DBG_PRINT (DBG_INFO,
"Entering AcpisimPowerSetPower.\n");
switch (irpsp->Parameters.Power.Type) {
case SystemPowerState:
status = AcpisimPowerSIrp (DeviceObject, Irp);
break;
case DevicePowerState:
status = AcpisimSetPowerDIrp (DeviceObject, Irp);
break;
default:
DBG_PRINT (DBG_ERROR,
"Undefined SET Power IRP type. Ignoring.\n");
IoSkipCurrentIrpStackLocation (Irp);
status = IoCallDriver (deviceextension->NextDevice, Irp);
}
DBG_PRINT (DBG_INFO,
"Exiting AcpisimPowerSetPower.\n");
return status;
}
NTSTATUS
AcpisimPowerSIrp
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the power handler for S IRPs. It sets a
completion routine, which will queue a D IRP. We don't
do anything unless it is a D IRP.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
Status returned from power handler
--*/
{
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
DBG_PRINT (DBG_INFO,
"Entering AcpisimPowerSIrp.\n");
IoMarkIrpPending (Irp);
IoCopyCurrentIrpStackLocationToNext (Irp);
IoSetCompletionRoutine (Irp,
AcpisimIssuePowerDIrp,
0,
TRUE,
TRUE,
TRUE);
PoCallDriver (deviceextension->NextDevice, Irp);
DBG_PRINT (DBG_INFO,
"Exiting AcpisimPowerSIrp.\n");
return STATUS_PENDING;
}
NTSTATUS
AcpisimQueryPowerDIrp
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the QUERY Power DIrp handler. Validate the state, and
say yes.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
Status returned from power handler
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
DBG_PRINT (DBG_INFO,
"Entering AcpisimQueryPowerDIrp.\n");
//
// Here, we are supposed to figure out if we can go to the
// power state specified by the IRP. Since we are a virtual
// device, we don't have a good reason to not go to a different
// power state. Update our state, and wait to complete requests.
//
AcpisimDecrementIrpCount (DeviceObject);
AcpisimDecrementIrpCount (DeviceObject);
AcpisimDecrementIrpCount (DeviceObject);
status = KeWaitForSingleObject (&deviceextension->IrpsCompleted,
Executive,
KernelMode,
FALSE,
0);
InterlockedIncrement (&deviceextension->OutstandingIrpCount);
InterlockedIncrement (&deviceextension->OutstandingIrpCount);
KeResetEvent (&deviceextension->IrpsCompleted);
ASSERT (NT_SUCCESS (status));
//
// Validate the D IRP
//
switch (irpsp->Parameters.Power.State.DeviceState) {
case PowerDeviceD0:
case PowerDeviceD1:
case PowerDeviceD2:
case PowerDeviceD3:
AcpisimUpdatePowerState (DeviceObject, POWER_STATE_POWER_PENDING);
status = STATUS_SUCCESS;
break;
default:
ASSERT (0);
DBG_PRINT (DBG_ERROR,
"AcpisimQueryPowerDIrp: Illegal or unknown PowerDeviceState. Failing.\n");
status = STATUS_INVALID_DEVICE_REQUEST;
}
PoStartNextPowerIrp (Irp);
IoSkipCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = status;
status = PoCallDriver (deviceextension->NextDevice, Irp);
ASSERT (NT_SUCCESS (status));
DBG_PRINT (DBG_INFO,
"Leaving AcpisimQueryPowerDIrp.\n");
return status;
}
NTSTATUS
AcpisimSetPowerDIrp
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
POWER_STATE powerstate;
DBG_PRINT (DBG_INFO,
"Entering AcpisimSetPowerDIrp.\n");
//
// Validate the D IRP
//
switch (irpsp->Parameters.Power.State.DeviceState) {
//
// For D0, if we are powered down, we need to pass the IRP down, and
// set a completion routine. We need the PDO to succeed the power
// up before we do.
//
case PowerDeviceD0:
if (deviceextension->PowerState != POWER_STATE_WORKING) {
IoCopyCurrentIrpStackLocationToNext (Irp);
IoSetCompletionRoutine (Irp,
AcpisimD0Completion,
0,
TRUE,
TRUE,
TRUE);
IoMarkIrpPending (Irp);
PoCallDriver (deviceextension->NextDevice, Irp);
status = STATUS_PENDING;
goto EndAcpisimSetPowerDIrp;
}
break;
case PowerDeviceD1:
powerstate.DeviceState = PowerDeviceD1;
PoSetPowerState (DeviceObject, DevicePowerState, powerstate);
AcpisimUpdatePowerState (DeviceObject, POWER_STATE_POWERED_DOWN);
AcpisimUpdateDevicePowerState (DeviceObject, irpsp->Parameters.Power.State.DeviceState);
status = STATUS_SUCCESS;
break;
case PowerDeviceD2:
powerstate.DeviceState = PowerDeviceD2;
PoSetPowerState (DeviceObject, DevicePowerState, powerstate);
AcpisimUpdatePowerState (DeviceObject, POWER_STATE_POWERED_DOWN);
AcpisimUpdateDevicePowerState (DeviceObject, irpsp->Parameters.Power.State.DeviceState);
status = STATUS_SUCCESS;
break;
case PowerDeviceD3:
powerstate.DeviceState = PowerDeviceD3;
PoSetPowerState (DeviceObject, DevicePowerState, powerstate);
AcpisimUpdatePowerState (DeviceObject, POWER_STATE_POWERED_DOWN);
AcpisimUpdateDevicePowerState (DeviceObject, irpsp->Parameters.Power.State.DeviceState);
status = STATUS_SUCCESS;
break;
default:
ASSERT (0);
DBG_PRINT (DBG_ERROR,
"AcpisimSetPowerDIrp: Illegal or unknown PowerDeviceState. Failing.\n");
status = STATUS_INVALID_DEVICE_REQUEST;
}
PoStartNextPowerIrp (Irp);
IoSkipCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = status;
status = PoCallDriver (deviceextension->NextDevice, Irp);
ASSERT (NT_SUCCESS (status));
EndAcpisimSetPowerDIrp:
DBG_PRINT (DBG_INFO,
"Leaving AcpisimSetPowerDIrp.\n");
return status;
}
NTSTATUS
AcpisimCompletionRoutine
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This is the generic Irp completion routine for when we
want to wait for an IRP to be completed by the PDO and
do post-completion work.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Context - Context passed in by IoSetCompletionRoutine.
Return Value:
STATUS_MORE_PROCESSING_REQUIRED
--*/
{
DBG_PRINT (DBG_INFO,
"Entering AcpisimCompletionRoutine.\n");
KeSetEvent (Context, 0, FALSE);
DBG_PRINT (DBG_INFO,
"Exiting AcpisimCompletionRoutine.\n");
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
AcpisimForwardIrpAndWait
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This forwards the IRP down the device stack, sets
a completion routine, and waits on the completion
event. Useful for doing IRP post-completion, based
on the result of the completion.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
The status set in the IRP when the IRP was completed.
--*/
{
KEVENT context;
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
DBG_PRINT (DBG_INFO,
"Entering AcpisimForwardIrpAndWait.\n");
KeInitializeEvent (&context, SynchronizationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext (Irp);
IoSetCompletionRoutine (Irp,
AcpisimCompletionRoutine,
&context,
TRUE,
TRUE,
TRUE);
status = IoCallDriver (deviceextension->NextDevice, Irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject (&context,
Executive,
KernelMode,
FALSE,
NULL);
status = Irp->IoStatus.Status;
}
DBG_PRINT (DBG_INFO,
"Exiting AcpisimForwardIrpAndWait.\n");
return status;
}
NTSTATUS
AcpisimIssuePowerDIrp
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This is the S-IRP completion routine. It examines the completed
IRP, and if there are no problems, asks the power manager to
send us the appropriate D-IRP.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Context - Context passed into IoSetCompletionRoutine
Return Value:
Status of requesting D-IRP operation.
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
POWER_STATE powerstate;
PPOWER_CONTEXT context = NULL;
DBG_PRINT (DBG_INFO,
"Entering AcpisimIssuePowerDIrp.\n");
powerstate.DeviceState = PowerDeviceUnspecified;
//
// Make sure this IRP wasn't failed by the PDO or Lower FFDO
//
if (!NT_SUCCESS (Irp->IoStatus.Status)) {
DBG_PRINT (DBG_INFO,
"AcpisimIssuePowerDIrp: Lower FFDO, BFDO, or PDO failed this IRP (%lx).\n",
status);
status = Irp->IoStatus.Status;
goto EndAcpisimIssuePowerDIrp;
}
if (NT_SUCCESS (Irp->IoStatus.Status)) {
//
// Ok, everybody is agreeing to this S state. Send ourselves
// the appropriate D IRP.
//
//
// Make sure this is an S Irp
//
ASSERT (irpsp->Parameters.Power.Type == SystemPowerState);
if (irpsp->Parameters.Power.Type != SystemPowerState) {
DBG_PRINT (DBG_ERROR,
"Didn't recieve an S Irp when we expected to, or somebody messed up the IRP. Fail it.\n");
status = STATUS_INVALID_DEVICE_REQUEST;
goto EndAcpisimIssuePowerDIrp;
}
ASSERT (irpsp->MinorFunction == IRP_MN_QUERY_POWER || irpsp->MinorFunction == IRP_MN_SET_POWER);
if (irpsp->MinorFunction != IRP_MN_QUERY_POWER && irpsp->MinorFunction != IRP_MN_SET_POWER) {
DBG_PRINT (DBG_ERROR,
"Irp isn't SET or QUERY. Not sure why this wasn't caught earlier (somebody probably messed it up).\nWe don't support any other type. Fail it.\n");
status = STATUS_INVALID_DEVICE_REQUEST;
goto EndAcpisimIssuePowerDIrp;
}
//
// Make sure the S IRP is valid
//
if (irpsp->Parameters.Power.State.SystemState >= PowerSystemMaximum) {
ASSERT (0);
DBG_PRINT (DBG_ERROR,
"Received an undefined S IRP, or somebody messed up the IRP. Fail it.\n");
status = STATUS_INVALID_DEVICE_REQUEST;
goto EndAcpisimIssuePowerDIrp;
}
//
// Use our power mapping table to convert S-->D state
//
powerstate.DeviceState = deviceextension->PowerMappings [irpsp->Parameters.Power.State.SystemState - 1];
DBG_PRINT (DBG_INFO,
"S%d --> D%d\n", irpsp->Parameters.Power.State.SystemState - 1, powerstate.DeviceState - 1);
//
// We need a context to pass a pointer to the S IRP to the D IRP handler
// and a pointer to the device object.
//
context = ExAllocatePoolWithTag (NonPagedPool,
sizeof (POWER_CONTEXT)+4,
POWER_CONTEXT_TAG);
if (!context) {
DBG_PRINT (DBG_ERROR,
"Unable to allocate memory for the context.\n");
status = STATUS_INSUFFICIENT_RESOURCES;
goto EndAcpisimIssuePowerDIrp;
}
context->SIrp = Irp;
context->Context = DeviceObject;
//
// Send the D Irp
//
status = PoRequestPowerIrp (deviceextension->Pdo,
irpsp->MinorFunction,
powerstate,
AcpisimCompleteSIrp,
context,
NULL);
ASSERT (NT_SUCCESS (status));
if (!NT_SUCCESS (status)) {
DBG_PRINT (DBG_ERROR,
"AcpisimIssuePowerDIrp: PoRequestPowerIrp failed (%lx).\n");
goto EndAcpisimIssuePowerDIrp;
}
}
status = STATUS_MORE_PROCESSING_REQUIRED;
EndAcpisimIssuePowerDIrp:
//
// We need to complete the request if something went wrong. Also note,
// it is not necessary to assume our state is S0/D0 again. The power
// manager will send us an S0 IRP.
//
if (!NT_SUCCESS (status) && status != STATUS_MORE_PROCESSING_REQUIRED) {
DBG_PRINT (DBG_ERROR,
"AcpisimIssuePowerDIrp: Something bad happened. Just complete the S Irp with an error.");
PoStartNextPowerIrp (Irp);
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
IoReleaseRemoveLock (&deviceextension->RemoveLock, Irp);
AcpisimDecrementIrpCount (DeviceObject);
if (context) {
ExFreePool (context);
}
}
DBG_PRINT (DBG_INFO,
"Exiting AcpisimIssuePowerDIrp.\n");
return status;
}
NTSTATUS
AcpisimCompleteSIrp
(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
This is the S-Irp completion routine set by PoRequestPowerIrp.
Arguments:
DeviceObject - pointer to the FDO
MinorFunction - type of request
PowerState - type of IRP
Context - Context passed into PoRequestPowerIrp
IoStatus - IoStatus block of completed D Irp
Return Value:
STATUS_SUCCESS
--*/
{
PPOWER_CONTEXT context = (PPOWER_CONTEXT) Context;
PDEVICE_OBJECT deviceobject = context->Context;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (deviceobject);
PIRP sirp = context->SIrp;
DBG_PRINT (DBG_INFO,
"Entering AcpisimCompleteSIrp.\n");
//
// Propagate the device power IRP's status in the system power IRP
//
sirp->IoStatus.Status = IoStatus->Status;
//
// Tell the power manager we are done with this IRP
//
PoStartNextPowerIrp (sirp);
IoCompleteRequest (sirp, IO_NO_INCREMENT);
IoReleaseRemoveLock (&deviceextension->RemoveLock, sirp);
ExFreePool (Context);
//
// Normally our dispatch routine decrements IRP counts,
// but since it was returned STATUS_PENDING, it wasn't
// decremented earlier
//
AcpisimDecrementIrpCount (deviceobject);
DBG_PRINT (DBG_INFO,
"Exiting AcpisimCompleteSIrp.\n");
return STATUS_SUCCESS;
}
NTSTATUS
AcpisimD0Completion
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This is the D0 Irp completion routine
Arguments:
DeviceObject - pointer to the FDO
MinorFunction - type of request
Context - Context passed into IoSetCompletionRoutine
Return Value:
Error status or STATUS_MORE_PROCESSING_REQUIRED
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
POWER_STATE powerstate;
DBG_PRINT (DBG_INFO,
"Entering AcpisimD0Completion.\n");
//
// Make sure this IRP wasn't failed by the PDO or Lower FFDO
//
if (!NT_SUCCESS (Irp->IoStatus.Status)) {
DBG_PRINT (DBG_INFO,
"AcpisimD0Completion: Lower FFDO, BFDO, or PDO failed this IRP (%lx).\n",
status);
status = Irp->IoStatus.Status;
goto EndAcpisimD0Completion;
}
//
// This is where we do actual D0 transition work. Since this
// is a virtual device, the only thing we do is change our
// internal state.
//
AcpisimUpdatePowerState (DeviceObject, POWER_STATE_WORKING);
AcpisimUpdateDevicePowerState (DeviceObject, irpsp->Parameters.Power.State.DeviceState);
powerstate.DeviceState = PowerDeviceD0;
PoSetPowerState (DeviceObject, DevicePowerState, powerstate);
status = STATUS_MORE_PROCESSING_REQUIRED;
EndAcpisimD0Completion:
PoStartNextPowerIrp (Irp);
IoCompleteRequest (Irp, IO_NO_INCREMENT);
IoReleaseRemoveLock (&deviceextension->RemoveLock, Irp);
AcpisimDecrementIrpCount (DeviceObject);
DBG_PRINT (DBG_INFO,
"Exiting AcpisimD0Completion.\n");
return status;
}
VOID
AcpisimInitDevPowerStateTable
(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This routine fills out the power mapping structure with defaults.
We simply default to using D3 in any non-S0 state.
Arguments:
DeviceObject - pointer to the FDO
Return Value:
None
--*/
{
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
UCHAR count;
deviceextension->PowerMappings[0] = PowerDeviceD0;
for (count = 1; count < 5; count ++) {
deviceextension->PowerMappings[count] = PowerDeviceD3;
}
}
NTSTATUS AcpisimDispatchIoctl
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the handler for IOCTL requests. We just call the supplied
function to handle the IOCTL, or pass it on if the handler doesn't
handle it.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
result of IRP processing
--*/
{
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG count = 0;
DBG_PRINT (DBG_INFO, "Entering AcpisimDispatchIoctl\n");
status = AcpisimHandleIoctl (DeviceObject, Irp);
if (status == STATUS_NOT_SUPPORTED) {
//
// IOCTL wasn't handled, pass it on...
//
IoSkipCurrentIrpStackLocation (Irp);
status = IoCallDriver (AcpisimLibGetNextDevice (DeviceObject), Irp);
} else {
//
// IOCTL was handled, complete it.
//
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
}
DBG_PRINT (DBG_INFO, "Exiting AcpisimDispatchIoctl\n");
return status;
}
NTSTATUS
AcpisimDispatchSystemControl
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the handler for System Control requests. Since we currently
don't support any System Control calls, we are just going to pass
them on to the next driver.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
result of IoCallDriver
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
DBG_PRINT (DBG_INFO, "Entering AcpisimDispatchSystemControl\n");
IoSkipCurrentIrpStackLocation (Irp);
status = IoCallDriver (AcpisimLibGetNextDevice (DeviceObject), Irp);
DBG_PRINT (DBG_INFO, "Exiting AcpisimDispatchSystemControl\n");
return status;
}
NTSTATUS AcpisimCreateClose
(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the handler for CreateFile and CloseHandle requests.
We do nothing except update our internal extension to track
the number of outstanding handles.
Arguments:
DeviceObject - pointer to the device object the IRP pertains to
Irp - pointer to the IRP
Return Value:
result of IRP processing
--*/
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (Irp);
PDEVICE_EXTENSION deviceextension = AcpisimGetDeviceExtension (DeviceObject);
ASSERT (irpsp->MajorFunction == IRP_MJ_CREATE || irpsp->MajorFunction == IRP_MJ_CLOSE);
switch (irpsp->MajorFunction) {
case IRP_MJ_CREATE:
InterlockedIncrement (&deviceextension->HandleCount);
status = STATUS_SUCCESS;
break;
case IRP_MJ_CLOSE:
InterlockedDecrement (&deviceextension->HandleCount);
status = STATUS_SUCCESS;
break;
default:
DBG_PRINT (DBG_ERROR,
"AcpisimCreateClose - unexpected Irp type.\n");
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, 0);
return STATUS_SUCCESS;
}