+++ /dev/null
-/*++
-
-Copyright (C) Microsoft Corporation, 1991 - 1999
-
-Module Name:
-
- class.c
-
-Abstract:
-
- SCSI class driver routines
-
-Environment:
-
- kernel mode only
-
-Notes:
-
-
-Revision History:
-
---*/
-
-#include "classp.h"
-
-#define CLASS_TAG_POWER 'WLcS'
-
-NTSTATUS
-NTAPI
-ClasspPowerHandler(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN CLASS_POWER_OPTIONS Options
- );
-
-IO_COMPLETION_ROUTINE ClasspPowerDownCompletion;
-
-IO_COMPLETION_ROUTINE ClasspPowerUpCompletion;
-
-VOID
-NTAPI
-RetryPowerRequest(
- PDEVICE_OBJECT DeviceObject,
- PIRP Irp,
- PCLASS_POWER_CONTEXT Context
- );
-
-NTSTATUS
-NTAPI
-ClasspStartNextPowerIrpCompletion(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN PVOID Context
- );
-
-
-/*++////////////////////////////////////////////////////////////////////////////
-
-ClassDispatchPower()
-
-Routine Description:
-
- This routine acquires the removelock for the irp and then calls the
- appropriate power callback.
-
-Arguments:
-
- DeviceObject -
- Irp -
-
-Return Value:
-
---*/
-NTSTATUS
-NTAPI
-ClassDispatchPower(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
-{
- PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
- ULONG isRemoved;
-
- //
- // NOTE: This code may be called at PASSIVE or DISPATCH, depending
- // upon the device object it is being called for.
- // don't do anything that would break under either circumstance.
- //
-
- isRemoved = ClassAcquireRemoveLock(DeviceObject, Irp);
-
- if(isRemoved) {
- ClassReleaseRemoveLock(DeviceObject, Irp);
- Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
- PoStartNextPowerIrp(Irp);
- ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
- return STATUS_DEVICE_DOES_NOT_EXIST;
- }
-
- return commonExtension->DevInfo->ClassPowerDevice(DeviceObject, Irp);
-} // end ClassDispatchPower()
-
-/*++////////////////////////////////////////////////////////////////////////////
-
-ClasspPowerUpCompletion()
-
-Routine Description:
-
- This routine is used for intermediate completion of a power up request.
- PowerUp requires four requests to be sent to the lower driver in sequence.
-
- * The queue is "power locked" to ensure that the class driver power-up
- work can be done before request processing resumes.
-
- * The power irp is sent down the stack for any filter drivers and the
- port driver to return power and resume command processing for the
- device. Since the queue is locked, no queued irps will be sent
- immediately.
-
- * A start unit command is issued to the device with appropriate flags
- to override the "power locked" queue.
-
- * The queue is "power unlocked" to start processing requests again.
-
- This routine uses the function in the srb which just completed to determine
- which state it is in.
-
-Arguments:
-
- DeviceObject - the device object being powered up
-
- Irp - the IO_REQUEST_PACKET containing the power request
-
- Srb - the SRB used to perform port/class operations.
-
-Return Value:
-
- STATUS_MORE_PROCESSING_REQUIRED or
- STATUS_SUCCESS
-
---*/
-NTSTATUS
-NTAPI
-ClasspPowerUpCompletion(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN PVOID CompletionContext
- )
-{
- PCLASS_POWER_CONTEXT context = CompletionContext;
- PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
-
- PIO_STACK_LOCATION currentStack = IoGetCurrentIrpStackLocation(Irp);
- PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation(Irp);
-
-
- NTSTATUS status = STATUS_MORE_PROCESSING_REQUIRED;
-
- DebugPrint((1, "ClasspPowerUpCompletion: Device Object %p, Irp %p, "
- "Context %p\n",
- DeviceObject, Irp, context));
-
- ASSERT(!TEST_FLAG(context->Srb.SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
- ASSERT(!TEST_FLAG(context->Srb.SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
- ASSERT(context->Options.PowerDown == FALSE);
- ASSERT(context->Options.HandleSpinUp);
-
- if(Irp->PendingReturned) {
- IoMarkIrpPending(Irp);
- }
-
- context->PowerChangeState.PowerUp++;
-
- switch(context->PowerChangeState.PowerUp) {
-
- case PowerUpDeviceLocked: {
-
- DebugPrint((1, "(%p)\tPreviously sent power lock\n", Irp));
-
- //
- // Issue the actual power request to the lower driver.
- //
-
- IoCopyCurrentIrpStackLocationToNext(Irp);
-
- //
- // If the lock wasn't successful then just bail out on the power
- // request unless we can ignore failed locks
- //
-
- if ((context->Options.LockQueue != FALSE) &&
- (!NT_SUCCESS(Irp->IoStatus.Status))) {
-
- DebugPrint((1, "(%p)\tIrp status was %lx\n",
- Irp, Irp->IoStatus.Status));
- DebugPrint((1, "(%p)\tSrb status was %lx\n",
- Irp, context->Srb.SrbStatus));
-
- //
- // Lock was not successful - throw down the power IRP
- // by itself and don't try to spin up the drive or unlock
- // the queue.
- //
-
- context->InUse = FALSE;
- context = NULL;
-
- //
- // Set the new power state
- //
-
- fdoExtension->DevicePowerState =
- currentStack->Parameters.Power.State.DeviceState;
-
- Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
-
- IoCopyCurrentIrpStackLocationToNext(Irp);
-
- IoSetCompletionRoutine(Irp,
- ClasspStartNextPowerIrpCompletion,
- NULL,
- TRUE,
- TRUE,
- TRUE);
-
- //
- // Indicate to Po that we've been successfully powered up so
- // it can do it's notification stuff.
- //
-
- PoSetPowerState(DeviceObject,
- currentStack->Parameters.Power.Type,
- currentStack->Parameters.Power.State);
-
- PoCallDriver(commonExtension->LowerDeviceObject, Irp);
-
- ClassReleaseRemoveLock(commonExtension->DeviceObject,
- Irp);
-
- return STATUS_MORE_PROCESSING_REQUIRED;
-
- } else {
- context->QueueLocked = (UCHAR) context->Options.LockQueue;
- }
-
- Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
-
- context->PowerChangeState.PowerUp = PowerUpDeviceLocked;
-
- IoSetCompletionRoutine(Irp,
- ClasspPowerUpCompletion,
- context,
- TRUE,
- TRUE,
- TRUE);
-
- status = PoCallDriver(commonExtension->LowerDeviceObject, Irp);
-
- DebugPrint((2, "(%p)\tPoCallDriver returned %lx\n", Irp, status));
- break;
- }
-
- case PowerUpDeviceOn: {
-
- PCDB cdb;
-
- if(NT_SUCCESS(Irp->IoStatus.Status)) {
-
- DebugPrint((1, "(%p)\tSending start unit to device\n", Irp));
-
- //
- // Issue the start unit command to the device.
- //
-
- context->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
- context->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
-
- context->Srb.SrbStatus = context->Srb.ScsiStatus = 0;
- context->Srb.DataTransferLength = 0;
-
- context->Srb.TimeOutValue = START_UNIT_TIMEOUT;
-
- context->Srb.SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER |
- SRB_FLAGS_DISABLE_AUTOSENSE |
- SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
- SRB_FLAGS_NO_QUEUE_FREEZE;
-
- if(context->Options.LockQueue) {
- SET_FLAG(context->Srb.SrbFlags, SRB_FLAGS_BYPASS_LOCKED_QUEUE);
- }
-
- context->Srb.CdbLength = 6;
-
- cdb = (PCDB) (context->Srb.Cdb);
- RtlZeroMemory(cdb, sizeof(CDB));
-
-
- cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
- cdb->START_STOP.Start = 1;
-
- context->PowerChangeState.PowerUp = PowerUpDeviceOn;
-
- IoSetCompletionRoutine(Irp,
- ClasspPowerUpCompletion,
- context,
- TRUE,
- TRUE,
- TRUE);
-
- nextStack->Parameters.Scsi.Srb = &(context->Srb);
- nextStack->MajorFunction = IRP_MJ_SCSI;
-
- status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
-
- DebugPrint((2, "(%p)\tIoCallDriver returned %lx\n", Irp, status));
-
- } else {
-
- //
- // we're done.
- //
-
- context->FinalStatus = Irp->IoStatus.Status;
- goto ClasspPowerUpCompletionFailure;
- }
-
- break;
- }
-
- case PowerUpDeviceStarted: { // 3
-
- //
- // First deal with an error if one occurred.
- //
-
- if(SRB_STATUS(context->Srb.SrbStatus) != SRB_STATUS_SUCCESS) {
-
- BOOLEAN retry;
-
- DebugPrint((1, "%p\tError occured when issuing START_UNIT "
- "command to device. Srb %p, Status %x\n",
- Irp,
- &context->Srb,
- context->Srb.SrbStatus));
-
- ASSERT(!(TEST_FLAG(context->Srb.SrbStatus,
- SRB_STATUS_QUEUE_FROZEN)));
- ASSERT(context->Srb.Function == SRB_FUNCTION_EXECUTE_SCSI);
-
- context->RetryInterval = 0;
-
- retry = ClassInterpretSenseInfo(
- commonExtension->DeviceObject,
- &context->Srb,
- IRP_MJ_SCSI,
- IRP_MJ_POWER,
- MAXIMUM_RETRIES - context->RetryCount,
- &status,
- &context->RetryInterval);
-
- if ((retry != FALSE) && (context->RetryCount-- != 0)) {
-
- DebugPrint((1, "(%p)\tRetrying failed request\n", Irp));
-
- //
- // Decrement the state so we come back through here the
- // next time.
- //
-
- context->PowerChangeState.PowerUp--;
-
- RetryPowerRequest(commonExtension->DeviceObject,
- Irp,
- context);
-
- break;
-
- }
-
- // reset retries
- context->RetryCount = MAXIMUM_RETRIES;
-
- }
-
-ClasspPowerUpCompletionFailure:
-
- DebugPrint((1, "(%p)\tPreviously spun device up\n", Irp));
-
- if (context->QueueLocked) {
- DebugPrint((1, "(%p)\tUnlocking queue\n", Irp));
-
- context->Srb.Function = SRB_FUNCTION_UNLOCK_QUEUE;
- context->Srb.SrbFlags = SRB_FLAGS_BYPASS_LOCKED_QUEUE;
- context->Srb.SrbStatus = context->Srb.ScsiStatus = 0;
- context->Srb.DataTransferLength = 0;
-
- nextStack->Parameters.Scsi.Srb = &(context->Srb);
- nextStack->MajorFunction = IRP_MJ_SCSI;
-
- context->PowerChangeState.PowerUp = PowerUpDeviceStarted;
-
- IoSetCompletionRoutine(Irp,
- ClasspPowerUpCompletion,
- context,
- TRUE,
- TRUE,
- TRUE);
-
- status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
- DebugPrint((1, "(%p)\tIoCallDriver returned %lx\n",
- Irp, status));
- break;
- }
-
- // Fall-through to next case...
-
- }
-
- case PowerUpDeviceUnlocked: {
-
- //
- // This is the end of the dance. Free the srb and complete the
- // request finally. We're ignoring possible intermediate
- // error conditions ....
- //
-
- if (context->QueueLocked) {
- DebugPrint((1, "(%p)\tPreviously unlocked queue\n", Irp));
- ASSERT(NT_SUCCESS(Irp->IoStatus.Status));
- ASSERT(context->Srb.SrbStatus == SRB_STATUS_SUCCESS);
- } else {
- DebugPrint((1, "(%p)\tFall-through (queue not locked)\n", Irp));
- }
-
- DebugPrint((1, "(%p)\tFreeing srb and completing\n", Irp));
- context->InUse = FALSE;
-
- status = context->FinalStatus;
- Irp->IoStatus.Status = status;
-
- context = NULL;
-
- //
- // Set the new power state
- //
-
- if(NT_SUCCESS(status)) {
- fdoExtension->DevicePowerState =
- currentStack->Parameters.Power.State.DeviceState;
- }
-
- //
- // Indicate to Po that we've been successfully powered up so
- // it can do it's notification stuff.
- //
-
- PoSetPowerState(DeviceObject,
- currentStack->Parameters.Power.Type,
- currentStack->Parameters.Power.State);
-
- DebugPrint((1, "(%p)\tStarting next power irp\n", Irp));
- ClassReleaseRemoveLock(DeviceObject, Irp);
- PoStartNextPowerIrp(Irp);
-
- return status;
- }
-
- case PowerUpDeviceInitial: {
- NT_ASSERT(context->PowerChangeState.PowerUp != PowerUpDeviceInitial);
- break;
- }
- }
-
- return STATUS_MORE_PROCESSING_REQUIRED;
-} // end ClasspPowerUpCompletion()
-
-/*++////////////////////////////////////////////////////////////////////////////
-
-ClasspPowerDownCompletion()
-
-Routine Description:
-
- This routine is used for intermediate completion of a power up request.
- PowerUp requires four requests to be sent to the lower driver in sequence.
-
- * The queue is "power locked" to ensure that the class driver power-up
- work can be done before request processing resumes.
-
- * The power irp is sent down the stack for any filter drivers and the
- port driver to return power and resume command processing for the
- device. Since the queue is locked, no queued irps will be sent
- immediately.
-
- * A start unit command is issued to the device with appropriate flags
- to override the "power locked" queue.
-
- * The queue is "power unlocked" to start processing requests again.
-
- This routine uses the function in the srb which just completed to determine
- which state it is in.
-
-Arguments:
-
- DeviceObject - the device object being powered up
-
- Irp - the IO_REQUEST_PACKET containing the power request
-
- Srb - the SRB used to perform port/class operations.
-
-Return Value:
-
- STATUS_MORE_PROCESSING_REQUIRED or
- STATUS_SUCCESS
-
---*/
-NTSTATUS
-NTAPI
-ClasspPowerDownCompletion(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN PVOID CompletionContext
- )
-{
- PCLASS_POWER_CONTEXT context = CompletionContext;
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
- PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
-
- PIO_STACK_LOCATION currentStack = IoGetCurrentIrpStackLocation(Irp);
- PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation(Irp);
-
- NTSTATUS status = STATUS_MORE_PROCESSING_REQUIRED;
-
- DebugPrint((1, "ClasspPowerDownCompletion: Device Object %p, "
- "Irp %p, Context %p\n",
- DeviceObject, Irp, context));
-
- ASSERT(!TEST_FLAG(context->Srb.SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
- ASSERT(!TEST_FLAG(context->Srb.SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
- ASSERT(context->Options.PowerDown == TRUE);
- ASSERT(context->Options.HandleSpinDown);
-
- if(Irp->PendingReturned) {
- IoMarkIrpPending(Irp);
- }
-
- context->PowerChangeState.PowerDown2++;
-
- switch(context->PowerChangeState.PowerDown2) {
-
- case PowerDownDeviceLocked2: {
-
- PCDB cdb;
-
- DebugPrint((1, "(%p)\tPreviously sent power lock\n", Irp));
-
- if ((context->Options.LockQueue != FALSE) &&
- (!NT_SUCCESS(Irp->IoStatus.Status))) {
-
- DebugPrint((1, "(%p)\tIrp status was %lx\n",
- Irp,
- Irp->IoStatus.Status));
- DebugPrint((1, "(%p)\tSrb status was %lx\n",
- Irp,
- context->Srb.SrbStatus));
-
- Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
-
- //
- // Lock was not successful - throw down the power IRP
- // by itself and don't try to spin down the drive or unlock
- // the queue.
- //
-
- context->InUse = FALSE;
- context = NULL;
-
- //
- // Set the new power state
- //
-
- fdoExtension->DevicePowerState =
- currentStack->Parameters.Power.State.DeviceState;
-
- //
- // Indicate to Po that we've been successfully powered down
- // so it can do it's notification stuff.
- //
-
- IoCopyCurrentIrpStackLocationToNext(Irp);
- IoSetCompletionRoutine(Irp,
- ClasspStartNextPowerIrpCompletion,
- NULL,
- TRUE,
- TRUE,
- TRUE);
-
- PoSetPowerState(DeviceObject,
- currentStack->Parameters.Power.Type,
- currentStack->Parameters.Power.State);
-
- fdoExtension->PowerDownInProgress = FALSE;
-
- PoCallDriver(commonExtension->LowerDeviceObject, Irp);
-
- ClassReleaseRemoveLock(commonExtension->DeviceObject,
- Irp);
-
- return STATUS_MORE_PROCESSING_REQUIRED;
-
- } else {
- context->QueueLocked = (UCHAR) context->Options.LockQueue;
- }
-
- if (!TEST_FLAG(fdoExtension->PrivateFdoData->HackFlags,
- FDO_HACK_NO_SYNC_CACHE)) {
-
- //
- // send SCSIOP_SYNCHRONIZE_CACHE
- //
-
- context->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
- context->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
-
- context->Srb.TimeOutValue = fdoExtension->TimeOutValue;
-
- context->Srb.SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER |
- SRB_FLAGS_DISABLE_AUTOSENSE |
- SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
- SRB_FLAGS_NO_QUEUE_FREEZE |
- SRB_FLAGS_BYPASS_LOCKED_QUEUE;
-
- context->Srb.SrbStatus = context->Srb.ScsiStatus = 0;
- context->Srb.DataTransferLength = 0;
-
- context->Srb.CdbLength = 10;
-
- cdb = (PCDB) context->Srb.Cdb;
-
- RtlZeroMemory(cdb, sizeof(CDB));
- cdb->SYNCHRONIZE_CACHE10.OperationCode = SCSIOP_SYNCHRONIZE_CACHE;
-
- IoSetCompletionRoutine(Irp,
- ClasspPowerDownCompletion,
- context,
- TRUE,
- TRUE,
- TRUE);
-
- nextStack->Parameters.Scsi.Srb = &(context->Srb);
- nextStack->MajorFunction = IRP_MJ_SCSI;
-
- status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
-
- DebugPrint((1, "(%p)\tIoCallDriver returned %lx\n", Irp, status));
- break;
-
- } else {
-
- DebugPrint((1, "(%p)\tPower Down: not sending SYNCH_CACHE\n",
- DeviceObject));
- context->PowerChangeState.PowerDown2++;
- context->Srb.SrbStatus = SRB_STATUS_SUCCESS;
- // and fall through....
- }
- // no break in case the device doesn't like synch_cache commands
-
- }
-
- case PowerDownDeviceFlushed2: {
-
- PCDB cdb;
-
- DebugPrint((1, "(%p)\tPreviously send SCSIOP_SYNCHRONIZE_CACHE\n",
- Irp));
-
- //
- // SCSIOP_SYNCHRONIZE_CACHE was sent
- //
-
- if(SRB_STATUS(context->Srb.SrbStatus) != SRB_STATUS_SUCCESS) {
-
- BOOLEAN retry;
-
- DebugPrint((1, "(%p)\tError occured when issuing "
- "SYNCHRONIZE_CACHE command to device. "
- "Srb %p, Status %lx\n",
- Irp,
- &context->Srb,
- context->Srb.SrbStatus));
-
- ASSERT(!(TEST_FLAG(context->Srb.SrbStatus,
- SRB_STATUS_QUEUE_FROZEN)));
- ASSERT(context->Srb.Function == SRB_FUNCTION_EXECUTE_SCSI);
-
- context->RetryInterval = 0;
- retry = ClassInterpretSenseInfo(
- commonExtension->DeviceObject,
- &context->Srb,
- IRP_MJ_SCSI,
- IRP_MJ_POWER,
- MAXIMUM_RETRIES - context->RetryCount,
- &status,
- &context->RetryInterval);
-
- if ((retry != FALSE) && (context->RetryCount-- != 0)) {
-
- DebugPrint((1, "(%p)\tRetrying failed request\n", Irp));
-
- //
- // decrement the state so we come back through here
- // the next time.
- //
-
- context->PowerChangeState.PowerDown2--;
- RetryPowerRequest(commonExtension->DeviceObject,
- Irp,
- context);
- break;
- }
-
- DebugPrint((1, "(%p)\tSYNCHRONIZE_CACHE not retried\n", Irp));
- context->RetryCount = MAXIMUM_RETRIES;
-
- } // end !SRB_STATUS_SUCCESS
-
- //
- // note: we are purposefully ignoring any errors. if the drive
- // doesn't support a synch_cache, then we're up a creek
- // anyways.
- //
-
- DebugPrint((1, "(%p)\tSending stop unit to device\n", Irp));
-
- //
- // Issue the start unit command to the device.
- //
-
- context->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
- context->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
-
- context->Srb.TimeOutValue = START_UNIT_TIMEOUT;
-
- context->Srb.SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER |
- SRB_FLAGS_DISABLE_AUTOSENSE |
- SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
- SRB_FLAGS_NO_QUEUE_FREEZE |
- SRB_FLAGS_BYPASS_LOCKED_QUEUE;
-
- context->Srb.SrbStatus = context->Srb.ScsiStatus = 0;
- context->Srb.DataTransferLength = 0;
-
- context->Srb.CdbLength = 6;
-
- cdb = (PCDB) context->Srb.Cdb;
- RtlZeroMemory(cdb, sizeof(CDB));
-
- cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
- cdb->START_STOP.Start = 0;
- cdb->START_STOP.Immediate = 1;
-
- IoSetCompletionRoutine(Irp,
- ClasspPowerDownCompletion,
- context,
- TRUE,
- TRUE,
- TRUE);
-
- nextStack->Parameters.Scsi.Srb = &(context->Srb);
- nextStack->MajorFunction = IRP_MJ_SCSI;
-
- status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
-
- DebugPrint((1, "(%p)\tIoCallDriver returned %lx\n", Irp, status));
- break;
-
- }
-
- case PowerDownDeviceStopped2: {
-
- BOOLEAN ignoreError = TRUE;
-
- //
- // stop was sent
- //
-
- if(SRB_STATUS(context->Srb.SrbStatus) != SRB_STATUS_SUCCESS) {
-
- BOOLEAN retry;
-
- DebugPrint((1, "(%p)\tError occured when issuing STOP_UNIT "
- "command to device. Srb %p, Status %lx\n",
- Irp,
- &context->Srb,
- context->Srb.SrbStatus));
-
- ASSERT(!(TEST_FLAG(context->Srb.SrbStatus,
- SRB_STATUS_QUEUE_FROZEN)));
- ASSERT(context->Srb.Function == SRB_FUNCTION_EXECUTE_SCSI);
-
- context->RetryInterval = 0;
- retry = ClassInterpretSenseInfo(
- commonExtension->DeviceObject,
- &context->Srb,
- IRP_MJ_SCSI,
- IRP_MJ_POWER,
- MAXIMUM_RETRIES - context->RetryCount,
- &status,
- &context->RetryInterval);
-
- if ((retry != FALSE) && (context->RetryCount-- != 0)) {
-
- DebugPrint((1, "(%p)\tRetrying failed request\n", Irp));
-
- //
- // decrement the state so we come back through here
- // the next time.
- //
-
- context->PowerChangeState.PowerDown2--;
- RetryPowerRequest(commonExtension->DeviceObject,
- Irp,
- context);
- break;
- }
-
- DebugPrint((1, "(%p)\tSTOP_UNIT not retried\n", Irp));
- context->RetryCount = MAXIMUM_RETRIES;
-
- } // end !SRB_STATUS_SUCCESS
-
-
- DebugPrint((1, "(%p)\tPreviously sent stop unit\n", Irp));
-
- //
- // some operations, such as a physical format in progress,
- // should not be ignored and should fail the power operation.
- //
-
- if (!NT_SUCCESS(status)) {
-
- PSENSE_DATA senseBuffer = context->Srb.SenseInfoBuffer;
-
- if (TEST_FLAG(context->Srb.SrbStatus,
- SRB_STATUS_AUTOSENSE_VALID) &&
- ((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_NOT_READY) &&
- (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) &&
- (senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_FORMAT_IN_PROGRESS)
- ) {
- ignoreError = FALSE;
- context->FinalStatus = STATUS_DEVICE_BUSY;
- status = context->FinalStatus;
- }
-
- }
-
- if (NT_SUCCESS(status) || ignoreError) {
-
- //
- // Issue the actual power request to the lower driver.
- //
-
- Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
-
- IoCopyCurrentIrpStackLocationToNext(Irp);
-
- IoSetCompletionRoutine(Irp,
- ClasspPowerDownCompletion,
- context,
- TRUE,
- TRUE,
- TRUE);
-
- status = PoCallDriver(commonExtension->LowerDeviceObject, Irp);
-
- DebugPrint((1, "(%p)\tPoCallDriver returned %lx\n", Irp, status));
- break;
- }
-
- // else fall through w/o sending the power irp, since the device
- // is reporting an error that would be "really bad" to power down
- // during.
-
- }
-
- case PowerDownDeviceOff2: {
-
- //
- // SpinDown request completed ... whether it succeeded or not is
- // another matter entirely.
- //
-
- DebugPrint((1, "(%p)\tPreviously sent power irp\n", Irp));
-
- if (context->QueueLocked) {
-
- DebugPrint((1, "(%p)\tUnlocking queue\n", Irp));
-
- context->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
-
- context->Srb.SrbStatus = context->Srb.ScsiStatus = 0;
- context->Srb.DataTransferLength = 0;
-
- context->Srb.Function = SRB_FUNCTION_UNLOCK_QUEUE;
- context->Srb.SrbFlags = SRB_FLAGS_BYPASS_LOCKED_QUEUE;
- nextStack->Parameters.Scsi.Srb = &(context->Srb);
- nextStack->MajorFunction = IRP_MJ_SCSI;
-
- IoSetCompletionRoutine(Irp,
- ClasspPowerDownCompletion,
- context,
- TRUE,
- TRUE,
- TRUE);
-
- status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
- DebugPrint((1, "(%p)\tIoCallDriver returned %lx\n",
- Irp,
- status));
- break;
- }
-
- }
-
- case PowerDownDeviceUnlocked2: {
-
- //
- // This is the end of the dance. Free the srb and complete the
- // request finally. We're ignoring possible intermediate
- // error conditions ....
- //
-
- if (context->QueueLocked == FALSE) {
- DebugPrint((1, "(%p)\tFall through (queue not locked)\n", Irp));
- } else {
- DebugPrint((1, "(%p)\tPreviously unlocked queue\n", Irp));
- ASSERT(NT_SUCCESS(Irp->IoStatus.Status));
- ASSERT(context->Srb.SrbStatus == SRB_STATUS_SUCCESS);
- }
-
- DebugPrint((1, "(%p)\tFreeing srb and completing\n", Irp));
- context->InUse = FALSE;
- status = context->FinalStatus; // allow failure to propagate
- context = NULL;
-
- if(Irp->PendingReturned) {
- IoMarkIrpPending(Irp);
- }
-
- Irp->IoStatus.Status = status;
- Irp->IoStatus.Information = 0;
-
- if (NT_SUCCESS(status)) {
-
- //
- // Set the new power state
- //
-
- fdoExtension->DevicePowerState =
- currentStack->Parameters.Power.State.DeviceState;
-
- }
-
-
- DebugPrint((1, "(%p)\tStarting next power irp\n", Irp));
-
- ClassReleaseRemoveLock(DeviceObject, Irp);
- PoStartNextPowerIrp(Irp);
- fdoExtension->PowerDownInProgress = FALSE;
-
- return status;
- }
-
- case PowerDownDeviceInitial2: {
- NT_ASSERT(context->PowerChangeState.PowerDown2 != PowerDownDeviceInitial2);
- break;
- }
- }
-
- return STATUS_MORE_PROCESSING_REQUIRED;
-} // end ClasspPowerDownCompletion()
-
-/*++////////////////////////////////////////////////////////////////////////////
-
-ClasspPowerHandler()
-
-Routine Description:
-
- This routine reduces the number of useless spinups and spindown requests
- sent to a given device by ignoring transitions to power states we are
- currently in.
-
- ISSUE-2000/02/20-henrygab - by ignoring spin-up requests, we may be
- allowing the drive
-
-Arguments:
-
- DeviceObject - the device object which is transitioning power states
- Irp - the power irp
- Options - a set of flags indicating what the device handles
-
-Return Value:
-
---*/
-NTSTATUS
-NTAPI
-ClasspPowerHandler(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN CLASS_POWER_OPTIONS Options // ISSUE-2000/02/20-henrygab - pass pointer, not whole struct
- )
-{
- PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
- PDEVICE_OBJECT lowerDevice = commonExtension->LowerDeviceObject;
- PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
- PIO_STACK_LOCATION nextIrpStack;
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
- PCLASS_POWER_CONTEXT context;
-
- if (!commonExtension->IsFdo) {
-
- //
- // certain assumptions are made here,
- // particularly: having the fdoExtension
- //
-
- DebugPrint((0, "ClasspPowerHandler: Called for PDO %p???\n",
- DeviceObject));
- ASSERT(!"PDO using ClasspPowerHandler");
- return STATUS_NOT_SUPPORTED;
- }
-
- DebugPrint((1, "ClasspPowerHandler: Power irp %p to %s %p\n",
- Irp, (commonExtension->IsFdo ? "fdo" : "pdo"), DeviceObject));
-
- switch(irpStack->MinorFunction) {
-
- case IRP_MN_SET_POWER: {
- PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
-
- DebugPrint((1, "(%p)\tIRP_MN_SET_POWER\n", Irp));
-
- DebugPrint((1, "(%p)\tSetting %s state to %d\n",
- Irp,
- (irpStack->Parameters.Power.Type == SystemPowerState ?
- "System" : "Device"),
- irpStack->Parameters.Power.State.SystemState));
-
- switch (irpStack->Parameters.Power.ShutdownType){
-
- case PowerActionSleep:
- case PowerActionHibernate:
- if (fdoData->HotplugInfo.MediaRemovable || fdoData->HotplugInfo.MediaHotplug){
- /*
- * We are suspending and this drive is either hot-pluggable
- * or contains removeable media.
- * Set the media dirty bit, since the media may change while
- * we are suspended.
- */
- SET_FLAG(DeviceObject->Flags, DO_VERIFY_VOLUME);
- }
- break;
- default:
- break;
- }
-
- break;
- }
-
- default: {
-
- DebugPrint((1, "(%p)\tIrp minor code = %#x\n",
- Irp, irpStack->MinorFunction));
- break;
- }
- }
-
- if (irpStack->Parameters.Power.Type != DevicePowerState ||
- irpStack->MinorFunction != IRP_MN_SET_POWER) {
-
- DebugPrint((1, "(%p)\tSending to lower device\n", Irp));
-
- goto ClasspPowerHandlerCleanup;
-
- }
-
- nextIrpStack = IoGetNextIrpStackLocation(Irp);
-
- //
- // already in exact same state, don't work to transition to it.
- //
-
- if(irpStack->Parameters.Power.State.DeviceState ==
- fdoExtension->DevicePowerState) {
-
- DebugPrint((1, "(%p)\tAlready in device state %x\n",
- Irp, fdoExtension->DevicePowerState));
- goto ClasspPowerHandlerCleanup;
-
- }
-
- //
- // or powering down from non-d0 state (device already stopped)
- // NOTE -- we're not sure whether this case can exist or not (the
- // power system may never send this sort of request) but it's trivial
- // to deal with.
- //
-
- if ((irpStack->Parameters.Power.State.DeviceState != PowerDeviceD0) &&
- (fdoExtension->DevicePowerState != PowerDeviceD0)) {
- DebugPrint((1, "(%p)\tAlready powered down to %x???\n",
- Irp, fdoExtension->DevicePowerState));
- fdoExtension->DevicePowerState =
- irpStack->Parameters.Power.State.DeviceState;
- goto ClasspPowerHandlerCleanup;
- }
-
- //
- // or going into a hibernation state when we're in the hibernation path.
- // If the device is spinning then we should leave it spinning - if it's not
- // then the dump driver will start it up for us.
- //
-
- if((irpStack->Parameters.Power.State.DeviceState == PowerDeviceD3) &&
- (irpStack->Parameters.Power.ShutdownType == PowerActionHibernate) &&
- (commonExtension->HibernationPathCount != 0)) {
-
- DebugPrint((1, "(%p)\tdoing nothing for hibernation request for "
- "state %x???\n",
- Irp, fdoExtension->DevicePowerState));
- fdoExtension->DevicePowerState =
- irpStack->Parameters.Power.State.DeviceState;
- goto ClasspPowerHandlerCleanup;
- }
- //
- // or when not handling powering up and are powering up
- //
-
- if ((!Options.HandleSpinUp) &&
- (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0)) {
-
- DebugPrint((2, "(%p)\tNot handling spinup to state %x\n",
- Irp, fdoExtension->DevicePowerState));
- fdoExtension->DevicePowerState =
- irpStack->Parameters.Power.State.DeviceState;
- goto ClasspPowerHandlerCleanup;
-
- }
-
- //
- // or when not handling powering down and are powering down
- //
-
- if ((!Options.HandleSpinDown) &&
- (irpStack->Parameters.Power.State.DeviceState != PowerDeviceD0)) {
-
- DebugPrint((2, "(%p)\tNot handling spindown to state %x\n",
- Irp, fdoExtension->DevicePowerState));
- fdoExtension->DevicePowerState =
- irpStack->Parameters.Power.State.DeviceState;
- goto ClasspPowerHandlerCleanup;
-
- }
-
- context = &(fdoExtension->PowerContext);
-
-#if DBG
- //
- // Mark the context as in use. We should be synchronizing this but
- // since it's just for debugging purposes we don't worry too much.
- //
-
- ASSERT(context->InUse == FALSE);
-#endif
-
- RtlZeroMemory(context, sizeof(CLASS_POWER_CONTEXT));
- context->InUse = TRUE;
-
- nextIrpStack->Parameters.Scsi.Srb = &(context->Srb);
- nextIrpStack->MajorFunction = IRP_MJ_SCSI;
-
- context->FinalStatus = STATUS_SUCCESS;
-
- context->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
- context->Srb.OriginalRequest = Irp;
- context->Srb.SrbFlags |= SRB_FLAGS_BYPASS_LOCKED_QUEUE
- | SRB_FLAGS_NO_QUEUE_FREEZE;
- context->Srb.Function = SRB_FUNCTION_LOCK_QUEUE;
-
- context->Srb.SenseInfoBuffer =
- commonExtension->PartitionZeroExtension->SenseData;
- context->Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE;
- context->RetryCount = MAXIMUM_RETRIES;
-
- context->Options = Options;
- context->DeviceObject = DeviceObject;
- context->Irp = Irp;
-
- if(irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0) {
-
- ASSERT(Options.HandleSpinUp);
-
- DebugPrint((2, "(%p)\tpower up - locking queue\n", Irp));
-
- //
- // We need to issue a queue lock request so that we
- // can spin the drive back up after the power is restored
- // but before any requests are processed.
- //
-
- context->Options.PowerDown = FALSE;
- context->PowerChangeState.PowerUp = PowerUpDeviceInitial;
- context->CompletionRoutine = ClasspPowerUpCompletion;
-
- } else {
-
- ASSERT(Options.HandleSpinDown);
-
- fdoExtension->PowerDownInProgress = TRUE;
-
- DebugPrint((2, "(%p)\tPowering down - locking queue\n", Irp));
-
- PoSetPowerState(DeviceObject,
- irpStack->Parameters.Power.Type,
- irpStack->Parameters.Power.State);
-
- context->Options.PowerDown = TRUE;
- context->PowerChangeState.PowerDown2 = PowerDownDeviceInitial2;
- context->CompletionRoutine = ClasspPowerDownCompletion;
-
- }
-
- //
- // we are not dealing with port-allocated sense in these routines.
- //
-
- ASSERT(!TEST_FLAG(context->Srb.SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
- ASSERT(!TEST_FLAG(context->Srb.SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
-
- //
- // we are always returning STATUS_PENDING, so we need to always
- // set the irp as pending.
- //
-
- IoMarkIrpPending(Irp);
-
- if(Options.LockQueue) {
-
- //
- // Send the lock irp down.
- //
-
- IoSetCompletionRoutine(Irp,
- context->CompletionRoutine,
- context,
- TRUE,
- TRUE,
- TRUE);
-
- IoCallDriver(lowerDevice, Irp);
-
- } else {
-
- //
- // Call the completion routine directly. It won't care what the
- // status of the "lock" was - it will just go and do the next
- // step of the operation.
- //
-
- context->CompletionRoutine(DeviceObject, Irp, context);
- }
-
- return STATUS_PENDING;
-
-ClasspPowerHandlerCleanup:
-
- ClassReleaseRemoveLock(DeviceObject, Irp);
-
- DebugPrint((1, "(%p)\tStarting next power irp\n", Irp));
- IoCopyCurrentIrpStackLocationToNext(Irp);
- IoSetCompletionRoutine(Irp,
- ClasspStartNextPowerIrpCompletion,
- NULL,
- TRUE,
- TRUE,
- TRUE);
- return PoCallDriver(lowerDevice, Irp);
-} // end ClasspPowerHandler()
-
-/*++////////////////////////////////////////////////////////////////////////////
-
-ClassMinimalPowerHandler()
-
-Routine Description:
-
- This routine is the minimum power handler for a storage driver. It does
- the least amount of work possible.
-
---*/
-NTSTATUS
-NTAPI
-ClassMinimalPowerHandler(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
-{
- PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
- PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
- NTSTATUS status;
-
- ClassReleaseRemoveLock(DeviceObject, Irp);
- PoStartNextPowerIrp(Irp);
-
- if(commonExtension->IsFdo) {
-
- if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
-
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
- DeviceObject->DeviceExtension;
-
- //
- // Check if the system is going to hibernate or standby.
- //
- if (irpStack->MinorFunction == IRP_MN_SET_POWER){
- PVPB vpb;
-
- switch (irpStack->Parameters.Power.ShutdownType){
-
- case PowerActionSleep:
- case PowerActionHibernate:
- //
- // If the volume is mounted, set the verify bit so that
- // the filesystem will be forced re-read the media
- // after coming out of hibernation or standby.
- //
- vpb = ClassGetVpb(fdoExtension->DeviceObject);
- if (vpb && (vpb->Flags & VPB_MOUNTED)){
- SET_FLAG(fdoExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
- }
- break;
- default:
- break;
- }
- }
- }
-
- IoCopyCurrentIrpStackLocationToNext(Irp);
- return PoCallDriver(commonExtension->LowerDeviceObject, Irp);
-
- } else {
-
- if (irpStack->MinorFunction != IRP_MN_SET_POWER &&
- irpStack->MinorFunction != IRP_MN_QUERY_POWER) {
-
- NOTHING;
-
- } else {
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
-
- }
- status = Irp->IoStatus.Status;
-
- ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
- return status;
- }
-} // end ClassMinimalPowerHandler()
-
-/*++////////////////////////////////////////////////////////////////////////////
-
-ClassSpinDownPowerHandler()
-
-Routine Description:
-
- This routine is a callback for disks and other things which require both
- a start and a stop to be sent to the device. (actually the starts are
- almost always optional, since most device power themselves on to process
- commands, but i digress).
-
- Determines proper use of spinup, spindown, and queue locking based upon
- ScanForSpecialFlags in the FdoExtension. This is the most common power
- handler passed into classpnp.sys
-
-Arguments:
-
- DeviceObject - Supplies the functional device object
-
- Irp - Supplies the request to be retried.
-
-Return Value:
-
- None
-
---*/
-NTSTATUS
-NTAPI
-ClassSpinDownPowerHandler(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
-{
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
- CLASS_POWER_OPTIONS options;
-
- fdoExtension = (PFUNCTIONAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- //
- // this will set all options to FALSE
- //
-
- RtlZeroMemory(&options, sizeof(CLASS_POWER_OPTIONS));
-
- //
- // check the flags to see what options we need to worry about
- //
-
- if (!TEST_FLAG(fdoExtension->ScanForSpecialFlags,
- CLASS_SPECIAL_DISABLE_SPIN_DOWN)) {
- options.HandleSpinDown = TRUE;
- }
-
- if (!TEST_FLAG(fdoExtension->ScanForSpecialFlags,
- CLASS_SPECIAL_DISABLE_SPIN_UP)) {
- options.HandleSpinUp = TRUE;
- }
-
- if (!TEST_FLAG(fdoExtension->ScanForSpecialFlags,
- CLASS_SPECIAL_NO_QUEUE_LOCK)) {
- options.LockQueue = TRUE;
- }
-
- DebugPrint((3, "ClasspPowerHandler: Devobj %p\n"
- "\t%shandling spin down\n"
- "\t%shandling spin up\n"
- "\t%slocking queue\n",
- DeviceObject,
- (options.HandleSpinDown ? "" : "not "),
- (options.HandleSpinUp ? "" : "not "),
- (options.LockQueue ? "" : "not ")
- ));
-
- //
- // do all the dirty work
- //
-
- return ClasspPowerHandler(DeviceObject, Irp, options);
-} // end ClassSpinDownPowerHandler()
-
-/*++////////////////////////////////////////////////////////////////////////////
-
-ClassStopUnitPowerHandler()
-
-Routine Description:
-
- This routine is an outdated call. To achieve equivalent functionality,
- the driver should set the following flags in ScanForSpecialFlags in the
- FdoExtension:
-
- CLASS_SPECIAL_DISABLE_SPIN_UP
- CLASS_SPECIAL_NO_QUEUE_LOCK
-
---*/
-NTSTATUS
-NTAPI
-ClassStopUnitPowerHandler(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
-{
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
-
- DebugPrint((0, "ClassStopUnitPowerHandler - Devobj %p using outdated call\n"
- "Drivers should set the following flags in ScanForSpecialFlags "
- " in the FDO extension:\n"
- "\tCLASS_SPECIAL_DISABLE_SPIN_UP\n"
- "\tCLASS_SPECIAL_NO_QUEUE_LOCK\n"
- "This will provide equivalent functionality if the power "
- "routine is then set to ClassSpinDownPowerHandler\n\n",
- DeviceObject));
-
- fdoExtension = (PFUNCTIONAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
- SET_FLAG(fdoExtension->ScanForSpecialFlags,
- CLASS_SPECIAL_DISABLE_SPIN_UP);
- SET_FLAG(fdoExtension->ScanForSpecialFlags,
- CLASS_SPECIAL_NO_QUEUE_LOCK);
-
- return ClassSpinDownPowerHandler(DeviceObject, Irp);
-} // end ClassStopUnitPowerHandler()
-
-/*++////////////////////////////////////////////////////////////////////////////
-
-RetryPowerRequest()
-
-Routine Description:
-
- This routine reinitializes the necessary fields, and sends the request
- to the lower driver.
-
-Arguments:
-
- DeviceObject - Supplies the device object associated with this request.
-
- Irp - Supplies the request to be retried.
-
- Context - Supplies a pointer to the power up context for this request.
-
-Return Value:
-
- None
-
---*/
-VOID
-NTAPI
-RetryPowerRequest(
- PDEVICE_OBJECT DeviceObject,
- PIRP Irp,
- PCLASS_POWER_CONTEXT Context
- )
-{
- PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
- PSCSI_REQUEST_BLOCK srb = &(Context->Srb);
- LARGE_INTEGER dueTime;
-
- DebugPrint((1, "(%p)\tDelaying retry by queueing DPC\n", Irp));
-
- ASSERT(Context->Irp == Irp);
- ASSERT(Context->DeviceObject == DeviceObject);
- ASSERT(!TEST_FLAG(Context->Srb.SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
- ASSERT(!TEST_FLAG(Context->Srb.SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
-
- //
- // reset the retry interval
- //
-
- Context->RetryInterval = 0;
-
- //
- // Reset byte count of transfer in SRB Extension.
- //
-
- srb->DataTransferLength = 0;
-
- //
- // Zero SRB statuses.
- //
-
- srb->SrbStatus = srb->ScsiStatus = 0;
-
- //
- // Set up major SCSI function.
- //
-
- nextIrpStack->MajorFunction = IRP_MJ_SCSI;
-
- //
- // Save SRB address in next stack for port driver.
- //
-
- nextIrpStack->Parameters.Scsi.Srb = srb;
-
- //
- // Set the completion routine up again.
- //
-
- IoSetCompletionRoutine(Irp, Context->CompletionRoutine, Context,
- TRUE, TRUE, TRUE);
-
-
- if (Context->RetryInterval == 0) {
-
- DebugPrint((2, "(%p)\tDelaying minimum time (.2 sec)\n", Irp));
- dueTime.QuadPart = (LONGLONG)1000000 * 2;
-
- } else {
-
- DebugPrint((2, "(%p)\tDelaying %x seconds\n",
- Irp, Context->RetryInterval));
- dueTime.QuadPart = (LONGLONG)1000000 * 10 * Context->RetryInterval;
-
- }
-
- ClassRetryRequest(DeviceObject, Irp, dueTime);
-
- return;
-
-} // end RetryRequest()
-
-/*++////////////////////////////////////////////////////////////////////////////
-
-ClasspStartNextPowerIrpCompletion()
-
-Routine Description:
-
- This routine guarantees that the next power irp (power up or down) is not
- sent until the previous one has fully completed.
-
---*/
-NTSTATUS
-NTAPI
-ClasspStartNextPowerIrpCompletion(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN PVOID Context
- )
-{
- if(Irp->PendingReturned) {
- IoMarkIrpPending(Irp);
- }
-
- PoStartNextPowerIrp(Irp);
- return STATUS_SUCCESS;
-} // end ClasspStartNextPowerIrpCompletion()