amlos.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  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. amlos.c
  9. Abstract:
  10. This module implements operating system support functions for the ACPI AML
  11. interpreter and namespace.
  12. Author:
  13. Evan Green 13-Nov-2012
  14. Environment:
  15. Kernel
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/kernel/driver.h>
  21. #include "acpiobj.h"
  22. #include "amlos.h"
  23. #include "amlops.h"
  24. #include "namespce.h"
  25. //
  26. // ---------------------------------------------------------------- Definitions
  27. //
  28. //
  29. // Define the allocation tag for ACPI AMLallocations.
  30. //
  31. #define ACPI_AML_ALLOCATION_TAG 0x696C6D41 // 'ilmA'
  32. //
  33. // ------------------------------------------------------ Data Type Definitions
  34. //
  35. /*++
  36. Structure Description:
  37. This structure stores the implementation of an ACPI mutex object.
  38. Members:
  39. QueuedLock - Stores a pointer to the OS queued lock implementing the
  40. synchronization primitive.
  41. OwningContext - Stores a pointer to the execution context (thread) that
  42. has the lock acquired.
  43. RecursionCount - Stores the number of acquire calls that have been made.
  44. SyncLevel - Stores the sync level of this mutex.
  45. PreviousSyncLevel - Stores the sync level of the execution context
  46. immediately before the acquire call was made.
  47. --*/
  48. typedef struct _ACPI_MUTEX {
  49. PQUEUED_LOCK QueuedLock;
  50. PAML_EXECUTION_CONTEXT OwningContext;
  51. ULONG RecursionCount;
  52. ULONG SyncLevel;
  53. ULONG PreviousSyncLevel;
  54. } ACPI_MUTEX, *PACPI_MUTEX;
  55. //
  56. // ----------------------------------------------- Internal Function Prototypes
  57. //
  58. //
  59. // -------------------------------------------------------------------- Globals
  60. //
  61. PQUEUED_LOCK AcpiPciLock = NULL;
  62. //
  63. // ------------------------------------------------------------------ Functions
  64. //
  65. KSTATUS
  66. AcpipInitializeOperatingSystemAmlSupport (
  67. VOID
  68. )
  69. /*++
  70. Routine Description:
  71. This routine initializes operating system specific support for the AML
  72. interpreter.
  73. Arguments:
  74. None.
  75. Return Value:
  76. Status code.
  77. --*/
  78. {
  79. KSTATUS Status;
  80. AcpiPciLock = KeCreateQueuedLock();
  81. if (AcpiPciLock == NULL) {
  82. Status = STATUS_INSUFFICIENT_RESOURCES;
  83. goto InitializeOperatingSystemAmlSupportEnd;
  84. }
  85. Status = STATUS_SUCCESS;
  86. InitializeOperatingSystemAmlSupportEnd:
  87. return Status;
  88. }
  89. PVOID
  90. AcpipAllocateMemory (
  91. ULONG Size
  92. )
  93. /*++
  94. Routine Description:
  95. This routine allocates memory from the operating system for the ACPI
  96. interpreter and namespace.
  97. Arguments:
  98. Size - Supplies the size of the allocation, in bytes.
  99. Return Value:
  100. Returns a pointer to the allocated memory on success.
  101. NULL on failure.
  102. --*/
  103. {
  104. return MmAllocatePagedPool(Size, ACPI_AML_ALLOCATION_TAG);
  105. }
  106. VOID
  107. AcpipFreeMemory (
  108. PVOID Allocation
  109. )
  110. /*++
  111. Routine Description:
  112. This routine frees memory allocated for the ACPI AML interpreter and
  113. namespace.
  114. Arguments:
  115. Allocation - Supplies a pointer to the allocated memory.
  116. Return Value:
  117. None.
  118. --*/
  119. {
  120. MmFreePagedPool(Allocation);
  121. return;
  122. }
  123. VOID
  124. AcpipFatalError (
  125. ULONGLONG Parameter1,
  126. ULONGLONG Parameter2,
  127. ULONGLONG Parameter3,
  128. ULONGLONG Parameter4
  129. )
  130. /*++
  131. Routine Description:
  132. This routine takes the system down as gracefully as possible.
  133. Arguments:
  134. Parameter1 - Supplies an optional parameter.
  135. Parameter2 - Supplies an optional parameter.
  136. Parameter3 - Supplies an optional parameter.
  137. Parameter4 - Supplies an optional parameter.
  138. Return Value:
  139. This function does not return.
  140. --*/
  141. {
  142. KeCrashSystem(CRASH_ACPI_FAILURE,
  143. Parameter1,
  144. Parameter2,
  145. Parameter3,
  146. Parameter4);
  147. }
  148. VOID
  149. AcpipSleep (
  150. ULONG Milliseconds
  151. )
  152. /*++
  153. Routine Description:
  154. This routine delays the current thread's execution by at least the given
  155. number of milliseconds (the delays can be significantly longer). During this
  156. time, other threads will run.
  157. Arguments:
  158. Milliseconds - Supplies the minimum number of milliseconds to delay.
  159. Return Value:
  160. None.
  161. --*/
  162. {
  163. ASSERT(KeGetRunLevel() == RunLevelLow);
  164. KeDelayExecution(FALSE, FALSE, Milliseconds * MICROSECONDS_PER_MILLISECOND);
  165. return;
  166. }
  167. VOID
  168. AcpipBusySpin (
  169. ULONG Microseconds
  170. )
  171. /*++
  172. Routine Description:
  173. This routine stalls the current processor by the given number of
  174. microseconds. This routine busy spins, unless preemption occurs no other
  175. threads will run during this delay.
  176. Arguments:
  177. Microseconds - Supplies the minimum number of microseconds to delay.
  178. Return Value:
  179. None.
  180. --*/
  181. {
  182. HlBusySpin(Microseconds);
  183. return;
  184. }
  185. ULONGLONG
  186. AcpipGetTimerValue (
  187. )
  188. /*++
  189. Routine Description:
  190. This routine returns a monotomically non-decreasing value representing the
  191. number of hundred nanosecond units that have elapsed since some epoch in
  192. the past (could be system boot).
  193. Arguments:
  194. None.
  195. Return Value:
  196. Returns the number of hundred nanosecond units (10^-7 seconds) that have
  197. elapsed.
  198. --*/
  199. {
  200. ULONGLONG Frequency;
  201. ULONGLONG Value;
  202. Frequency = HlQueryTimeCounterFrequency();
  203. Value = HlQueryTimeCounter();
  204. //
  205. // Scale to hundred nanosecond units.
  206. //
  207. Value = (Value * (NANOSECONDS_PER_SECOND / 100)) / Frequency;
  208. return Value;
  209. }
  210. PVOID
  211. AcpipCreateMutex (
  212. ULONG SyncLevel
  213. )
  214. /*++
  215. Routine Description:
  216. This routine creates an operating system mutex object to back an ACPI mutex
  217. used in the AML interpreter.
  218. Arguments:
  219. SyncLevel - Supplies the ACPI-defined sync level of the mutex.
  220. Return Value:
  221. Returns a pointer to the mutex object on success.
  222. NULL on failure.
  223. --*/
  224. {
  225. PACPI_MUTEX Mutex;
  226. KSTATUS Status;
  227. ASSERT(KeGetRunLevel() == RunLevelLow);
  228. Mutex = AcpipAllocateMemory(sizeof(ACPI_MUTEX));
  229. if (Mutex == NULL) {
  230. Status = STATUS_INSUFFICIENT_RESOURCES;
  231. goto CreateMutexEnd;
  232. }
  233. RtlZeroMemory(Mutex, sizeof(ACPI_MUTEX));
  234. Mutex->SyncLevel = SyncLevel;
  235. Mutex->QueuedLock = KeCreateQueuedLock();
  236. if (Mutex->QueuedLock == NULL) {
  237. Status = STATUS_INSUFFICIENT_RESOURCES;
  238. goto CreateMutexEnd;
  239. }
  240. Status = STATUS_SUCCESS;
  241. CreateMutexEnd:
  242. if (!KSUCCESS(Status)) {
  243. if (Mutex != NULL) {
  244. if (Mutex->QueuedLock != NULL) {
  245. KeDestroyQueuedLock(Mutex->QueuedLock);
  246. }
  247. AcpipFreeMemory(Mutex);
  248. Mutex = NULL;
  249. }
  250. }
  251. return Mutex;
  252. }
  253. VOID
  254. AcpipDestroyMutex (
  255. PVOID Mutex
  256. )
  257. /*++
  258. Routine Description:
  259. This routine destroys an operating system mutex object.
  260. Arguments:
  261. Mutex - Supplies a pointer to the OS mutex object returned during the
  262. create mutex routine.
  263. Return Value:
  264. None.
  265. --*/
  266. {
  267. PACPI_MUTEX AcpiMutex;
  268. ASSERT(KeGetRunLevel() == RunLevelLow);
  269. ASSERT(Mutex != NULL);
  270. AcpiMutex = (PACPI_MUTEX)Mutex;
  271. ASSERT(AcpiMutex->OwningContext == NULL);
  272. KeDestroyQueuedLock(AcpiMutex->QueuedLock);
  273. AcpipFreeMemory(AcpiMutex);
  274. return;
  275. }
  276. BOOL
  277. AcpipAcquireMutex (
  278. PAML_EXECUTION_CONTEXT Context,
  279. PVOID Mutex,
  280. ULONG TimeoutInMilliseconds
  281. )
  282. /*++
  283. Routine Description:
  284. This routine attempts to acquire a mutex object.
  285. Arguments:
  286. Context - Supplies a pointer to the execution context.
  287. Mutex - Supplies a pointer to the mutex to acquire.
  288. TimeoutInMilliseconds - Supplies the number of milliseconds to wait before
  289. returning anyway and timing out (failing the acquire).
  290. Return Value:
  291. TRUE if the timeout occurred and the mutex was not acquired.
  292. FALSE if the mutex was successfully acquired.
  293. --*/
  294. {
  295. PACPI_MUTEX AcpiMutex;
  296. KSTATUS Status;
  297. ASSERT(KeGetRunLevel() == RunLevelLow);
  298. AcpiMutex = (PACPI_MUTEX)Mutex;
  299. //
  300. // ACPI dictates that mutexes must be acquired in order by sync level.
  301. // This assert indicates bad firmware has attempted to acquire two mutexes
  302. // in the wrong order.
  303. //
  304. ASSERT(Context->SyncLevel <= AcpiMutex->SyncLevel);
  305. if (AcpiMutex->OwningContext == Context) {
  306. AcpiMutex->RecursionCount += 1;
  307. return TRUE;
  308. }
  309. if (TimeoutInMilliseconds == ACPI_MUTEX_WAIT_INDEFINITELY) {
  310. TimeoutInMilliseconds = WAIT_TIME_INDEFINITE;
  311. }
  312. Status = KeAcquireQueuedLockTimed(AcpiMutex->QueuedLock,
  313. TimeoutInMilliseconds);
  314. if (!KSUCCESS(Status)) {
  315. return FALSE;
  316. }
  317. //
  318. // Save the previous sync level in the mutex and set the sync level to that
  319. // of the mutex.
  320. //
  321. AcpiMutex->OwningContext = Context;
  322. AcpiMutex->PreviousSyncLevel = Context->SyncLevel;
  323. Context->SyncLevel = AcpiMutex->SyncLevel;
  324. return TRUE;
  325. }
  326. VOID
  327. AcpipReleaseMutex (
  328. PAML_EXECUTION_CONTEXT Context,
  329. PVOID Mutex
  330. )
  331. /*++
  332. Routine Description:
  333. This routine releases an acquired mutex object. This object must have been
  334. successfully acquired using the acquire routine.
  335. Arguments:
  336. Context - Supplies a pointer to the execution context.
  337. Mutex - Supplies a pointer to the mutex to release.
  338. Return Value:
  339. None.
  340. --*/
  341. {
  342. PACPI_MUTEX AcpiMutex;
  343. ASSERT(KeGetRunLevel() == RunLevelLow);
  344. AcpiMutex = (PACPI_MUTEX)Mutex;
  345. //
  346. // This assert fires when ACPI firmware attempts to release a mutex it
  347. // never acquired (or release more times than it acquired, as the mutex is
  348. // recursive).
  349. //
  350. ASSERT(AcpiMutex->OwningContext == Context);
  351. ASSERT(Context->SyncLevel == AcpiMutex->SyncLevel);
  352. //
  353. // If this is an inner recursive release, just decrement the count and
  354. // return.
  355. //
  356. if (AcpiMutex->RecursionCount != 0) {
  357. ASSERT(AcpiMutex->RecursionCount < 0x10000000);
  358. AcpiMutex->RecursionCount -= 1;
  359. return;
  360. }
  361. //
  362. // Clear the owning context and restore the sync level. Once this routine
  363. // is out of the mutex structure, drop the real lock that others are
  364. // blocked on.
  365. //
  366. AcpiMutex->OwningContext = NULL;
  367. Context->SyncLevel = AcpiMutex->PreviousSyncLevel;
  368. KeReleaseQueuedLock(AcpiMutex->QueuedLock);
  369. return;
  370. }
  371. PVOID
  372. AcpipCreateEvent (
  373. )
  374. /*++
  375. Routine Description:
  376. This routine creates an operating system event object to back an ACPI Event
  377. used in the AML interpreter.
  378. Arguments:
  379. None.
  380. Return Value:
  381. Returns a pointer to the event object on success.
  382. NULL on failure.
  383. --*/
  384. {
  385. PKEVENT Event;
  386. Event = KeCreateEvent(NULL);
  387. return Event;
  388. }
  389. VOID
  390. AcpipDestroyEvent (
  391. PVOID Event
  392. )
  393. /*++
  394. Routine Description:
  395. This routine destroys an operating system event object.
  396. Arguments:
  397. Event - Supplies a pointer to the OS event object returned during the
  398. create event routine.
  399. Return Value:
  400. None.
  401. --*/
  402. {
  403. KeDestroyEvent(Event);
  404. return;
  405. }
  406. BOOL
  407. AcpipWaitForEvent (
  408. PVOID Event,
  409. ULONG TimeoutInMilliseconds
  410. )
  411. /*++
  412. Routine Description:
  413. This routine waits at least the specified number of milliseconds for the
  414. given event object.
  415. Arguments:
  416. Event - Supplies a pointer to the event to wait for.
  417. TimeoutInMilliseconds - Supplies the number of milliseconds to wait before
  418. returning anyway and timing out (failing the wait).
  419. Return Value:
  420. TRUE if the timeout occurred and the event was not acquired.
  421. FALSE if execution continued because the event was signaled.
  422. --*/
  423. {
  424. KSTATUS Status;
  425. Status = KeWaitForEvent(Event, FALSE, TimeoutInMilliseconds);
  426. if (!KSUCCESS(Status)) {
  427. return FALSE;
  428. }
  429. return TRUE;
  430. }
  431. VOID
  432. AcpipSignalEvent (
  433. PVOID Event
  434. )
  435. /*++
  436. Routine Description:
  437. This routine signals an event, releasing all parties waiting on it.
  438. Arguments:
  439. Event - Supplies a pointer to the event to signal.
  440. Return Value:
  441. None.
  442. --*/
  443. {
  444. KeSignalEvent(Event, SignalOptionSignalAll);
  445. return;
  446. }
  447. VOID
  448. AcpipResetEvent (
  449. PVOID Event
  450. )
  451. /*++
  452. Routine Description:
  453. This routine resets an event back to its unsignaled state, causing any
  454. party who subsequently waits on this event to block.
  455. Arguments:
  456. Event - Supplies a pointer to the event to unsignal.
  457. Return Value:
  458. None.
  459. --*/
  460. {
  461. KeSignalEvent(Event, SignalOptionUnsignal);
  462. return;
  463. }
  464. KSTATUS
  465. AcpipNotifyOperatingSystem (
  466. PACPI_OBJECT Object,
  467. ULONGLONG NotificationValue
  468. )
  469. /*++
  470. Routine Description:
  471. This routine is called by executing AML code to notify the operating system
  472. of something.
  473. Arguments:
  474. Object - Supplies the object generating the notification. This object will
  475. be of type Processor, Thermal Zone, or Device.
  476. NotificationValue - Supplies the type of notification being sent.
  477. Return Value:
  478. Status code.
  479. --*/
  480. {
  481. RtlDebugPrint("ACPI: OS Notify 0x%I64x!\n", NotificationValue);
  482. ASSERT(FALSE);
  483. return STATUS_NOT_IMPLEMENTED;
  484. }
  485. VOID
  486. AcpipAcquirePciLock (
  487. )
  488. /*++
  489. Routine Description:
  490. This routine acquires the PCI lock, used to synchronize early access to
  491. PCI configuration space with the PCI driver actually coming online.
  492. Arguments:
  493. None.
  494. Return Value:
  495. None.
  496. --*/
  497. {
  498. //
  499. // This routine is expecting only to be called at low run level, as it
  500. // does not raise to acquire.
  501. //
  502. ASSERT(KeGetRunLevel() == RunLevelLow);
  503. KeAcquireQueuedLock(AcpiPciLock);
  504. return;
  505. }
  506. VOID
  507. AcpipReleasePciLock (
  508. )
  509. /*++
  510. Routine Description:
  511. This routine releases the PCI lock, used to synchronize early access to
  512. PCI configuration space with the PCI driver actually coming online.
  513. Arguments:
  514. None.
  515. Return Value:
  516. None.
  517. --*/
  518. {
  519. //
  520. // This routine is expecting only to be called at low run level, as it
  521. // does not raise to acquire.
  522. //
  523. ASSERT(KeGetRunLevel() == RunLevelLow);
  524. KeReleaseQueuedLock(AcpiPciLock);
  525. return;
  526. }
  527. //
  528. // --------------------------------------------------------- Internal Functions
  529. //