acpidrv.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. /*++
  2. Copyright (c) 2012 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. acpidrv.c
  9. Abstract:
  10. This module implements the ACPI driver functions.
  11. Author:
  12. Evan Green 29-Nov-2012
  13. Environment:
  14. Kernel
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/kernel/driver.h>
  20. #include "acpip.h"
  21. #include "fixedreg.h"
  22. #include "namespce.h"
  23. //
  24. // ---------------------------------------------------------------- Definitions
  25. //
  26. //
  27. // Define the identifier of the root ACPI device.
  28. //
  29. #define ACPI_ROOT_DEVICE_ID "ACPI"
  30. //
  31. // ------------------------------------------------------ Data Type Definitions
  32. //
  33. //
  34. // ----------------------------------------------- Internal Function Prototypes
  35. //
  36. VOID
  37. AcpiUnload (
  38. PVOID Driver
  39. );
  40. KSTATUS
  41. AcpiAddDevice (
  42. PVOID Driver,
  43. PCSTR DeviceId,
  44. PCSTR ClassId,
  45. PCSTR CompatibleIds,
  46. PVOID DeviceToken
  47. );
  48. VOID
  49. AcpiDispatchStateChange (
  50. PIRP Irp,
  51. PVOID DeviceContext,
  52. PVOID IrpContext
  53. );
  54. VOID
  55. AcpiDispatchOpen (
  56. PIRP Irp,
  57. PVOID DeviceContext,
  58. PVOID IrpContext
  59. );
  60. VOID
  61. AcpiDispatchClose (
  62. PIRP Irp,
  63. PVOID DeviceContext,
  64. PVOID IrpContext
  65. );
  66. VOID
  67. AcpiDispatchIo (
  68. PIRP Irp,
  69. PVOID DeviceContext,
  70. PVOID IrpContext
  71. );
  72. VOID
  73. AcpiDispatchSystemControl (
  74. PIRP Irp,
  75. PVOID DeviceContext,
  76. PVOID IrpContext
  77. );
  78. //
  79. // -------------------------------------------------------------------- Globals
  80. //
  81. //
  82. // Remember a pointer to the driver object returned by the system corresponding
  83. // to this driver.
  84. //
  85. PDRIVER AcpiDriver = NULL;
  86. //
  87. // Store a pointer to the FADT.
  88. //
  89. PFADT AcpiFadtTable = NULL;
  90. //
  91. // Store a global list of ACPI device objects.
  92. //
  93. LIST_ENTRY AcpiDeviceObjectListHead;
  94. LIST_ENTRY AcpiDeviceDependencyList;
  95. KSPIN_LOCK AcpiDeviceListLock;
  96. //
  97. // ------------------------------------------------------------------ Functions
  98. //
  99. __USED
  100. KSTATUS
  101. DriverEntry (
  102. PDRIVER Driver
  103. )
  104. /*++
  105. Routine Description:
  106. This routine is the entry point for the ACPI driver. It registers its other
  107. dispatch functions, and performs driver-wide initialization.
  108. Arguments:
  109. Driver - Supplies a pointer to the driver object.
  110. Return Value:
  111. STATUS_SUCCESS on success.
  112. Failure code on error.
  113. --*/
  114. {
  115. DRIVER_FUNCTION_TABLE FunctionTable;
  116. KSTATUS Status;
  117. AcpiDriver = Driver;
  118. INITIALIZE_LIST_HEAD(&AcpiDeviceObjectListHead);
  119. INITIALIZE_LIST_HEAD(&AcpiDeviceDependencyList);
  120. KeInitializeSpinLock(&AcpiDeviceListLock);
  121. AcpiFadtTable = AcpiFindTable(FADT_SIGNATURE, NULL);
  122. if (AcpiFadtTable == NULL) {
  123. Status = STATUS_NOT_SUPPORTED;
  124. goto DriverEntryEnd;
  125. }
  126. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  127. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  128. FunctionTable.Unload = AcpiUnload;
  129. FunctionTable.AddDevice = AcpiAddDevice;
  130. FunctionTable.DispatchStateChange = AcpiDispatchStateChange;
  131. FunctionTable.DispatchOpen = AcpiDispatchOpen;
  132. FunctionTable.DispatchClose = AcpiDispatchClose;
  133. FunctionTable.DispatchIo = AcpiDispatchIo;
  134. FunctionTable.DispatchSystemControl = AcpiDispatchSystemControl;
  135. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  136. if (!KSUCCESS(Status)) {
  137. goto DriverEntryEnd;
  138. }
  139. Status = AcpipInitializeFixedRegisterSupport();
  140. if (!KSUCCESS(Status)) {
  141. goto DriverEntryEnd;
  142. }
  143. //
  144. // Take control of the system from the BIOS by enabling ACPI mode.
  145. //
  146. Status = AcpipEnableAcpiMode();
  147. if (!KSUCCESS(Status)) {
  148. RtlDebugPrint("ACPI: Failed to enable ACPI mode: %d.\n", Status);
  149. goto DriverEntryEnd;
  150. }
  151. //
  152. // Fire up the AML interpreter.
  153. //
  154. Status = AcpipInitializeAmlInterpreter();
  155. if (!KSUCCESS(Status)) {
  156. goto DriverEntryEnd;
  157. }
  158. //
  159. // Add shutdown, reboot, and system state transition support.
  160. //
  161. Status = AcpipInitializeSystemStateTransitions();
  162. if (!KSUCCESS(Status)) {
  163. RtlDebugPrint("ACPI: Warning: InitSystemStateTransitions: %d\n",
  164. Status);
  165. Status = STATUS_SUCCESS;
  166. }
  167. DriverEntryEnd:
  168. if (!KSUCCESS(Status)) {
  169. AcpipUnmapFixedRegisters();
  170. }
  171. return Status;
  172. }
  173. VOID
  174. AcpiUnload (
  175. PVOID Driver
  176. )
  177. /*++
  178. Routine Description:
  179. This routine is called before a driver is about to be unloaded from memory.
  180. The driver should take this opportunity to free any resources it may have
  181. set up in the driver entry routine.
  182. Arguments:
  183. Driver - Supplies a pointer to the driver being torn down.
  184. Return Value:
  185. None.
  186. --*/
  187. {
  188. AcpipUnmapFixedRegisters();
  189. return;
  190. }
  191. KSTATUS
  192. AcpiAddDevice (
  193. PVOID Driver,
  194. PCSTR DeviceId,
  195. PCSTR ClassId,
  196. PCSTR CompatibleIds,
  197. PVOID DeviceToken
  198. )
  199. /*++
  200. Routine Description:
  201. This routine is called when the ACPI root device is enumerated. It will
  202. attach the driver to the device.
  203. Arguments:
  204. Driver - Supplies a pointer to the driver being called.
  205. DeviceId - Supplies a pointer to a string with the device ID.
  206. ClassId - Supplies a pointer to a string containing the device's class ID.
  207. CompatibleIds - Supplies a pointer to a string containing device IDs
  208. that would be compatible with this device.
  209. DeviceToken - Supplies an opaque token that the driver can use to identify
  210. the device in the system. This token should be used when attaching to
  211. the stack.
  212. Return Value:
  213. STATUS_SUCCESS on success.
  214. Failure code if the driver was unsuccessful in attaching itself.
  215. --*/
  216. {
  217. PACPI_DEVICE_CONTEXT Device;
  218. BOOL Match;
  219. KSTATUS Status;
  220. PACPI_OBJECT SystemBusObject;
  221. ASSERT(KeGetRunLevel() == RunLevelLow);
  222. Device = NULL;
  223. Status = STATUS_UNKNOWN_DEVICE;
  224. //
  225. // ACPI is the functional driver for the root object.
  226. //
  227. Match = IoAreDeviceIdsEqual(DeviceId, ACPI_ROOT_DEVICE_ID);
  228. if (Match != FALSE) {
  229. Device = MmAllocatePagedPool(sizeof(ACPI_DEVICE_CONTEXT),
  230. ACPI_ALLOCATION_TAG);
  231. if (Device == NULL) {
  232. Status = STATUS_INSUFFICIENT_RESOURCES;
  233. goto AddDeviceEnd;
  234. }
  235. RtlZeroMemory(Device, sizeof(ACPI_DEVICE_CONTEXT));
  236. Device->BusAddress = ACPI_INVALID_BUS_ADDRESS;
  237. SystemBusObject = AcpipFindNamedObject(AcpipGetNamespaceRoot(),
  238. ACPI_SYSTEM_BUS_OBJECT_NAME);
  239. ASSERT(SystemBusObject != NULL);
  240. Device->NamespaceObject = SystemBusObject;
  241. Device->Flags |= ACPI_DEVICE_BUS_DRIVER;
  242. Status = IoAttachDriverToDevice(Driver, DeviceToken, Device);
  243. if (!KSUCCESS(Status)) {
  244. goto AddDeviceEnd;
  245. }
  246. Device->NamespaceObject->U.Device.OsDevice = DeviceToken;
  247. Device->NamespaceObject->U.Device.DeviceContext = Device;
  248. KeAcquireSpinLock(&AcpiDeviceListLock);
  249. INSERT_AFTER(&(Device->ListEntry), &AcpiDeviceObjectListHead);
  250. KeReleaseSpinLock(&AcpiDeviceListLock);
  251. goto AddDeviceEnd;
  252. }
  253. //
  254. // ACPI does not recognize this device.
  255. //
  256. Status = STATUS_UNKNOWN_DEVICE;
  257. AddDeviceEnd:
  258. if (!KSUCCESS(Status)) {
  259. if (Device != NULL) {
  260. MmFreePagedPool(Device);
  261. }
  262. }
  263. return Status;
  264. }
  265. VOID
  266. AcpiDispatchStateChange (
  267. PIRP Irp,
  268. PVOID DeviceContext,
  269. PVOID IrpContext
  270. )
  271. /*++
  272. Routine Description:
  273. This routine handles State Change IRPs.
  274. Arguments:
  275. Irp - Supplies a pointer to the I/O request packet.
  276. DeviceContext - Supplies the context pointer supplied by the driver when it
  277. attached itself to the driver stack. Presumably this pointer contains
  278. driver-specific device context.
  279. IrpContext - Supplies the context pointer supplied by the driver when
  280. the IRP was created.
  281. Return Value:
  282. None.
  283. --*/
  284. {
  285. PACPI_DEVICE_CONTEXT Device;
  286. KSTATUS Status;
  287. Device = (PACPI_DEVICE_CONTEXT)DeviceContext;
  288. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  289. if (Irp->Direction == IrpUp) {
  290. switch (Irp->MinorCode) {
  291. case IrpMinorQueryResources:
  292. if ((Device->Flags & ACPI_DEVICE_BUS_DRIVER) != 0) {
  293. Status = AcpipQueryResourceRequirements(Irp->Device,
  294. Device,
  295. Irp);
  296. if (!KSUCCESS(Status)) {
  297. if (Status != STATUS_NOT_READY) {
  298. RtlDebugPrint("ACPI: Failed to get device resources."
  299. "Device 0x%08x, Status: %d\n",
  300. Irp->Device,
  301. Status);
  302. }
  303. }
  304. IoCompleteIrp(AcpiDriver, Irp, Status);
  305. //
  306. // If ACPI is not the head honcho, then play a supporting role
  307. // of translating any resources the bus driver requested.
  308. //
  309. } else {
  310. Status = AcpipFilterResourceRequirements(Irp->Device,
  311. Device,
  312. Irp);
  313. //
  314. // Fail an IRP that was going to succeed if this fails.
  315. //
  316. if ((!KSUCCESS(Status)) && (KSUCCESS(IoGetIrpStatus(Irp)))) {
  317. IoCompleteIrp(AcpiDriver, Irp, Status);
  318. }
  319. }
  320. break;
  321. case IrpMinorStartDevice:
  322. Status = AcpipStartDevice(Irp->Device, Device, Irp);
  323. if ((!KSUCCESS(Status)) ||
  324. ((Device->Flags & ACPI_DEVICE_BUS_DRIVER) != 0)) {
  325. IoCompleteIrp(AcpiDriver, Irp, Status);
  326. }
  327. break;
  328. case IrpMinorQueryChildren:
  329. Status = AcpipEnumerateDeviceChildren(Irp->Device, Device, Irp);
  330. if (!KSUCCESS(Status)) {
  331. RtlDebugPrint("ACPI: Failed to enumerate device children. "
  332. "Device 0x%08x, Status: %d\n",
  333. Irp->Device,
  334. Status);
  335. IoCompleteIrp(AcpiDriver, Irp, Status);
  336. //
  337. // If it was successful and ACPI is the bus driver, complete the
  338. // IRP.
  339. //
  340. } else if ((Device->Flags & ACPI_DEVICE_BUS_DRIVER) != 0) {
  341. IoCompleteIrp(AcpiDriver, Irp, Status);
  342. }
  343. break;
  344. case IrpMinorRemoveDevice:
  345. AcpipRemoveDevice(Device);
  346. if ((Device->Flags & ACPI_DEVICE_BUS_DRIVER) != 0) {
  347. IoCompleteIrp(AcpiDriver, Irp, STATUS_SUCCESS);
  348. }
  349. break;
  350. default:
  351. break;
  352. }
  353. }
  354. return;
  355. }
  356. VOID
  357. AcpiDispatchOpen (
  358. PIRP Irp,
  359. PVOID DeviceContext,
  360. PVOID IrpContext
  361. )
  362. /*++
  363. Routine Description:
  364. This routine handles Open IRPs.
  365. Arguments:
  366. Irp - Supplies a pointer to the I/O request packet.
  367. DeviceContext - Supplies the context pointer supplied by the driver when it
  368. attached itself to the driver stack. Presumably this pointer contains
  369. driver-specific device context.
  370. IrpContext - Supplies the context pointer supplied by the driver when
  371. the IRP was created.
  372. Return Value:
  373. None.
  374. --*/
  375. {
  376. return;
  377. }
  378. VOID
  379. AcpiDispatchClose (
  380. PIRP Irp,
  381. PVOID DeviceContext,
  382. PVOID IrpContext
  383. )
  384. /*++
  385. Routine Description:
  386. This routine handles Close IRPs.
  387. Arguments:
  388. Irp - Supplies a pointer to the I/O request packet.
  389. DeviceContext - Supplies the context pointer supplied by the driver when it
  390. attached itself to the driver stack. Presumably this pointer contains
  391. driver-specific device context.
  392. IrpContext - Supplies the context pointer supplied by the driver when
  393. the IRP was created.
  394. Return Value:
  395. None.
  396. --*/
  397. {
  398. return;
  399. }
  400. VOID
  401. AcpiDispatchIo (
  402. PIRP Irp,
  403. PVOID DeviceContext,
  404. PVOID IrpContext
  405. )
  406. /*++
  407. Routine Description:
  408. This routine handles I/O IRPs.
  409. Arguments:
  410. Irp - Supplies a pointer to the I/O request packet.
  411. DeviceContext - Supplies the context pointer supplied by the driver when it
  412. attached itself to the driver stack. Presumably this pointer contains
  413. driver-specific device context.
  414. IrpContext - Supplies the context pointer supplied by the driver when
  415. the IRP was created.
  416. Return Value:
  417. None.
  418. --*/
  419. {
  420. return;
  421. }
  422. VOID
  423. AcpiDispatchSystemControl (
  424. PIRP Irp,
  425. PVOID DeviceContext,
  426. PVOID IrpContext
  427. )
  428. /*++
  429. Routine Description:
  430. This routine handles System Control IRPs.
  431. Arguments:
  432. Irp - Supplies a pointer to the I/O request packet.
  433. DeviceContext - Supplies the context pointer supplied by the driver when it
  434. attached itself to the driver stack. Presumably this pointer contains
  435. driver-specific device context.
  436. IrpContext - Supplies the context pointer supplied by the driver when
  437. the IRP was created.
  438. Return Value:
  439. None.
  440. --*/
  441. {
  442. ASSERT(Irp->MajorCode == IrpMajorSystemControl);
  443. return;
  444. }