示例#1
0
文件: power.c 项目: kcrazy/winekit
NTSTATUS
Serenum_FDOPowerComplete (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
                          IN PVOID Context)
/*++
--*/
{
    POWER_STATE powerState;
    POWER_STATE_TYPE powerType;
    PIO_STACK_LOCATION stack;
    PFDO_DEVICE_DATA data;

    UNREFERENCED_PARAMETER(Context);


    if (Irp->PendingReturned) {
        IoMarkIrpPending(Irp);
    }


    data = (PFDO_DEVICE_DATA)DeviceObject->DeviceExtension;
    stack = IoGetCurrentIrpStackLocation(Irp);
    powerType = stack->Parameters.Power.Type;
    powerState = stack->Parameters.Power.State;

    switch (stack->MinorFunction) {
    case IRP_MN_SET_POWER:
        switch (powerType) {
        case DevicePowerState:
            //
            // Powering Up
            //
            ASSERT(powerState.DeviceState < data->DeviceState);
            data->DeviceState = powerState.DeviceState;

            PoSetPowerState(data->Self, powerType, powerState);
            break;

        default:
           break;
        }
        break;

    case IRP_MN_QUERY_POWER:
        ASSERT(IRP_MN_QUERY_POWER != stack->MinorFunction);
        break;

    default:
        //
        // Basically, this is ASSERT(0)
        //
        ASSERT(0xBADBAD == IRP_MN_QUERY_POWER);
        break;
    }


    PoStartNextPowerIrp(Irp);
    Serenum_DecIoCount(data);

    return STATUS_SUCCESS; // Continue completion...
}
static NTSTATUS vboxUsbPwrIoPostDevCompletion(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp, IN PVOID pvContext)
{
    PVBOXUSBDEV_EXT pDevExt = (PVBOXUSBDEV_EXT)pvContext;

    if (pIrp->PendingReturned)
    {
        IoMarkIrpPending(pIrp);
    }

    NTSTATUS Status = pIrp->IoStatus.Status;
    Assert(Status == STATUS_SUCCESS);
    if (NT_SUCCESS(Status))
    {
        PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
        switch (pSl->MinorFunction)
        {
            case IRP_MN_SET_POWER:
            {
                pDevExt->DdiState.PwrState.PowerState.DeviceState = pSl->Parameters.Power.State.DeviceState;
                PoSetPowerState(pDevExt->pFDO, DevicePowerState, pSl->Parameters.Power.State);
                break;
            }
            default:
            {
                break;
            }
        }
    }

    PoStartNextPowerIrp(pIrp);
    vboxUsbDdiStateRelease(pDevExt);
    return STATUS_SUCCESS;
}
示例#3
0
文件: fbtpwr.c 项目: RPG-7/reactos
NTSTATUS NTAPI FinishDevPoDnIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
{
    NTSTATUS           ntStatus;
    POWER_STATE        newState;
    PIO_STACK_LOCATION irpStack;

    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp: Entered\n"));

    ntStatus = Irp->IoStatus.Status;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    newState = irpStack->Parameters.Power.State;

    if (NT_SUCCESS(ntStatus) && irpStack->MinorFunction == IRP_MN_SET_POWER)
    {
        FreeBT_DbgPrint(3, ("FBTUSB: updating cache..\n"));
        DeviceExtension->DevPower = newState.DeviceState;
        PoSetPowerState(DeviceObject, DevicePowerState, newState);

    }

    PoStartNextPowerIrp(Irp);

    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp::"));
    FreeBT_IoDecrement(DeviceExtension);

    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp: Leaving\n"));

    return STATUS_SUCCESS;

}
示例#4
0
NTSTATUS Bus_StartFdo(__in PFDO_DEVICE_DATA FdoData, __in PIRP Irp)
{
    NTSTATUS status;
    POWER_STATE powerState;

    UNREFERENCED_PARAMETER(Irp);
    PAGED_CODE();

    status = IoSetDeviceInterfaceState(&FdoData->InterfaceName, TRUE);

    if (!NT_SUCCESS (status))
	{
        Bus_KdPrint(("IoSetDeviceInterfaceState failed: 0x%x\n", status));
        return status;
    }

    FdoData->DevicePowerState = PowerDeviceD0;
    powerState.DeviceState    = PowerDeviceD0;

	PoSetPowerState(FdoData->Self, DevicePowerState, powerState);

    SET_NEW_PNP_STATE(FdoData, Started);

    return status;
}
示例#5
0
NTSTATUS
FinishDevPoDnIrp(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PDEVICE_EXTENSION DeviceExtension
    )
/*++
 
Routine Description:

    This routine is the completion routine for device power DOWN 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        newState;
    PIO_STACK_LOCATION irpStack;

    //
    // initialize variables
    //
    ntStatus = Irp->IoStatus.Status;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    newState = irpStack->Parameters.Power.State;

    MobiUsb_DbgPrint(3, ("file mobipwr: FinishDevPoDnIrp - begins\n"));

    if(NT_SUCCESS(ntStatus) && irpStack->MinorFunction == IRP_MN_SET_POWER) {

        //
        // update the cache;
        //

        MobiUsb_DbgPrint(3, ("file mobipwr: updating cache..\n"));

        DeviceExtension->DevPower = newState.DeviceState;

        PoSetPowerState(DeviceObject, DevicePowerState, newState);
    }

    PoStartNextPowerIrp(Irp);

    MobiUsb_DbgPrint(3, ("file mobipwr: FinishDevPoDnIrp::"));
    MobiUsb_IoDecrement(DeviceExtension);

    MobiUsb_DbgPrint(3, ("file mobipwr: FinishDevPoDnIrp - ends\n"));

    return STATUS_SUCCESS;
}
DECLHIDDEN(VOID) vboxUsbPwrStateInit(PVBOXUSBDEV_EXT pDevExt)
{
    POWER_STATE PowerState;
    PowerState.SystemState = PowerSystemWorking;
    PowerState.DeviceState = PowerDeviceD0;
    PoSetPowerState(pDevExt->pFDO, DevicePowerState, PowerState);
    pDevExt->DdiState.PwrState.PowerState = PowerState;
    pDevExt->DdiState.PwrState.PowerDownLevel = PowerDeviceUnspecified;
}
示例#7
0
static NTSTATUS DDKAPI
on_power_state_complete(DEVICE_OBJECT *device_object,
                        IRP           *irp,
                        void          *context)
{
    libusb_device_t *dev = context;
    IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
    POWER_STATE power_state = stack_location->Parameters.Power.State;
    DEVICE_POWER_STATE dev_power_state;

    if (irp->PendingReturned)
    {
        IoMarkIrpPending(irp);
    }

    if (NT_SUCCESS(irp->IoStatus.Status))
    {
        if (stack_location->Parameters.Power.Type == SystemPowerState)
        {
            USBMSG("S%d %s\n",
				power_state.SystemState - PowerSystemWorking, dev->device_id);

            /* save current system state */
            dev->power_state.SystemState = power_state.SystemState;

            /* get supported device power state from the array reported by */
            /* IRP_MN_QUERY_CAPABILITIES */
            dev_power_state = dev->device_power_states[power_state.SystemState];

            /* set the device power state, but don't block the thread */
            power_set_device_state(dev, dev_power_state, FALSE);
        }
        else /* DevicePowerState */
        {
            USBMSG("D%d %s\n",
				power_state.DeviceState - PowerDeviceD0, dev->device_id);

            if (power_state.DeviceState <= dev->power_state.DeviceState)
            {
                /* device is powered up, */
                /* report device state to Power Manager */
                PoSetPowerState(dev->self, DevicePowerState, power_state);
            }
            /* save current device state */
            dev->power_state.DeviceState = power_state.DeviceState;
        }
    }
    else
    {
        USBMSG0("failed\n");
    }

    remove_lock_release(dev);

    return STATUS_SUCCESS;
}
示例#8
0
文件: pdo.c 项目: OpenXT/xc-windows
NTSTATUS
XenM2BPdoPower(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
    PXENM2B_PDO_EXTENSION pPdoExt = (PXENM2B_PDO_EXTENSION)pDeviceObject->DeviceExtension;
    PIO_STACK_LOCATION    pIrpStack;
    POWER_STATE           PowerState;
    POWER_STATE_TYPE      PowerType;
    NTSTATUS              Status = STATUS_SUCCESS;

    pIrpStack = IoGetCurrentIrpStackLocation(pIrp);

    PowerType = pIrpStack->Parameters.Power.Type;
    PowerState = pIrpStack->Parameters.Power.State;

    switch (pIrpStack->MinorFunction) {
    case IRP_MN_SET_POWER:
        TraceDebug(("%s: IRP_MN_SET_POWER\n", __FUNCTION__));

        if (PowerType == DevicePowerState) {
            TraceDebug(("%s: IRP_MN_SET_POWER DevicePowerState:%x\n", __FUNCTION__, PowerState.DeviceState));

            PoSetPowerState(pPdoExt->pDevice, DevicePowerState, PowerState);
            pPdoExt->DevicePowerState = PowerState.DeviceState;
        }
        else if (PowerType == SystemPowerState) {
            TraceDebug(("%s: IRP_MN_SET_POWER SystemPowerState:%x\n", __FUNCTION__, PowerState.SystemState));

            pPdoExt->SystemPowerState = PowerState.SystemState;
        }

        PoStartNextPowerIrp(pIrp);
        pIrp->IoStatus.Status = Status;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        break;

    case IRP_MN_QUERY_POWER:
        TraceDebug(("%s: IRP_MN_QUERY_POWER\n", __FUNCTION__));
        PoStartNextPowerIrp(pIrp);
        pIrp->IoStatus.Status = Status;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        break;

    case IRP_MN_WAIT_WAKE:
    case IRP_MN_POWER_SEQUENCE:
    default:
        PoStartNextPowerIrp(pIrp);
        Status = pIrp->IoStatus.Status;
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        break;
    }

    return Status;
}
示例#9
0
static DECLSPEC_NOINLINE NTSTATUS
PdoRemoveDevice(
    IN  PXENFILT_PDO    Pdo,
    IN  PIRP            Irp
    )
{
    PXENFILT_FDO        Fdo = __PdoGetFdo(Pdo);
    POWER_STATE         PowerState;
    NTSTATUS            status;

    status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp);
    if (!NT_SUCCESS(status))
        goto fail1;

    if (__PdoGetDevicePowerState(Pdo) != PowerDeviceD0)
        goto done;

    __PdoSetDevicePowerState(Pdo, PowerDeviceD3);
    __PdoSetSystemPowerState(Pdo, PowerSystemShutdown);

    PowerState.DeviceState = PowerDeviceD3;
    PoSetPowerState(Pdo->Dx->DeviceObject,
                    DevicePowerState,
                    PowerState);

