📄 intpwr.c
字号:
return STATUS_SUCCESS;
}
NTSTATUS
HoldIoRequests(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is called on query or set power DOWN irp for the device.
This routine queues a workitem.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
Return Value:
NT status value
--*/
{
NTSTATUS ntStatus;
PIO_WORKITEM item;
PDEVICE_EXTENSION deviceExtension;
PWORKER_THREAD_CONTEXT context;
//
// initialize variables
//
item = NULL;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
KdPrint( ("HoldIoRequests - begins\n"));
deviceExtension->QueueState = HoldRequests;
context = ExAllocatePool(NonPagedPool, sizeof(WORKER_THREAD_CONTEXT));
if(context) {
#ifndef WIN98DRIVER
item = IoAllocateWorkItem(DeviceObject);
#else
item = AllocateWorkItem98(DeviceObject);
#endif
context->Irp = Irp;
context->DeviceObject = DeviceObject;
context->WorkItem = item;
if(item) {
IoMarkIrpPending(Irp);
#ifndef WIN98DRIVER
IoQueueWorkItem(item, HoldIoRequestsWorkerRoutine,
DelayedWorkQueue, context);
#else
QueueWorkItem98(item, HoldIoRequestsWorkerRoutine,
DelayedWorkQueue, context);
#endif
ntStatus = STATUS_PENDING;
}
else {
KdPrint( ("Failed to allocate memory for workitem\n"));
ExFreePool(context);
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
else {
KdPrint( ("Failed to alloc memory for worker thread context\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
KdPrint( ("HoldIoRequests - ends\n"));
return ntStatus;
}
VOID
HoldIoRequestsWorkerRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
)
/*++
Routine Description:
This routine waits for the I/O in progress to finish and then
sends the device power irp (query/set) down the stack.
Arguments:
DeviceObject - pointer to device object
Context - context passed to the work-item.
Return Value:
None
--*/
{
PIRP irp;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
PWORKER_THREAD_CONTEXT context;
KdPrint( ("HoldIoRequestsWorkerRoutine - begins\n"));
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
context = (PWORKER_THREAD_CONTEXT) Context;
irp = (PIRP) context->Irp;
//
// wait for I/O in progress to finish.
// the stop event is signalled when the counter drops to 1.
// invoke IntUsb_IoDecrement twice: once each for the S-Irp and D-Irp.
//
KdPrint( ("HoldIoRequestsWorkerRoutine::"));
IntUsb_IoDecrement(deviceExtension);
KdPrint( ("HoldIoRequestsWorkerRoutine::"));
IntUsb_IoDecrement(deviceExtension);
KeWaitForSingleObject(&deviceExtension->StopEvent, Executive,
KernelMode, FALSE, NULL);
//
// Increment twice to restore the count
//
KdPrint( ("HoldIoRequestsWorkerRoutine::"));
IntUsb_IoIncrement(deviceExtension);
KdPrint( ("HoldIoRequestsWorkerRoutine::"));
IntUsb_IoIncrement(deviceExtension);
//
// now send the Irp down
//
IoCopyCurrentIrpStackLocationToNext(irp);
IoSetCompletionRoutine(irp, (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp,
deviceExtension, TRUE, TRUE, TRUE);
ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
if(!NT_SUCCESS(ntStatus)) {
KdPrint( ("Lower driver fail a power Irp\n"));
}
#ifndef WIN98DRIVER
IoFreeWorkItem(context->WorkItem);
#else
FreeWorkItem98(context->WorkItem);
#endif
ExFreePool((PVOID)context);
KdPrint( ("HoldIoRequestsWorkerRoutine - ends\n"));
}
NTSTATUS
QueueRequest(
IN OUT PDEVICE_EXTENSION DeviceExtension,
IN PIRP Irp
)
/*++
Routine Description:
Queue the Irp in the device queue
Arguments:
DeviceExtension - pointer to device extension
Irp - I/O request packet.
Return Value:
NT status value
--*/
{
KIRQL oldIrql;
NTSTATUS ntStatus;
//
// initialize variables
//
ntStatus = STATUS_PENDING;
KdPrint( ("QueueRequests - begins\n"));
ASSERT(HoldRequests == DeviceExtension->QueueState);
KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);
InsertTailList(&DeviceExtension->NewRequestsQueue,
&Irp->Tail.Overlay.ListEntry);
IoMarkIrpPending(Irp);
//
// Set the cancel routine
//
IoSetCancelRoutine(Irp, CancelQueued);
KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
KdPrint( ("QueueRequests - ends\n"));
return ntStatus;
}
VOID
CancelQueued(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine removes the irp from the queue and completes it with
STATUS_CANCELLED
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
Return Value:
None.
--*/
{
PDEVICE_EXTENSION deviceExtension;
KIRQL oldIrql;
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
oldIrql = Irp->CancelIrql;
KdPrint( ("CancelQueued - begins\n"));
//
// Release the cancel spin lock
//
IoReleaseCancelSpinLock(Irp->CancelIrql);
//
// Acquire the queue lock
//
KeAcquireSpinLockAtDpcLevel(&deviceExtension->QueueLock);
//
// Remove the cancelled Irp from queue and release the lock
//
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);
//
// complete with STATUS_CANCELLED
//
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KdPrint( ("CancelQueued - ends\n"));
return;
}
NTSTATUS
IssueWaitWake(
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
This routine will PoRequest a WAIT WAKE irp for the device
Arguments:
DeviceExtension - pointer to device extension
Return Value:
NT status value.
--*/
{
POWER_STATE poState;
NTSTATUS ntStatus;
KdPrint( ("IssueWaitWake - begins\n"));
if(InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 1)) {
return STATUS_DEVICE_BUSY;
}
InterlockedExchange(&DeviceExtension->FlagWWCancel, 0);
//
// lowest state from which this Irp will wake the system
//
poState.SystemState = DeviceExtension->DeviceCapabilities.SystemWake;
ntStatus = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject,
IRP_MN_WAIT_WAKE,
poState,
(PREQUEST_POWER_COMPLETE) WaitWakeCallback,
DeviceExtension,
&DeviceExtension->WaitWakeIrp);
if(!NT_SUCCESS(ntStatus)) {
InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 0);
}
KdPrint( ("IssueWaitWake - ends\n"));
return ntStatus;
}
VOID
CancelWaitWake(
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
This routine cancels the Wait Wake request.
Arguments:
DeviceExtension - pointer to the device extension
Return Value:
None.
--*/
{
PIRP Irp;
KdPrint( ("CancelWaitWake - begins\n"));
Irp = (PIRP) InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp,
NULL);
if(Irp) {
IoCancelIrp(Irp);
if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1)) {
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}
KdPrint( ("CancelWaitWake - ends\n"));
}
NTSTATUS
WaitWakeCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
This is the IoSet completion routine for the wait wake irp.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
DeviceExtension - pointer to device extension
Return Value:
NT status value
--*/
{
KdPrint( ("WaitWakeCompletionRoutine - begins\n"));
if(Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
//
// Nullify the WaitWakeIrp pointer-the Irp is released
// as part of the completion process. If it's already NULL,
// avoid race with the CancelWaitWake routine.
//
if(InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL)) {
PoStartNextPowerIrp(Irp);
return STATUS_SUCCESS;
}
//
// CancelWaitWake has run.
// If FlagWWCancel != 0, complete the Irp.
// If FlagWWCancel == 0, CancelWaitWake completes it.
//
if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1)) {
PoStartNextPowerIrp(Irp);
return STATUS_CANCELLED;
}
KdPrint( ("WaitWakeCompletionRoutine - ends\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
VOID
WaitWakeCallback(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
This is the PoRequest completion routine for the wait wake irp.
Arguments:
DeviceObject - pointer to device object
MinorFunction - irp minor function
PowerState - power state of the irp.
Context - context passed to the completion routine.
IoStatus - status block.
Return Value:
None
--*/
{
NTSTATUS ntStatus;
POWER_STATE powerState;
PDEVICE_EXTENSION deviceExtension;
KdPrint( ("WaitWakeCallback - begins\n"));
deviceExtension = (PDEVICE_EXTENSION) Context;
InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0);
if(!NT_SUCCESS(IoStatus->Status)) {
return;
}
//
// wake up the device
//
if(deviceExtension->DevPower == PowerDeviceD0) {
KdPrint( ("device already powered up...\n"));
return;
}
KdPrint( ("WaitWakeCallback::"));
IntUsb_IoIncrement(deviceExtension);
powerState.DeviceState = PowerDeviceD0;
ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,
IRP_MN_SET_POWER,
powerState,
(PREQUEST_POWER_COMPLETE) WWIrpCompletionFunc,
deviceExtension,
NULL);
if(deviceExtension->WaitWakeEnable) {
IssueWaitWake(deviceExtension);
}
KdPrint( ("WaitWakeCallback - ends\n"));
return;
}
PCHAR
PowerMinorFunctionString (
IN UCHAR MinorFunction
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
switch (MinorFunction) {
case IRP_MN_SET_POWER:
return "IRP_MN_SET_POWER\n";
case IRP_MN_QUERY_POWER:
return "IRP_MN_QUERY_POWER\n";
case IRP_MN_POWER_SEQUENCE:
return "IRP_MN_POWER_SEQUENCE\n";
case IRP_MN_WAIT_WAKE:
return "IRP_MN_WAIT_WAKE\n";
default:
return "IRP_MN_?????\n";
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -