ReactOS  0.4.13-dev-651-g5dbc677
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);
246  return STATUS_NOT_SUPPORTED;
247 }
#define TRUE
Definition: types.h:120
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
#define UNIMPLEMENTED
Definition: debug.h:114

◆ 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);
231  return STATUS_NOT_SUPPORTED;
232 }
#define TRUE
Definition: types.h:120
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
#define UNIMPLEMENTED
Definition: debug.h:114

◆ 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);
216  return STATUS_NOT_SUPPORTED;
217 }
#define TRUE
Definition: types.h:120
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
#define UNIMPLEMENTED
Definition: debug.h:114

◆ 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)) &&
134  (DeviceState != PowerDeviceD0))
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);
151  ASSERT(DeviceState != PowerDeviceUnspecified);
152 
153  /* Check if the device is being powered up */
154  if (DeviceState == PowerDeviceD0)
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 */
169  PmCaps.PMCSR.ControlStatus.PowerState = DeviceState - 1;
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 }
union _PCI_PM_CAPABILITY::@3637 PMCSR
#define TRUE
Definition: types.h:120
_In_ UCHAR _In_ POWER_STATE PowerState
Definition: pofuncs.h:42
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
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
struct _PCI_PMC::_PM_SUPPORT Support
USHORT PMEStatus
Definition: iotypes.h:3337
PCI_PMC Capabilities
Definition: iotypes.h:3349
LONG NTSTATUS
Definition: precomp.h:26
union _PCI_PM_CAPABILITY::@3636 PMC
VOID NTAPI PciWriteDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length)
Definition: config.c:91
#define PCI_CAPABILITY_ID_POWER_MANAGEMENT
Definition: iotypes.h:3290
smooth NULL
Definition: ftsmooth.c:416
BOOLEAN NTAPI PciCanDisableDecodes(IN PPCI_PDO_EXTENSION DeviceExtension, IN PPCI_COMMON_HEADER Config, IN ULONGLONG HackFlags, IN BOOLEAN ForPowerDown)
Definition: utils.c:955
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
Status
Definition: gdiplustypes.h:24
PCI_PMCSR ControlStatus
Definition: iotypes.h:3353
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
USHORT PowerState
Definition: iotypes.h:3332
#define PCI_HACK_NO_PM_CAPS
Definition: pci.h:39
#define UNIMPLEMENTED_DBGBREAK(...)
Definition: debug.h:57
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS NTAPI PciStallForPowerChange(IN PPCI_PDO_EXTENSION PdoExtension, IN DEVICE_POWER_STATE PowerState, IN ULONG_PTR CapOffset)
Definition: power.c:45
return STATUS_SUCCESS
Definition: btrfs.c:2777
PCI_CAPABILITIES_HEADER Header
Definition: iotypes.h:3347

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));
59  ASSERT(!(PdoExtension->HackFlags & PCI_HACK_NO_PM_CAPS));
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 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
PPCI_VERIFIER_DATA NTAPI PciVerifierRetrieveFailureData(IN ULONG FailureCode)
Definition: pcivrify.c:60
_In_ UCHAR _In_ POWER_STATE PowerState
Definition: pofuncs.h:42
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
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
_Out_ PKIRQL Irql
Definition: csq.h:179
#define STATUS_DEVICE_PROTOCOL_ERROR
Definition: ntstatus.h:609
UCHAR KIRQL
Definition: env_spec_w32.h:591
NTSTATUS NTAPI KeDelayExecutionThread(IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Interval OPTIONAL)
Definition: wait.c:283
DWORD Interval
Definition: netstat.c:33
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
VF_FAILURE_CLASS FailureClass
Definition: pci.h:414
PCHAR DebuggerMessageText
Definition: pci.h:416
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
ULONG PciPowerDelayTable[PowerDeviceD3 *PowerDeviceD3]
Definition: power.c:18
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
USHORT PowerState
Definition: iotypes.h:3332
#define PCI_HACK_NO_PM_CAPS
Definition: pci.h:39
VOID NTAPI PciReadDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length)
Definition: config.c:107
unsigned int ULONG
Definition: retypes.h:1
ULONG AssertionControl
Definition: pci.h:415
return STATUS_SUCCESS
Definition: btrfs.c:2777
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:99

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