done:
    if (__PdoIsMissing(Pdo)) {
        __PdoSetDevicePnpState(Pdo, Deleted);
        IoReleaseRemoveLockAndWait(&Pdo->Dx->RemoveLock, Irp);
    } else {
        __PdoSetDevicePnpState(Pdo, Enumerated);
        IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
    }

    status = PdoForwardIrpSynchronously(Pdo, Irp);
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    if (__PdoIsMissing(Pdo)) {
        FdoAcquireMutex(Fdo);
        PdoDestroy(Pdo);
        FdoReleaseMutex(Fdo);
    }

    return status;

fail1:
    Irp->IoStatus.Status = status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return status;
}
示例#10
0
文件: pnp.c 项目: Strongc/reactos
NTSTATUS
Bus_StartFdo (
    PFDO_DEVICE_DATA            FdoData,
    PIRP   Irp )
{
    NTSTATUS status = STATUS_SUCCESS;
    POWER_STATE powerState;
    ACPI_STATUS AcpiStatus;

    PAGED_CODE ();

    FdoData->Common.DevicePowerState = PowerDeviceD0;
    powerState.DeviceState = PowerDeviceD0;
    PoSetPowerState ( FdoData->Common.Self, DevicePowerState, powerState );

    SET_NEW_PNP_STATE(FdoData->Common, Started);

    AcpiStatus = AcpiInitializeSubsystem();
    if(ACPI_FAILURE(AcpiStatus)){
        DPRINT1("Unable to AcpiInitializeSubsystem\n");
        return STATUS_UNSUCCESSFUL;
    }
    
    
	AcpiStatus = AcpiInitializeTables(NULL, 16, 0);
    if (ACPI_FAILURE(status)){
        DPRINT1("Unable to AcpiInitializeSubsystem\n");
		return STATUS_UNSUCCESSFUL;
    }

    AcpiStatus = AcpiLoadTables();
    if(ACPI_FAILURE(AcpiStatus)){
        DPRINT1("Unable to AcpiLoadTables\n");
        AcpiTerminate();
        return STATUS_UNSUCCESSFUL;
    }

	DPRINT("Acpi subsystem init\n");
    /* Initialize ACPI bus manager */
    AcpiStatus = acpi_init();
    if (!ACPI_SUCCESS(AcpiStatus)) {
        DPRINT1("acpi_init() failed with status 0x%X\n", AcpiStatus);
        AcpiTerminate();
        return STATUS_UNSUCCESSFUL;
    }
	status = ACPIEnumerateDevices(FdoData);

    return status;
}
示例#11
0
static NTSTATUS DDKAPI
on_filter_power_state_complete(DEVICE_OBJECT *device_object,
                               IRP           *irp,
                               void          *context)
{
    libusb_device_t *dev = context;
    IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
    POWER_STATE power_state = stack_location->Parameters.Power.State;

    if (NT_SUCCESS(irp->IoStatus.Status))
    {
        if (stack_location->Parameters.Power.Type == SystemPowerState)
        {
            USBMSG("S%d\n",
				power_state.SystemState - PowerSystemWorking);

            /* save current system state */
            dev->power_state.SystemState = power_state.SystemState;


        }
        else /* DevicePowerState */
        {
            USBMSG("D%d\n",
				power_state.DeviceState - PowerDeviceD0);

            if (power_state.DeviceState <= dev->power_state.DeviceState)
            {
                /* device is powered up, */
                /* report device state to Power Manager */
                PoSetPowerState(dev->self, DevicePowerState, power_state);
            }

            /* save current device state */
            dev->power_state.DeviceState = power_state.DeviceState;
        }
    }
    else
    {
        USBMSG0("failed\n");
    }

    remove_lock_release(dev);

    return STATUS_SUCCESS;
}
示例#12
0
static DECLSPEC_NOINLINE NTSTATUS
PdoStopDevice(
    IN  PXENFILT_PDO    Pdo,
    IN  PIRP            Irp
    )
{
    POWER_STATE         PowerState;
    NTSTATUS            status;

    status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp);
    if (!NT_SUCCESS(status))
        goto fail1;

    if (__PdoGetDevicePowerState(Pdo) != PowerDeviceD0)
        goto done;

    __PdoSetDevicePowerState(Pdo, PowerDeviceD3);
    __PdoSetSystemPowerState(Pdo, PowerSystemShutdown);

    PowerState.DeviceState = PowerDeviceD3;
    PoSetPowerState(Pdo->Dx->DeviceObject,
                    DevicePowerState,
                    PowerState);

done:
    __PdoSetDevicePnpState(Pdo, Stopped);
    Irp->IoStatus.Status = STATUS_SUCCESS;

    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(Irp,
                           __PdoStopDevice,
                           Pdo,
                           TRUE,
                           TRUE,
                           TRUE);

    status = IoCallDriver(Pdo->LowerDeviceObject, Irp);

    return status;

fail1:
    Irp->IoStatus.Status = status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return status;
}
示例#13
0
文件: fbtpwr.c 项目: RPG-7/reactos
NTSTATUS NTAPI SetDeviceFunctional(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
{
    KIRQL              oldIrql;
    NTSTATUS           ntStatus;
    POWER_STATE        newState;
    PIO_STACK_LOCATION irpStack;
    DEVICE_POWER_STATE newDevState, oldDevState;

    ntStatus = Irp->IoStatus.Status;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    newState = irpStack->Parameters.Power.State;
    newDevState = newState.DeviceState;
    oldDevState = DeviceExtension->DevPower;

    FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional: Entered\n"));

    // update the cached state
    DeviceExtension->DevPower = newDevState;

    // restore appropriate amount of state to our h/w
    // this driver does not implement partial context
    // save/restore.
    PoSetPowerState(DeviceObject, DevicePowerState, newState);
    if(PowerDeviceD0 == newDevState)
    {
        KeAcquireSpinLock(&DeviceExtension->DevStateLock, &oldIrql);
        DeviceExtension->QueueState = AllowRequests;
        KeReleaseSpinLock(&DeviceExtension->DevStateLock, oldIrql);

        ProcessQueuedRequests(DeviceExtension);

    }

    PoStartNextPowerIrp(Irp);
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional::"));
    FreeBT_IoDecrement(DeviceExtension);

    FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional: Leaving\n"));

    return STATUS_SUCCESS;

}
示例#14
0
static DECLSPEC_NOINLINE NTSTATUS
PdoStartDevice(
    IN  PXENFILT_PDO    Pdo,
    IN  PIRP            Irp
    )
{
    POWER_STATE         PowerState;
    NTSTATUS            status;

    status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp);
    if (!NT_SUCCESS(status))
        goto fail1;

    status = PdoForwardIrpSynchronously(Pdo, Irp);
    if (!NT_SUCCESS(status))
        goto fail2;

    __PdoSetSystemPowerState(Pdo, PowerSystemWorking);
    __PdoSetDevicePowerState(Pdo, PowerDeviceD0);

    PowerState.DeviceState = PowerDeviceD0;
    PoSetPowerState(Pdo->Dx->DeviceObject,
                    DevicePowerState,
                    PowerState);

    __PdoSetDevicePnpState(Pdo, Started);

    IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);

    Irp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;

fail2:
    IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);

