Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

410 lines
8.2 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. gpeintf.c
  5. Abstract:
  6. This module implements the "PME" interfaces supported
  7. by the PCI driver.
  8. Author:
  9. Stephane Plante (splante) Feb-1-1999
  10. Revision History:
  11. --*/
  12. #include "pcip.h"
  13. NTSTATUS
  14. PciPmeInterfaceConstructor(
  15. PVOID DeviceExtension,
  16. PVOID PciInterface,
  17. PVOID InterfaceSpecificData,
  18. USHORT Version,
  19. USHORT Size,
  20. PINTERFACE InterfaceReturn
  21. );
  22. VOID
  23. PciPmeInterfaceDereference(
  24. IN PVOID Context
  25. );
  26. NTSTATUS
  27. PciPmeInterfaceInitializer(
  28. IN PPCI_ARBITER_INSTANCE Instance
  29. );
  30. VOID
  31. PciPmeInterfaceReference(
  32. IN PVOID Context
  33. );
  34. VOID
  35. PciPmeUpdateEnable(
  36. IN PDEVICE_OBJECT Pdo,
  37. IN BOOLEAN PmeEnable
  38. );
  39. //
  40. // Define the Pci PME interface "interface" structure
  41. //
  42. PCI_INTERFACE PciPmeInterface = {
  43. &GUID_PCI_PME_INTERFACE, // Interface Type
  44. sizeof(PCI_PME_INTERFACE), // Mininum Size
  45. PCI_PME_INTRF_STANDARD_VER, // Minimum Version
  46. PCI_PME_INTRF_STANDARD_VER, // Maximum Version
  47. PCIIF_FDO | PCIIF_ROOT, // Flags
  48. 0, // ReferenceCount
  49. PciInterface_PmeHandler, // Signature
  50. PciPmeInterfaceConstructor, // Constructor
  51. PciPmeInterfaceInitializer // Instance Initializer
  52. };
  53. #ifdef ALLOC_PRAGMA
  54. #pragma alloc_text(PAGE, PciPmeInterfaceConstructor)
  55. #pragma alloc_text(PAGE, PciPmeInterfaceDereference)
  56. #pragma alloc_text(PAGE, PciPmeInterfaceInitializer)
  57. #pragma alloc_text(PAGE, PciPmeInterfaceReference)
  58. #endif
  59. VOID
  60. PciPmeAdjustPmeEnable(
  61. IN PPCI_PDO_EXTENSION PdoExtension,
  62. IN BOOLEAN Enable,
  63. IN BOOLEAN ClearStatusOnly
  64. )
  65. /*++
  66. Routine Description:
  67. This is the only routine in the the PCI driver that is allowed to set
  68. the PME Enable pin for a device.
  69. Arguments:
  70. PdoExtension - The device that wants to have the PME enable set
  71. Enable - Turn on the PME pin or not
  72. ClearStatusOnly - Only clear the status --- ignore the Enable bit
  73. Return Value:
  74. VOID
  75. --*/
  76. {
  77. PCI_PM_CAPABILITY pmCap;
  78. UCHAR pmCapPtr = 0;
  79. //
  80. // Are there any pm capabilities?
  81. //
  82. if (!(PdoExtension->HackFlags & PCI_HACK_NO_PM_CAPS) ) {
  83. pmCapPtr = PciReadDeviceCapability(
  84. PdoExtension,
  85. PdoExtension->CapabilitiesPtr,
  86. PCI_CAPABILITY_ID_POWER_MANAGEMENT,
  87. &pmCap,
  88. sizeof(pmCap)
  89. );
  90. }
  91. if (pmCapPtr == 0) {
  92. return;
  93. }
  94. //
  95. // Set or clear the PMEEnable bit depending on the value of Enable
  96. //
  97. if (!ClearStatusOnly) {
  98. pmCap.PMCSR.ControlStatus.PMEEnable = (Enable != 0);
  99. }
  100. //
  101. // Write back what we read to clear the PME Status.
  102. //
  103. PciWriteDeviceConfig(
  104. PdoExtension,
  105. &(pmCap.PMCSR.ControlStatus),
  106. pmCapPtr + FIELD_OFFSET(PCI_PM_CAPABILITY, PMCSR.ControlStatus),
  107. sizeof(pmCap.PMCSR.ControlStatus)
  108. );
  109. }
  110. VOID
  111. PciPmeClearPmeStatus(
  112. IN PDEVICE_OBJECT Pdo
  113. )
  114. /*++
  115. Routine Description:
  116. This routine explicitly clears the PME status bit from a device
  117. Arguments:
  118. Pdo - The device whose pin we are to clear
  119. Return Value:
  120. VOID
  121. --*/
  122. {
  123. PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION) Pdo->DeviceExtension;
  124. ASSERT_PCI_PDO_EXTENSION( pdoExtension );
  125. //
  126. // Call the Adjust function to do the actual work. Note that passing
  127. // in the 3rd argument as TRUE means that the 2nd argument is ignored
  128. //
  129. PciPmeAdjustPmeEnable( pdoExtension, FALSE, TRUE );
  130. }
  131. VOID
  132. PciPmeGetInformation(
  133. IN PDEVICE_OBJECT Pdo,
  134. OUT PBOOLEAN PmeCapable,
  135. OUT PBOOLEAN PmeStatus,
  136. OUT PBOOLEAN PmeEnable
  137. )
  138. /*++
  139. Routine Description:
  140. Supplies the information regarding a PDO's PME capabilities
  141. Arguments:
  142. Pdo - The device object whose capabilities we care about
  143. PmeCapable - Can the device generate a PME?
  144. PmeStatus - Is the PME status for the device on?
  145. PmeEnable - Is the PME enable for the device on?
  146. Return Value:
  147. None
  148. --*/
  149. {
  150. BOOLEAN pmeCapable = FALSE;
  151. BOOLEAN pmeEnable = FALSE;
  152. BOOLEAN pmeStatus = FALSE;
  153. NTSTATUS status;
  154. PCI_PM_CAPABILITY pmCap;
  155. PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION) Pdo->DeviceExtension;
  156. UCHAR pmCapPtr = 0;
  157. ASSERT_PCI_PDO_EXTENSION( pdoExtension );
  158. //
  159. // Get the current power management capabilities from the device
  160. //
  161. if (!(pdoExtension->HackFlags & PCI_HACK_NO_PM_CAPS) ) {
  162. pmCapPtr = PciReadDeviceCapability(
  163. pdoExtension,
  164. pdoExtension->CapabilitiesPtr,
  165. PCI_CAPABILITY_ID_POWER_MANAGEMENT,
  166. &pmCap,
  167. sizeof(pmCap)
  168. );
  169. }
  170. if (pmCapPtr == 0) {
  171. //
  172. // No Pdo capabilities
  173. //
  174. goto PciPmeGetInformationExit;
  175. }
  176. //
  177. // At this point, we are found to be PME capable
  178. //
  179. pmeCapable = TRUE;
  180. //
  181. // Are enabled for PME?
  182. //
  183. if (pmCap.PMCSR.ControlStatus.PMEEnable == 1) {
  184. pmeEnable = TRUE;
  185. }
  186. //
  187. // Is the PME Status pin set?
  188. //
  189. if (pmCap.PMCSR.ControlStatus.PMEStatus == 1) {
  190. pmeStatus = TRUE;
  191. }
  192. PciPmeGetInformationExit:
  193. if (PmeCapable != NULL) {
  194. *PmeCapable = pmeCapable;
  195. }
  196. if (PmeStatus != NULL) {
  197. *PmeStatus = pmeStatus;
  198. }
  199. if (PmeEnable != NULL) {
  200. *PmeEnable = pmeEnable;
  201. }
  202. return;
  203. }
  204. NTSTATUS
  205. PciPmeInterfaceConstructor(
  206. PVOID DeviceExtension,
  207. PVOID PciInterface,
  208. PVOID InterfaceSpecificData,
  209. USHORT Version,
  210. USHORT Size,
  211. PINTERFACE InterfaceReturn
  212. )
  213. /*++
  214. Routine Description:
  215. Initialize the PCI_PME_INTERFACE fields.
  216. Arguments:
  217. PciInterface Pointer to the PciInterface record for this
  218. interface type.
  219. InterfaceSpecificData
  220. InterfaceReturn
  221. Return Value:
  222. Status
  223. --*/
  224. {
  225. PPCI_PME_INTERFACE standard = (PPCI_PME_INTERFACE) InterfaceReturn;
  226. switch(Version) {
  227. case PCI_PME_INTRF_STANDARD_VER:
  228. standard->GetPmeInformation = PciPmeGetInformation;
  229. standard->ClearPmeStatus = PciPmeClearPmeStatus;
  230. standard->UpdateEnable = PciPmeUpdateEnable;
  231. break;
  232. default:
  233. return STATUS_NOINTERFACE;
  234. }
  235. standard->Size = sizeof( PCI_PME_INTERFACE );
  236. standard->Version = Version;
  237. standard->Context = DeviceExtension;
  238. standard->InterfaceReference = PciPmeInterfaceReference;
  239. standard->InterfaceDereference = PciPmeInterfaceDereference;
  240. return STATUS_SUCCESS;
  241. }
  242. VOID
  243. PciPmeInterfaceDereference(
  244. IN PVOID Context
  245. )
  246. {
  247. return;
  248. }
  249. NTSTATUS
  250. PciPmeInterfaceInitializer(
  251. IN PPCI_ARBITER_INSTANCE Instance
  252. )
  253. /*++
  254. Routine Description:
  255. For bus interface, does nothing, shouldn't actually be called.
  256. Arguments:
  257. Instance Pointer to the PDO extension.
  258. Return Value:
  259. Returns the status of this operation.
  260. --*/
  261. {
  262. ASSERTMSG("PCI PciPmeInterfaceInitializer, unexpected call.", 0);
  263. return STATUS_UNSUCCESSFUL;
  264. }
  265. VOID
  266. PciPmeInterfaceReference(
  267. IN PVOID Context
  268. )
  269. {
  270. return;
  271. }
  272. VOID
  273. PciPmeUpdateEnable(
  274. IN PDEVICE_OBJECT Pdo,
  275. IN BOOLEAN PmeEnable
  276. )
  277. /*++
  278. Routine Description:
  279. This routine sets or clears the PME Enable bit on the specified
  280. device object
  281. Arguments:
  282. Pdo - The device object whose PME enable we care about
  283. PmeEnable - Wether or not we should enable PME on the device
  284. Return Value:
  285. None
  286. --*/
  287. {
  288. PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION) Pdo->DeviceExtension;
  289. ASSERT_PCI_PDO_EXTENSION( pdoExtension );
  290. //
  291. // Mark the device as not having its PME managed by PCI any more...
  292. //
  293. pdoExtension->NoTouchPmeEnable = 1;
  294. //
  295. // Call the interface that does the real work. Note that we always need
  296. // to supply the 3rd argument as FALSE --- we don't to just clear the
  297. // PME Status bit
  298. //
  299. PciPmeAdjustPmeEnable( pdoExtension, PmeEnable, FALSE );
  300. }