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.

1033 lines
23 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. gpe.c
  5. Abstract:
  6. This module is how the ACPI driver interfaces with GPE Events
  7. Author:
  8. Stephane Plante (splante)
  9. Environment:
  10. NT Kernel Mode Driver Only
  11. --*/
  12. #include "pch.h"
  13. //
  14. // Global tables for GPE handling (Both GP0 and GP1)
  15. //
  16. PUCHAR GpeEnable = NULL;
  17. PUCHAR GpeCurEnable = NULL;
  18. PUCHAR GpeWakeEnable = NULL;
  19. PUCHAR GpeIsLevel = NULL;
  20. PUCHAR GpeHandlerType = NULL;
  21. PUCHAR GpeWakeHandler = NULL;
  22. PUCHAR GpeSpecialHandler = NULL;
  23. PUCHAR GpePending = NULL;
  24. PUCHAR GpeRunMethod = NULL;
  25. PUCHAR GpeComplete = NULL;
  26. PUCHAR GpeSavedWakeMask = NULL;
  27. PUCHAR GpeSavedWakeStatus = NULL;
  28. PUCHAR GpeMap = NULL;
  29. //
  30. // Lock to protect all GPE related information
  31. //
  32. KSPIN_LOCK GpeTableLock;
  33. VOID
  34. ACPIGpeBuildEventMasks(
  35. VOID
  36. )
  37. /*++
  38. Routine Description:
  39. This routine looks at all the General Purpose Event sources and
  40. builds up a mask of which events should be enabled, which events
  41. are special, and which events are wake up events
  42. Arguments:
  43. None
  44. Return Value:
  45. None
  46. --*/
  47. {
  48. BOOLEAN convertedToNumber;
  49. KIRQL oldIrql;
  50. NTSTATUS status;
  51. PNSOBJ gpeObject;
  52. PNSOBJ gpeMethod;
  53. ULONG nameSeg;
  54. ULONG gpeIndex;
  55. //
  56. // NOTENOTE --- Check to make sure sure that the following sequence
  57. // of acquiring locks is correct
  58. //
  59. KeAcquireSpinLock( &AcpiDeviceTreeLock, &oldIrql );
  60. KeAcquireSpinLockAtDpcLevel( &GpeTableLock );
  61. //
  62. // First things first, we need to look at the \_GPE branch of the
  63. // tree to see which control methods, exist, if any
  64. //
  65. status = AMLIGetNameSpaceObject("\\_GPE", NULL, &gpeObject, 0);
  66. if (!NT_SUCCESS(status)) {
  67. ACPIPrint( (
  68. ACPI_PRINT_WARNING,
  69. "ACPIGpeBuildEventMasks - Could not find \\_GPE object %x\n",
  70. status
  71. ) );
  72. goto ACPIGpeBuildEventMasksExit;
  73. }
  74. //
  75. // Get the first child of the GPE root --- we will need to look
  76. // at all the methods under the object
  77. //
  78. gpeMethod = NSGETFIRSTCHILD(gpeObject);
  79. //
  80. // Use a for loop instead of a while loop to keep down the
  81. // number of nested statements
  82. //
  83. for (;gpeMethod; gpeMethod = NSGETNEXTSIBLING(gpeMethod) ) {
  84. //
  85. // Make sure that we are dealing with a method
  86. //
  87. if (NSGETOBJTYPE(gpeMethod) != OBJTYPE_METHOD) {
  88. continue;
  89. }
  90. //
  91. // The name of the object contains the index that we want
  92. // to associated with the object. We need to convert the string
  93. // representation into a numerical representation
  94. //
  95. // The encoding is as follows:
  96. // Object Name = _LXY [for example]
  97. // Object->dwNameSeg = yxL_
  98. // gpeIndex = (nameSeg >> 8) & 0xFF00 [the x]
  99. // gpeIndex += (nameSeg >> 24) & 0xFF [the y]
  100. //
  101. nameSeg = gpeMethod->dwNameSeg;
  102. gpeIndex = ( (nameSeg & 0x00FF0000) >> 8);
  103. gpeIndex |= ( (nameSeg & 0xFF000000) >> 24);
  104. nameSeg = ( (nameSeg & 0x0000FF00) >> 8);
  105. convertedToNumber = ACPIInternalConvertToNumber(
  106. (UCHAR) ( (gpeIndex & 0x00FF) ),
  107. (UCHAR) ( (gpeIndex & 0xFF00) >> 8),
  108. &gpeIndex
  109. );
  110. if (!convertedToNumber) {
  111. continue;
  112. }
  113. //
  114. // Set the proper bits to remember this GPE
  115. // Note: we pass convertedToNumber as the argument
  116. // since we don't particularly care what it returns
  117. //
  118. if ( (UCHAR) nameSeg == 'L') {
  119. //
  120. // Install the event as level triggered
  121. //
  122. ACPIGpeInstallRemoveIndex(
  123. gpeIndex,
  124. ACPI_GPE_LEVEL_INSTALL,
  125. ACPI_GPE_CONTROL_METHOD,
  126. &convertedToNumber
  127. );
  128. } else if ( (UCHAR) nameSeg == 'E') {
  129. //
  130. // Install the Edge triggered GPE
  131. //
  132. ACPIGpeInstallRemoveIndex(
  133. gpeIndex,
  134. ACPI_GPE_EDGE_INSTALL,
  135. ACPI_GPE_CONTROL_METHOD,
  136. &convertedToNumber
  137. );
  138. }
  139. } // for (...)
  140. ACPIGpeBuildEventMasksExit:
  141. //
  142. // We also need to look at all the vector objects and re-enable those
  143. //
  144. ACPIVectorBuildVectorMasks();
  145. //
  146. // At this point, we should re-enable the registers that should be
  147. // enabled
  148. //
  149. ACPIGpeEnableDisableEvents( TRUE );
  150. //
  151. // Done
  152. //
  153. KeReleaseSpinLockFromDpcLevel( &GpeTableLock );
  154. KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
  155. }
  156. VOID
  157. ACPIGpeBuildWakeMasks(
  158. IN PDEVICE_EXTENSION DeviceExtension
  159. )
  160. /*++
  161. Routine Description:
  162. This recursive routine walks the entire device extension space and
  163. tries to find device extension whose _PRW are special
  164. This routine is called with device tree and gpe table lock spinlocks
  165. owned
  166. Argument:
  167. DeviceExtension - The device whose children we need to examine
  168. Return Value:
  169. None
  170. --*/
  171. {
  172. EXTENSIONLIST_ENUMDATA eled;
  173. PDEVICE_EXTENSION childExtension;
  174. ULONG gpeRegister;
  175. ULONG gpeMask;
  176. //
  177. // Setup the data structures that we will use to walk the device
  178. // extension tree
  179. //
  180. ACPIExtListSetupEnum(
  181. &eled,
  182. &(DeviceExtension->ChildDeviceList),
  183. NULL,
  184. SiblingDeviceList,
  185. WALKSCHEME_NO_PROTECTION
  186. );
  187. //
  188. // Look at all children of the current device extension
  189. //
  190. for (childExtension = ACPIExtListStartEnum( &eled );
  191. ACPIExtListTestElement( &eled, TRUE);
  192. childExtension = ACPIExtListEnumNext( &eled) ) {
  193. //
  194. // Recurse first
  195. //
  196. ACPIGpeBuildWakeMasks( childExtension );
  197. //
  198. // Is there a _PRW on this extension?
  199. //
  200. if (!(childExtension->Flags & DEV_CAP_WAKE) ) {
  201. continue;
  202. }
  203. //
  204. // Remember which register and mask are used by this
  205. // gpe bit
  206. //
  207. gpeRegister = ACPIGpeIndexToGpeRegister(
  208. childExtension->PowerInfo.WakeBit
  209. );
  210. gpeMask = 1 << ( (UCHAR) childExtension->PowerInfo.WakeBit % 8);
  211. //
  212. // Does this vector have a GPE?
  213. //
  214. if ( (GpeEnable[gpeRegister] & gpeMask) ) {
  215. //
  216. // If we got here, and we aren't marked as DEV_CAP_NO_DISABLE_WAKE,
  217. // then we should turn off the GPE since this is a Wake event.
  218. // The easiest way to do this is to make sure that GpeWakeHandler
  219. // is masked with the appropriate bit
  220. //
  221. if (!(childExtension->Flags & DEV_CAP_NO_DISABLE_WAKE) ) {
  222. //
  223. // It has a GPE mask, so remember that there is a wake handler
  224. // for it. This should prevent us from arming the GPE without
  225. // a request for it.
  226. //
  227. if (!(GpeSpecialHandler[gpeRegister] & gpeMask) ) {
  228. GpeWakeHandler[gpeRegister] |= gpeMask;
  229. }
  230. } else {
  231. //
  232. // If we got here, then we should remember that we can
  233. // never consider this pin as *just* a wake handler
  234. //
  235. GpeSpecialHandler[gpeRegister] |= gpeMask;
  236. //
  237. // Make sure that the pin isn't set as a wake handler
  238. //
  239. GpeWakeHandler[gpeRegister] &= ~gpeMask;
  240. }
  241. }
  242. } // for ( ... )
  243. }
  244. VOID
  245. ACPIGpeClearEventMasks(
  246. )
  247. /*++
  248. Routine Description:
  249. This routine is called when the system wants to make sure that no
  250. General Purpose Events are enabled.
  251. This is typically done at:
  252. -System Init Time
  253. -Just before we load a namespace table
  254. -Just before we unload a namespace table
  255. Arguments:
  256. None
  257. Return Value:
  258. None
  259. --*/
  260. {
  261. KIRQL oldIrql;
  262. //
  263. // Need to hold the previous IRQL before we can touch these
  264. // registers
  265. //
  266. KeAcquireSpinLock( &GpeTableLock, &oldIrql );
  267. //
  268. // Disable all of the events
  269. //
  270. ACPIGpeEnableDisableEvents( FALSE );
  271. //
  272. // Clear all the events
  273. //
  274. ACPIGpeClearRegisters();
  275. //
  276. // Zero out all of these fields, since we will recalc them later
  277. //
  278. RtlZeroMemory( GpeCurEnable, AcpiInformation->GpeSize );
  279. RtlZeroMemory( GpeEnable, AcpiInformation->GpeSize );
  280. RtlZeroMemory( GpeWakeEnable, AcpiInformation->GpeSize );
  281. RtlZeroMemory( GpeWakeHandler, AcpiInformation->GpeSize );
  282. RtlZeroMemory( GpeSpecialHandler, AcpiInformation->GpeSize );
  283. RtlZeroMemory( GpeRunMethod, AcpiInformation->GpeSize );
  284. RtlZeroMemory( GpePending, AcpiInformation->GpeSize );
  285. RtlZeroMemory( GpeComplete, AcpiInformation->GpeSize );
  286. RtlZeroMemory( GpeIsLevel, AcpiInformation->GpeSize );
  287. RtlZeroMemory( GpeHandlerType, AcpiInformation->GpeSize );
  288. //
  289. // Done with the spinlock
  290. //
  291. KeReleaseSpinLock( &GpeTableLock, oldIrql );
  292. }
  293. VOID
  294. ACPIGpeClearRegisters(
  295. VOID
  296. )
  297. /*++
  298. Routine Description:
  299. Reset the contents of the GP Registers
  300. Arguments:
  301. None
  302. Return Value:
  303. None
  304. --*/
  305. {
  306. UCHAR scratch;
  307. ULONG i;
  308. //
  309. // Clear all GPE status registers
  310. //
  311. for (i = 0; i < AcpiInformation->GpeSize; i++) {
  312. //
  313. // Read the register and mask off uninteresting GPE levels
  314. //
  315. scratch = ACPIReadGpeStatusRegister (i);
  316. scratch &= GpeEnable[i] | GpeWakeEnable[i];
  317. //
  318. // Write back out to clear the status bits
  319. //
  320. ACPIWriteGpeStatusRegister (i, scratch);
  321. }
  322. }
  323. VOID
  324. ACPIGpeEnableDisableEvents (
  325. BOOLEAN Enable
  326. )
  327. /*++
  328. Routine Description:
  329. Not Exported
  330. Enable or disables GP events
  331. Arguments:
  332. Enable - TRUE if we want to enable GP events
  333. Return Value
  334. None
  335. --*/
  336. {
  337. UCHAR Mask;
  338. ULONG i;
  339. //
  340. // Transfer the current enable masks to their corresponding GPE registers
  341. //
  342. Mask = Enable ? (UCHAR) -1 : 0;
  343. for (i = 0; i < AcpiInformation->GpeSize; i++) {
  344. ACPIWriteGpeEnableRegister( i, (UCHAR) (GpeCurEnable[i] & Mask) );
  345. }
  346. }
  347. VOID
  348. ACPIGpeHalEnableDisableEvents(
  349. BOOLEAN Enable
  350. )
  351. /*++
  352. Routine Description:
  353. Called from the HAL only.
  354. Enables or disables GP events
  355. Will snapshot the appropriate registers
  356. Arguments:
  357. Enable - TRUE if we want to enable GP events
  358. Return Value:
  359. None
  360. --*/
  361. {
  362. ULONG i;
  363. if (Enable) {
  364. //
  365. // We have presumably woken up, so remember the PM1 Status register
  366. // and the GPE Status Register
  367. //
  368. for (i = 0; i < AcpiInformation->GpeSize; i++) {
  369. GpeSavedWakeStatus[i] = ACPIReadGpeStatusRegister(i);
  370. }
  371. AcpiInformation->pm1_wake_status = READ_PM1_STATUS();
  372. } else {
  373. //
  374. // We are going to standby without enabling any events. Make
  375. // sure to clear all the masks
  376. //
  377. AcpiInformation->pm1_wake_mask = 0;
  378. RtlZeroMemory( GpeSavedWakeMask, AcpiInformation->GpeSize );
  379. }
  380. //
  381. // Make sure to still enable/disable the registers
  382. //
  383. ACPIGpeEnableDisableEvents( Enable );
  384. }
  385. VOID
  386. ACPIGpeEnableWakeEvents(
  387. VOID
  388. )
  389. /*++
  390. Routine Description:
  391. This routine is called with interrupts disabled for the purpose of enabling
  392. those vectors that are required for wake support just before putting the
  393. system to sleep
  394. N.B. interrutps are disabled
  395. Arguments:
  396. None
  397. Return Value:
  398. None
  399. --*/
  400. {
  401. ULONG i;
  402. for (i = 0; i < AcpiInformation->GpeSize; i++) {
  403. ACPIWriteGpeEnableRegister (i, GpeWakeEnable[i]);
  404. GpeSavedWakeMask[i] = GpeWakeEnable[i];
  405. }
  406. AcpiInformation->pm1_wake_mask = READ_PM1_ENABLE();
  407. }
  408. ULONG
  409. ACPIGpeIndexToByteIndex (
  410. ULONG Index
  411. )
  412. /*++
  413. Routine Description:
  414. Translate a GpeIndex (event number) to a logical byte index (0 to GPE1 end, no hole).
  415. Handles the case where the GPE1 block event numbers are not immediately after the
  416. GPE0 event numbers (as specified by the GP1_Base_Index).
  417. Arguments:
  418. Index - The Gpe index to be translated (0-255);
  419. Return Value:
  420. The logical byte index.
  421. --*/
  422. {
  423. if (Index < AcpiInformation->GP1_Base_Index) {
  424. //
  425. // GP0 case is very simple
  426. //
  427. return (Index);
  428. } else {
  429. //
  430. // GP1 case must take into account:
  431. // 1) The base index of the GPE1 block
  432. // 2) The number of (logical) GPE0 registers preceeding the GPE1 registers
  433. //
  434. return ((Index - AcpiInformation->GP1_Base_Index) +
  435. AcpiInformation->Gpe0Size);
  436. }
  437. }
  438. ULONG
  439. ACPIGpeIndexToGpeRegister (
  440. ULONG Index
  441. )
  442. /*++
  443. Routine Description:
  444. Translate a GpeIndex (event number) to the logical Gpe register which contains it.
  445. Handles the case where the GPE1 block event numbers are not immediately after the
  446. GPE0 event numbers (as specified by the GP1_Base_Index).
  447. Arguments:
  448. Index - The Gpe index to be translated (0-255);
  449. Return Value:
  450. The logical Gpe register which contains the index.
  451. --*/
  452. {
  453. if (Index < AcpiInformation->GP1_Base_Index) {
  454. //
  455. // GP0 case is very simple
  456. //
  457. return (Index / 8);
  458. } else {
  459. //
  460. // GP1 case must take into account:
  461. // 1) The base index of the GPE1 block
  462. // 2) The number of (logical) GPE0 registers preceeding the GPE1 registers
  463. //
  464. return (((Index - AcpiInformation->GP1_Base_Index) / 8) +
  465. AcpiInformation->Gpe0Size);
  466. }
  467. }
  468. BOOLEAN
  469. ACPIGpeInstallRemoveIndex (
  470. ULONG GpeIndex,
  471. ULONG Action, // Edge = 0, Level = 1, Remove = 2
  472. ULONG Type,
  473. PBOOLEAN HasControlMethod
  474. )
  475. /*++
  476. Routine Description:
  477. Installs or removes GPEs from the global tables.
  478. NOTE: Should be called with the global GpeVectorTable locked, and GPEs disabled
  479. Arguments:
  480. GPEIndex - The GPE number to install or remove
  481. Action - Action to be performed:
  482. 0 - Install this GPE as an edge-sensitive interrupt
  483. 1 - Install this GPE as a level-sensitive interrupt
  484. 2 - Remove this GPE
  485. Type - Type of handler for this GPE:
  486. 0 - OS handler
  487. 1 - Control Method
  488. Return Value:
  489. None
  490. --*/
  491. {
  492. ULONG bitOffset;
  493. ULONG i;
  494. ULONG bit;
  495. //
  496. // Validate the GPE index (GPE number)
  497. //
  498. if (AcpiInformation->GP0_LEN == 0) {
  499. PACPI_GPE_ERROR_CONTEXT errContext;
  500. errContext = ExAllocatePoolWithTag(
  501. NonPagedPool,
  502. sizeof(ACPI_GPE_ERROR_CONTEXT),
  503. ACPI_MISC_POOLTAG
  504. );
  505. if (errContext) {
  506. errContext->GpeIndex = GpeIndex;
  507. ExInitializeWorkItem(
  508. &(errContext->Item),
  509. ACPIGpeInstallRemoveIndexErrorWorker,
  510. (PVOID) errContext
  511. );
  512. ExQueueWorkItem( &(errContext->Item), DelayedWorkQueue );
  513. }
  514. return FALSE;
  515. }
  516. if (!(ACPIGpeValidIndex (GpeIndex))) {
  517. return FALSE;
  518. }
  519. bitOffset = GpeIndex % 8;
  520. bit = (1 << bitOffset);
  521. i = ACPIGpeIndexToGpeRegister (GpeIndex);
  522. ASSERT( (i < (ULONG) AcpiInformation->GpeSize) );
  523. if (i >= (ULONG) AcpiInformation->GpeSize) {
  524. return FALSE;
  525. }
  526. //
  527. // Handler removal
  528. //
  529. if (Action == ACPI_GPE_REMOVE) {
  530. //
  531. // Fall back to using control method if there is one.
  532. // Otherwise, disable the event.
  533. //
  534. if (*HasControlMethod) {
  535. GpeEnable [i] |= bit;
  536. GpeCurEnable [i] |= bit;
  537. GpeHandlerType [i] |= bit;
  538. } else {
  539. GpeEnable [i] &= ~bit;
  540. GpeCurEnable [i] &= ~bit;
  541. GpeHandlerType [i] &= ~bit;
  542. ASSERT (!(GpeWakeEnable[i] & bit));
  543. }
  544. ACPIPrint ( (
  545. ACPI_PRINT_DPC,
  546. "ACPIGpeInstallRemoveIndex: Removing GPE #%d: Byte 0x%x bit %u\n",
  547. GpeIndex, i, bitOffset
  548. ) );
  549. return TRUE;
  550. }
  551. //
  552. // Handler installation
  553. //
  554. if ( (GpeEnable [i] & bit) ) {
  555. if ( !(GpeHandlerType[i] & bit) ) {
  556. //
  557. // a handler is already installed
  558. //
  559. return FALSE;
  560. }
  561. //
  562. // there is a control method (to be restored if handler removed)
  563. //
  564. *HasControlMethod = TRUE;
  565. } else {
  566. *HasControlMethod = FALSE;
  567. }
  568. //
  569. // Install this event
  570. //
  571. GpeEnable[i] |= bit;
  572. GpeCurEnable[i] |= bit;
  573. if (Action == ACPI_GPE_LEVEL_INSTALL) {
  574. //
  575. // Level event
  576. //
  577. GpeIsLevel[i] |= bit;
  578. } else {
  579. //
  580. // Edge event
  581. //
  582. GpeIsLevel[i] &= ~bit;
  583. }
  584. if (Type == ACPI_GPE_CONTROL_METHOD) {
  585. GpeHandlerType [i] |= bit;
  586. } else {
  587. GpeHandlerType [i] &= ~bit;
  588. }
  589. ACPIPrint ( (
  590. ACPI_PRINT_DPC,
  591. "ACPIGpeInstallRemoveIndex: Setting GPE #%d: Byte 0x%x bit %u\n",
  592. GpeIndex, i, bitOffset
  593. ) );
  594. return TRUE;
  595. }
  596. VOID
  597. ACPIGpeInstallRemoveIndexErrorWorker(
  598. IN PVOID Context
  599. )
  600. {
  601. PACPI_GPE_ERROR_CONTEXT errContext = (PACPI_GPE_ERROR_CONTEXT) Context;
  602. PWCHAR prtEntry[2];
  603. UNICODE_STRING indexName;
  604. WCHAR GPEName[] = L"GPE";
  605. WCHAR index[20];
  606. RtlInitUnicodeString(&indexName, index);
  607. if (NT_SUCCESS(RtlIntegerToUnicodeString( errContext->GpeIndex,0,&indexName))) {
  608. prtEntry[0] = GPEName;
  609. prtEntry[1] = index;
  610. ACPIWriteEventLogEntry(
  611. ACPI_ERR_NO_GPE_BLOCK,
  612. prtEntry,
  613. 2,
  614. NULL,
  615. 0
  616. );
  617. }
  618. ExFreePool( errContext );
  619. }
  620. BOOLEAN
  621. ACPIGpeIsEvent(
  622. VOID
  623. )
  624. /*++
  625. Routine Description:
  626. Not Exported
  627. Detects where or not the a GP event caused an interrupt. This routine is
  628. called at DIRQL or ISR time
  629. Arguments:
  630. None
  631. Return Value:
  632. TRUE - Yes, it was our interrupt
  633. FALSE - No, it was not
  634. --*/
  635. {
  636. UCHAR sts;
  637. ULONG i;
  638. //
  639. // Check all GPE registers to see if any of the status bits are set.
  640. //
  641. for (i = 0; i < AcpiInformation->GpeSize; i++) {
  642. sts = ACPIReadGpeStatusRegister (i);
  643. if (sts & GpeCurEnable[i]) {
  644. return TRUE;
  645. }
  646. }
  647. //
  648. // No GPE bits were set
  649. //
  650. return (FALSE);
  651. }
  652. ULONG
  653. ACPIGpeRegisterToGpeIndex(
  654. ULONG Register,
  655. ULONG BitPosition
  656. )
  657. /*++
  658. Routine Description:
  659. Translate a logical Gpe register and bit position into the associated Gpe index (event
  660. number). Handles the case where the GPE1 block event numbers are not immediately after the
  661. GPE0 event numbers (as specified by the GP1_Base_Index).
  662. Arguments:
  663. Register - The logical Gpe register
  664. BitPosition - Position of the index within the register
  665. Return Value:
  666. The Gpe index associated with the register/bit-position.
  667. --*/
  668. {
  669. if (Register < AcpiInformation->Gpe0Size) {
  670. //
  671. // GP0 case is simple
  672. //
  673. return (Register * 8) +
  674. BitPosition;
  675. } else {
  676. //
  677. // GP1 case must adjust for:
  678. // 1) The number of (logical) GPE0 registers preceeding the GPE1 registers
  679. // 2) The base index of the GPE1 block.
  680. //
  681. return ((Register - AcpiInformation->Gpe0Size) * 8) +
  682. AcpiInformation->GP1_Base_Index +
  683. BitPosition;
  684. }
  685. }
  686. VOID
  687. ACPIGpeUpdateCurrentEnable(
  688. IN ULONG GpeRegister,
  689. IN UCHAR Completed
  690. )
  691. /*++
  692. Routine Description:
  693. This routine is called to re-arm the GpeCurEnable data structure
  694. based on the contents of the GPE's that we have just processed
  695. Arguments:
  696. GpeRegister - Which index into the register we handled
  697. Completed - Bitmask of the handled GPEs
  698. Return Value:
  699. None
  700. --*/
  701. {
  702. //
  703. // This vector is no longer pending
  704. //
  705. GpePending[GpeRegister] &= ~Completed;
  706. //
  707. // First, remove any events that aren't in the current list of
  708. // enables, either wake or run-time
  709. //
  710. Completed &= (GpeEnable[GpeRegister] | GpeWakeEnable[GpeRegister]);
  711. //
  712. // Next, remove any events for which there is a wake handler,
  713. // but is not in the list of wake enables
  714. //
  715. Completed &= ~(GpeWakeHandler[GpeRegister] & ~GpeWakeEnable[GpeRegister]);
  716. //
  717. // Okay, now the cmp value should be exactly the list of GPEs to
  718. // re-enable
  719. //
  720. GpeCurEnable[GpeRegister] |= Completed;
  721. }
  722. BOOLEAN
  723. ACPIGpeValidIndex (
  724. ULONG Index
  725. )
  726. /*++
  727. Routine Description:
  728. Verifies that a GPE index is valid on this machine.
  729. Note: There can be a hole (in the GPE index values) between the GPE0 and the GPE1 blocks.
  730. This hole is defined by the size of the GPE0 block (which always starts at zero), and
  731. GP1_Base_Index (whose value is obtained from the FACP table).
  732. Arguments:
  733. Index - The Gpe index to be verified (0-255);
  734. Return Value:
  735. TRUE if a valid index, FALSE otherwise.
  736. --*/
  737. {
  738. if (Index < AcpiInformation->GP1_Base_Index) {
  739. //
  740. // GP0 case: Gpe index must fall within the range 0 to the end of GPE0
  741. //
  742. if (Index < (ULONG) (AcpiInformation->Gpe0Size * 8)) {
  743. return TRUE;
  744. } else {
  745. return FALSE;
  746. }
  747. } else {
  748. //
  749. // GP1 case: Gpe index must fall within the range GP1_Base_Index to the end of GPE1
  750. //
  751. if (Index < (ULONG) (AcpiInformation->GP1_Base_Index + (AcpiInformation->Gpe1Size * 8))) {
  752. return TRUE;
  753. } else {
  754. return FALSE;
  755. }
  756. }
  757. }