fail1:
    Irp->IoStatus.Status = status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return status;
}
示例#15
0
NTSTATUS PdoPortPower(
    IN PC0C_PDOPORT_EXTENSION pDevExt,
    IN PIRP                   pIrp)
{
  NTSTATUS status;
  PIO_STACK_LOCATION  pIrpStack = IoGetCurrentIrpStackLocation(pIrp);

  switch (pIrpStack->MinorFunction) {
  case IRP_MN_SET_POWER:
    switch (pIrpStack->Parameters.Power.Type) {
    case DevicePowerState:
      PoSetPowerState(pDevExt->pDevObj, DevicePowerState, pIrpStack->Parameters.Power.State);
      status = STATUS_SUCCESS;
      break;
    case SystemPowerState:
      status = STATUS_SUCCESS;
      break;
    default:
      status = STATUS_NOT_SUPPORTED;
      break;
    }
    break;
  case IRP_MN_QUERY_POWER:
    status = STATUS_SUCCESS;
    break;
  case IRP_MN_WAIT_WAKE:
  case IRP_MN_POWER_SEQUENCE:
  default:
    status = STATUS_NOT_SUPPORTED;
    break;
  }

  if (status != STATUS_NOT_SUPPORTED)
    pIrp->IoStatus.Status = status;

  PoStartNextPowerIrp(pIrp);
  status = pIrp->IoStatus.Status;
  IoCompleteRequest(pIrp, IO_NO_INCREMENT);

  return status;
}
示例#16
0
GENERICAPI NTSTATUS GENERIC_EXPORT InitializeGenericExtension(PGENERIC_EXTENSION pdx, PGENERIC_INIT_STRUCT isp)
	{							// InitializeGenericExtension
	if (isp->Size < FIELD_OFFSET(GENERIC_INIT_STRUCT, Flags)
		|| !isp->DeviceObject
		|| !isp->Ldo
		|| !isp->Pdo
		|| !isp->StartDevice
		|| !isp->StopDevice
		|| !isp->RemoveDevice
		|| isp->DeviceQueue && !isp->StartIo)

		return STATUS_INVALID_PARAMETER;

	RtlZeroMemory(pdx, sizeof(GENERIC_EXTENSION));

	pdx->DeviceObject = isp->DeviceObject;
	pdx->LowerDeviceObject = isp->Ldo;
	pdx->Pdo = isp->Pdo;
	pdx->StartDevice = isp->StartDevice;
	pdx->StopDevice = isp->StopDevice;
	pdx->RemoveDevice = isp->RemoveDevice;

	if (isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, OkayToRemove) + sizeof(PQUERYFUNCTION))
		{						// set OkayToStop & OkayToRemove pointers
		pdx->OkayToStop = isp->OkayToStop;
		pdx->OkayToRemove = isp->OkayToRemove;
		}						// set OkayToStop & OkayToRemove pointers

	if ((pdx->dqReadWrite = isp->DeviceQueue))
		{						// queue reads & writes
		if (!isp->StartIo)
			return STATUS_INVALID_PARAMETER;
		InitializeQueue(pdx->dqReadWrite, isp->StartIo);
		}						// queue reads & writes

	if ((pdx->RemoveLock = isp->RemoveLock))
		IoInitializeRemoveLock(pdx->RemoveLock, 0, 0, 0);

	pdx->state = STOPPED;
	
	pdx->devpower = PowerDeviceD0;
	pdx->syspower = PowerSystemWorking;
	POWER_STATE state;
	state.DeviceState = PowerDeviceD0;
	PoSetPowerState(pdx->DeviceObject, DevicePowerState, state);

	// Capture the mini-driver name for messages. This needs to be in ANSI because
	// unicode conversions at or above DISPATCH_LEVEL are not allowed

	if (!isp->DebugName.Length)
		strcpy(pdx->DebugName, "GENERIC");
	else
		{						// convert debug name
		ANSI_STRING asname = {0, sizeof(pdx->DebugName) - 1, pdx->DebugName};
		RtlUnicodeStringToAnsiString(&asname, &isp->DebugName, FALSE);
		pdx->DebugName[asname.Length] = 0;
		}						// convert debug name

	if (isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, Flags) + sizeof(ULONG))
		pdx->Flags = isp->Flags & GENERIC_CLIENT_FLAGS;

	if (isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, RestoreDeviceContext) + sizeof(PCONTEXTFUNCTION))
		{						// get power helper functions
		pdx->QueryPower = isp->QueryPower;
		pdx->SaveDeviceContext = isp->SaveDeviceContext;
		pdx->RestoreDeviceContext = isp->RestoreDeviceContext;
		}						// get power helper functions

	if (isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, PerfBoundary) + sizeof(DEVICE_POWER_STATE))
		pdx->PerfBoundary = isp->PerfBoundary;
	else
		pdx->PerfBoundary = PowerDeviceUnspecified;

	if (pdx->PerfBoundary == PowerDeviceUnspecified)
		pdx->PerfBoundary = PowerDeviceMaximum; // inhibit POWER_SEQUENCE optimization

	// Initialize variables related to asynchrounous IOCTL management.

	if (pdx->Flags & GENERIC_PENDING_IOCTLS)
		{						// driver may cache asyncronous IOCTLs
		InitializeListHead(&pdx->PendingIoctlList);
		pdx->IoctlAbortStatus = 0;

		// We need to initialize our IOCTL spin lock sometime, but just once.
		// Acquiring the cancel spin lock to guard this operation is a bit of
		// a hack, I suppose, but note that a class driver like this one never
		// gets an actual chance to initialize, so it's not my fault...

		KIRQL oldirql;
		IoAcquireCancelSpinLock(&oldirql);	// any global spin lock would do
		if (!IoctlListLockInitialized)
			{					// initialize global lock
			IoctlListLockInitialized = TRUE;
			KeInitializeSpinLock(&IoctlListLock);
			}					// initialize global lock
		IoReleaseCancelSpinLock(oldirql);
		}						// driver may cache asynchronous IOCTLs

	// Initialize to manage registered device interfaces

	ExInitializeFastMutex(&pdx->iflock);
	InitializeListHead(&pdx->iflist);

	// Indicate we handle power IRPs at PASSIVE_LEVEL

	pdx->DeviceObject->Flags |= DO_POWER_PAGABLE;

	KdPrint(("GENERIC - Initializing for %s\n", pdx->DebugName));

	// If requested to do so, register an AutoLaunch interface

	if (pdx->Flags & GENERIC_AUTOLAUNCH)
		GenericRegisterInterface(pdx, &GUID_AUTOLAUNCH_NOTIFY);

	// Register a power management interface

	GenericRegisterInterface(pdx, &GUID_GENERIC_POWER);

#ifdef _X86_
	win98 = IsWin98();
#endif

	return STATUS_SUCCESS;
	}							// InitializeGenericExtension
