Leaked source code of windows server 2003
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.

414 lines
8.6 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. PCI_PM_CAPABILITY pmCap = {0};
  154. PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION) Pdo->DeviceExtension;
  155. UCHAR pmCapPtr = 0;
  156. ASSERT_PCI_PDO_EXTENSION( pdoExtension );
  157. //
  158. // Get the current power management capabilities from the device
  159. //
  160. if (!(pdoExtension->HackFlags & PCI_HACK_NO_PM_CAPS) ) {
  161. pmCapPtr = PciReadDeviceCapability(
  162. pdoExtension,
  163. pdoExtension->CapabilitiesPtr,
  164. PCI_CAPABILITY_ID_POWER_MANAGEMENT,
  165. &pmCap,
  166. sizeof(pmCap)
  167. );
  168. }
  169. if (pmCapPtr == 0) {
  170. //
  171. // No power capabilities
  172. //
  173. goto PciPmeGetInformationExit;
  174. }
  175. //
  176. // At this point, we are found to be PME capable
  177. //
  178. pmeCapable = TRUE;
  179. //
  180. // Are enabled for PME?
  181. //
  182. if (pmCap.PMCSR.ControlStatus.PMEEnable == 1) {
  183. pmeEnable = TRUE;
  184. }
  185. //
  186. // Is the PME Status pin set?
  187. //
  188. if (pmCap.PMCSR.ControlStatus.PMEStatus == 1) {
  189. pmeStatus = TRUE;
  190. }
  191. PciPmeGetInformationExit:
  192. if (PmeCapable != NULL) {
  193. *PmeCapable = pmeCapable;
  194. }
  195. if (PmeStatus != NULL) {
  196. *PmeStatus = pmeStatus;
  197. }
  198. if (PmeEnable != NULL) {
  199. *PmeEnable = pmeEnable;
  200. }
  201. return;
  202. }
  203. NTSTATUS
  204. PciPmeInterfaceConstructor(
  205. PVOID DeviceExtension,
  206. PVOID PciInterface,
  207. PVOID InterfaceSpecificData,
  208. USHORT Version,
  209. USHORT Size,
  210. PINTERFACE InterfaceReturn
  211. )
  212. /*++
  213. Routine Description:
  214. Initialize the PCI_PME_INTERFACE fields.
  215. Arguments:
  216. PciInterface Pointer to the PciInterface record for this
  217. interface type.
  218. InterfaceSpecificData
  219. InterfaceReturn
  220. Return Value:
  221. Status
  222. --*/
  223. {
  224. PPCI_PME_INTERFACE standard = (PPCI_PME_INTERFACE) InterfaceReturn;
  225. switch(Version) {
  226. case PCI_PME_INTRF_STANDARD_VER:
  227. standard->GetPmeInformation = PciPmeGetInformation;
  228. standard->ClearPmeStatus = PciPmeClearPmeStatus;
  229. standard->UpdateEnable = PciPmeUpdateEnable;
  230. break;
  231. default:
  232. return STATUS_NOINTERFACE;
  233. }
  234. standard->Size = sizeof( PCI_PME_INTERFACE );
  235. standard->Version = Version;
  236. standard->Context = DeviceExtension;
  237. standard->InterfaceReference = PciPmeInterfaceReference;
  238. standard->InterfaceDereference = PciPmeInterfaceDereference;
  239. return STATUS_SUCCESS;
  240. }
  241. VOID
  242. PciPmeInterfaceDereference(
  243. IN PVOID Context
  244. )
  245. {
  246. return;
  247. }
  248. NTSTATUS
  249. PciPmeInterfaceInitializer(
  250. IN PPCI_ARBITER_INSTANCE Instance
  251. )
  252. /*++
  253. Routine Description:
  254. For bus interface, does nothing, shouldn't actually be called.
  255. Arguments:
  256. Instance Pointer to the PDO extension.
  257. Return Value:
  258. Returns the status of this operation.
  259. --*/
  260. {
  261. PCI_ASSERTMSG("PCI PciPmeInterfaceInitializer, unexpected call.", 0);
  262. return STATUS_UNSUCCESSFUL;
  263. }
  264. VOID
  265. PciPmeInterfaceReference(
  266. IN PVOID Context
  267. )
  268. {
  269. return;
  270. }
  271. VOID
  272. PciPmeUpdateEnable(
  273. IN PDEVICE_OBJECT Pdo,
  274. IN BOOLEAN PmeEnable
  275. )
  276. /*++
  277. Routine Description:
  278. This routine sets or clears the PME Enable bit on the specified
  279. device object
  280. Arguments:
  281. Pdo - The device object whose PME enable we care about
  282. PmeEnable - Wether or not we should enable PME on the device
  283. Return Value:
  284. None
  285. --*/
  286. {
  287. PPCI_PDO_EXTENSION pdoExtension = (PPCI_PDO_EXTENSION) Pdo->DeviceExtension;
  288. ASSERT_PCI_PDO_EXTENSION( pdoExtension );
  289. //
  290. // Mark the device as not having its PME managed by PCI any more...
  291. //
  292. pdoExtension->NoTouchPmeEnable = 1;
  293. //
  294. // Call the interface that does the real work. Note that we always need
  295. // to supply the 3rd argument as FALSE --- we don't to just clear the
  296. // PME Status bit
  297. //
  298. PciPmeAdjustPmeEnable( pdoExtension, PmeEnable, FALSE );
  299. }