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; }
NTSTATUS Bus_FDO_Power ( PFDO_DEVICE_DATA Data, PIRP Irp ) /*++ Handles power Irps sent to the FDO. This driver is power policy owner for the bus itself (not the devices on the bus).Power handling for the bus FDO should be implemented similar to the function driver (toaster.sys) power code. We will just print some debug outputs and forward this Irp to the next level. Arguments: Data - Pointer to the FDO device extension. Irp - Pointer to the irp. Return Value: NT status is returned. --*/ { NTSTATUS status; POWER_STATE powerState; POWER_STATE_TYPE powerType; PIO_STACK_LOCATION stack; stack = IoGetCurrentIrpStackLocation (Irp); powerType = stack->Parameters.Power.Type; powerState = stack->Parameters.Power.State; Bus_IncIoCount (Data); // // If the device is not stated yet, just pass it down. // if (Data->DevicePnPState == NotStarted) { PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); status = PoCallDriver(Data->NextLowerDriver, Irp); Bus_DecIoCount (Data); return status; } if (stack->MinorFunction == IRP_MN_SET_POWER) { Bus_KdPrint_Cont(Data, BUS_DBG_POWER_TRACE, ("\tRequest to set %s state to %s\n", ((powerType == SystemPowerState) ? "System" : "Device"), ((powerType == SystemPowerState) ? \ DbgSystemPowerString(powerState.SystemState) :\ DbgDevicePowerString(powerState.DeviceState)))); } PoStartNextPowerIrp (Irp); IoSkipCurrentIrpStackLocation(Irp); status = PoCallDriver (Data->NextLowerDriver, Irp); Bus_DecIoCount (Data); return status; }
NTSTATUS Bus_FDO_Power ( PFDO_DEVICE_DATA Data, PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; POWER_STATE powerState; POWER_STATE_TYPE powerType; PIO_STACK_LOCATION stack; ULONG AcpiState; ACPI_STATUS AcpiStatus; SYSTEM_POWER_STATE oldPowerState; stack = IoGetCurrentIrpStackLocation (Irp); powerType = stack->Parameters.Power.Type; powerState = stack->Parameters.Power.State; if (stack->MinorFunction == IRP_MN_SET_POWER) { DPRINT("\tRequest to set %s state to %s\n", ((powerType == SystemPowerState) ? "System" : "Device"), ((powerType == SystemPowerState) ? \ DbgSystemPowerString(powerState.SystemState) :\ DbgDevicePowerString(powerState.DeviceState))); } if (powerType == SystemPowerState) { switch (powerState.SystemState) { case PowerSystemSleeping1: AcpiState = ACPI_STATE_S1; break; case PowerSystemSleeping2: AcpiState = ACPI_STATE_S2; break; case PowerSystemSleeping3: AcpiState = ACPI_STATE_S3; break; case PowerSystemHibernate: AcpiState = ACPI_STATE_S4; break; case PowerSystemShutdown: AcpiState = ACPI_STATE_S5; break; default: AcpiState = ACPI_STATE_UNKNOWN; ASSERT(FALSE); break; } oldPowerState = Data->Common.SystemPowerState; Data->Common.SystemPowerState = powerState.SystemState; AcpiStatus = acpi_suspend(AcpiState); if (!ACPI_SUCCESS(AcpiStatus)) { DPRINT1("Failed to enter sleep state %d (Status 0x%X)\n", AcpiState, AcpiStatus); Data->Common.SystemPowerState = oldPowerState; status = STATUS_UNSUCCESSFUL; } } PoStartNextPowerIrp (Irp); IoSkipCurrentIrpStackLocation(Irp); status = PoCallDriver (Data->NextLowerDriver, Irp); return status; }
NTSTATUS PPJoy_Ctl_Power (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus; POWER_STATE PowerState; POWER_STATE_TYPE PowerType; PIO_STACK_LOCATION Stack; PDEVICE_EXTENSION DeviceExtension; PAGED_CODE (); /* If it is not for one of our control devices - pass on to HID.sys */ if (GET_NEXT_DEVICE_OBJECT(DeviceObject)) { PPJOY_DBGPRINT (FILE_POWER|PPJOY_HIDHACK, ("Not a control device - passing request on to HID.sys (PPJoy_Ctl_Power)") ); return HIDMajorFunctions[IoGetCurrentIrpStackLocation(Irp)->MajorFunction](DeviceObject,Irp); } PPJOY_DBGPRINT (FILE_POWER | PPJOY_FENTRY, ("Enter PPJoy_Ctl_Power(DeviceObject=0x%p,Irp=0x%p)",DeviceObject,Irp) ); DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject); ntStatus= PPJoy_EnterRequest (DeviceExtension); if (NT_SUCCESS(ntStatus)) { Stack= IoGetCurrentIrpStackLocation (Irp); PowerType= Stack->Parameters.Power.Type; PowerState= Stack->Parameters.Power.State; PPJOY_DBGPRINT (FILE_POWER|PPJOY_BABBLE, ("Received Power IRP %s",PowerMinorFunctionString(Stack->MinorFunction)) ); switch (Stack->MinorFunction) { case IRP_MN_SET_POWER: PPJOY_DBGPRINT (FILE_POWER|PPJOY_BABBLE, ("Request to set %s state to %s", \ ((PowerType==SystemPowerState)?"System":"Device"), \ ((PowerType==SystemPowerState)?DbgSystemPowerString(PowerState.SystemState): \ DbgDevicePowerString(PowerState.DeviceState))) ); if ((PowerType==DevicePowerState)||(PowerType==SystemPowerState)) ntStatus= STATUS_SUCCESS; break; case IRP_MN_QUERY_POWER: ntStatus= STATUS_SUCCESS; break; case IRP_MN_WAIT_WAKE: case IRP_MN_POWER_SEQUENCE: default: ntStatus= STATUS_NOT_SUPPORTED; break; } } /* Must be before IoCompleteRequest(), else bugcheck! */ PoStartNextPowerIrp (Irp); /* We are the lowest level driver for this device, complete IRP */ if (ntStatus!=STATUS_NOT_SUPPORTED) Irp->IoStatus.Status= ntStatus; IoCompleteRequest (Irp,IO_NO_INCREMENT); PPJoy_LeaveRequest (DeviceExtension); PPJOY_EXITPROC (FILE_POWER|PPJOY_FEXIT, "PPJOY_Ctl_Power",ntStatus); return ntStatus; }
NTSTATUS Bus_PDO_Power ( PPDO_DEVICE_DATA PdoData, PIRP Irp ) { NTSTATUS status; PIO_STACK_LOCATION stack; POWER_STATE powerState; POWER_STATE_TYPE powerType; ULONG error; stack = IoGetCurrentIrpStackLocation (Irp); powerType = stack->Parameters.Power.Type; powerState = stack->Parameters.Power.State; switch (stack->MinorFunction) { case IRP_MN_SET_POWER: DPRINT("\tSetting %s power state to %s\n", ((powerType == SystemPowerState) ? "System" : "Device"), ((powerType == SystemPowerState) ? \ DbgSystemPowerString(powerState.SystemState) : \ DbgDevicePowerString(powerState.DeviceState))); switch (powerType) { case DevicePowerState: if (!PdoData->AcpiHandle || !acpi_bus_power_manageable(PdoData->AcpiHandle)) { PoSetPowerState(PdoData->Common.Self, DevicePowerState, powerState); PdoData->Common.DevicePowerState = powerState.DeviceState; status = STATUS_SUCCESS; break; } switch (powerState.DeviceState) { case PowerDeviceD0: error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D0); break; case PowerDeviceD1: error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D1); break; case PowerDeviceD2: error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D2); break; case PowerDeviceD3: error = acpi_bus_set_power(PdoData->AcpiHandle, ACPI_STATE_D3); break; default: error = 0; break; } if (ACPI_SUCCESS(error)) { PoSetPowerState(PdoData->Common.Self, DevicePowerState, powerState); PdoData->Common.DevicePowerState = powerState.DeviceState; status = STATUS_SUCCESS; } else status = STATUS_UNSUCCESSFUL; break; case SystemPowerState: PdoData->Common.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. // 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; }