示例#17
0
文件: power.c 项目: GYGit/reactos
/*++////////////////////////////////////////////////////////////////////////////

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 == 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));

                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 == 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.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 issueing 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 == 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.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 propogate
            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()
示例#18
0
文件: power.c 项目: GYGit/reactos
/*++////////////////////////////////////////////////////////////////////////////

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 == 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;
        }

        case PowerUpDeviceInitial: {
            NT_ASSERT(context->PowerChangeState.PowerUp != PowerUpDeviceInitial);
            break;
        }
    }

    return STATUS_MORE_PROCESSING_REQUIRED;
} // end ClasspPowerUpCompletion()
示例#19
0
NTSTATUS
Bus_StartFdo (
    __in  PFDO_DEVICE_DATA            FdoData,
    __in  PIRP   Irp )
/*++

Routine Description:

    Initialize and start the bus controller. Get the resources
    by parsing the list and map them if required.

Arguments:

    DeviceData - Pointer to the FDO's device extension.
    Irp          - Pointer to the irp.

Return Value:

    NT Status is returned.

--*/
{
    NTSTATUS status;
    POWER_STATE powerState;

    PAGED_CODE ();

    //
    // Check the function driver source to learn
    // about parsing resource list.
    //

    //
    // Enable device interface. If the return status is
    // STATUS_OBJECT_NAME_EXISTS means we are enabling the interface
    // that was already enabled, which could happen if the device
    // is stopped and restarted for resource rebalancing.
    //

    status = IoSetDeviceInterfaceState(&FdoData->InterfaceName, TRUE);
    if (!NT_SUCCESS (status)) {
        Bus_KdPrint (FdoData, BUS_DBG_PNP_TRACE,
                ("IoSetDeviceInterfaceState failed: 0x%x\n", status));
        return status;
    }

    //
    // Set the device power state to fully on. Also if this Start
    // is due to resource rebalance, you should restore the device
    // to the state it was before you stopped the device and relinquished
    // resources.
    //

    FdoData->DevicePowerState = PowerDeviceD0;
    powerState.DeviceState = PowerDeviceD0;
    PoSetPowerState ( FdoData->Self, DevicePowerState, powerState );

    SET_NEW_PNP_STATE(FdoData, Started);

    //
    // Register with WMI
    //
    status = Bus_WmiRegistration(FdoData);
    if (!NT_SUCCESS (status)) {
        Bus_KdPrint (FdoData, BUS_DBG_SS_ERROR,
        ("StartFdo: Bus_WmiRegistration failed (%x)\n", status));
    }

    return status;
}
示例#20
0
文件: pnp.cpp 项目: maodapeng/WDUtils
// for pdo
NTSTATUS DoPdoPnP(PDEVICE_OBJECT pDevice,PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;
	PPdoExt pPdoExt = static_cast<PPdoExt>(pDevice->DeviceExtension);

	PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(pIrp);

	switch(pIoStack->MinorFunction)
	{
	case IRP_MN_START_DEVICE:
		// set power state
		pPdoExt->m_devPowerState = PowerDeviceD0;
		POWER_STATE state;
		state.DeviceState = PowerDeviceD0;
		PoSetPowerState(pDevice,DevicePowerState,state);

		// set pnp state directly
	case IRP_MN_STOP_DEVICE:
	case IRP_MN_QUERY_STOP_DEVICE:
	case IRP_MN_QUERY_REMOVE_DEVICE:
		SetNewPnpState(pPdoExt,pIoStack->MinorFunction);
		break;

		// check prev state
	case IRP_MN_CANCEL_REMOVE_DEVICE:
		if(pPdoExt->m_ulCurrentPnpState == IRP_MN_QUERY_REMOVE_DEVICE)
		{
			RestorePnpState(pPdoExt);
		}
		break;

		// the same
	case IRP_MN_CANCEL_STOP_DEVICE:
		if(pPdoExt->m_ulCurrentPnpState == IRP_MN_QUERY_STOP_DEVICE)
		{
			RestorePnpState(pPdoExt);
		}
		break;

		// remove
	case IRP_MN_REMOVE_DEVICE:
		{
			// delete only if we have reported the device physical removal
			if(pPdoExt->m_bReportMissing)
			{
				SetNewPnpState(pPdoExt,IRP_MN_REMOVE_DEVICE);

				PDEVICE_OBJECT pFdo = pPdoExt->m_pParentFdo;
				if(pFdo)
				{
					PFdoExt pFdoExt = static_cast<PFdoExt>(pFdo->DeviceExtension);

					// update fdo's pointer
					ExAcquireFastMutex(&pFdoExt->m_mutexEnumPdo);
					pFdoExt->m_pEnumPdo = NULL;
					ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo);
				}

				// delete device
				IoDeleteDevice(pDevice);
			}

			// if it's present
			if(pPdoExt->m_bPresent)
			{
				// set it as stopped
				SetNewPnpState(pPdoExt,IRP_MN_STOP_DEVICE);
			}
		}
		break;

		// query caps
	case IRP_MN_QUERY_CAPABILITIES:
		{
			PDEVICE_CAPABILITIES pCaps = pIoStack->Parameters.DeviceCapabilities.Capabilities;

			// version check
			if(pCaps->Version != 1 || pCaps->Size < sizeof(DEVICE_CAPABILITIES))
			{
				status = STATUS_UNSUCCESSFUL; 
				break;
			}

			IO_STATUS_BLOCK     ioStatus;
			KEVENT              pnpEvent;
			PDEVICE_OBJECT      pTargetObject;
			PIO_STACK_LOCATION  pIrpStack;
			PIRP                pPnpIrp;

			DEVICE_CAPABILITIES parentCaps;

			RtlZeroMemory(&parentCaps,sizeof(DEVICE_CAPABILITIES));
			parentCaps.Size = sizeof(DEVICE_CAPABILITIES);
			parentCaps.Version = 1;
			parentCaps.Address = -1;
			parentCaps.UINumber = -1;

			KeInitializeEvent(&pnpEvent,NotificationEvent,FALSE);

			pTargetObject = IoGetAttachedDeviceReference(
								static_cast<PFdoExt>(pPdoExt->m_pParentFdo->DeviceExtension)->m_pLowerDevice);

			// get parent fdo's caps
			pPnpIrp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,pTargetObject,NULL,0,NULL,&pnpEvent,&ioStatus);
			if(pPnpIrp == NULL) 
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
			}
			else
			{
				pPnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
				pIrpStack = IoGetNextIrpStackLocation(pPnpIrp);

				RtlZeroMemory(pIrpStack,sizeof(IO_STACK_LOCATION));
				pIrpStack->MajorFunction = IRP_MJ_PNP;
				pIrpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
				pIrpStack->Parameters.DeviceCapabilities.Capabilities = pCaps;
				status = IoCallDriver(pTargetObject,pPnpIrp);
				if (status == STATUS_PENDING) 
				{
					KeWaitForSingleObject(&pnpEvent,Executive,KernelMode,FALSE,NULL);
					status = ioStatus.Status;
				}
			}

			// dec the ref of the fdo's stack upper device
			ObDereferenceObject(pTargetObject);

			// copy the device state
			RtlCopyMemory(pCaps->DeviceState,parentCaps.DeviceState,(PowerSystemShutdown + 1) * sizeof(DEVICE_POWER_STATE));

			// set our own supported device state
			pCaps->DeviceState[PowerSystemWorking] = PowerDeviceD0;

			if(pCaps->DeviceState[PowerSystemSleeping1] != PowerDeviceD0)
				pCaps->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;

			if(pCaps->DeviceState[PowerSystemSleeping2] != PowerDeviceD0)
				pCaps->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;

			if(pCaps->DeviceState[PowerSystemSleeping3] != PowerDeviceD0)
				pCaps->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;

			// donot support d1 and d2
			pCaps->DeviceD1 = pCaps->DeviceD2 = FALSE;

			// no wake
			pCaps->DeviceWake = PowerDeviceUnspecified;
			pCaps->SystemWake = PowerSystemUnspecified;

			pCaps->WakeFromD0 = FALSE;
			pCaps->WakeFromD1 = FALSE;
			pCaps->WakeFromD2 = FALSE;
			pCaps->WakeFromD3 = FALSE;

			// no latency
			pCaps->D1Latency = 0;
			pCaps->D2Latency = 0;
			pCaps->D3Latency = 0;

			// can eject
			pCaps->EjectSupported = TRUE;

			// don't disable
			pCaps->HardwareDisabled = FALSE;

			// can be removed
			pCaps->Removable = TRUE;

			// don't display surprise remove warning dlg
			pCaps->SurpriseRemovalOK = TRUE;

			// no unique id
			pCaps->UniqueID = FALSE;

			// nead user action for install
			pCaps->SilentInstall = FALSE;

			// bus address
			pCaps->Address = 0;

			// ui display number
			pCaps->UINumber = 0;
		}
		break;

		// query pdo id
	case IRP_MN_QUERY_ID:
		{
			switch(pIoStack->Parameters.QueryId.IdType)
			{
			case BusQueryInstanceID:
				{
					PVOID buffer = ExAllocatePoolWithTag(PagedPool,10,'suBT');
					if(!buffer) 
					{
						status = STATUS_INSUFFICIENT_RESOURCES;
						break;
					}

					RtlStringCchPrintfW(static_cast<PWCHAR>(buffer),10,L"%04d",0);
					pIrp->IoStatus.Information = PtrToUlong(buffer);
					devDebugPrint("\tBusQueryInstanceID\n");
				}
				break;

			case BusQueryDeviceID:
				{
					PVOID buffer = ExAllocatePoolWithTag(PagedPool,PDO_DEVICE_ID_LENGTH,'suBT');
					if(!buffer) 
					{
						status = STATUS_INSUFFICIENT_RESOURCES;
						break;
					}
					RtlCopyMemory(buffer,PDO_DEVICE_ID,PDO_DEVICE_ID_LENGTH);
					pIrp->IoStatus.Information = PtrToUlong(buffer);
					devDebugPrint("\tBusQueryDeviceID\n");
				}
				break;

			case BusQueryHardwareIDs:
				{
					PVOID buffer = ExAllocatePoolWithTag(PagedPool,PDO_HARDWARE_IDS_LENGTH,'suBT');
					if(!buffer) 
					{
						status = STATUS_INSUFFICIENT_RESOURCES;
						break;
					}
					RtlCopyMemory(buffer,PDO_HARDWARE_IDS,PDO_HARDWARE_IDS_LENGTH);
					pIrp->IoStatus.Information = PtrToUlong(buffer);
					devDebugPrint("\tBusQueryHardwareIDs\n");
				}
				break;

			case BusQueryCompatibleIDs:
				{
					PVOID buffer = ExAllocatePoolWithTag(PagedPool,PDO_COMPATIBLE_IDS_LENGTH,'suBT');
					if(!buffer) 
					{
						status = STATUS_INSUFFICIENT_RESOURCES;
						break;
					}
					RtlCopyMemory(buffer,PDO_COMPATIBLE_IDS,PDO_COMPATIBLE_IDS_LENGTH);
					pIrp->IoStatus.Information = PtrToUlong(buffer);
					devDebugPrint("\tBusQueryCompatibleIDs\n");
				}
				break;
			}
		}
		break;

		// query text
	case IRP_MN_QUERY_DEVICE_TEXT:
		{
			switch (pIoStack->Parameters.QueryDeviceText.DeviceTextType) 
			{
			case DeviceTextDescription:
				if(!pIrp->IoStatus.Information) 
				{
					PVOID buffer = ExAllocatePoolWithTag (PagedPool,PDO_TEXT_LENGTH,'suBT');
					if(!buffer) 
					{
						status = STATUS_INSUFFICIENT_RESOURCES;
						break;
					}

					RtlStringCchPrintfW(static_cast<PWCHAR>(buffer),PDO_TEXT_LENGTH,L"%ws",PDO_TEXT);
					
					pIrp->IoStatus.Information = PtrToUlong(buffer);
					devDebugPrint("\tDeviceTextDescription\n");
				}
				break;

			default:
				status = pIrp->IoStatus.Status;
				break;
			}
		}
		break;

		// boot resource
	case IRP_MN_QUERY_RESOURCES:
		{
			PCM_RESOURCE_LIST pResList = static_cast<PCM_RESOURCE_LIST>(ExAllocatePoolWithTag(PagedPool,
																			sizeof(CM_RESOURCE_LIST),'suBT'));

			if(pResList)
			{
				// shareed busnumber resource 
				RtlZeroMemory(pResList,sizeof(CM_RESOURCE_LIST));

				pResList->Count = 1;
				pResList->List[0].BusNumber = 0;
				pResList->List[0].InterfaceType = Internal;
				pResList->List[0].PartialResourceList.Count = 1;
				pResList->List[0].PartialResourceList.Revision = 1;
				pResList->List[0].PartialResourceList.Version = 1;
				pResList->List[0].PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareShared;
				pResList->List[0].PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeBusNumber;
				pResList->List[0].PartialResourceList.PartialDescriptors[0].u.BusNumber.Length = 1;

				pIrp->IoStatus.Information = PtrToUlong(pResList);
			}
			else
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
			}
		}
		break;

		// resource requirements
	case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
		{
			PIO_RESOURCE_REQUIREMENTS_LIST pList = static_cast<PIO_RESOURCE_REQUIREMENTS_LIST>(
										ExAllocatePoolWithTag(PagedPool,sizeof(IO_RESOURCE_REQUIREMENTS_LIST),'suBT'));

			if(pList)
			{
				RtlZeroMemory(pList,sizeof(IO_RESOURCE_REQUIREMENTS_LIST));

				pList->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
				pList->AlternativeLists = 1;
				pList->InterfaceType = InterfaceTypeUndefined;
				pList->BusNumber = 0;
				pList->List[0].Version = 1;
				pList->List[0].Revision = 1;
				pList->List[0].Count = 1;
				pList->List[0].Descriptors[0].Option = IO_RESOURCE_PREFERRED;
				pList->List[0].Descriptors[0].ShareDisposition = CmResourceShareShared;

				pList->List[0].Descriptors[0].Type = CmResourceTypeBusNumber;
				pList->List[0].Descriptors[0].u.BusNumber.MaxBusNumber = 0x10;
				pList->List[0].Descriptors[0].u.BusNumber.Length = 1;

				pIrp->IoStatus.Information = PtrToUlong(pList);
			}
			else
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
			}
		}
		break;

		// bus info
	case IRP_MN_QUERY_BUS_INFORMATION:
		{
			PPNP_BUS_INFORMATION busInfo;

			busInfo = static_cast<PPNP_BUS_INFORMATION>(ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION),'suBT'));

			if (busInfo == NULL) 
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
				break;
			}

			busInfo->BusTypeGuid = GUID_TIAMO_BUS;

			busInfo->LegacyBusType = Internal;

			busInfo->BusNumber = 0;

			pIrp->IoStatus.Information = PtrToUlong(busInfo);
		}
		break;

		// usage
	case IRP_MN_DEVICE_USAGE_NOTIFICATION:
		status = STATUS_UNSUCCESSFUL;
		break;

	case IRP_MN_EJECT:
		{
			// device physical removed
			pPdoExt->m_bPresent = FALSE;
		}
		break;

	//case IRP_MN_QUERY_INTERFACE:
	//	break;

		// target relations
	case IRP_MN_QUERY_DEVICE_RELATIONS:
		{
			if(pIoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
			{
				/*switch(pIoStack->Parameters.QueryDeviceRelations.Type)
				{
				case EjectionRelations:
				devDebugPrint("\tquery EjectionRelations\n");
				break;
				case PowerRelations:
				devDebugPrint("\tquery PowerRelations\n");
				break;
				case RemovalRelations:
				devDebugPrint("\tquery RemovalRelations\n");
				break;
				case BusDeviceRelation:
				devDebugPrint("\tquery BusDeviceRelation\n");
				break;
				case SingleBusRelations:
				devDebugPrint("\tquery SingleBusRelations\n");
				break;
				}*/
				break;
			}

			PDEVICE_RELATIONS pRel = static_cast<PDEVICE_RELATIONS>(ExAllocatePoolWithTag(PagedPool,sizeof(DEVICE_RELATIONS),'suBT'));
			if(!pRel) 
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
				break;
			}

			pRel->Count = 1;
			pRel->Objects[0] = pDevice;
			ObReferenceObject(pDevice);

			status = STATUS_SUCCESS;
			pIrp->IoStatus.Information = PtrToUlong(pRel);
		}
		break;

	default:
		status = pIrp->IoStatus.Status;
		break;
	}

	// pdo should complete the irp
	pIrp->IoStatus.Status = status;
	IoCompleteRequest (pIrp, IO_NO_INCREMENT);

	return status;
}
示例#21
0
NTSTATUS
SetDeviceFunctional(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PDEVICE_EXTENSION DeviceExtension
    )
