ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

NTSTATUS ClasspPowerUpCompletion ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PCLASS_POWER_CONTEXT  Context 
)

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()

Generated on Mon May 28 2012 05:11:40 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.