ReactOS 0.4.15-dev-7924-g5949c20
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)
 
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]
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file power.c.

Function Documentation

◆ PciFdoIrpQueryPower()

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

Definition at line 236 of file power.c.

239{
241 UNREFERENCED_PARAMETER(IoStackLocation);
242 UNREFERENCED_PARAMETER(DeviceExtension);
243
245 while (TRUE);
247}
#define UNIMPLEMENTED
Definition: debug.h:115
_In_ PIRP Irp
Definition: csq.h:116
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423

◆ PciFdoSetPowerState()

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

Definition at line 221 of file power.c.

224{
226 UNREFERENCED_PARAMETER(IoStackLocation);
227 UNREFERENCED_PARAMETER(DeviceExtension);
228
230 while (TRUE);
232}

◆ PciFdoWaitWake()

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

Definition at line 206 of file power.c.

209{
211 UNREFERENCED_PARAMETER(IoStackLocation);
212 UNREFERENCED_PARAMETER(DeviceExtension);
213
215 while (TRUE);
217}

◆ PciSetPowerManagedDevicePowerState()

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

Definition at line 121 of file power.c.

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}
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
#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
BOOLEAN NTAPI PciCanDisableDecodes(IN PPCI_PDO_EXTENSION DeviceExtension, IN PPCI_COMMON_HEADER Config, IN ULONGLONG HackFlags, IN BOOLEAN ForPowerDown)
Definition: utils.c:955
NTSTATUS NTAPI PciStallForPowerChange(IN PPCI_PDO_EXTENSION PdoExtension, IN DEVICE_POWER_STATE PowerState, IN ULONG_PTR CapOffset)
Definition: power.c:45
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
Status
Definition: gdiplustypes.h:25
#define ASSERT(a)
Definition: mode.c:44
@ PowerDeviceUnspecified
Definition: ntpoapi.h:48
@ PowerDeviceD0
Definition: ntpoapi.h:49
#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
#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: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

Referenced by PciPdoIrpStartDevice(), 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 */
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}
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:81
_Out_ PKIRQL Irql
Definition: csq.h:179
#define FALSE
Definition: types.h:117
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:107
ULONG PciPowerDelayTable[PowerDeviceD3 *PowerDeviceD3]
Definition: power.c:18
@ 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
#define KernelMode
Definition: asm.h:34
DWORD Interval
Definition: netstat.c:30
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
@ PowerDeviceD3
Definition: ntpoapi.h:52
#define STATUS_DEVICE_PROTOCOL_ERROR
Definition: ntstatus.h:623
VF_FAILURE_CLASS FailureClass
Definition: pci.h:416
PCHAR DebuggerMessageText
Definition: pci.h:418
ULONG AssertionControl
Definition: pci.h:417

Referenced by PciSetPowerManagedDevicePowerState().

Variable Documentation

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