/*++
 
Routine Description:

    This routine processes queue of pending irps.

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet
    DeviceExtension - pointer to device extension

Return Value:

    NT status value

--*/
{
    KIRQL              oldIrql;
    NTSTATUS           ntStatus;
    POWER_STATE        newState;
    PIO_STACK_LOCATION irpStack;
    DEVICE_POWER_STATE newDevState,
                       oldDevState;

    //
    // initialize variables
    //

    ntStatus = Irp->IoStatus.Status;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    newState = irpStack->Parameters.Power.State;
    newDevState = newState.DeviceState;
    oldDevState = DeviceExtension->DevPower;

    MobiUsb_DbgPrint(3, ("file mobipwr: SetDeviceFunctional - begins\n"));

    //
    // update the cached state
    //
    DeviceExtension->DevPower = newDevState;

    //
    // restore appropriate amount of state to our h/w
    // this driver does not implement partial context
    // save/restore.
    //

    PoSetPowerState(DeviceObject, DevicePowerState, newState);

    if(PowerDeviceD0 == newDevState) {

    //
    // empty existing queue of all pending irps.
    //

        KeAcquireSpinLock(&DeviceExtension->DevStateLock, &oldIrql);

        DeviceExtension->QueueState = AllowRequests;
        
        KeReleaseSpinLock(&DeviceExtension->DevStateLock, oldIrql);

        ProcessQueuedRequests(DeviceExtension);
    }

    PoStartNextPowerIrp(Irp);

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    MobiUsb_DbgPrint(3, ("file mobipwr: SetDeviceFunctional::"));
    MobiUsb_IoDecrement(DeviceExtension);

    MobiUsb_DbgPrint(3, ("file mobipwr: SetDeviceFunctional - ends\n"));

    return STATUS_SUCCESS;
}
示例#22
0
文件: irp.cpp 项目: RareHare/reactos
NTSTATUS
NTAPI
PortClsPower(
    IN  PDEVICE_OBJECT DeviceObject,
    IN  PIRP Irp)
{
    PIO_STACK_LOCATION IoStack;
    PPCLASS_DEVICE_EXTENSION DeviceExtension;
    PQUERY_POWER_CONTEXT PwrContext;
    POWER_STATE PowerState;
    NTSTATUS Status = STATUS_SUCCESS;

    DPRINT("PortClsPower called\n");

    // get currrent stack location
    IoStack = IoGetCurrentIrpStackLocation(Irp);

    if (IoStack->MinorFunction != IRP_MN_SET_POWER && IoStack->MinorFunction != IRP_MN_QUERY_POWER)
    {
        // just forward the request
        Status = PcForwardIrpSynchronous(DeviceObject, Irp);

        // start next power irp
        PoStartNextPowerIrp(Irp);

        // complete request
        Irp->IoStatus.Status = Status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        // done
        return Status;
    }


    // get device extension
    DeviceExtension = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;

    // get current request type
    if (IoStack->Parameters.Power.Type == DevicePowerState)
    {
        // request for device power state
        if (DeviceExtension->DevicePowerState == IoStack->Parameters.Power.State.DeviceState)
        {
            // nothing has changed
            if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
            {
                // only forward query requests
                Status = PcForwardIrpSynchronous(DeviceObject, Irp);
            }

            // start next power irp
            PoStartNextPowerIrp(Irp);

            // complete request
            Irp->IoStatus.Status = Status;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);

            // done
            return Status;
        }

        if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
        {
            // check if there is a registered adapter power management
            if (DeviceExtension->AdapterPowerManagement)
            {
                // it is query if the change can be changed
                PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState);
                Status = DeviceExtension->AdapterPowerManagement->QueryPowerChangeState(PowerState);

                // sanity check
                PC_ASSERT(Status == STATUS_SUCCESS);
            }

            // only forward query requests
            PcForwardIrpSynchronous(DeviceObject, Irp);

            // start next power irp
            PoStartNextPowerIrp(Irp);

            // complete request
            Irp->IoStatus.Status = Status;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);

            // done
            return Status;
        }
        else
        {
            // set power state
            PowerState = *((POWER_STATE*)&IoStack->Parameters.Power.State.DeviceState);
            PoSetPowerState(DeviceObject, DevicePowerState, PowerState);

            // check if there is a registered adapter power management
            if (DeviceExtension->AdapterPowerManagement)
            {
                // notify of a power change state
                DeviceExtension->AdapterPowerManagement->PowerChangeState(PowerState);
            }

            // FIXME call all registered IPowerNotify interfaces via ISubdevice interface

            // store new power state
           DeviceExtension->DevicePowerState = IoStack->Parameters.Power.State.DeviceState;

            // complete request
            Irp->IoStatus.Status = Status;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);

            // done
            return Status;
        }
    }
    else
    {
        // sanity check
        PC_ASSERT(IoStack->Parameters.Power.Type == SystemPowerState);

        if (IoStack->MinorFunction == IRP_MN_QUERY_POWER)
        {
            // mark irp as pending
            IoMarkIrpPending(Irp);

            // allocate power completion context
            PwrContext = (PQUERY_POWER_CONTEXT)AllocateItem(NonPagedPool, sizeof(QUERY_POWER_CONTEXT), TAG_PORTCLASS);

            if (!PwrContext)
            {
                // no memory
                PoStartNextPowerIrp(Irp);

                // complete and forget
                Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                IoCompleteRequest(Irp, IO_NO_INCREMENT);

                // done
                return Status;
            }

            // setup power context
            PwrContext->Irp = Irp;
            PwrContext->DeviceObject = DeviceObject;

            // pass the irp down
            PowerState = *((POWER_STATE*)IoStack->Parameters.Power.State.SystemState);
            Status = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, IoStack->MinorFunction, PowerState, PwrCompletionFunction, (PVOID)PwrContext, NULL);

            // check for success
            if (!NT_SUCCESS(Status))
            {
                // failed
                Irp->IoStatus.Status = Status;
                IoCompleteRequest(Irp, IO_NO_INCREMENT);

                // done
                return Status;
            }

            // done
            return STATUS_PENDING;
        }
        else
        {
            // set power request
            DeviceExtension->SystemPowerState = IoStack->Parameters.Power.State.SystemState;

            // only forward query requests
            Status = PcForwardIrpSynchronous(DeviceObject, Irp);

            // start next power irp
            PoStartNextPowerIrp(Irp);

            // complete request
            Irp->IoStatus.Status = Status;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);

            // done
            return Status;
        }
    }
}
示例#23
0
NTSTATUS
NTAPI
PciPdoIrpStartDevice(IN PIRP Irp,
                     IN PIO_STACK_LOCATION IoStackLocation,
                     IN PPCI_PDO_EXTENSION DeviceExtension)
{
    NTSTATUS Status;
    BOOLEAN Changed, DoReset;
    POWER_STATE PowerState;
    PAGED_CODE();

    DoReset = FALSE;

    /* Begin entering the start phase */
    Status = PciBeginStateTransition((PVOID)DeviceExtension, PciStarted);
    if (!NT_SUCCESS(Status)) return Status;

    /* Check if this is a VGA device */
    if (((DeviceExtension->BaseClass == PCI_CLASS_PRE_20) &&
         (DeviceExtension->SubClass == PCI_SUBCLASS_PRE_20_VGA)) ||
        ((DeviceExtension->BaseClass == PCI_CLASS_DISPLAY_CTLR) &&
         (DeviceExtension->SubClass == PCI_SUBCLASS_VID_VGA_CTLR)))
    {
        /* Always force it on */
        DeviceExtension->CommandEnables |= (PCI_ENABLE_IO_SPACE |
                                            PCI_ENABLE_MEMORY_SPACE);
    }

    /* Check if native IDE is enabled and it owns the I/O ports */
    if (DeviceExtension->IoSpaceUnderNativeIdeControl)
    {
        /* Then don't allow I/O access */
        DeviceExtension->CommandEnables &= ~PCI_ENABLE_IO_SPACE;
    }

    /* Always enable bus mastering */
    DeviceExtension->CommandEnables |= PCI_ENABLE_BUS_MASTER;

    /* Check if the OS assigned resources differ from the PCI configuration */
    Changed = PciComputeNewCurrentSettings(DeviceExtension,
                                           IoStackLocation->Parameters.
                                           StartDevice.AllocatedResources);
    if (Changed)
    {
        /* Remember this for later */
        DeviceExtension->MovedDevice = TRUE;
    }
    else
    {
        /* All good */
        DPRINT1("PCI - START not changing resource settings.\n");
    }

    /* Check if the device was sleeping */
    if (DeviceExtension->PowerState.CurrentDeviceState != PowerDeviceD0)
    {
        /* Power it up */
        Status = PciSetPowerManagedDevicePowerState(DeviceExtension,
                                                    PowerDeviceD0,
                                                    FALSE);
        if (!NT_SUCCESS(Status))
        {
            /* Powerup fail, fail the request */
            PciCancelStateTransition((PVOID)DeviceExtension, PciStarted);
            return STATUS_DEVICE_POWER_FAILURE;
        }

        /* Tell the power manager that the device is powered up */
        PowerState.DeviceState = PowerDeviceD0;
        PoSetPowerState(DeviceExtension->PhysicalDeviceObject,
                        DevicePowerState,
                        PowerState);

        /* Update internal state */
        DeviceExtension->PowerState.CurrentDeviceState = PowerDeviceD0;

        /* This device's resources and decodes will need to be reset */
        DoReset = TRUE;
    }

    /* Update resource information now that the device is powered up and active */
    Status = PciSetResources(DeviceExtension, DoReset, TRUE);
    if (!NT_SUCCESS(Status))
    {
        /* That failed, so cancel the transition */
        PciCancelStateTransition((PVOID)DeviceExtension, PciStarted);
    }
    else
    {
        /* Fully commit, as the device is now started up and ready to go */
        PciCommitStateTransition((PVOID)DeviceExtension, PciStarted);
    }

    /* Return the result of the start request */
    return Status;
}
示例#24
0
/* [trobinso MOD 4/16/2010]
 * If running as a filter, do not act as power policy owner.
 */
