ReactOS 0.4.17-dev-1190-g4c812f4
power.c File Reference
#include <pci.h>
#include <debug.h>
Include dependency graph for power.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

NTSTATUS NTAPI PciStallForPowerChange (IN PPCI_PDO_EXTENSION PdoExtension, IN DEVICE_POWER_STATE PowerState, IN ULONG_PTR CapOffset)
 
NTSTATUS NTAPI PciSetPowerManagedDevicePowerState (IN PPCI_PDO_EXTENSION DeviceExtension, IN DEVICE_POWER_STATE DeviceState, IN BOOLEAN IrpSet)
 
static VOID NTAPI PciFdoDevicePowerCompletion (_In_ PDEVICE_OBJECT DeviceObject, _In_ UCHAR MinorFunction, _In_ POWER_STATE PowerState, _In_opt_ PVOID Context, _In_ PIO_STATUS_BLOCK IoStatus)
 Finishes a system set power request once the bus has been through the device state that request asked for.
 
static NTSTATUS NTAPI PciFdoSystemPowerCompletion (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
 Asks for the device state that matches a system set power request once the drivers below the bus have handled it.
 
NTSTATUS NTAPI PciFdoWaitWake (IN PIRP Irp, IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension)
 
NTSTATUS NTAPI PciFdoSetPowerState (IN PIRP Irp, IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension)
 
NTSTATUS NTAPI PciFdoIrpQueryPower (IN PIRP Irp, IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension)
 

Variables

ULONG PciPowerDelayTable [PowerDeviceD3 *PowerDeviceD3]
 
static REQUEST_POWER_COMPLETE PciFdoDevicePowerCompletion
 
static IO_COMPLETION_ROUTINE PciFdoSystemPowerCompletion
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file power.c.

Function Documentation

◆ PciFdoDevicePowerCompletion()

static VOID NTAPI PciFdoDevicePowerCompletion ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ UCHAR  MinorFunction,
_In_ POWER_STATE  PowerState,
_In_opt_ PVOID  Context,
_In_ PIO_STATUS_BLOCK  IoStatus 
)
static

Finishes a system set power request once the bus has been through the device state that request asked for.

Parameters
[in]ContextThe system power IRP that is still held.

Definition at line 218 of file power.c.

224{
225 PIRP SystemIrp = Context;
226
229 ASSERT(SystemIrp != NULL);
230
231 /* The system transition goes ahead even if the bus could not follow it */
232 if (!NT_SUCCESS(IoStatus->Status))
233 {
234 DPRINT1("PCIX - Bus failed to enter device state %lu (0x%08lx)\n",
235 PowerState.DeviceState,
236 IoStatus->Status);
237 }
238
239 PoStartNextPowerIrp(SystemIrp);
241}
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
#define ASSERT(a)
Definition: mode.c:44
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
#define IoCompleteRequest
Definition: irp.c:1272
VOID NTAPI PoStartNextPowerIrp(IN PIRP Irp)
Definition: power.c:758
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ WDF_DEVICE_POWER_STATE PowerState
Definition: wdfdevice.h:3040
_In_ UCHAR _In_ UCHAR MinorFunction
Definition: wdfdevice.h:1705
#define IO_NO_INCREMENT
Definition: iotypes.h:598

◆ PciFdoIrpQueryPower()

NTSTATUS NTAPI PciFdoIrpQueryPower ( IN PIRP  Irp,
IN PIO_STACK_LOCATION  IoStackLocation,
IN PPCI_FDO_EXTENSION  DeviceExtension 
)

Definition at line 351 of file power.c.

354{
357 UNREFERENCED_PARAMETER(DeviceExtension);
358
359 /* Refusing states that would break an armed wake is not implemented yet */
360 DPRINT1("PCIX - Wake-aware power queries are not implemented, accepting the state\n");
361 return STATUS_SUCCESS;
362}
_In_ PIRP Irp
Definition: kse.h:79
#define STATUS_SUCCESS
Definition: shellext.h:65
_In_ PIO_STACK_LOCATION IoStackLocation
Definition: usbdlib.h:292

