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.

2167 lines
58 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. syspower.c
  5. Abstract:
  6. Contains all the code that deals with the system having to determine
  7. System Power State to Device Power State mappings
  8. Author:
  9. Stephane Plante (splante)
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. October 29th, 1998
  14. --*/
  15. #include "pch.h"
  16. //
  17. // Quick Lookup table to map S-States to SxD methods
  18. //
  19. ULONG AcpiSxDMethodTable[] = {
  20. PACKED_SWD,
  21. PACKED_S0D,
  22. PACKED_S1D,
  23. PACKED_S2D,
  24. PACKED_S3D,
  25. PACKED_S4D,
  26. PACKED_S5D
  27. };
  28. #ifdef ALLOC_PRAGMA
  29. #pragma alloc_text(PAGE,ACPISystemPowerGetSxD)
  30. #pragma alloc_text(PAGE,ACPISystemPowerProcessRootMapping)
  31. #pragma alloc_text(PAGE,ACPISystemPowerProcessSxD)
  32. #pragma alloc_text(PAGE,ACPISystemPowerQueryDeviceCapabilities)
  33. #pragma alloc_text(PAGE,ACPISystemPowerUpdateWakeCapabilities)
  34. #endif
  35. NTSTATUS
  36. ACPISystemPowerDetermineSupportedDeviceStates(
  37. IN PDEVICE_EXTENSION DeviceExtension,
  38. IN SYSTEM_POWER_STATE SystemState,
  39. OUT ULONG *SupportedDeviceStates
  40. )
  41. /*++
  42. Routine Description:
  43. This recursive routine looks at all the children of the current
  44. device extension and determines what device states might be supported
  45. at the specified system state. This is accomplished by looking at the
  46. _SxD methods and looking at the power plane information
  47. Arguments:
  48. DeviceExtension - The device whose children we want to know
  49. information about
  50. SystemState - The system state we want to know about
  51. SupportedDeviceStates - Set bits represent supported D-states
  52. Return Value:
  53. NTSTATUS
  54. --*/
  55. {
  56. DEVICE_POWER_STATE deviceState;
  57. EXTENSIONLIST_ENUMDATA eled;
  58. KIRQL oldIrql;
  59. NTSTATUS status = STATUS_SUCCESS;
  60. PDEVICE_EXTENSION childExtension;
  61. SYSTEM_POWER_STATE prSystemState;
  62. ASSERT(
  63. SystemState >= PowerSystemWorking &&
  64. SystemState <= PowerSystemShutdown
  65. );
  66. ASSERT( SupportedDeviceStates != NULL );
  67. //
  68. // Setup the data structure that we will use to walk the device extension
  69. // tree
  70. //
  71. ACPIExtListSetupEnum(
  72. &eled,
  73. &(DeviceExtension->ChildDeviceList),
  74. &AcpiDeviceTreeLock,
  75. SiblingDeviceList,
  76. WALKSCHEME_REFERENCE_ENTRIES
  77. );
  78. //
  79. // Look at all children of the current device extension
  80. //
  81. for (childExtension = ACPIExtListStartEnum( &eled );
  82. ACPIExtListTestElement( &eled, (BOOLEAN) NT_SUCCESS(status) );
  83. childExtension = ACPIExtListEnumNext( &eled) ) {
  84. //
  85. // Recurse first
  86. //
  87. status = ACPISystemPowerDetermineSupportedDeviceStates(
  88. childExtension,
  89. SystemState,
  90. SupportedDeviceStates
  91. );
  92. if (!NT_SUCCESS(status)) {
  93. continue;
  94. }
  95. //
  96. // Get the _SxD mapping for the device
  97. //
  98. status = ACPISystemPowerGetSxD(
  99. childExtension,
  100. SystemState,
  101. &deviceState
  102. );
  103. if (NT_SUCCESS( status ) ) {
  104. //
  105. // We support this D-state
  106. //
  107. *SupportedDeviceStates |= (1 << deviceState );
  108. ACPIDevPrint( (
  109. ACPI_PRINT_SXD,
  110. childExtension,
  111. " S%x->D%x\n",
  112. (SystemState - 1),
  113. (deviceState - 1)
  114. ) );
  115. //
  116. // Don't bother looking at the _PRx methods
  117. //
  118. continue;
  119. } else if (status != STATUS_OBJECT_NAME_NOT_FOUND) {
  120. //
  121. // If we hit another error, then we should continue now
  122. // Note that continuing will cause us to terminate the loop
  123. //
  124. ACPIDevPrint( (
  125. ACPI_PRINT_FAILURE,
  126. childExtension,
  127. " - ACPISystemPowerdetermineSupportedDeviceStates = %08lx\n",
  128. status
  129. ) );
  130. continue;
  131. } else {
  132. //
  133. // If we got here, then that means that the childExtension doesn't
  134. // have a _SxD method, which is okay. We reset the status so that
  135. // the loop test will succeed, or at least won't fail because there
  136. // wasn't an _SxD method.
  137. //
  138. status = STATUS_SUCCESS;
  139. }
  140. //
  141. // We are going to play with the power nodes, so we must be holding
  142. // the power lock
  143. //
  144. KeAcquireSpinLock( &AcpiPowerLock, &oldIrql );
  145. //
  146. // Look at all the device states that might be supported via
  147. // the _PR methods
  148. //
  149. for (deviceState = PowerDeviceD0;
  150. deviceState <= PowerDeviceD2;
  151. deviceState++) {
  152. prSystemState = ACPISystemPowerDetermineSupportedSystemState(
  153. childExtension,
  154. deviceState
  155. );
  156. if (prSystemState >= SystemState) {
  157. //
  158. // This d-state maps to a deeper S-state than what we
  159. // are looking for, so we should be implicitly supporting
  160. // this d-state for the current S-state
  161. //
  162. *SupportedDeviceStates |= (1 << deviceState);
  163. ACPIDevPrint( (
  164. ACPI_PRINT_SXD,
  165. childExtension,
  166. " PR%x maps to S%x, so S%x->D%x\n",
  167. (deviceState - 1),
  168. (prSystemState - 1),
  169. (SystemState - 1),
  170. (deviceState - 1)
  171. ) );
  172. }
  173. }
  174. //
  175. // Done with the lock
  176. //
  177. KeReleaseSpinLock( &AcpiPowerLock, oldIrql );
  178. }
  179. //
  180. // Done
  181. //
  182. return STATUS_SUCCESS;
  183. }
  184. DEVICE_POWER_STATE
  185. ACPISystemPowerDetermineSupportedDeviceWakeState(
  186. IN PDEVICE_EXTENSION DeviceExtension
  187. )
  188. /*++
  189. Routine Description:
  190. This routine looks at the PowerInformation structure and determines
  191. the D-State that is supported by the wake state
  192. As a rule of thumb, if the S-State is not supported, then we
  193. return PowerDeviceUnspecified
  194. Note: The parent is holding the AcpiPowerLock
  195. Arguments:
  196. DeviceExtension - The extension that we wish to check
  197. Return Value:
  198. DEVICE_POWER_STATE
  199. --*/
  200. {
  201. DEVICE_POWER_STATE deviceState = PowerDeviceMaximum;
  202. PACPI_DEVICE_POWER_NODE deviceNode;
  203. deviceNode = DeviceExtension->PowerInfo.PowerNode[PowerDeviceUnspecified];
  204. while (deviceNode != NULL) {
  205. //
  206. // Does the current device node support a lower device then the
  207. // current maximum device state?
  208. //
  209. if (deviceNode->AssociatedDeviceState < deviceState) {
  210. //
  211. // Yes, so this is the new maximum system state
  212. //
  213. deviceState = deviceNode->AssociatedDeviceState;
  214. }
  215. deviceNode = deviceNode->Next;
  216. }
  217. //
  218. // PowerSystemMaximum is not a valid entry. So if that is what we would
  219. // return, then change that to return PowerSystemUnspecified
  220. //
  221. if (deviceState == PowerDeviceMaximum) {
  222. deviceState = PowerDeviceUnspecified;
  223. }
  224. return deviceState;
  225. }
  226. SYSTEM_POWER_STATE
  227. ACPISystemPowerDetermineSupportedSystemState(
  228. IN PDEVICE_EXTENSION DeviceExtension,
  229. IN DEVICE_POWER_STATE DeviceState
  230. )
  231. /*++
  232. Routine Description:
  233. This routine looks at the PowerInformation structure and determines
  234. the S-State that is supported by the D-state
  235. As a rule of thumb, if the D-State is not supported, then we
  236. return PowerSystemUnspecified
  237. Note: The parent is holding the AcpiPowerLock
  238. Arguments:
  239. DeviceExtension - The extension that we wish to check
  240. DeviceState - The state that we wish to sanity check
  241. Return Value:
  242. SYSTEM_POWER_STATE
  243. --*/
  244. {
  245. PACPI_DEVICE_POWER_NODE deviceNode;
  246. SYSTEM_POWER_STATE systemState = PowerSystemMaximum;
  247. if (DeviceState == PowerDeviceD3) {
  248. goto ACPISystemPowerDetermineSupportedSystemStateExit;
  249. }
  250. deviceNode = DeviceExtension->PowerInfo.PowerNode[DeviceState];
  251. while (deviceNode != NULL) {
  252. //
  253. // Does the current device node support a lower system then the
  254. // current maximum system state?
  255. //
  256. if (deviceNode->SystemState < systemState) {
  257. //
  258. // Yes, so this is the new maximum system state
  259. //
  260. systemState = deviceNode->SystemState;
  261. }
  262. deviceNode = deviceNode->Next;
  263. }
  264. ACPISystemPowerDetermineSupportedSystemStateExit:
  265. //
  266. // PowerSystemMaximum is not a valid entry. So if that is what we would
  267. // return, then change that to return PowerSystemUnspecified
  268. //
  269. if (systemState == PowerSystemMaximum) {
  270. systemState = PowerSystemUnspecified;
  271. }
  272. return systemState;
  273. }
  274. NTSTATUS
  275. ACPISystemPowerGetSxD(
  276. IN PDEVICE_EXTENSION DeviceExtension,
  277. IN SYSTEM_POWER_STATE SystemState,
  278. OUT DEVICE_POWER_STATE *DeviceState
  279. )
  280. /*++
  281. Routine Description:
  282. This is the worker function that is called when we want to run an
  283. SxD method. We give the function an S-State, and we get back a
  284. D-State.
  285. Arguments:
  286. DeviceExtension - The device to run the SxD on
  287. SystemState - The S-state to determine the D-State for
  288. DeviceState - Where we store the answer
  289. Return Value:
  290. NTSTATUS
  291. --*/
  292. {
  293. NTSTATUS status;
  294. ULONG value;
  295. PAGED_CODE();
  296. //
  297. // Assume that we don't find an answer
  298. //
  299. *DeviceState = PowerDeviceUnspecified;
  300. //
  301. // We want this code to run even though there is no namespace object
  302. // for the device. Since we don't want to add a check to GetNamedChild
  303. // that checks for null, we need to handle this special case here
  304. //
  305. if ( (DeviceExtension->Flags & DEV_PROP_NO_OBJECT) ||
  306. (DeviceExtension->Flags & DEV_PROP_FAILED_INIT) ) {
  307. return STATUS_OBJECT_NAME_NOT_FOUND;
  308. }
  309. //
  310. // Evaluate the control method
  311. //
  312. status = ACPIGetIntegerSync(
  313. DeviceExtension,
  314. AcpiSxDMethodTable[SystemState],
  315. &value,
  316. NULL
  317. );
  318. if (NT_SUCCESS(status)) {
  319. //
  320. // Convert this number to a D-State
  321. //
  322. *DeviceState = ACPIDeviceMapPowerState( value );
  323. } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  324. //
  325. // HACKHACK --- Program Management wants us to force the PCI Root Bus
  326. // mappings for S1 to be D1. So look for a device node that has
  327. // both the PCI flag and the HID flag set, and if so, return that
  328. // we support D1
  329. //
  330. if (SystemState == PowerSystemSleeping1 &&
  331. (DeviceExtension->Flags & DEV_MASK_HID) &&
  332. (DeviceExtension->Flags & DEV_CAP_PCI) ) {
  333. *DeviceState = PowerDeviceD1;
  334. status = STATUS_SUCCESS;
  335. }
  336. #if DBG
  337. } else {
  338. ACPIDevPrint( (
  339. ACPI_PRINT_CRITICAL,
  340. DeviceExtension,
  341. "ACPISystemPowerGetSxD: Cannot run _S%cD - 0x%08lx\n",
  342. (SystemState == 0 ? 'w' : '0' + (UCHAR) (SystemState - 1) ),
  343. status
  344. ) );
  345. #endif
  346. }
  347. //
  348. // Done
  349. //
  350. return status;
  351. }
  352. NTSTATUS
  353. ACPISystemPowerInitializeRootMapping(
  354. IN PDEVICE_EXTENSION DeviceExtension,
  355. IN PDEVICE_CAPABILITIES DeviceCapabilities
  356. )
  357. /*++
  358. Routine Description:
  359. This routine is responsible for initializing the S->D mapping for the
  360. root device extension
  361. Arguments:
  362. DeviceExtension - Pointer to the root device extension
  363. DeviceCapabilitites - DeviceCapabilitites
  364. Return Value:
  365. NTSTATUS
  366. --*/
  367. {
  368. BOOLEAN sxdFound;
  369. DEVICE_POWER_STATE deviceMap[PowerSystemMaximum];
  370. KIRQL oldIrql;
  371. NTSTATUS status;
  372. SYSTEM_POWER_STATE sysIndex;
  373. //
  374. // Can we actually do any real work here?
  375. //
  376. if ( (DeviceExtension->Flags & DEV_PROP_BUILT_POWER_TABLE) ||
  377. (DeviceExtension->DeviceState != Started) ) {
  378. goto ACPISystemPowerInitializeRootMappingExit;
  379. }
  380. //
  381. // Initialize the root mapping
  382. //
  383. RtlZeroMemory( deviceMap, sizeof(DEVICE_POWER_STATE) * PowerSystemMaximum );
  384. //
  385. // Copy the mapping from the device extension. See the comment at the
  386. // end as to why we don't grab a spinlock
  387. //
  388. IoCopyDeviceCapabilitiesMapping(
  389. DeviceExtension->PowerInfo.DevicePowerMatrix,
  390. deviceMap
  391. );
  392. //
  393. // Make sure that S0->D0
  394. //
  395. deviceMap[PowerSystemWorking] = PowerDeviceD0;
  396. //
  397. // Special case the fact that someone one might want to have the
  398. // HAL return a different template. If the capabilities that we got
  399. // handed have some values in them, have them override our defaults
  400. //
  401. for (sysIndex = PowerSystemSleeping1;
  402. sysIndex <= PowerSystemShutdown;
  403. sysIndex++) {
  404. if (DeviceCapabilities->DeviceState[sysIndex] != PowerDeviceUnspecified) {
  405. deviceMap[sysIndex] = DeviceCapabilities->DeviceState[sysIndex];
  406. }
  407. }
  408. //
  409. // Porcess the SxD methods if there are any
  410. //
  411. status = ACPISystemPowerProcessSxD(
  412. DeviceExtension,
  413. deviceMap,
  414. &sxdFound
  415. );
  416. if (!NT_SUCCESS(status)) {
  417. ACPIDevPrint( (
  418. ACPI_PRINT_CRITICAL,
  419. DeviceExtension,
  420. "- ACPISystemPowerProcessSxD = %08lx\n",
  421. status
  422. ) );
  423. return status;
  424. }
  425. //
  426. // Make sure that the Shutdown case doesn't map to PowerDeviceUnspecified
  427. // If it does, then it should really map to PowerDeviceD3
  428. //
  429. if (deviceMap[PowerSystemShutdown] == PowerDeviceUnspecified) {
  430. deviceMap[PowerSystemShutdown] = PowerDeviceD3;
  431. }
  432. //
  433. // Look at all the children capabilities to help us decide the root
  434. // mapping
  435. //
  436. status = ACPISystemPowerProcessRootMapping(
  437. DeviceExtension,
  438. deviceMap
  439. );
  440. if (!NT_SUCCESS(status)) {
  441. ACPIDevPrint( (
  442. ACPI_PRINT_CRITICAL,
  443. DeviceExtension,
  444. " - ACPISystemPowerProcessRootMapping = %08lx\n",
  445. status
  446. ) );
  447. goto ACPISystemPowerInitializeRootMappingExit;
  448. }
  449. //
  450. // If we have reached this point, then we have build the SxD table
  451. // and never need to do so again
  452. //
  453. ACPIInternalUpdateFlags(
  454. &(DeviceExtension->Flags),
  455. DEV_PROP_BUILT_POWER_TABLE,
  456. FALSE
  457. );
  458. #if DBG
  459. //
  460. // We haven't updated the device extension yet, so we can still do this
  461. // at this point in the game
  462. //
  463. ACPIDebugDeviceCapabilities(
  464. DeviceExtension,
  465. DeviceCapabilities,
  466. "Initial"
  467. );
  468. ACPIDebugPowerCapabilities( DeviceExtension, "Before Update" );
  469. #endif
  470. //
  471. // Copy the mapping to the device extension
  472. //
  473. KeAcquireSpinLock( &AcpiPowerLock, &oldIrql );
  474. IoCopyDeviceCapabilitiesMapping(
  475. deviceMap,
  476. DeviceExtension->PowerInfo.DevicePowerMatrix
  477. );
  478. KeReleaseSpinLock( &AcpiPowerLock, oldIrql );
  479. #if DBG
  480. ACPIDebugPowerCapabilities( DeviceExtension, "After Update" );
  481. #endif
  482. ACPISystemPowerInitializeRootMappingExit:
  483. //
  484. // Hmm.. I'm tempted to grab a spinlock here, but since we cannot
  485. // updating the capabilities for this device, I think it is safe
  486. // to not do so. We need to grab the spinlock when setting these
  487. // values so that we can sync with the power code
  488. //
  489. //
  490. // Copy the power capabilities to their final location
  491. //
  492. IoCopyDeviceCapabilitiesMapping(
  493. DeviceExtension->PowerInfo.DevicePowerMatrix,
  494. DeviceCapabilities->DeviceState
  495. );
  496. #if DBG
  497. ACPIDebugDeviceCapabilities(DeviceExtension, DeviceCapabilities, "Done" );
  498. #endif
  499. //
  500. // Done
  501. //
  502. return STATUS_SUCCESS;
  503. }
  504. NTSTATUS
  505. ACPISystemPowerProcessRootMapping(
  506. IN PDEVICE_EXTENSION DeviceExtension,
  507. IN DEVICE_POWER_STATE DeviceMap[PowerSystemMaximum]
  508. )
  509. /*++
  510. Routine Description:
  511. This routine is called by the FDO to figure out what the minimal set
  512. of capabilities for each s state are. These then become the root
  513. capabilitites
  514. Arguments:
  515. DeviceExtension - The root device extension
  516. DeviceMap - The current mapping
  517. Return Value:
  518. NTSTATUS
  519. --*/
  520. {
  521. DEVICE_POWER_STATE deviceState;
  522. KIRQL oldIrql;
  523. NTSTATUS status;
  524. SYSTEM_POWER_STATE systemState;
  525. ULONG supportedDeviceStates;
  526. PAGED_CODE();
  527. //
  528. // Loop on all the system supported states
  529. //
  530. for (systemState = PowerSystemSleeping1;
  531. systemState <= PowerSystemShutdown;
  532. systemState++) {
  533. //
  534. // Do we support this state?
  535. //
  536. if (!(AcpiSupportedSystemStates & (1 << systemState) ) ) {
  537. continue;
  538. }
  539. //
  540. // We always support the D3 state
  541. //
  542. supportedDeviceStates = (1 << PowerDeviceD3);
  543. //
  544. // Determine the supported Device states for this System state
  545. //
  546. status = ACPISystemPowerDetermineSupportedDeviceStates(
  547. DeviceExtension,
  548. systemState,
  549. &supportedDeviceStates
  550. );
  551. if (!NT_SUCCESS(status)) {
  552. ACPIDevPrint( (
  553. ACPI_PRINT_WARNING,
  554. DeviceExtension,
  555. "Cannot determine D state for S%x - %08lx\n",
  556. (systemState - 1),
  557. status
  558. ) );
  559. DeviceMap[systemState] = PowerDeviceD3;
  560. continue;
  561. }
  562. //
  563. // Starting from the device states that we currently are set to
  564. // (which we would have gotten by running the _SxD method on the
  565. // \_SB), look to see if we can use a lower D-state instead.
  566. //
  567. // Note: It is *VERY* important to remember that *ALL* devices can
  568. // support D3, so the following loop will *always* terminate in the
  569. // D3 case.
  570. //
  571. for (deviceState = DeviceMap[systemState];
  572. deviceState <= PowerDeviceD3;
  573. deviceState++) {
  574. //
  575. // Is this a supported device state?
  576. //
  577. if (!(supportedDeviceStates & (1 << deviceState) ) ) {
  578. //
  579. // no? then look at the next one
  580. //
  581. continue;
  582. }
  583. //
  584. // This is the D-state that we need to use
  585. //
  586. DeviceMap[systemState] = deviceState;
  587. break;
  588. }
  589. }
  590. //
  591. // Always return success
  592. //
  593. return STATUS_SUCCESS;
  594. }
  595. NTSTATUS
  596. ACPISystemPowerProcessSxD(
  597. IN PDEVICE_EXTENSION DeviceExtension,
  598. IN DEVICE_POWER_STATE CurrentMapping[PowerSystemMaximum],
  599. IN PBOOLEAN MatchFound
  600. )
  601. /*++
  602. Routine Description:
  603. This routine updates the current S-to-D mapping with the information
  604. in the ACPI namespace. If it finds any _SxD routines, then it tells the
  605. caller
  606. Arguments:
  607. DeviceExtension - Device to check
  608. CurrentMapping - The current mapping to modify
  609. MatchFound - Where to indicate if we have found a match or not
  610. Return Value:
  611. NTSTATUS
  612. --*/
  613. {
  614. DEVICE_POWER_STATE dState;
  615. NTSTATUS status;
  616. SYSTEM_POWER_STATE sState;
  617. PAGED_CODE();
  618. ASSERT( MatchFound != NULL );
  619. //
  620. // Assume no match
  621. //
  622. *MatchFound = FALSE;
  623. //
  624. // Loop for all the S-States that we care about
  625. //
  626. for (sState = PowerSystemWorking; sState < PowerSystemMaximum; sState++) {
  627. //
  628. // Does the system support this S-State?
  629. //
  630. if (!(AcpiSupportedSystemStates & (1 << sState)) ) {
  631. //
  632. // This S-state is not supported by the system. Mark it as such
  633. //
  634. CurrentMapping[sState] = PowerDeviceUnspecified;
  635. continue;
  636. }
  637. //
  638. // Evaluate the control method
  639. //
  640. status = ACPISystemPowerGetSxD( DeviceExtension, sState, &dState );
  641. if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  642. //
  643. // Not a critical error
  644. //
  645. continue;
  646. }
  647. if (!NT_SUCCESS(status)) {
  648. ACPIDevPrint( (
  649. ACPI_PRINT_CRITICAL,
  650. DeviceExtension,
  651. "ACPISystemPowerProcessSxD: Cannot Evaluate _SxD - 0x%08lx\n",
  652. status
  653. ) );
  654. continue;
  655. }
  656. //
  657. // Match found
  658. //
  659. *MatchFound = TRUE;
  660. //
  661. // Is this value greater then the number within the table?
  662. //
  663. if (dState > CurrentMapping[sState]) {
  664. //
  665. // Yes, so we have a new mapping
  666. //
  667. CurrentMapping[sState] = dState;
  668. }
  669. }
  670. //
  671. // Done
  672. //
  673. return STATUS_SUCCESS;
  674. }
  675. NTSTATUS
  676. ACPISystemPowerQueryDeviceCapabilities(
  677. IN PDEVICE_EXTENSION DeviceExtension,
  678. IN PDEVICE_CAPABILITIES DeviceCapabilities
  679. )
  680. /*++
  681. Routine Description:
  682. Any routine that needs to know the device capabilities will call this
  683. function for the power capabilities
  684. Arguments:
  685. DeviceExtension - The extension whose capabilities we want
  686. DeviceCapabilities - Where to store the capabilities
  687. Return Value:
  688. NTSTATUS
  689. --*/
  690. {
  691. #if DBG
  692. BOOLEAN dumpAtEnd = FALSE;
  693. #endif
  694. DEVICE_CAPABILITIES parentCapabilities;
  695. NTSTATUS status;
  696. PDEVICE_CAPABILITIES baseCapabilities;
  697. PAGED_CODE();
  698. //
  699. // We only need to do this once
  700. //
  701. if (!(DeviceExtension->Flags & DEV_PROP_BUILT_POWER_TABLE) ) {
  702. #if DBG
  703. ACPIDebugDeviceCapabilities(
  704. DeviceExtension,
  705. DeviceCapabilities,
  706. "From PDO"
  707. );
  708. #endif
  709. //
  710. // Our next action depends on wether or not we are a filter (only)
  711. // or a PDO
  712. //
  713. if ( (DeviceExtension->Flags & DEV_TYPE_FILTER) &&
  714. !(DeviceExtension->Flags & DEV_TYPE_PDO) ) {
  715. //
  716. // In this case, our base capabilities are the ones that have
  717. // already been passed to us
  718. //
  719. baseCapabilities = DeviceCapabilities;
  720. } else {
  721. //
  722. // We must get the capabilities of the parent device
  723. //
  724. status = ACPIInternalGetDeviceCapabilities(
  725. DeviceExtension->ParentExtension->DeviceObject,
  726. &parentCapabilities
  727. );
  728. if (!NT_SUCCESS(status)) {
  729. ACPIDevPrint( (
  730. ACPI_PRINT_CRITICAL,
  731. DeviceExtension,
  732. " - Could not get parent caps - %08lx\n",
  733. status
  734. ) );
  735. return status;
  736. }
  737. //
  738. // our base capabilities are the one that we just fetched
  739. //
  740. baseCapabilities = &parentCapabilities;
  741. #if DBG
  742. ACPIDebugDeviceCapabilities(
  743. DeviceExtension,
  744. baseCapabilities,
  745. "From Parent"
  746. );
  747. #endif
  748. }
  749. #if DBG
  750. ACPIDebugPowerCapabilities( DeviceExtension, "Before Update" );
  751. #endif
  752. //
  753. // Update our capabilities with those of our parent
  754. //
  755. status = ACPISystemPowerUpdateDeviceCapabilities(
  756. DeviceExtension,
  757. baseCapabilities,
  758. DeviceCapabilities
  759. );
  760. if (!NT_SUCCESS(status)) {
  761. ACPIDevPrint( (
  762. ACPI_PRINT_CRITICAL,
  763. DeviceExtension,
  764. " - Could not update caps - %08lx\n",
  765. status
  766. ) );
  767. //
  768. // If this is a pdo, then this is a fatal error
  769. //
  770. if ( (DeviceExtension->Flags & DEV_TYPE_PDO) ) {
  771. ACPIInternalError( ACPI_SYSPOWER );
  772. }
  773. return status;
  774. }
  775. #if DBG
  776. ACPIDebugPowerCapabilities( DeviceExtension, "After Update" );
  777. dumpAtEnd = TRUE;
  778. #endif
  779. //
  780. // Never do this again
  781. //
  782. ACPIInternalUpdateFlags(
  783. &(DeviceExtension->Flags),
  784. DEV_PROP_BUILT_POWER_TABLE,
  785. FALSE
  786. );
  787. }
  788. //
  789. // Hmm.. I'm tempted to grab a spinlock here, but since we cannot
  790. // updating the capabilities for this device, I think it is safe
  791. // to not do so. We need to grab the spinlock when setting these
  792. // values so that we can sync with the power code
  793. //
  794. //
  795. // Okay, at this point, we think the device extension's capabilities
  796. // are appropriate for the stack at hand. Let's copy them over
  797. //
  798. IoCopyDeviceCapabilitiesMapping(
  799. DeviceExtension->PowerInfo.DevicePowerMatrix,
  800. DeviceCapabilities->DeviceState
  801. );
  802. //
  803. // then set those capabilities as well.
  804. //
  805. DeviceCapabilities->SystemWake = DeviceExtension->PowerInfo.SystemWakeLevel;
  806. DeviceCapabilities->DeviceWake = DeviceExtension->PowerInfo.DeviceWakeLevel;
  807. //
  808. // Set the other capabilities
  809. //
  810. DeviceCapabilities->DeviceD1 = DeviceExtension->PowerInfo.SupportDeviceD1;
  811. DeviceCapabilities->DeviceD2 = DeviceExtension->PowerInfo.SupportDeviceD2;
  812. DeviceCapabilities->WakeFromD0 = DeviceExtension->PowerInfo.SupportWakeFromD0;
  813. DeviceCapabilities->WakeFromD1 = DeviceExtension->PowerInfo.SupportWakeFromD1;
  814. DeviceCapabilities->WakeFromD2 = DeviceExtension->PowerInfo.SupportWakeFromD2;
  815. DeviceCapabilities->WakeFromD3 = DeviceExtension->PowerInfo.SupportWakeFromD3;
  816. #if DBG
  817. if (dumpAtEnd) {
  818. ACPIDebugDeviceCapabilities(
  819. DeviceExtension,
  820. DeviceCapabilities,
  821. "Done"
  822. );
  823. }
  824. #endif
  825. //
  826. // Done
  827. //
  828. return STATUS_SUCCESS;
  829. }
  830. NTSTATUS
  831. ACPISystemPowerUpdateDeviceCapabilities(
  832. IN PDEVICE_EXTENSION DeviceExtension,
  833. IN PDEVICE_CAPABILITIES BaseCapabilities,
  834. IN PDEVICE_CAPABILITIES DeviceCapabilities
  835. )
  836. /*++
  837. Routine Description:
  838. This routine updates the DevicePowerMatrix of the device extension with
  839. the current S to D mapping for the device.
  840. The BaseCapabilities are used as the template. That is, they provide
  841. values that we then modify.
  842. The DeviceCapabilities are the actual capabilities that are returned
  843. to the OS. Note that it is possible for the BaseCapabilities to the be
  844. same pointer as the DeviceCapabilities (if its a Filter).
  845. Arguments:
  846. DeviceExtension - The device whose capabilities we want
  847. BaseCapabilities - The base values
  848. DeviceCapabilities - The device capabilities
  849. Return Value:
  850. NTSTATUS
  851. --*/
  852. {
  853. BOOLEAN matchFound;
  854. DEVICE_POWER_STATE currentDState;
  855. DEVICE_POWER_STATE currentMapping[PowerSystemMaximum];
  856. DEVICE_POWER_STATE devIndex;
  857. DEVICE_POWER_STATE deviceWakeLevel = PowerDeviceUnspecified;
  858. DEVICE_POWER_STATE filterWakeLevel = PowerDeviceUnspecified;
  859. KIRQL oldIrql;
  860. NTSTATUS status = STATUS_SUCCESS;
  861. SYSTEM_POWER_STATE sysIndex;
  862. SYSTEM_POWER_STATE supportedState;
  863. SYSTEM_POWER_STATE systemWakeLevel = PowerSystemUnspecified;
  864. ULONG interestingBits;
  865. ULONG mask;
  866. ULONG supported = 0;
  867. ULONG supportedPr = 0;
  868. ULONG supportedPs = 0;
  869. ULONG supportedWake = 0;
  870. //
  871. // We should remember what the capabilities of the device. We need
  872. // to remember because we will be modifying these capabilities in
  873. // the next call (if required)
  874. //
  875. IoCopyDeviceCapabilitiesMapping(
  876. BaseCapabilities->DeviceState,
  877. currentMapping
  878. );
  879. //
  880. // Sanity checks
  881. //
  882. if (currentMapping[PowerSystemWorking] != PowerDeviceD0) {
  883. #if DBG
  884. ACPIDebugDeviceCapabilities(
  885. DeviceExtension,
  886. BaseCapabilities,
  887. "PowerSystemWorking != PowerDeviceD0"
  888. );
  889. #endif
  890. // ASSERT( currentMapping[PowerSystemWorking] == PowerDeviceD0 );
  891. currentMapping[PowerSystemWorking] = PowerDeviceD0;
  892. }
  893. //
  894. // Get the D-States that are supported by this extension
  895. //
  896. status = ACPIDevicePowerDetermineSupportedDeviceStates(
  897. DeviceExtension,
  898. &supportedPr,
  899. &supportedPs
  900. );
  901. if (!NT_SUCCESS(status)) {
  902. //
  903. // Hmm...
  904. //
  905. ACPIDevPrint( (
  906. ACPI_PRINT_CRITICAL,
  907. DeviceExtension,
  908. "ACPIDevicePowerDetermineSupportedDeviceStates = 0x%08lx\n",
  909. status
  910. ) );
  911. return status;
  912. }
  913. //
  914. // The supported index is the union of which _PR and which _PS are
  915. // present
  916. supported = (supportedPr | supportedPs);
  917. //
  918. // At this point, if there are no supported bits, then we should check
  919. // the device capabilities and what our parent supports
  920. //
  921. if (!supported) {
  922. //
  923. // Do some special checkin if we are a filter. We can only do the
  924. // following if the caps indicate that there is a D0 or D3 support
  925. //
  926. if ( (DeviceExtension->Flags & DEV_TYPE_FILTER) &&
  927. !(DeviceExtension->Flags & DEV_TYPE_PDO) &&
  928. !(DeviceCapabilities->DeviceD1) &&
  929. !(DeviceCapabilities->DeviceD2) ) {
  930. //
  931. // This is a filter, and we don't know any of its power caps, so
  932. // the thing to do (because of Video) is to decide to not touch
  933. // the mapping
  934. //
  935. goto ACPISystemPowerUpdateDeviceCapabilitiesExit;
  936. }
  937. //
  938. // Assume that we support D0 and D3
  939. //
  940. supported = (1 << PowerDeviceD0) | (1 << PowerDeviceD3);
  941. //
  942. // Do we support D1?
  943. //
  944. if (DeviceCapabilities->DeviceD1) {
  945. supported |= (1 << PowerDeviceD1);
  946. }
  947. //
  948. // Do we support D2?
  949. //
  950. if (DeviceCapabilities->DeviceD2) {
  951. supported |= (1 << PowerDeviceD2);
  952. }
  953. }
  954. //
  955. // We also need to update the Wake Capabilities. We do this so
  956. // that we get the correct SystemWakeLevel based on the information
  957. // present
  958. //
  959. status = ACPISystemPowerUpdateWakeCapabilities(
  960. DeviceExtension,
  961. BaseCapabilities,
  962. DeviceCapabilities,
  963. currentMapping,
  964. &supportedWake,
  965. &systemWakeLevel,
  966. &deviceWakeLevel,
  967. &filterWakeLevel
  968. );
  969. if (!NT_SUCCESS(status)) {
  970. ACPIDevPrint( (
  971. ACPI_PRINT_CRITICAL,
  972. DeviceExtension,
  973. "ACPISystemPowerUpdateWakeCapabilities = 0x%08lx\n",
  974. status
  975. ) );
  976. return status;
  977. }
  978. //
  979. // Now, we must look at the base capabilities and determine
  980. // if we need to modify them
  981. //
  982. for (sysIndex = PowerSystemSleeping1; sysIndex <= PowerSystemShutdown; sysIndex++) {
  983. //
  984. // Does the system support this S-State?
  985. //
  986. if (!(AcpiSupportedSystemStates & (1 << sysIndex) ) ) {
  987. continue;
  988. }
  989. //
  990. // See if there is an _SxD for this state
  991. //
  992. status = ACPISystemPowerGetSxD( DeviceExtension, sysIndex, &devIndex );
  993. if (NT_SUCCESS(status)) {
  994. //
  995. // We have found a match. Is it better then the current mapping?
  996. //
  997. if (devIndex > currentMapping[sysIndex]) {
  998. //
  999. // Yes, so we have a new mapping
  1000. //
  1001. currentMapping[sysIndex] = devIndex;
  1002. }
  1003. continue;
  1004. } else if (status != STATUS_OBJECT_NAME_NOT_FOUND) {
  1005. ACPIDevPrint( (
  1006. ACPI_PRINT_CRITICAL,
  1007. DeviceExtension,
  1008. "ACPISystemPowerUpdateDeviceCapabilities: Cannot Evalutate "
  1009. "_SxD - 0x%08lx\n",
  1010. status
  1011. ) );
  1012. }
  1013. //
  1014. // What is the base d-state for the current mapping
  1015. //
  1016. currentDState = currentMapping[sysIndex];
  1017. //
  1018. // Remember that we didn't find a match
  1019. //
  1020. matchFound = FALSE;
  1021. //
  1022. // Calculate the interesting pr bits. Do this by ignoring any bit
  1023. // less then the one indicated by the current mapping
  1024. //
  1025. mask = (1 << currentDState) - 1;
  1026. interestingBits = supported & ~mask;
  1027. //
  1028. // While there are interesting bits, look to see if they are
  1029. // available for the current state
  1030. //
  1031. while (interestingBits) {
  1032. //
  1033. // Determine what the highest possible D state that we can
  1034. // have on this device. Clear what we are looking at from
  1035. // the interesting bits
  1036. //
  1037. devIndex = (DEVICE_POWER_STATE) RtlFindLeastSignificantBit(
  1038. (ULONGLONG) interestingBits
  1039. );
  1040. mask = (1 << devIndex);
  1041. interestingBits &= ~mask;
  1042. //
  1043. // If this S-state is less than the wake level of the device
  1044. // then we should try to find a D-state that we can wake from
  1045. //
  1046. if (sysIndex <= systemWakeLevel) {
  1047. //
  1048. // If we can wake from a deeper state, then lets consider
  1049. // those bits
  1050. //
  1051. if ( (supportedWake & interestingBits) ) {
  1052. continue;
  1053. }
  1054. //
  1055. // Don't consider anything deeper than the deviceWake,
  1056. // although this should be taken care in the supportedWake
  1057. // test
  1058. //
  1059. if (devIndex == filterWakeLevel) {
  1060. matchFound = TRUE;
  1061. currentMapping[sysIndex] = devIndex;
  1062. }
  1063. }
  1064. //
  1065. // If our only choice is D3, than we automatically match that
  1066. // since all S states can map to D3.
  1067. //
  1068. if (devIndex == PowerDeviceD3) {
  1069. matchFound = TRUE;
  1070. currentMapping[sysIndex] = devIndex;
  1071. break;
  1072. }
  1073. //
  1074. // If we are looking at a _PR entry, then we need to determine
  1075. // if the power plane actually supports this S state
  1076. //
  1077. if (supportedPr == 0) {
  1078. //
  1079. // We are looking at a _PS entry, and automatically match
  1080. // those
  1081. //
  1082. matchFound = TRUE;
  1083. currentMapping[sysIndex] = devIndex;
  1084. break;
  1085. }
  1086. //
  1087. // We must holding a spinlock for the following
  1088. //
  1089. KeAcquireSpinLock( &AcpiPowerLock, &oldIrql );
  1090. //
  1091. // What system state does this pr state support. If the
  1092. // If the function does not support the D state, then Power
  1093. // SystemUnspecified is returned. The only time that we
  1094. // expect this value is when devIndex == PowerDeviceD3
  1095. //
  1096. supportedState = ACPISystemPowerDetermineSupportedSystemState(
  1097. DeviceExtension,
  1098. devIndex
  1099. );
  1100. if (supportedState == PowerSystemUnspecified) {
  1101. //
  1102. // Paranoia
  1103. //
  1104. ACPIDevPrint( (
  1105. ACPI_PRINT_CRITICAL,
  1106. DeviceExtension,
  1107. "D%x returned PowerSystemUnspecified!\n",
  1108. (devIndex - 1)
  1109. ) );
  1110. KeBugCheckEx(
  1111. ACPI_BIOS_ERROR,
  1112. ACPI_CANNOT_MAP_SYSTEM_TO_DEVICE_STATES,
  1113. (ULONG_PTR) DeviceExtension,
  1114. 0,
  1115. devIndex
  1116. );
  1117. }
  1118. //
  1119. // Done with the power lock
  1120. //
  1121. KeReleaseSpinLock( &AcpiPowerLock, oldIrql );
  1122. //
  1123. // The only way to match is if the return value from
  1124. // ACPISystemPowerDetermineSupportedSystemState returns an S
  1125. // state greater than or equal to the one that we are currently
  1126. // processing.
  1127. //
  1128. if (supportedState >= sysIndex) {
  1129. matchFound = TRUE;
  1130. currentMapping[sysIndex] = devIndex;
  1131. break;
  1132. }
  1133. } // while
  1134. //
  1135. // If we didn't find a match at this point, that should be fatal
  1136. //
  1137. if (!matchFound) {
  1138. ACPIDevPrint( (
  1139. ACPI_PRINT_CRITICAL,
  1140. DeviceExtension,
  1141. "No match found for S%x\n",
  1142. (sysIndex - 1)
  1143. ) );
  1144. KeBugCheckEx(
  1145. ACPI_BIOS_ERROR,
  1146. ACPI_CANNOT_MAP_SYSTEM_TO_DEVICE_STATES,
  1147. (ULONG_PTR) DeviceExtension,
  1148. 1,
  1149. sysIndex
  1150. );
  1151. }
  1152. } // for
  1153. ACPISystemPowerUpdateDeviceCapabilitiesExit:
  1154. //
  1155. // Now, we re-run the wake capabilities to make sure that we get the correct
  1156. // device wake level
  1157. //
  1158. status = ACPISystemPowerUpdateWakeCapabilities(
  1159. DeviceExtension,
  1160. BaseCapabilities,
  1161. DeviceCapabilities,
  1162. currentMapping,
  1163. &supportedWake,
  1164. &systemWakeLevel,
  1165. &deviceWakeLevel,
  1166. &filterWakeLevel
  1167. );
  1168. if (!NT_SUCCESS(status)) {
  1169. ACPIDevPrint( (
  1170. ACPI_PRINT_CRITICAL,
  1171. DeviceExtension,
  1172. "ACPISystemPowerUpdateWakeCapabilities = 0x%08lx\n",
  1173. status
  1174. ) );
  1175. return status;
  1176. }
  1177. //
  1178. // We must holding a spinlock for the following
  1179. //
  1180. KeAcquireSpinLock( &AcpiPowerLock, &oldIrql );
  1181. //
  1182. // Copy the mapping back onto the device
  1183. //
  1184. IoCopyDeviceCapabilitiesMapping(
  1185. currentMapping,
  1186. DeviceExtension->PowerInfo.DevicePowerMatrix
  1187. );
  1188. //
  1189. // Remember the system wake level, device wake level, and what
  1190. // the various support Wake and Power states are
  1191. //
  1192. DeviceExtension->PowerInfo.DeviceWakeLevel = deviceWakeLevel;
  1193. DeviceExtension->PowerInfo.SystemWakeLevel = systemWakeLevel;
  1194. DeviceExtension->PowerInfo.SupportDeviceD1 = ( ( supported & ( 1 << PowerDeviceD1 ) ) != 0);
  1195. DeviceExtension->PowerInfo.SupportDeviceD2 = ( ( supported & ( 1 << PowerDeviceD2 ) ) != 0);
  1196. DeviceExtension->PowerInfo.SupportWakeFromD0 = ( ( supportedWake & ( 1 << PowerDeviceD0 ) ) != 0);
  1197. DeviceExtension->PowerInfo.SupportWakeFromD1 = ( ( supportedWake & ( 1 << PowerDeviceD1 ) ) != 0);
  1198. DeviceExtension->PowerInfo.SupportWakeFromD2 = ( ( supportedWake & ( 1 << PowerDeviceD2 ) ) != 0);
  1199. DeviceExtension->PowerInfo.SupportWakeFromD3 = ( ( supportedWake & ( 1 << PowerDeviceD3 ) ) != 0);
  1200. //
  1201. // Done with the power lock
  1202. //
  1203. KeReleaseSpinLock( &AcpiPowerLock, oldIrql );
  1204. //
  1205. // Again, because we allowed device extension with no name space objects
  1206. // to use this function, we must make sure not to set the ACPI_POWER
  1207. // property unless they have a name space object
  1208. //
  1209. if (!(DeviceExtension->Flags & DEV_PROP_NO_OBJECT)) {
  1210. //
  1211. // Set the ACPI Power Management bits
  1212. //
  1213. ACPIInternalUpdateFlags(
  1214. &(DeviceExtension->Flags),
  1215. DEV_PROP_ACPI_POWER,
  1216. FALSE
  1217. );
  1218. }
  1219. //
  1220. // Done
  1221. //
  1222. return STATUS_SUCCESS;
  1223. }
  1224. NTSTATUS
  1225. ACPISystemPowerUpdateWakeCapabilities(
  1226. IN PDEVICE_EXTENSION DeviceExtension,
  1227. IN PDEVICE_CAPABILITIES BaseCapabilities,
  1228. IN PDEVICE_CAPABILITIES DeviceCapabilities,
  1229. IN DEVICE_POWER_STATE CurrentMapping[PowerSystemMaximum],
  1230. IN ULONG *SupportedWake,
  1231. IN SYSTEM_POWER_STATE *SystemWakeLevel,
  1232. IN DEVICE_POWER_STATE *DeviceWakeLevel,
  1233. IN DEVICE_POWER_STATE *FilterWakeLevel
  1234. )
  1235. /*++
  1236. Routine Description:
  1237. This routine calculates the Wake Capabilities of the device based on
  1238. the present capabilities
  1239. Arguments:
  1240. DeviceExtension - The device whose capabilities we want
  1241. BaseCapabilities - The base values
  1242. ParentCapabilities - The capabilities for the device
  1243. CurrentMapping - The current S->D mapping
  1244. SupportedWake - BitMap of the supported Wake states
  1245. SystemWakeLevel - The S-State that we can wake up from
  1246. DeviceWakeLevel - The D-State that we can wake up from
  1247. Return Value:
  1248. NTSTATUS
  1249. --*/
  1250. {
  1251. PAGED_CODE();
  1252. if ( (DeviceExtension->Flags & DEV_TYPE_FILTER) &&
  1253. !(DeviceExtension->Flags & DEV_TYPE_PDO) ) {
  1254. return ACPISystemPowerUpdateWakeCapabilitiesForFilters(
  1255. DeviceExtension,
  1256. BaseCapabilities,
  1257. DeviceCapabilities,
  1258. CurrentMapping,
  1259. SupportedWake,
  1260. SystemWakeLevel,
  1261. DeviceWakeLevel,
  1262. FilterWakeLevel
  1263. );
  1264. } else {
  1265. if (FilterWakeLevel != NULL) {
  1266. *FilterWakeLevel = PowerDeviceUnspecified;
  1267. }
  1268. return ACPISystemPowerUpdateWakeCapabilitiesForPDOs(
  1269. DeviceExtension,
  1270. BaseCapabilities,
  1271. DeviceCapabilities,
  1272. CurrentMapping,
  1273. SupportedWake,
  1274. SystemWakeLevel,
  1275. DeviceWakeLevel,
  1276. FilterWakeLevel
  1277. );
  1278. }
  1279. }
  1280. NTSTATUS
  1281. ACPISystemPowerUpdateWakeCapabilitiesForFilters(
  1282. IN PDEVICE_EXTENSION DeviceExtension,
  1283. IN PDEVICE_CAPABILITIES BaseCapabilities,
  1284. IN PDEVICE_CAPABILITIES DeviceCapabilities,
  1285. IN DEVICE_POWER_STATE CurrentMapping[PowerSystemMaximum],
  1286. IN ULONG *SupportedWake,
  1287. IN SYSTEM_POWER_STATE *SystemWakeLevel,
  1288. IN DEVICE_POWER_STATE *DeviceWakeLevel,
  1289. IN DEVICE_POWER_STATE *FilterWakeLevel
  1290. )
  1291. /*++
  1292. Routine Description:
  1293. This routine calculates the Wake Capabilities of the device based on
  1294. the present capabilities. This version of the function uses the
  1295. devices states that the device can wake from to determine what the
  1296. appropriate system level is.
  1297. Arguments:
  1298. DeviceExtension - The device whose capabilities we want
  1299. BaseCapabilities - The base values
  1300. DeviceCapabilities - The capabilities for the device
  1301. CurrentMapping - The current S->D mapping
  1302. SupportedWake - BitMap of the supported Wake states
  1303. SystemWakeLevel - The S-State that we can wake up from
  1304. DeviceWakeLevel - The D-State that we can wake up from
  1305. Return Value:
  1306. NTSTATUS
  1307. --*/
  1308. {
  1309. BOOLEAN noPdoWakeSupport = FALSE;
  1310. BOOLEAN foundDState = FALSE;
  1311. DEVICE_POWER_STATE deviceWake;
  1312. DEVICE_POWER_STATE deviceTempWake;
  1313. KIRQL oldIrql;
  1314. NTSTATUS status;
  1315. PACPI_POWER_INFO powerInfo;
  1316. SYSTEM_POWER_STATE systemWake;
  1317. SYSTEM_POWER_STATE tempWake;
  1318. UNREFERENCED_PARAMETER( BaseCapabilities );
  1319. //
  1320. // Use the capabilities from the Device
  1321. //
  1322. deviceWake = DeviceCapabilities->DeviceWake;
  1323. systemWake = DeviceCapabilities->SystemWake;
  1324. //
  1325. // Does the device support wake from D0? D1? D2? D3?
  1326. //
  1327. if (DeviceCapabilities->WakeFromD0) {
  1328. *SupportedWake |= (1 << PowerDeviceD0 );
  1329. }
  1330. if (DeviceCapabilities->WakeFromD1) {
  1331. *SupportedWake |= (1 << PowerDeviceD1 );
  1332. }
  1333. if (DeviceCapabilities->WakeFromD2) {
  1334. *SupportedWake |= (1 << PowerDeviceD2 );
  1335. }
  1336. if (DeviceCapabilities->WakeFromD3) {
  1337. *SupportedWake |= (1 << PowerDeviceD3 );
  1338. }
  1339. //
  1340. // If we don't support any wake states in the PDO (ie: DeviceWake or
  1341. // SystemWake is 0) then we should remember that for future considerations
  1342. //
  1343. if (deviceWake == PowerDeviceUnspecified ||
  1344. systemWake == PowerSystemUnspecified) {
  1345. noPdoWakeSupport = TRUE;
  1346. deviceWake = PowerDeviceUnspecified;
  1347. systemWake = PowerSystemUnspecified;
  1348. }
  1349. //
  1350. // If we support the device wake (ie: there is a _PRW), then we
  1351. // should take the minimum of the systemWake we got from the parent
  1352. // and the value that is stored in the _PRW
  1353. //
  1354. if ( (DeviceExtension->Flags & DEV_CAP_WAKE) ) {
  1355. //
  1356. // Need power lock for the following.
  1357. //
  1358. KeAcquireSpinLock( &AcpiPowerLock, &oldIrql );
  1359. //
  1360. // Remember the current system wake level
  1361. //
  1362. tempWake = DeviceExtension->PowerInfo.SystemWakeLevel;
  1363. //
  1364. // See what D-state (if any) that the power plane information
  1365. // maps to
  1366. //
  1367. deviceTempWake = ACPISystemPowerDetermineSupportedDeviceWakeState(
  1368. DeviceExtension
  1369. );
  1370. KeReleaseSpinLock( &AcpiPowerLock, oldIrql );
  1371. //
  1372. // Take the minimum
  1373. //
  1374. if (tempWake < systemWake || noPdoWakeSupport) {
  1375. systemWake = tempWake;
  1376. }
  1377. //
  1378. // Did the PRW have useful information for us?
  1379. //
  1380. if (deviceTempWake != PowerDeviceUnspecified) {
  1381. //
  1382. // Note that in this case, they are basically overriding all
  1383. // other supported wake up states, so the thing to do is only
  1384. // remember this wake level
  1385. //
  1386. foundDState = TRUE;
  1387. deviceWake = deviceTempWake;
  1388. }
  1389. //
  1390. // See if there is a device wake specified for this S-state?
  1391. //
  1392. status = ACPISystemPowerGetSxD(
  1393. DeviceExtension,
  1394. tempWake,
  1395. &deviceTempWake
  1396. );
  1397. if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  1398. status = ACPISystemPowerGetSxD(
  1399. DeviceExtension,
  1400. systemWake,
  1401. &deviceTempWake
  1402. );
  1403. }
  1404. if (NT_SUCCESS(status)) {
  1405. //
  1406. // Note that in this case, they are basically overriding all other
  1407. // supported Wake up states, so the thing to do is only remember
  1408. // this wake level
  1409. //
  1410. foundDState = TRUE;
  1411. deviceWake = deviceTempWake;
  1412. }
  1413. if (!foundDState) {
  1414. //
  1415. // Crossreference the system wake level with the matrix
  1416. // Need spinlock to do this
  1417. //
  1418. deviceWake = CurrentMapping[systemWake];
  1419. //
  1420. // If this value isn't known, then we guess that it can
  1421. // from D3. In other words, unless they have made some
  1422. // explicity mechanism to tell which D-state to wake from,
  1423. // assume that we can do it from D3
  1424. //
  1425. if (deviceWake == PowerDeviceUnspecified) {
  1426. deviceWake = PowerDeviceD3;
  1427. }
  1428. }
  1429. //
  1430. // We should only check to see if the D-state is a wakeable state
  1431. // in the parent only if the parent claims to support wake
  1432. //
  1433. if (!noPdoWakeSupport) {
  1434. //
  1435. // The logic behind the following is that if we are a filter, even
  1436. // if we support device wake (that is the _PRW is in the PCI device
  1437. // itself, not for the root PCI bus), than we still need to make sure
  1438. // that the D-State that we mapped to is one that is supported by
  1439. // the hardware.
  1440. //
  1441. for (;deviceWake < PowerDeviceMaximum; deviceWake++) {
  1442. //
  1443. // If we we support this wake state, then we can stop
  1444. //
  1445. if (*SupportedWake & (1 << deviceWake) ) {
  1446. break;
  1447. }
  1448. }
  1449. }
  1450. //
  1451. // If we got here, and the D-state is PowerDeviceMaximum, then we
  1452. // don't really support wake on the device
  1453. //
  1454. if (deviceWake == PowerDeviceMaximum ||
  1455. deviceWake == PowerDeviceUnspecified) {
  1456. deviceWake = PowerDeviceUnspecified;
  1457. systemWake = PowerSystemUnspecified;
  1458. *SupportedWake = 0;
  1459. } else {
  1460. //
  1461. // In this situation, we will end up only supporting this wake state
  1462. //
  1463. *SupportedWake = (1 << deviceWake );
  1464. }
  1465. } else {
  1466. //
  1467. // See if there is a device wake specified for this S-state
  1468. //
  1469. status = ACPISystemPowerGetSxD(
  1470. DeviceExtension,
  1471. systemWake,
  1472. &deviceTempWake
  1473. );
  1474. if (NT_SUCCESS(status)) {
  1475. //
  1476. // Find the best supported wake level
  1477. //
  1478. for (;deviceTempWake > PowerDeviceUnspecified; deviceTempWake--) {
  1479. if ( (*SupportedWake & (1 << deviceTempWake) ) ) {
  1480. deviceWake = deviceTempWake;
  1481. break;
  1482. }
  1483. }
  1484. }
  1485. //
  1486. // Make sure that the system wake level is a valid one
  1487. //
  1488. for (; systemWake > PowerSystemUnspecified; systemWake--) {
  1489. //
  1490. // Since S-States that we don't support map to
  1491. // PowerDeviceUnspecified, we cannot consider any of those S
  1492. // states in this test. We also cannot consider them for other
  1493. // obvious reasons as well
  1494. //*
  1495. if (!(AcpiSupportedSystemStates & (1 << systemWake) ) ||
  1496. (CurrentMapping[systemWake] == PowerDeviceUnspecified) ) {
  1497. continue;
  1498. }
  1499. //
  1500. // Does this S-state support the given S-State?
  1501. //
  1502. if (CurrentMapping[systemWake] <= deviceWake) {
  1503. break;
  1504. }
  1505. //
  1506. // Does the device state for the current system wake mapping
  1507. // allow wake-from sleep?
  1508. //
  1509. if (*SupportedWake & (1 << CurrentMapping[systemWake]) ) {
  1510. //
  1511. // Yes? then we had better update our idea of what the
  1512. // device wake state should be...
  1513. //
  1514. deviceWake = CurrentMapping[systemWake];
  1515. break;
  1516. }
  1517. }
  1518. //
  1519. // If we got into a situation were we cannot find a single S-state
  1520. // that we can wake from, then we must make sure that the device
  1521. // wake is null
  1522. //
  1523. if (systemWake == PowerSystemUnspecified) {
  1524. //
  1525. // Remember that the device wake and supported wake states
  1526. // are null
  1527. //
  1528. deviceWake = PowerDeviceUnspecified;
  1529. *SupportedWake = 0;
  1530. }
  1531. }
  1532. //
  1533. // Return the proper device wake and system wake values
  1534. //
  1535. if (SystemWakeLevel != NULL) {
  1536. *SystemWakeLevel = systemWake;
  1537. }
  1538. if (DeviceWakeLevel != NULL) {
  1539. *DeviceWakeLevel = deviceWake;
  1540. }
  1541. if (FilterWakeLevel != NULL) {
  1542. *FilterWakeLevel = deviceWake;
  1543. }
  1544. //
  1545. // Done
  1546. //
  1547. return STATUS_SUCCESS;
  1548. }
  1549. NTSTATUS
  1550. ACPISystemPowerUpdateWakeCapabilitiesForPDOs(
  1551. IN PDEVICE_EXTENSION DeviceExtension,
  1552. IN PDEVICE_CAPABILITIES BaseCapabilities,
  1553. IN PDEVICE_CAPABILITIES DeviceCapabilities,
  1554. IN DEVICE_POWER_STATE CurrentMapping[PowerSystemMaximum],
  1555. IN ULONG *SupportedWake,
  1556. IN SYSTEM_POWER_STATE *SystemWakeLevel,
  1557. IN DEVICE_POWER_STATE *DeviceWakeLevel,
  1558. IN DEVICE_POWER_STATE *FilterWakeLevel
  1559. )
  1560. /*++
  1561. Routine Description:
  1562. This routine calculates the Wake Capabilities of the device based on
  1563. the present capabilities. This version of the function uses the
  1564. system state that the device can wake from to determine what the
  1565. appropriate device level is.
  1566. Arguments:
  1567. DeviceExtension - The device whose capabilities we want
  1568. BaseCapabilities - The base values
  1569. DeviceCapabilities - The capabilities for the device
  1570. CurrentMapping - The current S->D mapping
  1571. SupportedWake - BitMap of the supported Wake states
  1572. SystemWakeLevel - The S-State that we can wake up from
  1573. DeviceWakeLevel - The D-State that we can wake up from
  1574. Return Value:
  1575. NTSTATUS
  1576. --*/
  1577. {
  1578. BOOLEAN foundDState = FALSE;
  1579. DEVICE_POWER_STATE deviceWake;
  1580. DEVICE_POWER_STATE deviceTempWake;
  1581. DEVICE_POWER_STATE filterWake = PowerDeviceUnspecified;
  1582. KIRQL oldIrql;
  1583. NTSTATUS status;
  1584. SYSTEM_POWER_STATE systemWake;
  1585. UNREFERENCED_PARAMETER( DeviceCapabilities );
  1586. UNREFERENCED_PARAMETER( BaseCapabilities );
  1587. //
  1588. // Use the capabilities of the device
  1589. //
  1590. if (!(DeviceExtension->Flags & DEV_CAP_WAKE) ) {
  1591. deviceWake = PowerDeviceUnspecified;
  1592. systemWake = PowerSystemUnspecified;
  1593. goto ACPISystemPowerUpdateWakeCapabilitiesForPDOsExit;
  1594. }
  1595. //
  1596. // Hold the lock for the following
  1597. //
  1598. KeAcquireSpinLock( &AcpiPowerLock, &oldIrql );
  1599. //
  1600. // Use the wake level that we know about. If this wakelevel
  1601. // isn't supported, than there is a bios error
  1602. //
  1603. systemWake = DeviceExtension->PowerInfo.SystemWakeLevel;
  1604. deviceTempWake = ACPISystemPowerDetermineSupportedDeviceWakeState(
  1605. DeviceExtension
  1606. );
  1607. //
  1608. // Done with the lock
  1609. //
  1610. KeReleaseSpinLock( &AcpiPowerLock, oldIrql );
  1611. //
  1612. // Sanity check
  1613. //
  1614. if (!(AcpiSupportedSystemStates & (1 << systemWake) ) ) {
  1615. #if 0
  1616. if (!(AcpiOverrideAttributes & ACPI_OVERRIDE_MP_SLEEP) ) {
  1617. KeBugCheckEx(
  1618. ACPI_BIOS_ERROR,
  1619. ACPI_CANNOT_MAP_SYSTEM_TO_DEVICE_STATES,
  1620. (ULONG_PTR) DeviceExtension,
  1621. 2,
  1622. systemWake
  1623. );
  1624. }
  1625. #endif
  1626. deviceWake = PowerDeviceUnspecified;
  1627. systemWake = PowerSystemUnspecified;
  1628. goto ACPISystemPowerUpdateWakeCapabilitiesForPDOsExit;
  1629. }
  1630. if (deviceTempWake != PowerDeviceUnspecified) {
  1631. //
  1632. // Note that in this case, they are basically overriding all
  1633. // other supported wake up states, so the thing to do is only
  1634. // remember this wake level
  1635. //
  1636. foundDState = TRUE;
  1637. deviceWake = deviceTempWake;
  1638. filterWake = deviceTempWake;
  1639. *SupportedWake = (1 << deviceWake );
  1640. }
  1641. //
  1642. // See if there is an SxD method that will give us a hint
  1643. //
  1644. status = ACPISystemPowerGetSxD(
  1645. DeviceExtension,
  1646. systemWake,
  1647. &deviceTempWake
  1648. );
  1649. if (NT_SUCCESS(status)) {
  1650. //
  1651. // Note that in this case, they are basically overriding all other
  1652. // supported Wake up states, so the thing to do is only remember
  1653. // this wake level
  1654. deviceWake = deviceTempWake;
  1655. filterWake = deviceTempWake;
  1656. foundDState = TRUE;
  1657. }
  1658. if (!foundDState) {
  1659. //
  1660. // Crossreference the system wake level with the matrix
  1661. // Need spinlock to do this
  1662. //
  1663. deviceWake = CurrentMapping[systemWake];
  1664. //
  1665. // If this value isn't known, then we guess that it can
  1666. // from D3. In other words, unless they have made some
  1667. // explicity mechanism to tell which D-state to wake from,
  1668. // assume that we can do it from D3
  1669. //
  1670. if (deviceWake == PowerDeviceUnspecified) {
  1671. deviceWake = PowerDeviceD3;
  1672. }
  1673. }
  1674. ACPISystemPowerUpdateWakeCapabilitiesForPDOsExit:
  1675. //
  1676. // Set the return values
  1677. //
  1678. if (deviceWake != PowerDeviceUnspecified) {
  1679. *SupportedWake = (1 << deviceWake );
  1680. } else {
  1681. *SupportedWake = 0;
  1682. }
  1683. if (SystemWakeLevel != NULL) {
  1684. *SystemWakeLevel = systemWake;
  1685. }
  1686. if (DeviceWakeLevel != NULL) {
  1687. *DeviceWakeLevel = deviceWake;
  1688. }
  1689. if (FilterWakeLevel != NULL) {
  1690. *FilterWakeLevel = filterWake;
  1691. }
  1692. //
  1693. // Done
  1694. //
  1695. return STATUS_SUCCESS;
  1696. }