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.

533 lines
12 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. acpiec.c
  5. Abstract:
  6. ACPI Embedded Controller Driver
  7. Author:
  8. Ken Reneris
  9. Environment:
  10. Kernel mode
  11. Notes:
  12. Revision History:
  13. 13-Feb-97
  14. PnP/Power support - Bob Moore
  15. --*/
  16. #include "ecp.h"
  17. //
  18. // List of FDOs managed by this driver
  19. //
  20. PDEVICE_OBJECT FdoList = NULL;
  21. #if DEBUG
  22. ULONG ECDebug = EC_ERRORS;
  23. #endif
  24. //
  25. // Prototypes
  26. //
  27. NTSTATUS
  28. DriverEntry(
  29. IN PDRIVER_OBJECT DriverObject,
  30. IN PUNICODE_STRING RegistryPath
  31. );
  32. NTSTATUS
  33. AcpiEcPnpDispatch(
  34. IN PDEVICE_OBJECT DeviceObject,
  35. IN PIRP Irp
  36. );
  37. NTSTATUS
  38. AcpiEcPowerDispatch(
  39. IN PDEVICE_OBJECT DeviceObject,
  40. IN PIRP Irp
  41. );
  42. NTSTATUS
  43. AcpiEcAddDevice(
  44. IN PDRIVER_OBJECT DriverObject,
  45. IN PDEVICE_OBJECT Pdo
  46. );
  47. //
  48. // ReadWrite and PowerDispatch should stay resident
  49. //
  50. #ifdef ALLOC_PRAGMA
  51. #pragma alloc_text(INIT,DriverEntry)
  52. #pragma alloc_text(PAGE,AcpiEcUnload)
  53. #pragma alloc_text(PAGE,AcpiEcOpenClose)
  54. #pragma alloc_text(PAGE,AcpiEcInternalControl)
  55. #endif
  56. NTSTATUS
  57. DriverEntry(
  58. IN PDRIVER_OBJECT DriverObject,
  59. IN PUNICODE_STRING RegistryPath
  60. )
  61. /*++
  62. Routine Description:
  63. This routine initializes the ACPI Embedded Controller Driver
  64. Arguments:
  65. DriverObject - Pointer to driver object created by system.
  66. RegistryPath - Pointer to the Unicode name of the registry path for this driver.
  67. Return Value:
  68. The function value is the final status from the initialization operation.
  69. --*/
  70. {
  71. //
  72. // Set up the device driver entry points.
  73. //
  74. #if DEBUG
  75. // Security: Can only open file handles in debug builds
  76. DriverObject->MajorFunction[IRP_MJ_CREATE] = AcpiEcOpenClose;
  77. DriverObject->MajorFunction[IRP_MJ_CLOSE] = AcpiEcOpenClose;
  78. #endif
  79. DriverObject->MajorFunction[IRP_MJ_READ] = AcpiEcReadWrite;
  80. DriverObject->MajorFunction[IRP_MJ_WRITE] = AcpiEcReadWrite;
  81. DriverObject->MajorFunction[IRP_MJ_POWER] = AcpiEcPowerDispatch;
  82. DriverObject->MajorFunction[IRP_MJ_PNP] = AcpiEcPnpDispatch;
  83. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AcpiEcForwardRequest;
  84. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = AcpiEcInternalControl;
  85. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = AcpiEcForwardRequest;
  86. DriverObject->DriverExtension->AddDevice = AcpiEcAddDevice;
  87. DriverObject->DriverUnload = AcpiEcUnload;
  88. return STATUS_SUCCESS;
  89. }
  90. VOID
  91. AcpiEcUnload(
  92. IN PDRIVER_OBJECT DriverObject
  93. )
  94. /*++
  95. Routine Description:
  96. This routine unloads the ACPI Embedded Controller Driver
  97. Note: The driver should be already disconnected from the GPE by this time.
  98. Arguments:
  99. DriverObject - Pointer to driver object created by system.
  100. Return Value:
  101. None.
  102. --*/
  103. {
  104. PVOID LockPtr;
  105. KIRQL OldIrql;
  106. PECDATA EcData;
  107. EcPrint(EC_LOW, ("AcpiEcUnload: Entering\n" ));
  108. LockPtr = MmLockPagableCodeSection(AcpiEcUnload);
  109. while (DriverObject->DeviceObject) {
  110. EcData = DriverObject->DeviceObject->DeviceExtension;
  111. //
  112. // Device can only be active if initialization was completed
  113. //
  114. if (EcData->IsStarted) {
  115. //
  116. // Set state to determine when unload can occur, and issue a device service
  117. // call to get it unloaded now of the device is idle
  118. //
  119. ASSERT (EcData->DeviceState == EC_DEVICE_WORKING);
  120. EcData->DeviceState = EC_DEVICE_UNLOAD_PENDING;
  121. AcpiEcServiceDevice (EcData);
  122. //
  123. // Wait for device to cleanup
  124. //
  125. while (EcData->DeviceState != EC_DEVICE_UNLOAD_COMPLETE) {
  126. KeWaitForSingleObject (&EcData->Unload, Suspended, KernelMode, FALSE, NULL);
  127. }
  128. }
  129. //
  130. // Make sure caller signalling the unload is done
  131. //
  132. KeAcquireSpinLock (&EcData->Lock, &OldIrql);
  133. KeReleaseSpinLock (&EcData->Lock, OldIrql);
  134. //
  135. // Free resources
  136. //
  137. IoFreeIrp (EcData->QueryRequest);
  138. IoFreeIrp (EcData->MiscRequest);
  139. if (EcData->VectorTable) {
  140. ExFreePool (EcData->VectorTable);
  141. }
  142. IoDeleteDevice (EcData->DeviceObject);
  143. }
  144. //
  145. // Done
  146. //
  147. MmUnlockPagableImageSection(LockPtr);
  148. EcPrint(EC_LOW, ("AcpiEcUnload: Driver Unloaded\n"));
  149. }
  150. NTSTATUS
  151. AcpiEcOpenClose(
  152. IN PDEVICE_OBJECT DeviceObject,
  153. IN PIRP Irp
  154. )
  155. {
  156. PAGED_CODE();
  157. //
  158. // Complete the request and return status.
  159. //
  160. Irp->IoStatus.Status = STATUS_SUCCESS;
  161. Irp->IoStatus.Information = 0;
  162. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  163. return(STATUS_SUCCESS);
  164. }
  165. NTSTATUS
  166. AcpiEcReadWrite(
  167. IN PDEVICE_OBJECT DeviceObject,
  168. IN PIRP Irp
  169. )
  170. /*++
  171. Routine Description:
  172. This routine is the dispatch routine for read & write requests.
  173. Arguments:
  174. DeviceObject - Pointer to class device object.
  175. Irp - Pointer to the request packet.
  176. Return Value:
  177. Status is returned.
  178. --*/
  179. {
  180. PIO_STACK_LOCATION irpSp;
  181. PECDATA EcData;
  182. KIRQL OldIrql;
  183. BOOLEAN StartIo;
  184. NTSTATUS Status;
  185. #if DEBUG
  186. UCHAR i;
  187. #endif
  188. Status = STATUS_INVALID_PARAMETER;
  189. Irp->IoStatus.Information = 0;
  190. Irp->IoStatus.Status = Status;
  191. //
  192. // Get a pointer to the current parameters for this request. The
  193. // information is contained in the current stack location.
  194. //
  195. irpSp = IoGetCurrentIrpStackLocation(Irp);
  196. EcData = DeviceObject->DeviceExtension;
  197. #if !DEBUG
  198. //
  199. // Security: Refuse any request sent from user mode (except on debug builds)
  200. //
  201. if (Irp->RequestorMode != KernelMode) {
  202. Status = STATUS_ACCESS_DENIED;
  203. Irp->IoStatus.Status = Status;
  204. } else
  205. #endif
  206. if (irpSp->Parameters.Read.ByteOffset.HighPart ||
  207. irpSp->Parameters.Read.ByteOffset.LowPart > 255 ||
  208. irpSp->Parameters.Read.ByteOffset.LowPart + irpSp->Parameters.Read.Length > 256) {
  209. //
  210. // Verify offset is within Embedded Controller range
  211. //
  212. Status = STATUS_END_OF_FILE;
  213. Irp->IoStatus.Status = Status;
  214. } else {
  215. //
  216. // Queue the transfer up
  217. //
  218. KeAcquireSpinLock (&EcData->Lock, &OldIrql);
  219. if (EcData->DeviceState > EC_DEVICE_UNLOAD_PENDING) {
  220. //
  221. // Device is unloading
  222. //
  223. Status = STATUS_NO_SUCH_DEVICE;
  224. Irp->IoStatus.Status = Status;
  225. } else {
  226. #if DEBUG
  227. if ((irpSp->MajorFunction == IRP_MJ_WRITE) && (ECDebug & EC_TRANSACTION)) {
  228. EcPrint (EC_TRANSACTION, ("AcpiEcReadWrite: Write ("));
  229. for (i=0; i < irpSp->Parameters.Write.Length; i++) {
  230. EcPrint (EC_TRANSACTION, ("%02x ",
  231. ((PUCHAR)Irp->AssociatedIrp.SystemBuffer) [i]));
  232. }
  233. EcPrint (EC_TRANSACTION, (") to %02x length %02x\n",
  234. (UCHAR)irpSp->Parameters.Write.ByteOffset.LowPart,
  235. (UCHAR)irpSp->Parameters.Write.Length));
  236. }
  237. #endif
  238. Status = STATUS_PENDING;
  239. Irp->IoStatus.Status = Status;
  240. IoMarkIrpPending (Irp);
  241. InsertTailList (&EcData->WorkQueue, &Irp->Tail.Overlay.ListEntry);
  242. StartIo = DeviceObject->CurrentIrp == NULL;
  243. AcpiEcLogAction (EcData, EC_ACTION_QUEUED_IO, StartIo);
  244. }
  245. KeReleaseSpinLock (&EcData->Lock, OldIrql);
  246. }
  247. //
  248. // Handle status
  249. //
  250. if (Status == STATUS_PENDING) {
  251. //
  252. // IO is queued, if device is not busy start it
  253. //
  254. if (StartIo) {
  255. AcpiEcServiceDevice (EcData);
  256. }
  257. } else {
  258. //
  259. // For opregion requests, there is no way to fail the request, so return -1
  260. //
  261. RtlFillMemory (Irp->AssociatedIrp.SystemBuffer, irpSp->Parameters.Read.Length, 0xff);
  262. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  263. }
  264. return Status;
  265. }
  266. NTSTATUS
  267. AcpiEcPowerDispatch(
  268. IN PDEVICE_OBJECT DeviceObject,
  269. IN PIRP Irp
  270. )
  271. /*++
  272. Routine Description:
  273. This routine is the dispatch routine for power requests.
  274. Arguments:
  275. DeviceObject - Pointer to class device object.
  276. Irp - Pointer to the request packet.
  277. Return Value:
  278. Status is returned.
  279. --*/
  280. {
  281. NTSTATUS status;
  282. PECDATA ecData = DeviceObject->DeviceExtension;
  283. //
  284. // Start the next power irp
  285. //
  286. PoStartNextPowerIrp( Irp );
  287. //
  288. // Handle the irp
  289. //
  290. if (ecData->LowerDeviceObject != NULL) {
  291. IoSkipCurrentIrpStackLocation( Irp );
  292. status = PoCallDriver( ecData->LowerDeviceObject, Irp );
  293. } else {
  294. //
  295. // Complete irp with the current code;
  296. status = Irp->IoStatus.Status;
  297. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  298. }
  299. return status;
  300. }
  301. NTSTATUS
  302. AcpiEcInternalControl(
  303. IN PDEVICE_OBJECT DeviceObject,
  304. IN PIRP Irp
  305. )
  306. /*++
  307. Routine Description:
  308. Internal IOCTL dispatch routine
  309. Arguments:
  310. DeviceObject - Pointer to class device object.
  311. Irp - Pointer to the request packet.
  312. Return Value:
  313. Status is returned.
  314. --*/
  315. {
  316. PIO_STACK_LOCATION IrpSp;
  317. PECDATA EcData;
  318. NTSTATUS Status;
  319. PAGED_CODE();
  320. Status = STATUS_INVALID_PARAMETER;
  321. Irp->IoStatus.Information = 0;
  322. //
  323. // Get a pointer to the current parameters for this request. The
  324. // information is contained in the current stack location.
  325. //
  326. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  327. EcData = DeviceObject->DeviceExtension;
  328. EcPrint (EC_NOTE, ("AcpiEcInternalControl: dispatch, code = %d\n",
  329. IrpSp->Parameters.DeviceIoControl.IoControlCode));
  330. Status = STATUS_INVALID_PARAMETER;
  331. switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  332. case EC_CONNECT_QUERY_HANDLER:
  333. Status = AcpiEcConnectHandler (EcData, Irp);
  334. break;
  335. case EC_DISCONNECT_QUERY_HANDLER:
  336. Status = AcpiEcDisconnectHandler (EcData, Irp);
  337. break;
  338. }
  339. if (Status != STATUS_PENDING) {
  340. Irp->IoStatus.Status = Status;
  341. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  342. }
  343. return Status;
  344. }
  345. NTSTATUS
  346. AcpiEcForwardRequest(
  347. IN PDEVICE_OBJECT DeviceObject,
  348. IN PIRP Irp
  349. )
  350. /*++
  351. Routine Description:
  352. This routine forwards the irp down the stack
  353. Arguments:
  354. DeviceObject - The target
  355. Irp - The request
  356. Return Value:
  357. NTSTATUS
  358. --*/
  359. {
  360. NTSTATUS status;
  361. PECDATA ecData = DeviceObject->DeviceExtension;
  362. if (ecData->LowerDeviceObject != NULL) {
  363. IoSkipCurrentIrpStackLocation( Irp );
  364. status = IoCallDriver( ecData->LowerDeviceObject, Irp );
  365. } else {
  366. status = Irp->IoStatus.Status;
  367. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  368. }
  369. return status;
  370. }