|
|
/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
gpeintf.c
Abstract:
This module implements the "PME" interfaces supported by the PCI driver.
Author:
Stephane Plante (splante) Feb-1-1999
Revision History:
--*/
#include "pcip.h"
NTSTATUS PciPmeInterfaceConstructor( PVOID DeviceExtension, PVOID PciInterface, PVOID InterfaceSpecificData, USHORT Version, USHORT Size, PINTERFACE InterfaceReturn );
VOID PciPmeInterfaceDereference( IN PVOID Context );
NTSTATUS PciPmeInterfaceInitializer( IN PPCI_ARBITER_INSTANCE Instance );
VOID PciPmeInterfaceReference( IN PVOID Context );
VOID PciPmeUpdateEnable( IN PDEVICE_OBJECT Pdo, IN BOOLEAN PmeEnable );
//
// Define the Pci PME interface "interface" structure
//
PCI_INTERFACE PciPmeInterface = { &GUID_PCI_PME_INTERFACE, // Interface Type
sizeof(PCI_PME_INTERFACE), // Mininum Size
PCI_PME_INTRF_STANDARD_VER, // Minimum Version
PCI_PME_INTRF_STANDARD_VER, // Maximum Version
PCIIF_FDO | PCIIF_ROOT, // Flags
0, // ReferenceCount
PciInterface_PmeHandler, // Signature
PciPmeInterfaceConstructor, // Constructor
PciPmeInterfaceInitializer // Instance Initializer
};
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, PciPmeInterfaceConstructor)
#pragma alloc_text(PAGE, PciPmeInterfaceDereference)
#pragma alloc_text(PAGE, PciPmeInterfaceInitializer)
#pragma alloc_text(PAGE, PciPmeInterfaceReference)
#endif
VOID PciPmeAdjustPmeEnable( IN PPCI_PDO_EXTENSION PdoExtension, IN BOOLEAN Enable, IN BOOLEAN ClearStatusOnly ) /*++
Routine Description:
This is the only routine in the the PCI driver that is allowed to set the PME Enable pin for a device.
Arguments:
PdoExtension - The device that wants to have the PME enable set Enable - Turn on the PME pin or not ClearStatusOnly - Only clear the status --- ignore the Enable bit
Return Value:
VOID
--*/ { PCI_PM_CAPABILITY pmCap; UCHAR pmCapPtr = 0;
//
// Are there any pm capabilities?
//
if (!(PdoExtension->HackFlags & PCI_HACK_NO_PM_CAPS) ) {
pmCapPtr = PciReadDeviceCapability( PdoExtension, PdoExtension->CapabilitiesPtr, PCI_CAPABILITY_ID_POWER_MANAGEMENT, &pmCap, sizeof(pmCap) );
} if (pmCapPtr == 0) {
return;
}
//
// Set or clear the PMEEnable bit depending on the value of Enable
//
if (!ClearStatusOnly) {
pmCap.PMCSR.ControlStatus.PMEEnable = (Enable != 0);
}
//
// Write back what we read to clear the PME Status.
//
PciWriteDeviceConfig( PdoExtension, &(pmCap.PMCSR.ControlStatus), pmCapPtr + FIELD_OFFSET(PCI_PM_CAPABILITY, PMCSR.ControlStatus), sizeof(pmCap.PMCSR.ControlStatus) ); }
VOID PciPmeClearPmeStatus( IN PDEVICE_OBJECT Pdo ) /*++
Routine Description:
This routine explicitly clears the PME status bit from a device
Arguments:
Pdo - The device whose pin we are to clear
Return Value:
VOID
--*/ { PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION) Pdo->DeviceExtension;
ASSERT_PCI_PDO_EXTENSION( pdoExtension );
//
// Call the Adjust function to do the actual work. Note that passing
// in the 3rd argument as TRUE means that the 2nd argument is ignored
//
PciPmeAdjustPmeEnable( pdoExtension, FALSE, TRUE ); }
VOID PciPmeGetInformation( IN PDEVICE_OBJECT Pdo, OUT PBOOLEAN PmeCapable, OUT PBOOLEAN PmeStatus, OUT PBOOLEAN PmeEnable ) /*++
Routine Description:
Supplies the information regarding a PDO's PME capabilities
Arguments:
Pdo - The device object whose capabilities we care about PmeCapable - Can the device generate a PME? PmeStatus - Is the PME status for the device on? PmeEnable - Is the PME enable for the device on?
Return Value:
None
--*/ { BOOLEAN pmeCapable = FALSE; BOOLEAN pmeEnable = FALSE; BOOLEAN pmeStatus = FALSE; PCI_PM_CAPABILITY pmCap = {0}; PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION) Pdo->DeviceExtension; UCHAR pmCapPtr = 0;
ASSERT_PCI_PDO_EXTENSION( pdoExtension );
//
// Get the current power management capabilities from the device
//
if (!(pdoExtension->HackFlags & PCI_HACK_NO_PM_CAPS) ) {
pmCapPtr = PciReadDeviceCapability( pdoExtension, pdoExtension->CapabilitiesPtr, PCI_CAPABILITY_ID_POWER_MANAGEMENT, &pmCap, sizeof(pmCap) );
}
if (pmCapPtr == 0) {
//
// No power capabilities
//
goto PciPmeGetInformationExit;
}
//
// At this point, we are found to be PME capable
//
pmeCapable = TRUE;
//
// Are enabled for PME?
//
if (pmCap.PMCSR.ControlStatus.PMEEnable == 1) {
pmeEnable = TRUE;
}
//
// Is the PME Status pin set?
//
if (pmCap.PMCSR.ControlStatus.PMEStatus == 1) {
pmeStatus = TRUE;
}
PciPmeGetInformationExit:
if (PmeCapable != NULL) {
*PmeCapable = pmeCapable;
} if (PmeStatus != NULL) {
*PmeStatus = pmeStatus;
} if (PmeEnable != NULL) {
*PmeEnable = pmeEnable;
} return;
}
NTSTATUS PciPmeInterfaceConstructor( PVOID DeviceExtension, PVOID PciInterface, PVOID InterfaceSpecificData, USHORT Version, USHORT Size, PINTERFACE InterfaceReturn ) /*++
Routine Description:
Initialize the PCI_PME_INTERFACE fields.
Arguments:
PciInterface Pointer to the PciInterface record for this interface type. InterfaceSpecificData
InterfaceReturn
Return Value:
Status
--*/
{ PPCI_PME_INTERFACE standard = (PPCI_PME_INTERFACE) InterfaceReturn; switch(Version) { case PCI_PME_INTRF_STANDARD_VER: standard->GetPmeInformation = PciPmeGetInformation; standard->ClearPmeStatus = PciPmeClearPmeStatus; standard->UpdateEnable = PciPmeUpdateEnable; break; default: return STATUS_NOINTERFACE; }
standard->Size = sizeof( PCI_PME_INTERFACE ); standard->Version = Version; standard->Context = DeviceExtension; standard->InterfaceReference = PciPmeInterfaceReference; standard->InterfaceDereference = PciPmeInterfaceDereference; return STATUS_SUCCESS; }
VOID PciPmeInterfaceDereference( IN PVOID Context ) { return; }
NTSTATUS PciPmeInterfaceInitializer( IN PPCI_ARBITER_INSTANCE Instance ) /*++
Routine Description:
For bus interface, does nothing, shouldn't actually be called.
Arguments:
Instance Pointer to the PDO extension.
Return Value:
Returns the status of this operation.
--*/
{ PCI_ASSERTMSG("PCI PciPmeInterfaceInitializer, unexpected call.", 0); return STATUS_UNSUCCESSFUL; }
VOID PciPmeInterfaceReference( IN PVOID Context ) { return; }
VOID PciPmeUpdateEnable( IN PDEVICE_OBJECT Pdo, IN BOOLEAN PmeEnable ) /*++
Routine Description:
This routine sets or clears the PME Enable bit on the specified device object
Arguments:
Pdo - The device object whose PME enable we care about PmeEnable - Wether or not we should enable PME on the device
Return Value:
None
--*/ { PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION) Pdo->DeviceExtension;
ASSERT_PCI_PDO_EXTENSION( pdoExtension );
//
// Mark the device as not having its PME managed by PCI any more...
//
pdoExtension->NoTouchPmeEnable = 1;
//
// Call the interface that does the real work. Note that we always need
// to supply the 3rd argument as FALSE --- we don't to just clear the
// PME Status bit
//
PciPmeAdjustPmeEnable( pdoExtension, PmeEnable, FALSE ); }
|