◆ PciFdoSetPowerState()

NTSTATUS NTAPI PciFdoSetPowerState ( IN PIRP  Irp,
IN PIO_STACK_LOCATION  IoStackLocation,
IN PPCI_FDO_EXTENSION  DeviceExtension 
)

Definition at line 318 of file power.c.

321{
323
324 /* Bridge hardware is handled by the PDO below, so only the state is kept */
326 {
327 DeviceExtension->PowerState.CurrentDeviceState = State.DeviceState;
328 return STATUS_SUCCESS;
329 }
330
331 DeviceExtension->PowerState.CurrentSystemState = State.SystemState;
332 if (DeviceExtension->DeviceState != PciStarted)
333 return STATUS_SUCCESS;
334
335 /* The bus owns its power policy and follows up with a device state request */
336 Irp->IoStatus.Status = STATUS_SUCCESS;
341 DeviceExtension,
342 TRUE,
343 TRUE,
344 TRUE);
345 PoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
346 return STATUS_PENDING;
347}
_Check_return_ _In_ ULONG _In_ DEVICE_POWER_STATE DevicePowerState
Definition: dispmprt.h:1274
#define TRUE
Definition: types.h:120
@ PciStarted
Definition: pci.h:169
static IO_COMPLETION_ROUTINE PciFdoSystemPowerCompletion
Definition: power.c:243
IoMarkIrpPending(Irp)
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
#define IoCopyCurrentIrpStackLocationToNext(Irp)
Definition: ntifs_ex.h:413
union _IO_STACK_LOCATION::@1814 Parameters
struct _IO_STACK_LOCATION::@5020::@5056 Power
#define STATUS_PENDING
Definition: telnetd.h:14

◆ PciFdoSystemPowerCompletion()

static NTSTATUS NTAPI PciFdoSystemPowerCompletion ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_In_reads_opt_(_Inexpressible_("varies")) PVOID  Context 
)
static

Asks for the device state that matches a system set power request once the drivers below the bus have handled it.

Parameters
[in]ContextThe FDO extension of the bus.
Returns
STATUS_MORE_PROCESSING_REQUIRED while the device state request is out.

Definition at line 259 of file power.c.

263{
264 PPCI_FDO_EXTENSION DeviceExtension = Context;
268
270 ASSERT(DeviceExtension != NULL);
271
273 if (IoStackLocation->Parameters.Power.State.SystemState == PowerSystemWorking)
274 {
275 Target.DeviceState = PowerDeviceD0;
276 }
277 else
278 {
279 Target.DeviceState = PowerDeviceD3;
280 }
281
282 if ((NT_SUCCESS(Irp->IoStatus.Status)) &&
283 (DeviceExtension->PowerState.CurrentDeviceState != Target.DeviceState))
284 {
287 Target,
289 Irp,
290 NULL);
291 if (NT_SUCCESS(Status))
293
294 DPRINT1("PCIX - Could not request device state %lu (0x%08lx)\n",
295 Target.DeviceState,
296 Status);
297 }
298
301}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
LONG NTSTATUS
Definition: precomp.h:26
static REQUEST_POWER_COMPLETE PciFdoDevicePowerCompletion
Definition: power.c:205
Status
Definition: gdiplustypes.h:24
NTSTATUS NTAPI PoRequestPowerIrp(_In_ PDEVICE_OBJECT DeviceObject, _In_ UCHAR MinorFunction, _In_ POWER_STATE PowerState, _In_opt_ PREQUEST_POWER_COMPLETE CompletionFunction, _In_opt_ __drv_aliasesMem PVOID Context, _Outptr_opt_ PIRP *pIrp)
Definition: power.c:659
@ PowerSystemWorking
Definition: ntpoapi.h:36
@ PowerDeviceD0
Definition: ntpoapi.h:49
@ PowerDeviceD3
Definition: ntpoapi.h:52
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
PDEVICE_OBJECT FunctionalDeviceObject
Definition: pci.h:250
PCI_POWER_STATE PowerState
Definition: pci.h:267
DEVICE_POWER_STATE CurrentDeviceState
Definition: pci.h:218
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
#define STATUS_CONTINUE_COMPLETION
#define IRP_MN_SET_POWER