NTSTATUS dispatch_power(libusb_device_t *dev, IRP *irp)
{
    IO_STACK_LOCATION *stack_location = IoGetCurrentIrpStackLocation(irp);
    POWER_STATE power_state;
    NTSTATUS status;

    status = remove_lock_acquire(dev);

    if (!NT_SUCCESS(status))
    {
        irp->IoStatus.Status = status;
        PoStartNextPowerIrp(irp);
        IoCompleteRequest(irp, IO_NO_INCREMENT);
        return status;
    }

    if (stack_location->MinorFunction == IRP_MN_SET_POWER)
    {
        power_state = stack_location->Parameters.Power.State;

        if (stack_location->Parameters.Power.Type == SystemPowerState)
        {
            USBMSG("IRP_MN_SET_POWER: S%d %s\n",
				power_state.SystemState - PowerSystemWorking, dev->device_id);
        }
        else
        {
            USBMSG("IRP_MN_SET_POWER: D%d %s\n",
				power_state.DeviceState - PowerDeviceD0, dev->device_id);

            if (power_state.DeviceState > dev->power_state.DeviceState)
            {
                /* device is powered down, report device state to the */
                /* Power Manager before sending the IRP down */
                /* (power up is handled by the completion routine) */
                PoSetPowerState(dev->self, DevicePowerState, power_state);
            }
        }

        /* TODO: should PoStartNextPowerIrp() be called here or from the */
        /* completion routine? */
        PoStartNextPowerIrp(irp);

        IoCopyCurrentIrpStackLocationToNext(irp);
        if (!dev->is_filter && !dev->disallow_power_control)
        {
            IoSetCompletionRoutine(irp,
                                   on_power_state_complete,
                                   dev,
                                   TRUE, /* on success */
                                   TRUE, /* on error   */
                                   TRUE);/* on cancel  */
        }
        else
        {
            IoSetCompletionRoutine(irp,
                                   on_filter_power_state_complete,
                                   dev,
                                   TRUE, /* on success */
                                   TRUE, /* on error   */
                                   TRUE);/* on cancel  */
        }

        return PoCallDriver(dev->next_stack_device, irp);
    }
    else
    {
		/* pass all other power IRPs down without setting a completion routine */
        PoStartNextPowerIrp(irp);
        IoSkipCurrentIrpStackLocation(irp);
        status = PoCallDriver(dev->next_stack_device, irp);
        remove_lock_release(dev);

        return status;
    }
}
示例#25
0
NTSTATUS
Bus_PDO_Power (
    PPDO_DEVICE_DATA    PdoData,
    PIRP                Irp
    )
/*++
    Handles power Irps sent to the PDOs.
    Typically a bus driver, that is not a power
    policy owner for the device, does nothing
    more than starting the next power IRP and
    completing this one.

Arguments:

    PdoData - Pointer to the PDO device extension.
    Irp     - Pointer to the irp.

Return Value:

    NT status is returned.

--*/

