📄 intdev.c
字号:
}
//
// If there is not already a WW IRP pending, submit one now
//
if(DeviceExtension->WaitWakeEnable) {
IssueWaitWake(DeviceExtension);
}
//
// power down the device
//
irpContext = (PIRP_COMPLETION_CONTEXT)
ExAllocatePool(NonPagedPool,
sizeof(IRP_COMPLETION_CONTEXT));
if(!irpContext) {
KdPrint( ("Failed to alloc memory for irpContext\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
else {
//
// increment the count. In the HoldIoRequestWorkerRoutine, the
// count is decremented twice (one for the system Irp and the
// other for the device Irp. An increment here compensates for
// the sytem irp..The decrement corresponding to this increment
// is in the completion function
//
KdPrint( ("IdleNotificationCallback::"));
IntUsb_IoIncrement(DeviceExtension);
powerState.DeviceState = DeviceExtension->PowerDownLevel;
KeInitializeEvent(&irpCompletionEvent, NotificationEvent, FALSE);
irpContext->DeviceExtension = DeviceExtension;
irpContext->Event = &irpCompletionEvent;
ntStatus = PoRequestPowerIrp(
DeviceExtension->PhysicalDeviceObject,
IRP_MN_SET_POWER,
powerState,
(PREQUEST_POWER_COMPLETE) PoIrpCompletionFunc,
irpContext,
NULL);
if(STATUS_PENDING == ntStatus) {
KdPrint( ("IdleNotificationCallback::"
"waiting for the power irp to complete\n"));
KeWaitForSingleObject(&irpCompletionEvent,
Executive,
KernelMode,
FALSE,
NULL);
}
}
if(!NT_SUCCESS(ntStatus)) {
if(irpContext) {
ExFreePool(irpContext);
}
}
KdPrint( ("IdleNotificationCallback - ends\n"));
}
NTSTATUS
IdleNotificationRequestComplete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
Completion routine for idle notification irp
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
DeviceExtension - pointer to device extension
Return Value:
NT status value
--*/
{
NTSTATUS ntStatus;
POWER_STATE powerState;
KIRQL oldIrql;
LARGE_INTEGER dueTime;
PIRP idleIrp;
PUSB_IDLE_CALLBACK_INFO idleCallbackInfo;
KdPrint( ("IdleNotificationRequestCompete - begins\n"));
idleIrp = NULL;
//
// check the Irp status
//
ntStatus = Irp->IoStatus.Status;
if(!NT_SUCCESS(ntStatus) && ntStatus != STATUS_NOT_SUPPORTED) {
KdPrint( ("Idle irp completes with error::"));
switch(ntStatus) {
case STATUS_INVALID_DEVICE_REQUEST:
KdPrint( ("STATUS_INVALID_DEVICE_REQUEST\n"));
break;
case STATUS_CANCELLED:
KdPrint( ("STATUS_CANCELLED\n"));
break;
case STATUS_POWER_STATE_INVALID:
KdPrint( ("STATUS_POWER_STATE_INVALID\n"));
goto IdleNotificationRequestComplete_Exit;
case STATUS_DEVICE_BUSY:
KdPrint( ("STATUS_DEVICE_BUSY\n"));
break;
default:
KdPrint( ("default: status = %X\n", ntStatus));
break;
}
//
// if in error, issue a SetD0
//
KdPrint( ("IdleNotificationRequestComplete::"));
IntUsb_IoIncrement(DeviceExtension);
powerState.DeviceState = PowerDeviceD0;
ntStatus = PoRequestPowerIrp(
DeviceExtension->PhysicalDeviceObject,
IRP_MN_SET_POWER,
powerState,
(PREQUEST_POWER_COMPLETE) PoIrpAsyncCompletionFunc,
DeviceExtension,
NULL);
if(!NT_SUCCESS(ntStatus)) {
KdPrint( ("PoRequestPowerIrp failed\n"));
}
}
IdleNotificationRequestComplete_Exit:
KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql);
idleCallbackInfo = DeviceExtension->IdleCallbackInfo;
DeviceExtension->IdleCallbackInfo = NULL;
idleIrp = (PIRP) InterlockedExchangePointer(
&DeviceExtension->PendingIdleIrp,
NULL);
InterlockedExchange(&DeviceExtension->IdleReqPend, 0);
KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
if(idleCallbackInfo) {
ExFreePool(idleCallbackInfo);
}
//
// since the irp was created using IoAllocateIrp,
// the Irp needs to be freed using IoFreeIrp.
// Also return STATUS_MORE_PROCESSING_REQUIRED so that
// the kernel does not reference this in the near future.
//
if(idleIrp) {
KdPrint( ("completion routine has a valid irp and frees it\n"));
IoFreeIrp(Irp);
KeSetEvent(&DeviceExtension->NoIdleReqPendEvent,
IO_NO_INCREMENT,
FALSE);
}
else {
//
// The CancelSelectiveSuspend routine has grabbed the Irp from the device
// extension. Now the last one to decrement the FreeIdleIrpCount should
// free the irp.
//
if(0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount)) {
KdPrint( ("completion routine frees the irp\n"));
IoFreeIrp(Irp);
KeSetEvent(&DeviceExtension->NoIdleReqPendEvent,
IO_NO_INCREMENT,
FALSE);
}
}
if(DeviceExtension->SSEnable) {
KdPrint( ("Set the timer to fire DPCs\n"));
dueTime.QuadPart = -10000 * IDLE_INTERVAL; // 5000 ms
KeSetTimerEx(&DeviceExtension->Timer,
dueTime,
IDLE_INTERVAL, // 5000 ms
&DeviceExtension->DeferredProcCall);
KdPrint( ("IdleNotificationRequestCompete - ends\n"));
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
VOID
CancelSelectSuspend(
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
This routine is invoked to cancel selective suspend request.
Arguments:
DeviceExtension - pointer to device extension
Return Value:
None.
--*/
{
PIRP irp;
KIRQL oldIrql;
irp = NULL;
KdPrint( ("CancelSelectSuspend - begins\n"));
KeAcquireSpinLock(&DeviceExtension->IdleReqStateLock, &oldIrql);
if(!CanDeviceSuspend(DeviceExtension))
{
KdPrint( ("Device is not idle\n"));
irp = (PIRP) InterlockedExchangePointer(
&DeviceExtension->PendingIdleIrp,
NULL);
}
KeReleaseSpinLock(&DeviceExtension->IdleReqStateLock, oldIrql);
//
// since we have a valid Irp ptr,
// we can call IoCancelIrp on it,
// without the fear of the irp
// being freed underneath us.
//
if(irp) {
//
// This routine has the irp pointer.
// It is safe to call IoCancelIrp because we know that
// the compleiton routine will not free this irp unless...
//
//
if(IoCancelIrp(irp)) {
KdPrint( ("IoCancelIrp returns TRUE\n"));
}
else {
KdPrint( ("IoCancelIrp returns FALSE\n"));
}
//
// ....we decrement the FreeIdleIrpCount from 2 to 1.
// if completion routine runs ahead of us, then this routine
// decrements the FreeIdleIrpCount from 1 to 0 and hence shall
// free the irp.
//
if(0 == InterlockedDecrement(&DeviceExtension->FreeIdleIrpCount)) {
KdPrint( ("CancelSelectSuspend frees the irp\n"));
IoFreeIrp(irp);
KeSetEvent(&DeviceExtension->NoIdleReqPendEvent,
IO_NO_INCREMENT,
FALSE);
}
}
KdPrint( ("CancelSelectSuspend - ends\n"));
return;
}
VOID
PoIrpCompletionFunc(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
Completion routine for power irp PoRequested in
IdleNotificationCallback.
Arguments:
DeviceObject - pointer to device object
MinorFunciton - minor function for the irp.
PowerState - irp power state
Context - context passed to the completion function
IoStatus - status block.
Return Value:
None
--*/
{
PIRP_COMPLETION_CONTEXT irpContext;
//
// initialize variables
//
if(Context) {
irpContext = (PIRP_COMPLETION_CONTEXT) Context;
}
//
// all we do is set the event and decrement the count
//
if(irpContext) {
KeSetEvent(irpContext->Event, 0, FALSE);
KdPrint( ("PoIrpCompletionFunc::"));
IntUsb_IoDecrement(irpContext->DeviceExtension);
ExFreePool(irpContext);
}
return;
}
VOID
PoIrpAsyncCompletionFunc(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
Completion routine for power irp PoRequested in IdleNotification
RequestComplete routine.
Arguments:
DeviceObject - pointer to device object
MinorFunciton - minor function for the irp.
PowerState - irp power state
Context - context passed to the completion function
IoStatus - status block.
Return Value:
None
--*/
{
PDEVICE_EXTENSION DeviceExtension;
//
// initialize variables
//
DeviceExtension = (PDEVICE_EXTENSION) Context;
//
// all we do is decrement the count
//
KdPrint( ("PoIrpAsyncCompletionFunc::"));
IntUsb_IoDecrement(DeviceExtension);
return;
}
VOID
WWIrpCompletionFunc(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
Completion routine for PoRequest wait wake irp
Arguments:
DeviceObject - pointer to device object
MinorFunciton - minor function for the irp.
PowerState - irp power state
Context - context passed to the completion function
IoStatus - status block.
Return Value:
None
--*/
{
PDEVICE_EXTENSION DeviceExtension;
//
// initialize variables
//
DeviceExtension = (PDEVICE_EXTENSION) Context;
//
// all we do is decrement the count
//
KdPrint( ("WWIrpCompletionFunc::"));
IntUsb_IoDecrement(DeviceExtension);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -