?? bulkpwr.c
字號:
BulkUsb_DbgPrint(3, ("FinishDevPoDnIrp - ends\n"));
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
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
BulkUsb_DbgPrint(3, ("HoldIoRequests - begins\n"));
deviceExtension->QueueState = HoldRequests;
context = ExAllocatePool(NonPagedPool, sizeof(WORKER_THREAD_CONTEXT));
if(context) {
item = IoAllocateWorkItem(DeviceObject);
context->Irp = Irp;
context->DeviceObject = DeviceObject;
context->WorkItem = item;
if(item) {
IoMarkIrpPending(Irp);
IoQueueWorkItem(item, HoldIoRequestsWorkerRoutine,
DelayedWorkQueue, context);
ntStatus = STATUS_PENDING;
}
else {
BulkUsb_DbgPrint(3, ("Failed to allocate memory for workitem\n"));
ExFreePool(context);
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
else {
BulkUsb_DbgPrint(1, ("Failed to alloc memory for worker thread context\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
BulkUsb_DbgPrint(3, ("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;
BulkUsb_DbgPrint(3, ("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 BulkUsb_IoDecrement twice: once each for the S-Irp and D-Irp.
//
BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::"));
BulkUsb_IoDecrement(deviceExtension);
BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::"));
BulkUsb_IoDecrement(deviceExtension);
KeWaitForSingleObject(&deviceExtension->StopEvent, Executive,
KernelMode, FALSE, NULL);
//
// Increment twice to restore the count
//
BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::"));
BulkUsb_IoIncrement(deviceExtension);
BulkUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::"));
BulkUsb_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)) {
BulkUsb_DbgPrint(1, ("Lower driver fail a power Irp\n"));
}
IoFreeWorkItem(context->WorkItem);
ExFreePool((PVOID)context);
BulkUsb_DbgPrint(3, ("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;
BulkUsb_DbgPrint(3, ("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);
BulkUsb_DbgPrint(3, ("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;
BulkUsb_DbgPrint(3, ("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);
BulkUsb_DbgPrint(3, ("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;
BulkUsb_DbgPrint(3, ("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);
}
BulkUsb_DbgPrint(3, ("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;
BulkUsb_DbgPrint(3, ("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);
}
}
BulkUsb_DbgPrint(3, ("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
--*/
{
BulkUsb_DbgPrint(3, ("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;
}
BulkUsb_DbgPrint(3, ("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;
BulkUsb_DbgPrint(3, ("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) {
BulkUsb_DbgPrint(3, ("device already powered up...\n"));
return;
}
BulkUsb_DbgPrint(3, ("WaitWakeCallback::"));
BulkUsb_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);
}
BulkUsb_DbgPrint(3, ("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 + -