amlos.c 14 KB

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