Home | Info | Community | Development | myReactOS | Contact Us
Definition at line 152 of file power.c.
Referenced by ClasspPowerHandler().
{ 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 == TRUE) && (!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 == TRUE) && (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; } } return STATUS_MORE_PROCESSING_REQUIRED; } // end ClasspPowerUpCompletion()