◆ PciFdoWaitWake()

NTSTATUS NTAPI PciFdoWaitWake ( IN PIRP  Irp,
IN PIO_STACK_LOCATION  IoStackLocation,
IN PPCI_FDO_EXTENSION  DeviceExtension 
)

Definition at line 305 of file power.c.

308{
310
311 /* Arming the bus for its children's wake requests is not implemented yet */
312 DPRINT1("PCIX - Bus wake arming is not implemented, passing wait-wake down\n");
313 return PciPassIrpFromFdoToPdo(DeviceExtension, Irp);
314}
NTSTATUS NTAPI PciPassIrpFromFdoToPdo(IN PPCI_FDO_EXTENSION DeviceExtension, IN PIRP Irp)
Definition: dispatch.c:70

◆ PciSetPowerManagedDevicePowerState()

NTSTATUS NTAPI PciSetPowerManagedDevicePowerState ( IN PPCI_PDO_EXTENSION  DeviceExtension,
IN DEVICE_POWER_STATE  DeviceState,
IN BOOLEAN  IrpSet 
)

Definition at line 123 of file power.c.

126{
128 PCI_PM_CAPABILITY PmCaps;
129 ULONG CapsOffset;
130
131 /* Assume success */
133
134 /* Check if this device can support low power states */
135 if (!(PciCanDisableDecodes(DeviceExtension, NULL, 0, TRUE)) &&
137 {
138 /* Simply return success, ignoring this request */
139 DPRINT1("PCIX - Cannot disable decodes on this device, ignoring PM request...\n");
140 return Status;
141 }
142
143 /* Does the device support power management at all? */
144 if (!(DeviceExtension->HackFlags & PCI_HACK_NO_PM_CAPS))
145 {
146 /* Get the PM capabilities register */
147 CapsOffset = PciReadDeviceCapability(DeviceExtension,
148 DeviceExtension->CapabilitiesPtr,
150 &PmCaps.Header,
151 sizeof(PCI_PM_CAPABILITY));
152 ASSERT(CapsOffset);
154
155 /* Check if the device is being powered up */
157 {
158 /* Set full power state */
159 PmCaps.PMCSR.ControlStatus.PowerState = 0;
160
161 /* Check if the device supports Cold-D3 poweroff */
162 if (PmCaps.PMC.Capabilities.Support.PMED3Cold)
163 {
164 /* If there was a pending PME, clear it */
165 PmCaps.PMCSR.ControlStatus.PMEStatus = 1;
166 }
167 }
168 else
169 {
170 /* Otherwise, just set the new power state, converting from NT */
172 }
173
174 /* Write the new power state in the PMCSR */
175 PciWriteDeviceConfig(DeviceExtension,
176 &PmCaps.PMCSR,
177 CapsOffset + FIELD_OFFSET(PCI_PM_CAPABILITY, PMCSR),
178 sizeof(PCI_PMCSR));
179
180 /* Now wait for the change to "stick" based on the spec-mandated time */
181 Status = PciStallForPowerChange(DeviceExtension, DeviceState, CapsOffset);
182 if (!NT_SUCCESS(Status)) return Status;
183 }
184 else
185 {
186 /* Nothing to do! */
187 DPRINT1("PCIX - No PM on this device, ignoring request\n");
188 }
189
190 /* Check if new resources have to be assigned */
191 if (IrpSet)
192 {
193 /* Check if the new device state is lower (higher power) than now */
194 if (DeviceState < DeviceExtension->PowerState.CurrentDeviceState)
195 {
196 /* Leaving D3 may reset the function, so write its configuration again */
197 Status = PciSetResources(DeviceExtension, FALSE, FALSE);
198 }
199 }
200
201 /* Return the power state change status */
202 return Status;
203}
#define FALSE
Definition: types.h:117
NTSTATUS NTAPI PciSetResources(IN PPCI_PDO_EXTENSION PdoExtension, IN BOOLEAN DoReset, IN BOOLEAN SomethingSomethingDarkSide)
Definition: enum.c:2490
VOID NTAPI PciWriteDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length)
Definition: config.c:133
UCHAR NTAPI PciReadDeviceCapability(IN PPCI_PDO_EXTENSION DeviceExtension, IN UCHAR Offset, IN ULONG CapabilityId, OUT PPCI_CAPABILITIES_HEADER Buffer, IN ULONG Length)
Definition: utils.c:958
BOOLEAN NTAPI PciCanDisableDecodes(IN PPCI_PDO_EXTENSION DeviceExtension, IN PPCI_COMMON_HEADER Config, IN ULONGLONG HackFlags, IN BOOLEAN ForPowerDown)
Definition: utils.c:1027
NTSTATUS NTAPI PciStallForPowerChange(IN PPCI_PDO_EXTENSION PdoExtension, IN DEVICE_POWER_STATE PowerState, IN ULONG_PTR CapOffset)
Definition: power.c:45
@ PowerDeviceUnspecified
Definition: ntpoapi.h:48
#define PCI_HACK_NO_PM_CAPS
Definition: pci.h:40
USHORT PowerState
Definition: iotypes.h:3704
USHORT PMEStatus
Definition: iotypes.h:3709
struct _PCI_PMC::_PM_SUPPORT Support
PCI_CAPABILITIES_HEADER Header
Definition: iotypes.h:3719
PCI_PMCSR ControlStatus
Definition: iotypes.h:3725
union _PCI_PM_CAPABILITY::@5067 PMCSR
PCI_PMC Capabilities
Definition: iotypes.h:3721
union _PCI_PM_CAPABILITY::@5066 PMC
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFDEVICE _Out_ PWDF_DEVICE_STATE DeviceState
Definition: wdfdevice.h:2005
#define PCI_CAPABILITY_ID_POWER_MANAGEMENT
Definition: iotypes.h:3662

