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.

957 lines
24 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. acpiosnt.c
  5. Abstract:
  6. This module implements the OS specific functions for the Windows NT
  7. version of the ACPI driver
  8. Author:
  9. Jason Clark (jasoncl)
  10. Stephane Plante (splante)
  11. Environment:
  12. Kernel mode only.
  13. Revision History:
  14. 09-Oct-96 Initial Revision
  15. 20-Nov-96 Interrupt Vector support
  16. 31-Mar-97 Cleanup
  17. --*/
  18. #include "pch.h"
  19. #include "amlihook.h"
  20. // from shared\acpiinit.c
  21. extern PACPIInformation AcpiInformation;
  22. // from irqarb.c
  23. extern ULONG InterruptModel;
  24. NTSTATUS
  25. DriverEntry (
  26. IN PDRIVER_OBJECT DriverObject,
  27. IN PUNICODE_STRING RegistryPath
  28. );
  29. PPM_DISPATCH_TABLE PmHalDispatchTable;
  30. FAST_IO_DISPATCH ACPIFastIoDispatch;
  31. #ifdef ALLOC_PRAGMA
  32. #pragma alloc_text(INIT,DriverEntry)
  33. #pragma alloc_text(PAGE,OSInterruptVector)
  34. #pragma alloc_text(PAGE,NotifyHalWithMachineStates)
  35. #endif
  36. ACPI_HAL_DISPATCH_TABLE AcpiHalDispatchTable;
  37. NTSTATUS
  38. DriverEntry (
  39. PDRIVER_OBJECT DriverObject,
  40. IN PUNICODE_STRING RegistryPath
  41. )
  42. /*++
  43. Routine Description:
  44. The ACPI driver's entry point
  45. Arguments:
  46. DriverObject - Pointer to the object that represents this driver
  47. Return Value:
  48. N/A
  49. --*/
  50. {
  51. NTSTATUS status;
  52. ULONG i;
  53. ULONG argSize;
  54. //
  55. // If the AMLIHOOK interface is enabled
  56. // hook it.
  57. //
  58. AmliHook_InitTestHookInterface();
  59. //
  60. // Remember the name of the driver object
  61. //
  62. AcpiDriverObject = DriverObject;
  63. //
  64. // Save registry path for use by WMI registration code
  65. //
  66. AcpiRegistryPath.Length = 0;
  67. AcpiRegistryPath.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
  68. AcpiRegistryPath.Buffer = ExAllocatePoolWithTag(
  69. PagedPool,
  70. RegistryPath->Length+sizeof(WCHAR),
  71. ACPI_MISC_POOLTAG
  72. );
  73. if (AcpiRegistryPath.Buffer != NULL) {
  74. RtlCopyUnicodeString(&AcpiRegistryPath, RegistryPath);
  75. } else {
  76. AcpiRegistryPath.MaximumLength = 0;
  77. }
  78. //
  79. // Read the keys that we need to operate this driver from the
  80. // registry
  81. //
  82. ACPIInitReadRegistryKeys();
  83. //
  84. // This flag may be set, when its not required, nor desired
  85. // so take the opportunity to clean it up now
  86. //
  87. if (AcpiOverrideAttributes & ACPI_OVERRIDE_MP_SLEEP) {
  88. KAFFINITY processors = KeQueryActiveProcessors();
  89. //
  90. // If this is a UP system, then turn off this override
  91. //
  92. if (processors == 1) {
  93. AcpiOverrideAttributes &= ~ACPI_OVERRIDE_MP_SLEEP;
  94. }
  95. }
  96. //
  97. // Initialize the DPCs
  98. //
  99. KeInitializeDpc( &AcpiPowerDpc, ACPIDevicePowerDpc, NULL );
  100. KeInitializeDpc( &AcpiBuildDpc, ACPIBuildDeviceDpc, NULL );
  101. KeInitializeDpc( &AcpiGpeDpc, ACPIInterruptDispatchEventDpc, NULL );
  102. //
  103. // Initialize the timer
  104. //
  105. KeInitializeTimer( &AcpiGpeTimer );
  106. //
  107. // Initialize the SpinLocks
  108. //
  109. KeInitializeSpinLock( &AcpiDeviceTreeLock );
  110. KeInitializeSpinLock( &AcpiPowerLock );
  111. KeInitializeSpinLock( &AcpiPowerQueueLock );
  112. KeInitializeSpinLock( &AcpiBuildQueueLock );
  113. KeInitializeSpinLock( &AcpiThermalLock );
  114. KeInitializeSpinLock( &AcpiButtonLock );
  115. KeInitializeSpinLock( &AcpiFatalLock );
  116. KeInitializeSpinLock( &AcpiUpdateFlagsLock );
  117. KeInitializeSpinLock( &AcpiGetLock );
  118. //
  119. // Initialize the List Entry's
  120. //
  121. InitializeListHead( &AcpiPowerDelayedQueueList );
  122. InitializeListHead( &AcpiPowerQueueList );
  123. InitializeListHead( &AcpiPowerPhase0List );
  124. InitializeListHead( &AcpiPowerPhase1List );
  125. InitializeListHead( &AcpiPowerPhase2List );
  126. InitializeListHead( &AcpiPowerPhase3List );
  127. InitializeListHead( &AcpiPowerPhase4List );
  128. InitializeListHead( &AcpiPowerPhase5List );
  129. InitializeListHead( &AcpiPowerWaitWakeList );
  130. InitializeListHead( &AcpiPowerSynchronizeList );
  131. InitializeListHead( &AcpiPowerNodeList );
  132. InitializeListHead( &AcpiBuildQueueList );
  133. InitializeListHead( &AcpiBuildDeviceList );
  134. InitializeListHead( &AcpiBuildOperationRegionList );
  135. InitializeListHead( &AcpiBuildPowerResourceList );
  136. InitializeListHead( &AcpiBuildRunMethodList );
  137. InitializeListHead( &AcpiBuildSynchronizationList );
  138. InitializeListHead( &AcpiBuildThermalZoneList );
  139. InitializeListHead( &AcpiUnresolvedEjectList );
  140. InitializeListHead( &AcpiThermalList );
  141. InitializeListHead( &AcpiButtonList );
  142. InitializeListHead( &AcpiGetListEntry );
  143. //
  144. // Initialize the variables/booleans
  145. //
  146. AcpiPowerDpcRunning = FALSE;
  147. AcpiPowerWorkDone = FALSE;
  148. AcpiBuildDpcRunning = FALSE;
  149. AcpiBuildFixedButtonEnumerated = FALSE;
  150. AcpiBuildWorkDone = FALSE;
  151. AcpiFatalOutstanding = FALSE;
  152. AcpiGpeDpcRunning = FALSE;
  153. AcpiGpeDpcScheduled = FALSE;
  154. AcpiGpeWorkDone = FALSE;
  155. //
  156. // Initialize the LookAside lists.
  157. //
  158. ExInitializeNPagedLookasideList(
  159. &BuildRequestLookAsideList,
  160. NULL,
  161. NULL,
  162. 0,
  163. sizeof(ACPI_BUILD_REQUEST),
  164. ACPI_DEVICE_POOLTAG,
  165. (PAGE_SIZE / sizeof(ACPI_BUILD_REQUEST) )
  166. );
  167. ExInitializeNPagedLookasideList(
  168. &RequestLookAsideList,
  169. NULL,
  170. NULL,
  171. 0,
  172. sizeof(ACPI_POWER_REQUEST),
  173. ACPI_POWER_POOLTAG,
  174. (PAGE_SIZE * 4 / sizeof(ACPI_POWER_REQUEST) )
  175. );
  176. ExInitializeNPagedLookasideList(
  177. &DeviceExtensionLookAsideList,
  178. NULL,
  179. NULL,
  180. 0,
  181. sizeof(DEVICE_EXTENSION),
  182. ACPI_DEVICE_POOLTAG,
  183. 64
  184. );
  185. ExInitializeNPagedLookasideList(
  186. &ObjectDataLookAsideList,
  187. NULL,
  188. NULL,
  189. 0,
  190. sizeof(OBJDATA),
  191. ACPI_OBJECT_POOLTAG,
  192. (PAGE_SIZE / sizeof(OBJDATA) )
  193. );
  194. ExInitializeNPagedLookasideList(
  195. &PswContextLookAsideList,
  196. NULL,
  197. NULL,
  198. 0,
  199. sizeof(ACPI_WAKE_PSW_CONTEXT),
  200. ACPI_POWER_POOLTAG,
  201. 16
  202. );
  203. //
  204. // Initialize internal worker
  205. //
  206. ACPIInitializeWorker ();
  207. //
  208. // Make sure that we have an AddDevice function that will create
  209. // the basic FDO for this device when it is called
  210. //
  211. DriverObject->DriverExtension->AddDevice = ACPIDispatchAddDevice;
  212. //
  213. // All irps will be sent through a single dispatch point
  214. //
  215. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  216. DriverObject->MajorFunction[ i ] = ACPIDispatchIrp;
  217. }
  218. DriverObject->DriverUnload = ACPIUnload;
  219. //
  220. // Fill out the Fast Io Detach callback for our bus filter
  221. //
  222. RtlZeroMemory(&ACPIFastIoDispatch, sizeof(FAST_IO_DISPATCH)) ;
  223. ACPIFastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH) ;
  224. ACPIFastIoDispatch.FastIoDetachDevice = ACPIFilterFastIoDetachCallback ;
  225. DriverObject->FastIoDispatch = &ACPIFastIoDispatch ;
  226. //
  227. // Initialize some HAL stuff
  228. //
  229. AcpiHalDispatchTable.Signature = ACPI_HAL_DISPATCH_SIGNATURE;
  230. AcpiHalDispatchTable.Version = ACPI_HAL_DISPATCH_VERSION;
  231. AcpiHalDispatchTable.AcpipEnableDisableGPEvents =
  232. &ACPIGpeHalEnableDisableEvents;
  233. AcpiHalDispatchTable.AcpipInitEnableAcpi =
  234. &ACPIEnableInitializeACPI;
  235. AcpiHalDispatchTable.AcpipGpeEnableWakeEvents =
  236. &ACPIWakeEnableWakeEvents;
  237. HalInitPowerManagement(
  238. (PPM_DISPATCH_TABLE)(&AcpiHalDispatchTable),
  239. &PmHalDispatchTable
  240. );
  241. return STATUS_SUCCESS;
  242. }
  243. VOID
  244. OSInitializeCallbacks(
  245. VOID
  246. )
  247. /*++
  248. Routine Description:
  249. This routine is called right after the interper has been initialized,
  250. but before AML code has actually been executed.
  251. Arguments:
  252. None
  253. Return Value:
  254. None
  255. --*/
  256. {
  257. POPREGIONHANDLER dummy;
  258. #if DBG
  259. NTSTATUS status;
  260. status =
  261. #endif
  262. AMLIRegEventHandler(
  263. EVTYPE_OPCODE_EX,
  264. OP_LOAD,
  265. ACPICallBackLoad,
  266. 0
  267. );
  268. #if DBG
  269. if (!NT_SUCCESS(status)) {
  270. ACPIBreakPoint();
  271. }
  272. status =
  273. #endif
  274. AMLIRegEventHandler(
  275. EVTYPE_OPCODE_EX,
  276. OP_UNLOAD,
  277. ACPICallBackUnload,
  278. 0
  279. );
  280. #if DBG
  281. if (!NT_SUCCESS(status)) {
  282. ACPIBreakPoint();
  283. }
  284. status =
  285. #endif
  286. AMLIRegEventHandler(
  287. EVTYPE_DESTROYOBJ,
  288. 0,
  289. (PFNHND)ACPITableNotifyFreeObject,
  290. 0
  291. );
  292. #if DBG
  293. if (!NT_SUCCESS(status)) {
  294. ACPIBreakPoint();
  295. }
  296. status =
  297. #endif
  298. AMLIRegEventHandler(
  299. EVTYPE_NOTIFY,
  300. 0,
  301. NotifyHandler,
  302. 0
  303. );
  304. #if DBG
  305. if (!NT_SUCCESS(status)) {
  306. ACPIBreakPoint();
  307. }
  308. status =
  309. #endif
  310. AMLIRegEventHandler(
  311. EVTYPE_ACQREL_GLOBALLOCK,
  312. 0,
  313. GlobalLockEventHandler,
  314. 0
  315. );
  316. #if DBG
  317. if (!NT_SUCCESS(status)) {
  318. ACPIBreakPoint();
  319. }
  320. status =
  321. #endif
  322. AMLIRegEventHandler(
  323. EVTYPE_CREATE,
  324. 0,
  325. OSNotifyCreate,
  326. 0
  327. );
  328. #if DBG
  329. if (!NT_SUCCESS(status)) {
  330. ACPIBreakPoint();
  331. }
  332. status =
  333. #endif
  334. AMLIRegEventHandler(
  335. EVTYPE_FATAL,
  336. 0,
  337. OSNotifyFatalError,
  338. 0
  339. );
  340. #if DBG
  341. if (!NT_SUCCESS(status)) {
  342. ACPIBreakPoint();
  343. }
  344. #endif
  345. //
  346. // Register internal support of PCI operational regions. Note that
  347. // we don't specify a region object here because we haven't yet created it
  348. //
  349. RegisterOperationRegionHandler(
  350. NULL,
  351. EVTYPE_RS_COOKACCESS,
  352. REGSPACE_PCICFG, // PCI config space
  353. (PFNHND)PciConfigSpaceHandler,
  354. 0,
  355. &dummy);
  356. }
  357. BOOLEAN
  358. OSInterruptVector(
  359. PVOID Context
  360. )
  361. /*++
  362. Routine Description:
  363. This routine is charged with claiming an Interrupt for the device
  364. Arguments:
  365. Context - Context Pointer (points to FDO currently)
  366. Return
  367. TRUE for success
  368. --*/
  369. {
  370. NTSTATUS status;
  371. PDEVICE_EXTENSION deviceExtension;
  372. PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDesc;
  373. ULONG Count;
  374. PAGED_CODE();
  375. deviceExtension = ACPIInternalGetDeviceExtension( (PDEVICE_OBJECT) Context );
  376. //
  377. // Grab the translated interrupt vector from our resource list
  378. //
  379. Count = 0;
  380. InterruptDesc = RtlUnpackPartialDesc(
  381. CmResourceTypeInterrupt,
  382. deviceExtension->ResourceList,
  383. &Count
  384. );
  385. if (InterruptDesc == NULL) {
  386. ACPIDevPrint( (
  387. ACPI_PRINT_CRITICAL,
  388. deviceExtension,
  389. " - Could not find interrupt descriptor\n"
  390. ) );
  391. KeBugCheckEx(
  392. ACPI_BIOS_ERROR,
  393. ACPI_ROOT_RESOURCES_FAILURE,
  394. (ULONG_PTR) deviceExtension,
  395. (ULONG_PTR) deviceExtension->ResourceList,
  396. 1
  397. );
  398. }
  399. //
  400. // Initialize our DPC object
  401. //
  402. KeInitializeDpc(
  403. &(deviceExtension->Fdo.InterruptDpc),
  404. ACPIInterruptServiceRoutineDPC,
  405. deviceExtension
  406. );
  407. //
  408. // Now, lets connect ourselves to the interrupt
  409. //
  410. status = IoConnectInterrupt(
  411. &(deviceExtension->Fdo.InterruptObject),
  412. (PKSERVICE_ROUTINE) ACPIInterruptServiceRoutine,
  413. deviceExtension,
  414. NULL,
  415. InterruptDesc->u.Interrupt.Vector,
  416. (KIRQL)InterruptDesc->u.Interrupt.Level,
  417. (KIRQL)InterruptDesc->u.Interrupt.Level,
  418. LevelSensitive,
  419. CmResourceShareShared,
  420. InterruptDesc->u.Interrupt.Affinity,
  421. FALSE
  422. );
  423. if (!NT_SUCCESS(status)) {
  424. ACPIPrint( (
  425. ACPI_PRINT_CRITICAL,
  426. "OSInterruptVector: Could not connected to interrupt - %#08lx\n",
  427. status
  428. ) );
  429. return FALSE;
  430. }
  431. //
  432. // Tell the HAL directly that we are done with the interrupt init
  433. // stuff and it can start using the ACPI timer.
  434. //
  435. HalAcpiTimerInit(0,0);
  436. //
  437. // Done
  438. //
  439. return (TRUE);
  440. }
  441. VOID
  442. ACPIAssert (
  443. ULONG Condition,
  444. ULONG ErrorCode,
  445. PCHAR ReplacementText,
  446. PCHAR SupplementalText,
  447. ULONG Flags
  448. )
  449. /*++
  450. Routine Description:
  451. This is called to allow OS specific code to perform some additional OS
  452. specific processing for Asserts. After this function returns, the normal
  453. ASSERT macro will be called
  454. Arguments:
  455. Condition
  456. ErrorCode
  457. ReplacementText
  458. SupplementalText
  459. Flags
  460. Return Value:
  461. NONE
  462. --*/
  463. {
  464. if (!Condition) {
  465. ACPIPrint( (
  466. ACPI_PRINT_CRITICAL,
  467. "ACPIAssert: \n"
  468. " ErrorCode = %08lx Flags = %08lx\n"
  469. " ReplacmentText = %s\n"
  470. " SupplmentalText = %s\n",
  471. ErrorCode, Flags,
  472. ReplacementText,
  473. SupplementalText
  474. ) );
  475. ASSERT(Condition);
  476. }
  477. return;
  478. }
  479. PNSOBJ
  480. OSConvertDeviceHandleToPNSOBJ(
  481. PVOID DeviceHandle
  482. )
  483. /*++
  484. Routine Description:
  485. This function converts a DeviceHandle (which will always be a
  486. DeviceObject on NT) to a PNSObj handle.
  487. Arguments:
  488. DeviceHandle -- A DeviceObject whose PNSOBJ we want to determine.
  489. Return Value:
  490. The PNSOBJ for the given DeviceHandle or NULL if the conversion
  491. could not be done.
  492. --*/
  493. {
  494. PDEVICE_OBJECT deviceObject;
  495. PDEVICE_EXTENSION deviceExtension;
  496. deviceObject = (PDEVICE_OBJECT) DeviceHandle;
  497. ASSERT( deviceObject != NULL );
  498. if (deviceObject == NULL) {
  499. return (NULL);
  500. }
  501. deviceExtension = ACPIInternalGetDeviceExtension(deviceObject);
  502. ASSERT( deviceExtension != NULL );
  503. if (deviceExtension == NULL) {
  504. return (NULL);
  505. }
  506. return deviceExtension->AcpiObject;
  507. }
  508. NTSTATUS
  509. NotifyHalWithMachineStates(
  510. VOID
  511. )
  512. /*++
  513. Routine Description:
  514. This routine marshals the information about C states and
  515. S states that the HAL needs and then passes it down.
  516. Arguments:
  517. none
  518. Return Value:
  519. status
  520. --*/
  521. {
  522. BOOLEAN overrideMpSleep = FALSE;
  523. CHAR picMethod[] = "\\_PIC";
  524. NTSTATUS status;
  525. OBJDATA data;
  526. PHAL_SLEEP_VAL sleepVals = NULL;
  527. PNSOBJ pnsobj = NULL;
  528. PUCHAR SleepState[] = { "\\_S1", "\\_S2", "\\_S3",
  529. "\\_S4", "\\_S5" };
  530. SYSTEM_POWER_STATE systemState;
  531. UCHAR processor = 0;
  532. UCHAR state;
  533. ULONG flags = 0;
  534. ULONG pNum = 0;
  535. PSYSTEM_POWER_STATE_DISABLE_REASON pReasonOverride,pReasonBios,pReasonMP;
  536. SYSTEM_POWER_LOGGING_ENTRY PowerLoggingEntry;
  537. NTSTATUS LogStatus;
  538. PAGED_CODE();
  539. //
  540. // Notify the HAL with the location of the PBLKs
  541. //
  542. while(ProcessorList[pNum] && pNum < ACPI_SUPPORTED_PROCESSORS) {
  543. //
  544. // find the number of processors
  545. //
  546. pNum++;
  547. }
  548. ACPIPrint( (
  549. ACPI_PRINT_LOADING,
  550. "NotifyHalWithMachineStates: Number of processors is %d\n",
  551. pNum
  552. ) );
  553. sleepVals = ExAllocatePoolWithTag(
  554. NonPagedPool,
  555. sizeof(HAL_SLEEP_VAL) * 5,
  556. ACPI_MISC_POOLTAG
  557. );
  558. if (!sleepVals) {
  559. return STATUS_INSUFFICIENT_RESOURCES;
  560. }
  561. pReasonMP = NULL;
  562. pReasonOverride = ExAllocatePoolWithTag(
  563. PagedPool,
  564. sizeof(SYSTEM_POWER_STATE_DISABLE_REASON),
  565. ACPI_MISC_POOLTAG
  566. );
  567. if (!pReasonOverride) {
  568. ExFreePool(sleepVals);
  569. return STATUS_INSUFFICIENT_RESOURCES;
  570. }
  571. pReasonBios = ExAllocatePoolWithTag(
  572. PagedPool,
  573. sizeof(SYSTEM_POWER_STATE_DISABLE_REASON),
  574. ACPI_MISC_POOLTAG
  575. );
  576. if (!pReasonBios) {
  577. ExFreePool(pReasonOverride);
  578. ExFreePool(sleepVals);
  579. return STATUS_INSUFFICIENT_RESOURCES;
  580. }
  581. RtlZeroMemory(pReasonOverride,sizeof(SYSTEM_POWER_STATE_DISABLE_REASON));
  582. RtlZeroMemory(pReasonBios,sizeof(SYSTEM_POWER_STATE_DISABLE_REASON));
  583. pReasonOverride->PowerReasonCode = SPSD_REASON_NONE;
  584. pReasonBios->PowerReasonCode = SPSD_REASON_NONE;
  585. //
  586. // If there are more than 1 processors (ie: this is an MP machine)
  587. // and the OverrideMpSleep attribute is set, then we should remember that
  588. // so that we disallow all S-States other than S0, S4, and S5
  589. //
  590. if (AcpiOverrideAttributes & ACPI_OVERRIDE_MP_SLEEP) {
  591. overrideMpSleep = TRUE;
  592. pReasonMP = ExAllocatePoolWithTag(
  593. PagedPool,
  594. sizeof(SYSTEM_POWER_STATE_DISABLE_REASON),
  595. ACPI_MISC_POOLTAG
  596. );
  597. if (!pReasonMP) {
  598. ExFreePool(pReasonBios);
  599. ExFreePool(pReasonOverride);
  600. ExFreePool(sleepVals);
  601. return STATUS_INSUFFICIENT_RESOURCES;
  602. }
  603. RtlZeroMemory(pReasonMP,sizeof(SYSTEM_POWER_STATE_DISABLE_REASON));
  604. pReasonMP->PowerReasonCode = SPSD_REASON_NONE;
  605. }
  606. //
  607. // Remember that the only s-states that we support are S0, S4, and S5,
  608. // by default
  609. //
  610. AcpiSupportedSystemStates =
  611. (1 << PowerSystemWorking) +
  612. (1 << PowerSystemHibernate) +
  613. (1 << PowerSystemShutdown);
  614. //
  615. // Get the values that the HAL needs for sleeping the machine
  616. // for each sleep state that this machine supports.
  617. //
  618. for (systemState = PowerSystemSleeping1, state = 0;
  619. state < 5;
  620. systemState++, state++) {
  621. if ( ( (systemState == PowerSystemSleeping1) &&
  622. (AcpiOverrideAttributes & ACPI_OVERRIDE_DISABLE_S1) ) ||
  623. ( (systemState == PowerSystemSleeping2) &&
  624. (AcpiOverrideAttributes & ACPI_OVERRIDE_DISABLE_S2) ) ||
  625. ( (systemState == PowerSystemSleeping3) &&
  626. (AcpiOverrideAttributes & ACPI_OVERRIDE_DISABLE_S3) )) {
  627. ACPIPrint( (
  628. ACPI_PRINT_LOADING,
  629. "ACPI: SleepState %s disabled due to override\n",
  630. SleepState[state]
  631. ) );
  632. sleepVals[state].Supported = FALSE;
  633. //
  634. // the value of "state" variable is equivalent to the
  635. // POWER_STATE_HANDLER_TYPE enum, which is what we want for the
  636. // logging stuff, not systemState.
  637. //
  638. pReasonOverride->AffectedState[state] = TRUE;
  639. pReasonOverride->PowerReasonCode = SPSD_REASON_BIOSINCOMPATIBLE;
  640. continue;
  641. }
  642. status = AMLIGetNameSpaceObject(SleepState[state], NULL, &pnsobj, 0);
  643. if ( !NT_SUCCESS(status) ) {
  644. ACPIPrint( (
  645. ACPI_PRINT_LOADING,
  646. "ACPI: SleepState %s not supported\n",
  647. SleepState[state]
  648. ) );
  649. sleepVals[state].Supported = FALSE;
  650. //
  651. // the value of "state" variable is equivalent to the
  652. // POWER_STATE_HANDLER_TYPE enum, which is what we want for the
  653. // logging stuff, not systemState.
  654. //
  655. pReasonBios->AffectedState[state] = TRUE;
  656. pReasonBios->PowerReasonCode = SPSD_REASON_NOBIOSSUPPORT;
  657. continue;
  658. }
  659. if (overrideMpSleep && systemState < PowerSystemHibernate) {
  660. ACPIPrint( (
  661. ACPI_PRINT_WARNING,
  662. "ACPI: SleepState %s not supported due to override\n",
  663. SleepState[state]
  664. ) );
  665. sleepVals[state].Supported = FALSE;
  666. //
  667. // the value of "state" variable is equivalent to the
  668. // POWER_STATE_HANDLER_TYPE enum, which is what we want for the
  669. // logging stuff, not systemState.
  670. //
  671. pReasonMP->AffectedState[state] = TRUE;
  672. pReasonMP->PowerReasonCode = SPSD_REASON_MPOVERRIDE;
  673. continue;
  674. }
  675. //
  676. // Remember that we support this state
  677. //
  678. AcpiSupportedSystemStates |= (1 << systemState);
  679. sleepVals[state].Supported = TRUE;
  680. //
  681. // Retrieve the value that will be written into the SLP_TYPa
  682. // register.
  683. //
  684. AMLIEvalPackageElement (pnsobj, 0, &data);
  685. sleepVals[state].Pm1aVal = (UCHAR)data.uipDataValue;
  686. AMLIFreeDataBuffs(&data, 1);
  687. //
  688. // Retriece the value that will be written in to the SLp_TYPb
  689. // register
  690. //
  691. AMLIEvalPackageElement (pnsobj, 1, &data);
  692. sleepVals[state].Pm1bVal = (UCHAR)data.uipDataValue;
  693. AMLIFreeDataBuffs(&data, 1);
  694. }
  695. //
  696. // notify the power manager why we aren't supporting some
  697. // power states
  698. //
  699. PowerLoggingEntry.LoggingType = LOGGING_TYPE_SPSD;
  700. if (pReasonBios->PowerReasonCode != SPSD_REASON_NONE) {
  701. PowerLoggingEntry.LoggingEntry = pReasonBios;
  702. LogStatus = ZwPowerInformation(
  703. SystemPowerLoggingEntry,
  704. &PowerLoggingEntry,
  705. sizeof(PowerLoggingEntry),
  706. NULL,
  707. 0);
  708. if (LogStatus != STATUS_SUCCESS) {
  709. ExFreePool(pReasonBios);
  710. }
  711. } else {
  712. ExFreePool(pReasonBios);
  713. }
  714. if (pReasonOverride->PowerReasonCode != SPSD_REASON_NONE) {
  715. PowerLoggingEntry.LoggingEntry = pReasonOverride;
  716. LogStatus = ZwPowerInformation(
  717. SystemPowerLoggingEntry,
  718. &PowerLoggingEntry,
  719. sizeof(PowerLoggingEntry),
  720. NULL,
  721. 0);
  722. if (LogStatus != STATUS_SUCCESS) {
  723. ExFreePool(pReasonOverride);
  724. }
  725. } else {
  726. ExFreePool(pReasonOverride);
  727. }
  728. if (pReasonMP) {
  729. if (pReasonMP->PowerReasonCode != SPSD_REASON_NONE) {
  730. PowerLoggingEntry.LoggingEntry = pReasonMP;
  731. LogStatus = ZwPowerInformation(
  732. SystemPowerLoggingEntry,
  733. &PowerLoggingEntry,
  734. sizeof(PowerLoggingEntry),
  735. NULL,
  736. 0);
  737. if (LogStatus != STATUS_SUCCESS) {
  738. ExFreePool(pReasonMP);
  739. }
  740. } else {
  741. ExFreePool(pReasonMP);
  742. }
  743. }
  744. //
  745. // Notify the HAL
  746. //
  747. HalAcpiMachineStateInit(NULL, sleepVals, &InterruptModel);
  748. ExFreePool(sleepVals);
  749. //
  750. // Notify the namespace with the _PIC val.
  751. //
  752. if (InterruptModel > 0) {
  753. status = AMLIGetNameSpaceObject(picMethod,NULL,&pnsobj,0);
  754. if (!NT_SUCCESS(status)) {
  755. //
  756. // The OEM didn't supply a _PIC method. That's OK.
  757. // We'll assume that IRQ will somehow work without it.
  758. //
  759. return status;
  760. }
  761. RtlZeroMemory(&data, sizeof(data));
  762. data.dwDataType = OBJTYPE_INTDATA;
  763. data.uipDataValue = InterruptModel;
  764. status = AMLIEvalNameSpaceObject(pnsobj, NULL, 1, &data);
  765. if (!NT_SUCCESS(status)) {
  766. //
  767. // Failure to evaluate the _PIC method is not OK.
  768. //
  769. KeBugCheckEx(
  770. ACPI_BIOS_ERROR,
  771. ACPI_FAILED_PIC_METHOD,
  772. InterruptModel,
  773. status,
  774. (ULONG_PTR) pnsobj
  775. );
  776. }
  777. }
  778. //
  779. // Done
  780. //
  781. return status;
  782. }