ReactOS 0.4.15-dev-7942-gd23573b
power.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS PCI Bus Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/bus/pci/power.c
5 * PURPOSE: Bus/Device Power Management
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include <pci.h>
12
13#define NDEBUG
14#include <debug.h>
15
16/* GLOBALS ********************************************************************/
17
19{
20 0, // D0 -> D0
21 0, // D1 -> D0
22 200, // D2 -> D0
23 10000, // D3 -> D0
24
25 0, // D0 -> D1
26 0, // D1 -> D1
27 200, // D2 -> D1
28 10000, // D3 -> D1
29
30 200, // D0 -> D2
31 200, // D1 -> D2
32 0, // D2 -> D2
33 10000, // D3 -> D2
34
35 10000, // D0 -> D3
36 10000, // D1 -> D3
37 10000, // D2 -> D3
38 0 // D3 -> D3
39};
40
41/* FUNCTIONS ******************************************************************/
42
47 IN ULONG_PTR CapOffset)
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 */
65 TimeoutEntry = PciPowerDelayTable[PowerState * PdoExtension->PowerState.CurrentDeviceState];
66
67 /* PCI power states are one less than NT power states */
68 PciState = PowerState - 1;
69
70 /* The state status is stored in the PMCSR offset */
71 PmcsrOffset = CapOffset + FIELD_OFFSET(PCI_PM_CAPABILITY, PMCSR);
72
73 /* Try changing the power state up to 100 times */
74 TryCount = 100;
75 while (--TryCount)
76 {
77 /* Check if this state transition will take time */
78 if (TimeoutEntry > 0)
79 {
80 /* Check if this is happening at high IRQL */
81 if (Irql >= DISPATCH_LEVEL)
82 {
83 /* Can't wait at high IRQL, stall the processor */
84 KeStallExecutionProcessor(TimeoutEntry);
85 }
86 else
87 {
88 /* Do a wait for the timeout specified instead */
89 Interval.QuadPart = -10 * TimeoutEntry;
90 Interval.QuadPart -= KeQueryTimeIncrement() - 1;
92 }
93 }
94
95 /* Read the PMCSR and see if the state has changed */
96 PciReadDeviceConfig(PdoExtension, &Pmcsr, PmcsrOffset, sizeof(PCI_PMCSR));
97 if (Pmcsr.PowerState == PciState) return STATUS_SUCCESS;
98
99 /* Try again, forcing a timeout of 1ms */
100 TimeoutEntry = 1000;
101 }
102
103 /* Call verifier with this error */
104 VerifierData = PciVerifierRetrieveFailureData(2);
105 ASSERT(VerifierData);
106 VfFailDeviceNode(PdoExtension->PhysicalDeviceObject,
107 PCI_VERIFIER_DETECTED_VIOLATION,
108 2, // The PMCSR register was not updated within the spec-mandated time.
109 VerifierData->FailureClass,
110 &VerifierData->AssertionControl,
111 VerifierData->DebuggerMessageText,
112 "%DevObj%Ulong",
113 PdoExtension->PhysicalDeviceObject,
114 PciState);
115
117}
118
120NTAPI
123 IN BOOLEAN IrpSet)
124{
126 PCI_PM_CAPABILITY PmCaps;
127 ULONG CapsOffset;
128
129 /* Assume success */
131
132 /* Check if this device can support low power states */
133 if (!(PciCanDisableDecodes(DeviceExtension, NULL, 0, TRUE)) &&
135 {
136 /* Simply return success, ignoring this request */
137 DPRINT1("Cannot disable decodes on this device, ignoring PM request...\n");
138 return Status;
139 }
140
141 /* Does the device support power management at all? */
142 if (!(DeviceExtension->HackFlags & PCI_HACK_NO_PM_CAPS))
143 {
144 /* Get the PM capabilities register */
145 CapsOffset = PciReadDeviceCapability(DeviceExtension,
146 DeviceExtension->CapabilitiesPtr,
148 &PmCaps.Header,
149 sizeof(PCI_PM_CAPABILITY));
150 ASSERT(CapsOffset);
152
153 /* Check if the device is being powered up */
155 {
156 /* Set full power state */
157 PmCaps.PMCSR.ControlStatus.PowerState = 0;
158
159 /* Check if the device supports Cold-D3 poweroff */
160 if (PmCaps.PMC.Capabilities.Support.PMED3Cold)
161 {
162 /* If there was a pending PME, clear it */
163 PmCaps.PMCSR.ControlStatus.PMEStatus = 1;
164 }
165 }
166 else
167 {
168 /* Otherwise, just set the new power state, converting from NT */
170 }
171
172 /* Write the new power state in the PMCSR */
173 PciWriteDeviceConfig(DeviceExtension,
174 &PmCaps.PMCSR,
175 CapsOffset + FIELD_OFFSET(PCI_PM_CAPABILITY, PMCSR),
176 sizeof(PCI_PMCSR));
177
178 /* Now wait for the change to "stick" based on the spec-mandated time */
179 Status = PciStallForPowerChange(DeviceExtension, DeviceState, CapsOffset);
180 if (!NT_SUCCESS(Status)) return Status;
181 }
182 else
183 {
184 /* Nothing to do! */
185 DPRINT1("No PM on this device, ignoring request\n");
186 }
187
188 /* Check if new resources have to be assigned */
189 if (IrpSet)
190 {
191 /* Check if the new device state is lower (higher power) than now */
192 if (DeviceState < DeviceExtension->PowerState.CurrentDeviceState)
193 {
194 /* We would normally re-assign resources after powerup */
197 }
198 }
199
200 /* Return the power state change status */
201 return Status;
202}
203
205NTAPI
207 IN PIO_STACK_LOCATION IoStackLocation,
208 IN PPCI_FDO_EXTENSION DeviceExtension)
209{
211 UNREFERENCED_PARAMETER(IoStackLocation);
212 UNREFERENCED_PARAMETER(DeviceExtension);
213
215 while (TRUE);
217}
218
220NTAPI
222 IN PIO_STACK_LOCATION IoStackLocation,
223 IN PPCI_FDO_EXTENSION DeviceExtension)
224{
226 UNREFERENCED_PARAMETER(IoStackLocation);
227 UNREFERENCED_PARAMETER(DeviceExtension);
228
230 while (TRUE);
232}
233
235NTAPI
237 IN PIO_STACK_LOCATION IoStackLocation,
238 IN PPCI_FDO_EXTENSION DeviceExtension)
239{
241 UNREFERENCED_PARAMETER(IoStackLocation);
242 UNREFERENCED_PARAMETER(DeviceExtension);
243
245 while (TRUE);
247}
248
249/* EOF */
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:81
#define UNIMPLEMENTED
Definition: debug.h:115
_In_ PIRP Irp
Definition: csq.h:116
_Out_ PKIRQL Irql
Definition: csq.h:179
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID NTAPI PciWriteDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length)
Definition: config.c:91
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:886
PPCI_VERIFIER_DATA NTAPI PciVerifierRetrieveFailureData(IN ULONG FailureCode)
Definition: pcivrify.c:60
BOOLEAN NTAPI PciCanDisableDecodes(IN PPCI_PDO_EXTENSION DeviceExtension, IN PPCI_COMMON_HEADER Config, IN ULONGLONG HackFlags, IN BOOLEAN ForPowerDown)
Definition: utils.c:955
VOID NTAPI PciReadDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length)
Definition: config.c:107
NTSTATUS NTAPI PciFdoWaitWake(IN PIRP Irp, IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension)
Definition: power.c:206
NTSTATUS NTAPI PciFdoSetPowerState(IN PIRP Irp, IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension)
Definition: power.c:221
ULONG PciPowerDelayTable[PowerDeviceD3 *PowerDeviceD3]
Definition: power.c:18
NTSTATUS NTAPI PciStallForPowerChange(IN PPCI_PDO_EXTENSION PdoExtension, IN DEVICE_POWER_STATE PowerState, IN ULONG_PTR CapOffset)
Definition: power.c:45
NTSTATUS NTAPI PciSetPowerManagedDevicePowerState(IN PPCI_PDO_EXTENSION DeviceExtension, IN DEVICE_POWER_STATE DeviceState, IN BOOLEAN IrpSet)
Definition: power.c:121
NTSTATUS NTAPI PciFdoIrpQueryPower(IN PIRP Irp, IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension)
Definition: power.c:236
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
@ PdoExtension
Definition: precomp.h:49
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
Status
Definition: gdiplustypes.h:25
#define ASSERT(a)
Definition: mode.c:44
#define KernelMode
Definition: asm.h:34
DWORD Interval
Definition: netstat.c:30
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
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
@ PowerDeviceUnspecified
Definition: ntpoapi.h:48
@ PowerDeviceD0
Definition: ntpoapi.h:49
@ PowerDeviceD3
Definition: ntpoapi.h:52
enum _DEVICE_POWER_STATE DEVICE_POWER_STATE
#define STATUS_DEVICE_PROTOCOL_ERROR
Definition: ntstatus.h:623
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define PCI_HACK_NO_PM_CAPS
Definition: pci.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
USHORT PowerState
Definition: iotypes.h:3689
USHORT PMEStatus
Definition: iotypes.h:3694
struct _PCI_PMC::_PM_SUPPORT Support
PCI_CAPABILITIES_HEADER Header
Definition: iotypes.h:3704
PCI_PMCSR ControlStatus
Definition: iotypes.h:3710
union _PCI_PM_CAPABILITY::@4025 PMCSR
union _PCI_PM_CAPABILITY::@4024 PMC
PCI_PMC Capabilities
Definition: iotypes.h:3706
VF_FAILURE_CLASS FailureClass
Definition: pci.h:416
PCHAR DebuggerMessageText
Definition: pci.h:418
ULONG AssertionControl
Definition: pci.h:417
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFDEVICE _Out_ PWDF_DEVICE_STATE DeviceState
Definition: wdfdevice.h:1999
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ WDF_DEVICE_POWER_STATE PowerState
Definition: wdfdevice.h:3034
#define PCI_CAPABILITY_ID_POWER_MANAGEMENT
Definition: iotypes.h:3647