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.

456 lines
9.0 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. eclowio.c
  5. Abstract:
  6. Interface module to ACPI driver functions. It encapsulates the grungy Irp details.
  7. Author:
  8. Bob Moore (Intel)
  9. Environment:
  10. Notes:
  11. Revision History:
  12. 00-Feb-15 [vincentg] - modified to use oprghdlr.sys to register/deregister
  13. op region handler
  14. --*/
  15. #include "ecp.h"
  16. #include "oprghdlr.h"
  17. #include <initguid.h>
  18. #include <wdmguid.h>
  19. #ifdef ALLOC_PRAGMA
  20. #pragma alloc_text(PAGE, AcpiEcGetAcpiInterfaces)
  21. #pragma alloc_text(PAGE, AcpiEcGetGpeVector)
  22. #pragma alloc_text(PAGE, AcpiEcInstallOpRegionHandler)
  23. #pragma alloc_text(PAGE, AcpiEcRemoveOpRegionHandler)
  24. #endif
  25. NTSTATUS
  26. AcpiEcGetAcpiInterfaces (
  27. IN PECDATA EcData
  28. )
  29. /*++
  30. Routine Description:
  31. Call ACPI driver to get the direct-call interfaces.
  32. Arguments:
  33. EcData - Pointer to the EC driver device extension
  34. Return Value:
  35. Status is returned.
  36. --*/
  37. {
  38. KEVENT event;
  39. IO_STATUS_BLOCK ioStatus;
  40. NTSTATUS status;
  41. PIRP irp;
  42. PIO_STACK_LOCATION irpSp;
  43. PAGED_CODE();
  44. //
  45. // Initialize an event to block on
  46. //
  47. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  48. //
  49. // Build an irp
  50. //
  51. irp = IoBuildSynchronousFsdRequest(
  52. IRP_MJ_PNP,
  53. EcData->LowerDeviceObject,
  54. NULL,
  55. 0,
  56. NULL,
  57. &event,
  58. &ioStatus
  59. );
  60. if (!irp) {
  61. return STATUS_INSUFFICIENT_RESOURCES;
  62. }
  63. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  64. irp->IoStatus.Information = 0;
  65. //
  66. // Get the the current irp location
  67. //
  68. irpSp = IoGetNextIrpStackLocation( irp );
  69. //
  70. // Use QUERY_INTERFACE to get the address of the direct-call
  71. // ACPI interfaces.
  72. //
  73. irpSp->MajorFunction = IRP_MJ_PNP;
  74. irpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
  75. irpSp->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_ACPI_INTERFACE_STANDARD;
  76. irpSp->Parameters.QueryInterface.Version = 1;
  77. irpSp->Parameters.QueryInterface.Size = sizeof (AcpiInterfaces);
  78. irpSp->Parameters.QueryInterface.Interface = (PINTERFACE) &AcpiInterfaces;
  79. irpSp->Parameters.QueryInterface.InterfaceSpecificData = NULL;
  80. //
  81. // send the request down
  82. //
  83. status = IoCallDriver( EcData->LowerDeviceObject, irp );
  84. if (status == STATUS_PENDING) {
  85. KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
  86. status = ioStatus.Status;
  87. }
  88. //
  89. // Done
  90. //
  91. return status;
  92. }
  93. NTSTATUS
  94. AcpiEcGetGpeVector (
  95. IN PECDATA EcData
  96. )
  97. /*++
  98. Routine Description:
  99. Run the _GPE method (Under the EC device in the namespace) to get the
  100. GPE vector assigned to the EC.
  101. Note: This routine is called at PASSIVE_LEVEL
  102. Arguments:
  103. EcData - Pointer to the EC driver device extension
  104. Return Value:
  105. Status is returned.
  106. --*/
  107. {
  108. ACPI_EVAL_INPUT_BUFFER inputBuffer;
  109. ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
  110. KEVENT event;
  111. IO_STATUS_BLOCK ioStatus;
  112. NTSTATUS status;
  113. PACPI_METHOD_ARGUMENT argument;
  114. PIRP irp;
  115. PAGED_CODE();
  116. //
  117. // Initialize the event
  118. //
  119. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  120. //
  121. // Initialize the input buffer
  122. //
  123. RtlZeroMemory( &inputBuffer, sizeof(ACPI_EVAL_INPUT_BUFFER) );
  124. inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
  125. inputBuffer.MethodNameAsUlong = CM_GPE_METHOD;
  126. //
  127. // Initialize the output buffer
  128. //
  129. RtlZeroMemory( &outputBuffer, sizeof(ACPI_EVAL_OUTPUT_BUFFER ) );
  130. //
  131. // Initialize an IRP
  132. //
  133. irp = IoBuildDeviceIoControlRequest(
  134. IOCTL_ACPI_EVAL_METHOD,
  135. EcData->LowerDeviceObject,
  136. &inputBuffer,
  137. sizeof(ACPI_EVAL_INPUT_BUFFER),
  138. &outputBuffer,
  139. sizeof(ACPI_EVAL_OUTPUT_BUFFER),
  140. FALSE,
  141. &event,
  142. &ioStatus
  143. );
  144. //
  145. // Irp initialization failed?
  146. //
  147. if (!irp) {
  148. status = STATUS_INSUFFICIENT_RESOURCES;
  149. goto AcpiEcGetGpeVectorExit;
  150. }
  151. //
  152. // Send to ACPI driver
  153. //
  154. status = IoCallDriver (EcData->LowerDeviceObject, irp);
  155. if (status == STATUS_PENDING) {
  156. //
  157. // Wait for request to be completed
  158. //
  159. KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
  160. //
  161. // Get the real status
  162. //
  163. status = ioStatus.Status;
  164. }
  165. //
  166. // Did we fail the request?
  167. //
  168. if (!NT_SUCCESS(status)) {
  169. goto AcpiEcGetGpeVectorExit;
  170. }
  171. //
  172. // Sanity checks
  173. //
  174. ASSERT( ioStatus.Information >= sizeof(ACPI_EVAL_OUTPUT_BUFFER) );
  175. if (ioStatus.Information < sizeof(ACPI_EVAL_OUTPUT_BUFFER) ||
  176. outputBuffer.Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
  177. outputBuffer.Count == 0) {
  178. status = STATUS_UNSUCCESSFUL;
  179. goto AcpiEcGetGpeVectorExit;
  180. }
  181. //
  182. // Crack the result
  183. //
  184. argument = &(outputBuffer.Argument[0]);
  185. //
  186. // We are expecting an integer
  187. //
  188. if (argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) {
  189. status = STATUS_ACPI_INVALID_DATA;
  190. goto AcpiEcGetGpeVectorExit;
  191. }
  192. //
  193. // Get the value
  194. //
  195. EcData->GpeVector = (UCHAR) argument->Argument;
  196. AcpiEcGetGpeVectorExit:
  197. //
  198. // Done
  199. //
  200. return status;
  201. }
  202. NTSTATUS
  203. AcpiEcConnectGpeVector (
  204. IN PECDATA EcData
  205. )
  206. /*++
  207. Routine Description:
  208. Call ACPI driver to connect the EC driver to a GPE vector
  209. Arguments:
  210. EcData - Pointer to the EC driver device extension
  211. Return Value:
  212. Status is returned.
  213. --*/
  214. {
  215. return (AcpiInterfaces.GpeConnectVector (
  216. AcpiInterfaces.Context,
  217. EcData->GpeVector,
  218. Latched, // Edge triggered
  219. FALSE, // Can't be shared
  220. AcpiEcGpeServiceRoutine,
  221. EcData,
  222. &EcData->GpeVectorObject));
  223. }
  224. NTSTATUS
  225. AcpiEcDisconnectGpeVector (
  226. IN PECDATA EcData
  227. )
  228. /*++
  229. Routine Description:
  230. Call ACPI driver to disconnect the EC driver from a GPE vector. Called
  231. from device unload, stop.
  232. Arguments:
  233. EcData - Pointer to the EC driver device extension
  234. Return Value:
  235. Status is returned.
  236. --*/
  237. {
  238. NTSTATUS status;
  239. if (EcData->GpeVectorObject) {
  240. status = AcpiInterfaces.GpeDisconnectVector (EcData->GpeVectorObject);
  241. EcData->GpeVectorObject = NULL;
  242. } else {
  243. status = STATUS_SUCCESS;
  244. }
  245. return status;
  246. }
  247. NTSTATUS
  248. AcpiEcInstallOpRegionHandler(
  249. IN PECDATA EcData
  250. )
  251. /*++
  252. Routine Description:
  253. Call ACPI driver to install the EC driver operation region handler
  254. Arguments:
  255. EcData - Pointer to the EC driver device extension
  256. Return Value:
  257. Status is returned.
  258. --*/
  259. {
  260. NTSTATUS status = STATUS_SUCCESS;
  261. PAGED_CODE ();
  262. status = RegisterOpRegionHandler (EcData->LowerDeviceObject,
  263. ACPI_OPREGION_ACCESS_AS_COOKED,
  264. ACPI_OPREGION_REGION_SPACE_EC,
  265. (PACPI_OP_REGION_HANDLER) AcpiEcOpRegionHandler,
  266. EcData,
  267. 0,
  268. &EcData->OperationRegionObject);
  269. return status;
  270. }
  271. NTSTATUS
  272. AcpiEcRemoveOpRegionHandler (
  273. IN PECDATA EcData
  274. )
  275. /*++
  276. Routine Description:
  277. Call ACPI driver to remove the EC driver operation region handler.
  278. Called from device unload, stop.
  279. Arguments:
  280. EcData - Pointer to the EC driver device extension
  281. Return Value:
  282. Status is returned.
  283. --*/
  284. {
  285. NTSTATUS status = STATUS_SUCCESS;
  286. PAGED_CODE ();
  287. status = DeRegisterOpRegionHandler (EcData->LowerDeviceObject,
  288. EcData->OperationRegionObject);
  289. return status;
  290. }
  291. NTSTATUS
  292. AcpiEcForwardIrpAndWait (
  293. IN PECDATA EcData,
  294. IN PIRP Irp
  295. )
  296. /*++
  297. Routine Description:
  298. Utility routine to send an irp down, and wait for the result.
  299. Arguments:
  300. EcData - Pointer to the EC driver device extension
  301. Irp - Irp to send and complete
  302. Return Value:
  303. Status is returned.
  304. --*/
  305. {
  306. KEVENT pdoStartedEvent;
  307. NTSTATUS status;
  308. KeInitializeEvent (&pdoStartedEvent, SynchronizationEvent, FALSE);
  309. IoCopyCurrentIrpStackLocationToNext (Irp);
  310. IoSetCompletionRoutine (Irp, AcpiEcIoCompletion, &pdoStartedEvent,
  311. TRUE, TRUE, TRUE);
  312. //
  313. // Always wait for the completion routine
  314. //
  315. status = IoCallDriver (EcData->LowerDeviceObject, Irp);
  316. if (status == STATUS_PENDING) {
  317. KeWaitForSingleObject (&pdoStartedEvent, Executive, KernelMode, FALSE, NULL);
  318. status = Irp->IoStatus.Status;
  319. }
  320. return status;
  321. }