{
    NTSTATUS            status;
    PIO_STACK_LOCATION  stack;
    POWER_STATE         powerState;
    POWER_STATE_TYPE    powerType;

    stack = IoGetCurrentIrpStackLocation (Irp);
    powerType = stack->Parameters.Power.Type;
    powerState = stack->Parameters.Power.State;

    switch (stack->MinorFunction) {
    case IRP_MN_SET_POWER:

        Bus_KdPrint_Cont(PdoData, BUS_DBG_POWER_TRACE,
                     ("\tSetting %s power state to %s\n",
                     ((powerType == SystemPowerState) ?  "System" : "Device"),
                     ((powerType == SystemPowerState) ? \
                        DbgSystemPowerString(powerState.SystemState) : \
                        DbgDevicePowerString(powerState.DeviceState))));

        switch (powerType) {
            case DevicePowerState:
                PoSetPowerState (PdoData->Self, powerType, powerState);
                PdoData->DevicePowerState = powerState.DeviceState;
                status = STATUS_SUCCESS;
                break;

            case SystemPowerState:
                PdoData->SystemPowerState = powerState.SystemState;
                status = STATUS_SUCCESS;
                break;

            default:
                status = STATUS_NOT_SUPPORTED;
                break;
        }
        break;

    case IRP_MN_QUERY_POWER:
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_WAIT_WAKE:
        //
        // We cannot support wait-wake because we are root-enumerated
        // driver, and our parent, the PnP manager, doesn't support wait-wake.
        // If you are a bus enumerated device, and if  your parent bus supports
        // wait-wake,  you should send a wait/wake IRP (PoRequestPowerIrp)
        // in response to this request.
        // If you want to test the wait/wake logic implemented in the function
        // driver (toaster.sys), you could do the following simulation:
        // a) Mark this IRP pending.
        // b) Set a cancel routine.
        // c) Save this IRP in the device extension
        // d) Return STATUS_PENDING.
        // Later on if you suspend and resume your system, your BUS_FDO_POWER
        // will be called to power the bus. In response to IRP_MN_SET_POWER, if the
        // powerstate is PowerSystemWorking, complete this Wake IRP.
        // If the function driver, decides to cancel the wake IRP, your cancel routine
        // will be called. There you just complete the IRP with STATUS_CANCELLED.
        //
    case IRP_MN_POWER_SEQUENCE:
    default:
        status = STATUS_NOT_SUPPORTED;
        break;
    }

    if (status != STATUS_NOT_SUPPORTED) {

        Irp->IoStatus.Status = status;
    }

    PoStartNextPowerIrp(Irp);
    status = Irp->IoStatus.Status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);

    return status;
}
示例#26
0
文件: pcmcia.c 项目: GYGit/reactos
NTSTATUS
NTAPI
PcmciaPower(PDEVICE_OBJECT DeviceObject,
            PIRP Irp)
{
    PPCMCIA_COMMON_EXTENSION Common = DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
    NTSTATUS Status;

    switch (IrpSp->MinorFunction)
    {
        case IRP_MN_QUERY_POWER:
            /* I don't see any reason that we should care */
            DPRINT("PCMCIA: IRP_MN_QUERY_POWER\n");
            Status = STATUS_SUCCESS;
            break;

        case IRP_MN_POWER_SEQUENCE:
            DPRINT("PCMCIA: IRP_MN_POWER_SEQUENCE\n");
            RtlCopyMemory(IrpSp->Parameters.PowerSequence.PowerSequence,
                          &Common->PowerSequence,
                          sizeof(POWER_SEQUENCE));
            Status = STATUS_SUCCESS;
            break;

        case IRP_MN_WAIT_WAKE:
            /* Not really sure about this */
            DPRINT("PCMCIA: IRP_MN_WAIT_WAKE\n");
            Status = STATUS_NOT_SUPPORTED;
            break;

        case IRP_MN_SET_POWER:
            DPRINT("PCMCIA: IRP_MN_SET_POWER\n");
            if (IrpSp->Parameters.Power.Type == SystemPowerState)
            {
                Common->SystemPowerState = IrpSp->Parameters.Power.State.SystemState;

                Status = STATUS_SUCCESS;
            }
            else
            {
                Common->DevicePowerState = IrpSp->Parameters.Power.State.DeviceState;

                /* Update the POWER_SEQUENCE struct */
                if (Common->DevicePowerState <= PowerDeviceD1)
                    Common->PowerSequence.SequenceD1++;

                if (Common->DevicePowerState <= PowerDeviceD2)
                    Common->PowerSequence.SequenceD2++;

                if (Common->DevicePowerState <= PowerDeviceD3)
                    Common->PowerSequence.SequenceD3++;

                /* Start the underlying device if we are handling this for a PDO */
                if (!Common->IsFDO)
                    Status = PcmciaPdoSetPowerState((PPCMCIA_PDO_EXTENSION)Common);
                else
                    Status = STATUS_SUCCESS;
            }

            /* Report that we changed state to the Power Manager */
            PoSetPowerState(DeviceObject,
                            IrpSp->Parameters.Power.Type,
                            IrpSp->Parameters.Power.State);
            break;

        default:
            DPRINT1("PCMCIA: Invalid MN code in MJ_POWER handler %x\n", IrpSp->MinorFunction);
            ASSERT(FALSE);
            Status = STATUS_INVALID_DEVICE_REQUEST;
            break;
    }

    Irp->IoStatus.Status = Status;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return Status;
}
示例#27
0
文件: power.c 项目: GYGit/reactos
/*++////////////////////////////////////////////////////////////////////////////

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()
示例#28
0
文件: irp.cpp 项目: RareHare/reactos
NTSTATUS
NTAPI
PortClsPnp(
    IN  PDEVICE_OBJECT DeviceObject,
    IN  PIRP Irp)
{
    NTSTATUS Status;
    PPCLASS_DEVICE_EXTENSION DeviceExt;
    PIO_STACK_LOCATION IoStack;
    POWER_STATE PowerState;
    IResourceList* resource_list = NULL;
    //ULONG Index;
    //PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor, UnPartialDescriptor;

    DeviceExt = (PPCLASS_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
    IoStack = IoGetCurrentIrpStackLocation(Irp);


    DPRINT("PortClsPnp called %u\n", IoStack->MinorFunction);

    //PC_ASSERT(DeviceExt);

    switch (IoStack->MinorFunction)
    {
        case IRP_MN_START_DEVICE:
            DPRINT("IRP_MN_START_DEVICE\n");

            // Create the resource list
            Status = PcNewResourceList(
                        &resource_list,
                        NULL,
                        PagedPool,
                        IoStack->Parameters.StartDevice.AllocatedResourcesTranslated,
                        IoStack->Parameters.StartDevice.AllocatedResources);
            if (!NT_SUCCESS(Status))
            {
                DPRINT("PcNewResourceList failed [0x%8x]\n", Status);
                Irp->IoStatus.Status = Status;
                IoCompleteRequest(Irp, IO_NO_INCREMENT);
                return Status;
            }

            // forward irp to lower device object
            Status = PcForwardIrpSynchronous(DeviceObject, Irp);

            if (!NT_SUCCESS(Status))
            {
                // lower device object failed to start
                resource_list->Release();
                // complete the request
                IoCompleteRequest(Irp, IO_NO_INCREMENT);
                // return result
                return Status;
            }

            // sanity check
            //PC_ASSERT(DeviceExt->StartDevice);
            // Call the StartDevice routine
            DPRINT("Calling StartDevice at 0x%8p\n", DeviceExt->StartDevice);
            Status = DeviceExt->StartDevice(DeviceObject, Irp, resource_list);
            if (!NT_SUCCESS(Status))
            {
                DPRINT("StartDevice returned a failure code [0x%8x]\n", Status);
                Irp->IoStatus.Status = Status;
                IoCompleteRequest(Irp, IO_NO_INCREMENT);
                return Status;
            }

            // Assign the resource list to our extension
            DeviceExt->resources = resource_list;

            // store device power state
            DeviceExt->DevicePowerState = PowerDeviceD0;
            DeviceExt->SystemPowerState = PowerSystemWorking;

            // notify power manager of current state
            PowerState = *((POWER_STATE*)&DeviceExt->DevicePowerState);
            PoSetPowerState(DeviceObject, DevicePowerState, PowerState);

            Irp->IoStatus.Status = STATUS_SUCCESS;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            return Status;

        case IRP_MN_REMOVE_DEVICE:
            // Clean up
            DPRINT("IRP_MN_REMOVE_DEVICE\n");

            // sanity check
            PC_ASSERT(DeviceExt);

            // FIXME more cleanup */
            if (DeviceExt->resources)
            {
                // free resource list */
                DeviceExt->resources->Release();

                // set to null
                DeviceExt->resources = NULL;
            }

            // Forward request
            Status = PcForwardIrpSynchronous(DeviceObject, Irp);

            return PcCompleteIrp(DeviceObject, Irp, Status);

        case IRP_MN_QUERY_INTERFACE:
            DPRINT("IRP_MN_QUERY_INTERFACE\n");
            Status = PcForwardIrpSynchronous(DeviceObject, Irp);
            return PcCompleteIrp(DeviceObject, Irp, Status);
        case IRP_MN_QUERY_DEVICE_RELATIONS:
            DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
            Status = PcForwardIrpSynchronous(DeviceObject, Irp);
            return PcCompleteIrp(DeviceObject, Irp, Status);
        case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
            DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
            Status = PcForwardIrpSynchronous(DeviceObject, Irp);
            return PcCompleteIrp(DeviceObject, Irp, Status);
       case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
            DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
            Status = PcForwardIrpSynchronous(DeviceObject, Irp);
            return PcCompleteIrp(DeviceObject, Irp, Status);
       case IRP_MN_READ_CONFIG:
            DPRINT("IRP_MN_READ_CONFIG\n");
            Status = PcForwardIrpSynchronous(DeviceObject, Irp);
            return PcCompleteIrp(DeviceObject, Irp, Status);
    }

    DPRINT("unhandled function %u\n", IoStack->MinorFunction);
    Status = Irp->IoStatus.Status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return Status;
}
GENERICAPI NTSTATUS  InitializeGenericExtension(PGENERIC_EXTENSION pdx, PGENERIC_INIT_STRUCT isp)
    {                            // InitializeGenericExtension
    if(isp->Size < FIELD_OFFSET(GENERIC_INIT_STRUCT, Flags)
        || !isp->DeviceObject
        || !isp->Ldo
        || !isp->Pdo
        || !isp->StartDevice
        || !isp->StopDevice
        || !isp->RemoveDevice
        || isp->DeviceQueue && !isp->StartIo)

        return STATUS_INVALID_PARAMETER;

    RtlZeroMemory(pdx, sizeof(GENERIC_EXTENSION));

    pdx->DeviceObject = isp->DeviceObject;
    pdx->LowerDeviceObject = isp->Ldo;
    pdx->Pdo = isp->Pdo;
    pdx->StartDevice = isp->StartDevice;
    pdx->StopDevice = isp->StopDevice;
    pdx->RemoveDevice = isp->RemoveDevice;

    if(isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, OkayToRemove) + sizeof(PQUERYFUNCTION))
        {                        // set OkayToStop & OkayToRemove pointers
        pdx->OkayToStop = isp->OkayToStop;
        pdx->OkayToRemove = isp->OkayToRemove;
        }                        // set OkayToStop & OkayToRemove pointers

    if((pdx->RemoveLock = isp->RemoveLock))
        IoInitializeRemoveLock(pdx->RemoveLock, 0, 0, 0);

    pdx->state = STOPPED;
    
    pdx->devpower = PowerDeviceD0;
    pdx->syspower = PowerSystemWorking;
    POWER_STATE state;
    state.DeviceState = PowerDeviceD0;
    PoSetPowerState(pdx->DeviceObject, DevicePowerState, state);

    // In version 1.3, I added support for multiple IRP queues

    if(isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, NumberOfQueues) + sizeof(ULONG)
        && isp->NumberOfQueues)
        {                        // multiple queues
        ULONG i;
        if(isp->DeviceQueue || isp->StartIo)
            return STATUS_INVALID_PARAMETER;    // can't mix new and old ways of identifying queues
        if(isp->Size < FIELD_OFFSET(GENERIC_INIT_STRUCT, Queues) + isp->NumberOfQueues * 2 * sizeof(PVOID))
            return STATUS_INVALID_PARAMETER;    // init structure not big enough
        for (i = 0; i < isp->NumberOfQueues; ++i)
            if(!isp->Queues[i].DeviceQueue || !isp->Queues[i].StartIo)
                return STATUS_INVALID_PARAMETER;    // none of the entries can be NULL

        pdx->nqueues = isp->NumberOfQueues;
        pdx->queues = (PDEVQUEUE*) ExAllocatePoolWithTag(NonPagedPool, isp->NumberOfQueues * sizeof(PDEVQUEUE), SPOT_TAG);
        if(!pdx->queues)
            return STATUS_INSUFFICIENT_RESOURCES;

        for (i = 0; i < isp->NumberOfQueues; ++i)
            {                    // for each queue
            pdx->queues[i] = isp->Queues[i].DeviceQueue;
            InitializeQueue(pdx->queues[i], isp->Queues[i].StartIo);
            }                    // for each queue
        }                        // multiple queues

    else if(isp->DeviceQueue)
        {                        // single queue
        pdx->nqueues = 1;
        pdx->queues = (PDEVQUEUE*) ExAllocatePoolWithTag(NonPagedPool, sizeof(PDEVQUEUE), SPOT_TAG);
        if(!pdx->queues)
            return STATUS_INSUFFICIENT_RESOURCES;
        pdx->queues[0] = isp->DeviceQueue;
        InitializeQueue(pdx->queues[0], isp->StartIo);
        }                        // single queue

    // In version 1.9, I added support for FlushPendingIo.
    // In version 1.10, GetDevicePowerState

    if(isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, Queues))
        {                        // additional reserved fields
        pdx->FlushPendingIo = isp->FlushPendingIo;
        pdx->GetDevicePowerState = isp->GetDevicePowerState;
        }                        // additional reserved fields

    // Capture the mini-driver name for messages. This needs to be in ANSI because
    // unicode conversions at or above DISPATCH_LEVEL are not allowed. In retrospect, I
    // should have made the field in the INIT struct be in ANSI to start with...

    if(!isp->DebugName.Length)
        strcpy(pdx->DebugName, "GENERIC");
    else
        {                        // convert debug name
        ANSI_STRING asname = {0, sizeof(pdx->DebugName) - 1, pdx->DebugName};
        RtlUnicodeStringToAnsiString(&asname, &isp->DebugName, FALSE);
        pdx->DebugName[asname.Length] = 0;
        }                        // convert debug name

    if(isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, Flags) + sizeof(ULONG))
        pdx->Flags = isp->Flags & GENERIC_CLIENT_FLAGS;

    if(isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, RestoreDeviceContext) + sizeof(PCONTEXTFUNCTION))
        {                        // get power helper functions
        pdx->QueryPower = isp->QueryPower;
        pdx->SaveDeviceContext = isp->SaveDeviceContext;
        pdx->RestoreDeviceContext = isp->RestoreDeviceContext;
        }                        // get power helper functions

    if(isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, PerfBoundary) + sizeof(DEVICE_POWER_STATE))
        pdx->PerfBoundary = isp->PerfBoundary;
    else
        pdx->PerfBoundary = PowerDeviceUnspecified;

    if(pdx->PerfBoundary == PowerDeviceUnspecified)
        pdx->PerfBoundary = PowerDeviceMaximum; // inhibit POWER_SEQUENCE optimization

    // Initialize variables related to asynchrounous IOCTL management. In version 2.0, this
    // is now always done rather than depending on a flag in the init struct.

    InitializeListHead(&pdx->PendingIoctlList);
    pdx->IoctlAbortStatus = 0;
    KeInitializeSpinLock(&pdx->IoctlListLock);

    // Initialize to manage registered device interfaces

    KeInitializeEvent(&pdx->iflock, SynchronizationEvent, TRUE);
    InitializeListHead(&pdx->iflist);

    // Indicate we handle power IRPs at PASSIVE_LEVEL

    pdx->DeviceObject->Flags |= DO_POWER_PAGABLE;

    KdPrint(("GENERIC - Initializing for %s\n", pdx->DebugName));

    // If device honors paging-path notifications, initialize a synchronization
    // event in the signalled state to act as a simple mutex (SP-7)

    if(pdx->Flags & GENERIC_USAGE_PAGING)
        KeInitializeEvent(&pdx->evPagingPath, SynchronizationEvent, TRUE);

    // If requested to do so, register an AutoLaunch interface

    if(pdx->Flags & GENERIC_AUTOLAUNCH)
        GenericRegisterInterface(pdx, &GUID_AUTOLAUNCH_NOTIFY);

    // Register a power management interface

    GenericRegisterInterface(pdx, &GUID_GENERIC_POWER);