Referenced by PciPdoEnterDevicePowerState(), PciPdoIrpStartDevice(), PciPdoTurnOff(), and PciScanBus().

◆ PciStallForPowerChange()

NTSTATUS NTAPI PciStallForPowerChange ( IN PPCI_PDO_EXTENSION  PdoExtension,
IN DEVICE_POWER_STATE  PowerState,
IN ULONG_PTR  CapOffset 
)

Definition at line 45 of file power.c.

48{
49 ULONG PciState, TimeoutEntry, PmcsrOffset, TryCount;
50 PPCI_VERIFIER_DATA VerifierData;
52 PCI_PMCSR Pmcsr;
53 KIRQL Irql;
54
55 /* Make sure the power state is valid, and the device can support it */
56 ASSERT((PdoExtension->PowerState.CurrentDeviceState >= PowerDeviceD0) &&
57 (PdoExtension->PowerState.CurrentDeviceState <= PowerDeviceD3));
60
61 /* Save the current IRQL */
63
64 /* Pick the expected timeout for this transition */
66 (PdoExtension->PowerState.CurrentDeviceState -
68
69 /* PCI power states are one less than NT power states */
70 PciState = PowerState - 1;
71
72 /* The state status is stored in the PMCSR offset */
73 PmcsrOffset = CapOffset + FIELD_OFFSET(PCI_PM_CAPABILITY, PMCSR);
74
75 /* Try changing the power state up to 100 times */
76 TryCount = 100;
77 while (--TryCount)
78 {
79 /* Check if this state transition will take time */
80 if (TimeoutEntry > 0)
81 {
82 /* Check if this is happening at high IRQL */
83 if (Irql >= DISPATCH_LEVEL)
84 {
85 /* Can't wait at high IRQL, stall the processor */
86 KeStallExecutionProcessor(TimeoutEntry);
87 }
88 else
89 {
90 /* Do a wait for the timeout specified instead */
91 Interval.QuadPart = -10 * TimeoutEntry;
92 Interval.QuadPart -= KeQueryTimeIncrement() - 1;
94 }
95 }
96
97 /* Read the PMCSR and see if the state has changed */
98 PciReadDeviceConfig(PdoExtension, &Pmcsr, PmcsrOffset, sizeof(PCI_PMCSR));
99 if (Pmcsr.PowerState == PciState) return STATUS_SUCCESS;
100
101 /* Try again, forcing a timeout of 1ms */
102 TimeoutEntry = 1000;
103 }
104
105 /* Call verifier with this error */
106 VerifierData = PciVerifierRetrieveFailureData(2);
107 ASSERT(VerifierData);
108 VfFailDeviceNode(PdoExtension->PhysicalDeviceObject,
109 PCI_VERIFIER_DETECTED_VIOLATION,
110 2, // The PMCSR register was not updated within the spec-mandated time.
111 VerifierData->FailureClass,
112 &VerifierData->AssertionControl,
113 VerifierData->DebuggerMessageText,
114 "%DevObj%Ulong",
115 PdoExtension->PhysicalDeviceObject,
116 PciState);
117
119}
_Out_ PKIRQL Irql
Definition: csq.h:179
PPCI_VERIFIER_DATA NTAPI PciVerifierRetrieveFailureData(IN ULONG FailureCode)
Definition: pcivrify.c:60
VOID NTAPI PciReadDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length)
Definition: config.c:149
ULONG PciPowerDelayTable[PowerDeviceD3 *PowerDeviceD3]
Definition: power.c:18
@ PdoExtension
Definition: precomp.h:61
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
#define KeStallExecutionProcessor(MicroSeconds)
Definition: precomp.h:27
#define KernelMode
Definition: asm.h:38
DWORD Interval
Definition: netstat.c:28
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:151
VOID __cdecl VfFailDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject, IN ULONG BugCheckMajorCode, IN ULONG BugCheckMinorCode, IN VF_FAILURE_CLASS FailureClass, IN OUT PULONG AssertionControl, IN PSTR DebuggerMessageText, IN PSTR ParameterFormatString,...)
Definition: driver.c:34
#define STATUS_DEVICE_PROTOCOL_ERROR
Definition: ntstatus.h:717
VF_FAILURE_CLASS FailureClass
Definition: pci.h:481
PCHAR DebuggerMessageText
Definition: pci.h:483
ULONG AssertionControl
Definition: pci.h:482

Referenced by PciSetPowerManagedDevicePowerState().

Variable Documentation

◆ PciFdoDevicePowerCompletion

REQUEST_POWER_COMPLETE PciFdoDevicePowerCompletion
static

Definition at line 205 of file power.c.

Referenced by PciFdoSystemPowerCompletion().

◆ PciFdoSystemPowerCompletion

IO_COMPLETION_ROUTINE PciFdoSystemPowerCompletion
static

Definition at line 243 of file power.c.

Referenced by PciFdoSetPowerState().

◆ PciPowerDelayTable

ULONG PciPowerDelayTable[PowerDeviceD3 *PowerDeviceD3]
Initial value:
=
{
0,
0,
200,
10000,
0,
0,
200,
10000,
200,
200,
0,
10000,
10000,
10000,
10000,
0
}

Definition at line 18 of file power.c.

Referenced by PciStallForPowerChange().