ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

power.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS PCI Bus Driver
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            drivers/bus/pci/power.c
00005  * PURPOSE:         Bus/Device Power Management
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  */
00008 
00009 /* INCLUDES *******************************************************************/
00010 
00011 #include <pci.h>
00012 #define NDEBUG
00013 #include <debug.h>
00014 
00015 /* GLOBALS ********************************************************************/
00016 
00017 ULONG PciPowerDelayTable[PowerDeviceD3 * PowerDeviceD3] =
00018 {
00019     0,      // D0 -> D0
00020     0,      // D1 -> D0
00021     200,    // D2 -> D0
00022     10000,  // D3 -> D0
00023 
00024     0,      // D0 -> D1
00025     0,      // D1 -> D1
00026     200,    // D2 -> D1
00027     10000,  // D3 -> D1
00028 
00029     200,    // D0 -> D2
00030     200,    // D1 -> D2
00031     0,      // D2 -> D2
00032     10000,  // D3 -> D2
00033 
00034     10000,  // D0 -> D3
00035     10000,  // D1 -> D3
00036     10000,  // D2 -> D3
00037     0       // D3 -> D3
00038 };
00039 
00040 /* FUNCTIONS ******************************************************************/
00041 
00042 NTSTATUS
00043 NTAPI
00044 PciStallForPowerChange(IN PPCI_PDO_EXTENSION PdoExtension,
00045                        IN DEVICE_POWER_STATE PowerState,
00046                        IN ULONG_PTR CapOffset)
00047 {
00048     ULONG PciState, TimeoutEntry, PmcsrOffset, TryCount;
00049     PPCI_VERIFIER_DATA VerifierData;
00050     LARGE_INTEGER Interval;
00051     PCI_PMCSR Pmcsr;
00052     KIRQL Irql;
00053 
00054     /* Make sure the power state is valid, and the device can support it */
00055     ASSERT((PdoExtension->PowerState.CurrentDeviceState >= PowerDeviceD0) &&
00056            (PdoExtension->PowerState.CurrentDeviceState <= PowerDeviceD3));
00057     ASSERT((PowerState >= PowerDeviceD0) && (PowerState <= PowerDeviceD3));
00058     ASSERT(!(PdoExtension->HackFlags & PCI_HACK_NO_PM_CAPS));
00059 
00060     /* Save the current IRQL */
00061     Irql = KeGetCurrentIrql();
00062 
00063     /* Pick the expected timeout for this transition */
00064     TimeoutEntry = PciPowerDelayTable[PowerState * PdoExtension->PowerState.CurrentDeviceState];
00065 
00066     /* PCI power states are one less than NT power states */
00067     PciState = PowerState - 1;
00068 
00069     /* The state status is stored in the PMCSR offset */
00070     PmcsrOffset = CapOffset + FIELD_OFFSET(PCI_PM_CAPABILITY, PMCSR);
00071 
00072     /* Try changing the power state up to 100 times */
00073     TryCount = 100;
00074     while (--TryCount)
00075     {
00076         /* Check if this state transition will take time */
00077         if (TimeoutEntry > 0)
00078         {
00079             /* Check if this is happening at high IRQL */
00080             if (Irql >= DISPATCH_LEVEL)
00081             {
00082                 /* Can't wait at high IRQL, stall the processor */
00083                 KeStallExecutionProcessor(TimeoutEntry);
00084             }
00085             else
00086             {
00087                 /* Do a wait for the timeout specified instead */
00088                 Interval.QuadPart = -10 * TimeoutEntry;
00089                 Interval.QuadPart -= KeQueryTimeIncrement() - 1;
00090                 KeDelayExecutionThread(0, 0, &Interval);
00091             }
00092         }
00093 
00094         /* Read the PMCSR and see if the state has changed */
00095         PciReadDeviceConfig(PdoExtension, &Pmcsr, PmcsrOffset, sizeof(PCI_PMCSR));
00096         if (Pmcsr.PowerState == PciState) return STATUS_SUCCESS;
00097 
00098         /* Try again, forcing a timeout of 1ms */
00099         TimeoutEntry = 1000;
00100     }
00101 
00102     /* Call verifier with this error */
00103     VerifierData = PciVerifierRetrieveFailureData(2);
00104     ASSERT(VerifierData);
00105     VfFailDeviceNode(PdoExtension->PhysicalDeviceObject,
00106                      PCI_VERIFIER_DETECTED_VIOLATION,
00107                      2, // The PMCSR register was not updated within the spec-mandated time.
00108                      VerifierData->FailureClass,
00109                      &VerifierData->AssertionControl,
00110                      VerifierData->DebuggerMessageText,
00111                      "%DevObj%Ulong",
00112                      PdoExtension->PhysicalDeviceObject,
00113                      PciState);
00114 
00115     return STATUS_DEVICE_PROTOCOL_ERROR;
00116 }
00117 
00118 NTSTATUS
00119 NTAPI
00120 PciSetPowerManagedDevicePowerState(IN PPCI_PDO_EXTENSION DeviceExtension,
00121                                    IN DEVICE_POWER_STATE DeviceState,
00122                                    IN BOOLEAN IrpSet)
00123 {
00124     NTSTATUS Status;
00125     PCI_PM_CAPABILITY PmCaps;
00126     ULONG CapsOffset;
00127 
00128     /* Assume success */
00129     Status = STATUS_SUCCESS;
00130 
00131     /* Check if this device can support low power states */
00132     if (!(PciCanDisableDecodes(DeviceExtension, NULL, 0, TRUE)) &&
00133          (DeviceState != PowerDeviceD0))
00134     {
00135         /* Simply return success, ignoring this request */
00136         DPRINT1("Cannot disable decodes on this device, ignoring PM request...\n");
00137         return Status;
00138     }
00139 
00140     /* Does the device support power management at all? */
00141     if (!(DeviceExtension->HackFlags & PCI_HACK_NO_PM_CAPS))
00142     {
00143         /* Get the PM capabailities register */
00144         CapsOffset = PciReadDeviceCapability(DeviceExtension,
00145                                              DeviceExtension->CapabilitiesPtr,
00146                                              PCI_CAPABILITY_ID_POWER_MANAGEMENT,
00147                                              &PmCaps.Header,
00148                                              sizeof(PCI_PM_CAPABILITY));
00149         ASSERT(CapsOffset);
00150         ASSERT(DeviceState != PowerDeviceUnspecified);
00151 
00152         /* Check if the device is being powered up */
00153         if (DeviceState == PowerDeviceD0)
00154         {
00155             /* Set full power state */
00156             PmCaps.PMCSR.ControlStatus.PowerState = 0;
00157 
00158             /* Check if the device supports Cold-D3 poweroff */
00159             if (PmCaps.PMC.Capabilities.Support.PMED3Cold)
00160             {
00161                 /* If there was a pending PME, clear it */
00162                 PmCaps.PMCSR.ControlStatus.PMEStatus = 1;
00163             }
00164         }
00165         else
00166         {
00167             /* Otherwise, just set the new power state, converting from NT */
00168             PmCaps.PMCSR.ControlStatus.PowerState = DeviceState - 1;
00169         }
00170 
00171         /* Write the new power state in the PMCSR */
00172         PciWriteDeviceConfig(DeviceExtension,
00173                              &PmCaps.PMCSR,
00174                              CapsOffset + FIELD_OFFSET(PCI_PM_CAPABILITY, PMCSR),
00175                              sizeof(PCI_PMCSR));
00176 
00177         /* Now wait for the change to "stick" based on the spec-mandated time */
00178         Status = PciStallForPowerChange(DeviceExtension, DeviceState, CapsOffset);
00179         if (!NT_SUCCESS(Status)) return Status;
00180     }
00181     else
00182     {
00183         /* Nothing to do! */
00184         DPRINT1("No PM on this device, ignoring request\n");
00185     }
00186 
00187     /* Check if new resources have to be assigned */
00188     if (IrpSet)
00189     {
00190         /* Check if the new device state is lower (higher power) than now */
00191         if (DeviceState < DeviceExtension->PowerState.CurrentDeviceState)
00192         {
00193             /* We would normally re-assign resources after powerup */
00194             UNIMPLEMENTED;
00195             while (TRUE);
00196         }
00197     }
00198 
00199     /* Return the power state change status */
00200     return Status;
00201 }
00202 
00203 NTSTATUS
00204 NTAPI
00205 PciFdoWaitWake(IN PIRP Irp,
00206                IN PIO_STACK_LOCATION IoStackLocation,
00207                IN PPCI_FDO_EXTENSION DeviceExtension)
00208 {
00209     UNIMPLEMENTED;
00210     while (TRUE);
00211     return STATUS_NOT_SUPPORTED;
00212 }
00213 
00214 NTSTATUS
00215 NTAPI
00216 PciFdoSetPowerState(IN PIRP Irp,
00217                     IN PIO_STACK_LOCATION IoStackLocation,
00218                     IN PPCI_FDO_EXTENSION DeviceExtension)
00219 {
00220     UNIMPLEMENTED;
00221     while (TRUE);
00222     return STATUS_NOT_SUPPORTED;
00223 }
00224 
00225 NTSTATUS
00226 NTAPI
00227 PciFdoIrpQueryPower(IN PIRP Irp,
00228                     IN PIO_STACK_LOCATION IoStackLocation,
00229                     IN PPCI_FDO_EXTENSION DeviceExtension)
00230 {
00231     UNIMPLEMENTED;
00232     while (TRUE);
00233     return STATUS_NOT_SUPPORTED;
00234 }
00235 
00236 /* EOF */

Generated on Sat May 26 2012 04:23:00 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.