#ifdef _X86_
    win98 = IsWin98();
#endif

    return STATUS_SUCCESS;
    }                            // InitializeGenericExtension
示例#30
0
文件: pnp.cpp 项目: maodapeng/WDUtils
// fdo pnp
NTSTATUS DoFdoPnP(PDEVICE_OBJECT pDevice,PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;
	PFdoExt pFdoExt = static_cast<PFdoExt>(pDevice->DeviceExtension);

	// nead call next driver
	BOOLEAN bCallNext = TRUE;

	PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(pIrp);

	// inc io count
	IncIoCount(pFdoExt);

	// save minor code
	UCHAR uMinorCode = pIoStack->MinorFunction;

	switch(uMinorCode)
	{
	case IRP_MN_START_DEVICE:
		{
			// send down first
			status = SendIrpToLowerDeviceSyn(pFdoExt->m_pLowerDevice,pIrp);
			if(NT_SUCCESS(status))
			{
				// set device power state
				pFdoExt->m_devPowerState = PowerDeviceD0;
				POWER_STATE state;
				state.DeviceState = PowerDeviceD0;
				PoSetPowerState(pDevice,DevicePowerState,state);

				// set device interface state
				status = IoSetDeviceInterfaceState(&pFdoExt->m_symbolicName,TRUE);

				// set device pnp state
				SetNewPnpState(pFdoExt,IRP_MN_START_DEVICE);
			}

			// complete the irp
			pIrp->IoStatus.Status = status;
			IoCompleteRequest(pIrp,IO_NO_INCREMENT);

			// do not call down the device stack
			bCallNext = FALSE;
		}
		break;

		// set pnp state directly
	case IRP_MN_QUERY_REMOVE_DEVICE:
	case IRP_MN_QUERY_STOP_DEVICE:
		SetNewPnpState(pFdoExt,uMinorCode);
		break;

		// check for current pnp state,and restore it
	case IRP_MN_CANCEL_REMOVE_DEVICE:
		if(pFdoExt->m_ulCurrentPnpState == IRP_MN_QUERY_REMOVE_DEVICE)
			RestorePnpState(pFdoExt);

		break;

		// the same
	case IRP_MN_CANCEL_STOP_DEVICE:
		if(pFdoExt->m_ulCurrentPnpState == IRP_MN_QUERY_STOP_DEVICE)
			RestorePnpState(pFdoExt);

		break;

		// remove
	case IRP_MN_REMOVE_DEVICE:
		{
			// normal remove
			if(pFdoExt->m_ulCurrentPnpState != IRP_MN_SURPRISE_REMOVAL)
			{
				// just stop device interface
				if(pFdoExt->m_symbolicName.Buffer)
				{
					// set device interface false
					IoSetDeviceInterfaceState(&pFdoExt->m_symbolicName,FALSE);

					RtlFreeUnicodeString(&pFdoExt->m_symbolicName);
				}
			}

			// update pnp state
			SetNewPnpState(pFdoExt,IRP_MN_REMOVE_DEVICE);

			// dec outstandingio by 2
			DecIoCount(pFdoExt);

			DecIoCount(pFdoExt);

			// wait other irps finish
			KeWaitForSingleObject(&pFdoExt->m_evRemove,Executive,KernelMode,FALSE,NULL);

			// check pdo
			ExAcquireFastMutex(&pFdoExt->m_mutexEnumPdo);

			// if the pdo is present
			if(pFdoExt->m_pEnumPdo)
			{
				PPdoExt pPdoExt = static_cast<PPdoExt>(pFdoExt->m_pEnumPdo->DeviceExtension);

				// surprise removal.update those field
				if(pPdoExt->m_ulCurrentPnpState == IRP_MN_SURPRISE_REMOVAL)
				{
					pPdoExt->m_pParentFdo = NULL;
					pPdoExt->m_bReportMissing = TRUE;
					pFdoExt->m_pEnumPdo = NULL;
				}

				// delete the pdo device
				IoDeleteDevice(pFdoExt->m_pEnumPdo);
			}

			ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo);

			pIrp->IoStatus.Status = STATUS_SUCCESS;

			// call next driver,do not need to wait the finish
			IoSkipCurrentIrpStackLocation(pIrp);
			status = IoCallDriver(pFdoExt->m_pLowerDevice,pIrp);

			// first detach it from the device stack
			IoDetachDevice(pFdoExt->m_pLowerDevice);

			// then delete it,note that the device extension will become invalid,so dec need to check the minor code carefully
			IoDeleteDevice(pDevice);

			bCallNext = FALSE;
		}
		break;

		// stop
	case IRP_MN_STOP_DEVICE:
		DecIoCount(pFdoExt);

		KeWaitForSingleObject(&pFdoExt->m_evStop,Executive,KernelMode,FALSE,NULL);

		IncIoCount(pFdoExt);

		SetNewPnpState(pFdoExt,IRP_MN_STOP_DEVICE);
		break;
	
		// query bus relations
	case IRP_MN_QUERY_DEVICE_RELATIONS:
		{
			// only care bus relations
			if (BusRelations != pIoStack->Parameters.QueryDeviceRelations.Type) 
			{
				/*switch(pIoStack->Parameters.QueryDeviceRelations.Type)
				{
				case EjectionRelations:
					devDebugPrint("\tquery EjectionRelations\n");
					break;
				case PowerRelations:
					devDebugPrint("\tquery PowerRelations\n");
					break;
				case RemovalRelations:
					devDebugPrint("\tquery RemovalRelations\n");
					break;
				case TargetDeviceRelation:
					devDebugPrint("\tquery TargetDeviceRelation\n");
					break;
				case SingleBusRelations:
					devDebugPrint("\tquery SingleBusRelations\n");
					break;
				}*/
				
				break;
			}

			// old relations
			PDEVICE_RELATIONS pOldRel = static_cast<PDEVICE_RELATIONS>(ULongToPtr(pIrp->IoStatus.Information));
			ULONG ulNewCount = 0;

			ExAcquireFastMutex(&pFdoExt->m_mutexEnumPdo);

			// no pdo
			if(!pFdoExt->m_pEnumPdo)
			{
				devDebugPrint("\tBusRelations no device plugin \n");
                ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo);
				break;
			}
			
			PPdoExt pPdoExt = static_cast<PPdoExt>(pFdoExt->m_pEnumPdo->DeviceExtension);
			
			// if the pdo is not present
			if(!pPdoExt->m_bPresent)
			{
				// then we report it as missing
				pPdoExt->m_bReportMissing = TRUE;
			}
			else
			{
				// report the pdo
				ObReferenceObject(pFdoExt->m_pEnumPdo);
				ulNewCount ++;
			}

			// add the old count
			if(pOldRel)
				ulNewCount += pOldRel->Count;

			// allocate paged memory
			ULONG len = sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (ulNewCount - 1);
			PDEVICE_RELATIONS pRel = static_cast<PDEVICE_RELATIONS>(ExAllocatePoolWithTag(PagedPool,len,'suBT'));

			// do not set the status,we should continue with the orignal devices that the upper devices reported
			if(!pRel)
				break;

			// copy old value
			if(pOldRel)
			{
				RtlCopyMemory(pRel,pOldRel,len - sizeof(PDEVICE_OBJECT));
				if(pPdoExt->m_bPresent)
					pRel->Objects[pOldRel->Count] = pFdoExt->m_pEnumPdo;

				// free the previous buffer
				ExFreePool(pOldRel);
			}
			else
			{
				// the device is present
				if(pPdoExt->m_bPresent)
					pRel->Objects[0] = pFdoExt->m_pEnumPdo;
			}

			pRel->Count = ulNewCount;

			pIrp->IoStatus.Information = PtrToUlong(pRel);

			devDebugPrint("\tBusRelations pdo present %d,report %d\n",pPdoExt->m_bPresent,ulNewCount);

			ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo);
		}
		break;

		// surprise removal
	case IRP_MN_SURPRISE_REMOVAL:
		{
			// set pnp state
			SetNewPnpState(pFdoExt,IRP_MN_SURPRISE_REMOVAL);

			// stop the fdo
			if(pFdoExt->m_symbolicName.Buffer)
			{
				// set device interface
				IoSetDeviceInterfaceState(&pFdoExt->m_symbolicName,FALSE);

				RtlFreeUnicodeString(&pFdoExt->m_symbolicName);
			}

			// update pdo's field
			ExAcquireFastMutex(&pFdoExt->m_mutexEnumPdo);
			PPdoExt pPdoExt = static_cast<PPdoExt>(pFdoExt->m_pEnumPdo->DeviceExtension);
			pPdoExt->m_pParentFdo = NULL;
			pPdoExt->m_bReportMissing = TRUE;
			ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo);
		}
		break;

	default:
		status = pIrp->IoStatus.Status;
		break;
	}

	// nead call lower device
	if(bCallNext)
	{
		pIrp->IoStatus.Status = status;
		IoSkipCurrentIrpStackLocation(pIrp);
		status = IoCallDriver(pFdoExt->m_pLowerDevice,pIrp);
	}
	
	// specail check for remove irp
	if(uMinorCode != IRP_MN_REMOVE_DEVICE)
		DecIoCount(pFdoExt);

	return status;
}