Source code of Windows XP (NT5)
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.

2480 lines
58 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. root.c
  5. Abstract:
  6. This module contains the root FDO handler for the NT Driver
  7. Author:
  8. Stephane Plante (splante)
  9. Environment:
  10. NT Kernel Model Driver only
  11. Revision History:
  12. July-09-97 Added support to Unify QueryDeviceRelations from filter.c
  13. --*/
  14. #include "pch.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, ACPIRootIrpCancelRemoveOrStopDevice)
  17. #pragma alloc_text(PAGE, ACPIRootIrpQueryBusRelations)
  18. #pragma alloc_text(PAGE, ACPIRootIrpQueryCapabilities)
  19. #pragma alloc_text(PAGE, ACPIRootIrpQueryDeviceRelations)
  20. #pragma alloc_text(PAGE, ACPIRootIrpQueryRemoveOrStopDevice)
  21. #pragma alloc_text(PAGE, ACPIRootIrpStartDevice)
  22. #pragma alloc_text(PAGE, ACPIRootIrpStopDevice)
  23. #pragma alloc_text(PAGE, ACPIRootIrpQueryInterface)
  24. #endif
  25. NTSTATUS
  26. ACPIRootIrpCancelRemoveOrStopDevice(
  27. IN PDEVICE_OBJECT DeviceObject,
  28. IN PIRP Irp
  29. )
  30. /*++
  31. Routine Description:
  32. This routine transitions the device from the inactive to the
  33. started state
  34. Arguments:
  35. DeviceObject - The target
  36. Irp - The request
  37. Return Value:
  38. NTSTATUS
  39. --*/
  40. {
  41. NTSTATUS status = STATUS_SUCCESS;
  42. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  43. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  44. UCHAR minorFunction = irpStack->MinorFunction;
  45. PAGED_CODE();
  46. //
  47. // Where we allowed to stop the device? If so, then undo whatever it
  48. // was we did, otherwise let the world know about the cancel
  49. //
  50. if (!(deviceExtension->Flags & DEV_CAP_NO_STOP) ) {
  51. //
  52. // Check to see if we have placed this device in the inactive state
  53. //
  54. if (deviceExtension->DeviceState == Inactive) {
  55. //
  56. // Mark the device state to its previous state
  57. //
  58. deviceExtension->DeviceState = deviceExtension->PreviousState;
  59. }
  60. }
  61. //
  62. // We are successfull
  63. //
  64. Irp->IoStatus.Status = status;
  65. //
  66. // Pass the Irp Along
  67. //
  68. Irp->IoStatus.Status = STATUS_SUCCESS ;
  69. IoSkipCurrentIrpStackLocation( Irp );
  70. status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
  71. //
  72. // Done
  73. //
  74. ACPIDevPrint( (
  75. ACPI_PRINT_IRP,
  76. deviceExtension,
  77. "(%#08lx): %s = %#08lx\n",
  78. Irp,
  79. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  80. status
  81. ) );
  82. return status;
  83. }
  84. NTSTATUS
  85. ACPIRootIrpCompleteRoutine(
  86. IN PDEVICE_OBJECT DeviceObject,
  87. IN PIRP Irp,
  88. IN PVOID Context
  89. )
  90. /*++
  91. Routine Description:
  92. This is the routine that is called when one of the IRPS that was
  93. noticed by ACPIRootIrp* and was judged to be an IRP that we need
  94. to examine later on...
  95. Arguments:
  96. DeviceObject - A pointer to the Filter Object
  97. Irp - A pointer to the completed request
  98. Context - Whatever Irp-dependent information we need to know
  99. Return Value:
  100. NTSTATUS
  101. --*/
  102. {
  103. PKEVENT event = (PKEVENT) Context;
  104. #if DBG
  105. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  106. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  107. if (deviceExtension != NULL) {
  108. //
  109. // Let the world know what we just got...
  110. //
  111. ACPIDevPrint( (
  112. ACPI_PRINT_IRP,
  113. deviceExtension,
  114. "(%#08lx): %s = %#08lx (Complete)\n",
  115. Irp,
  116. ACPIDebugGetIrpText(IRP_MJ_PNP, irpStack->MinorFunction),
  117. Irp->IoStatus.Status
  118. ) );
  119. }
  120. #endif
  121. //
  122. // Signal the event
  123. //
  124. KeSetEvent( event, IO_NO_INCREMENT, FALSE );
  125. //
  126. // Always return MORE_PROCESSING_REQUIRED
  127. //
  128. return STATUS_MORE_PROCESSING_REQUIRED;
  129. }
  130. NTSTATUS
  131. ACPIRootIrpQueryBusRelations(
  132. IN PDEVICE_OBJECT DeviceObject,
  133. IN PIRP Irp,
  134. OUT PDEVICE_RELATIONS *PdeviceRelations
  135. )
  136. /*++
  137. Routine Description:
  138. This routine is the dispatch point for the IRP_MN_QUERY_DEVICE_RELATIONS
  139. requests sent to the Root or Filter Device Objects
  140. Arguments:
  141. DeviceObject - Pointer to the device object we received the request for
  142. Irp - Pointer to the request
  143. Return Value:
  144. NTSTATUS
  145. --*/
  146. {
  147. NTSTATUS detectStatus;
  148. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  149. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  150. PNSOBJ acpiObject = NULL;
  151. UCHAR minorFunction = irpStack->MinorFunction;
  152. PAGED_CODE();
  153. //
  154. // lets look at the ACPIObject that we have and we can see
  155. // if it is valid
  156. //
  157. acpiObject = deviceExtension->AcpiObject;
  158. ASSERT( acpiObject != NULL );
  159. if (acpiObject == NULL) {
  160. ACPIDevPrint( (
  161. ACPI_PRINT_WARNING,
  162. deviceExtension,
  163. "(%#08lx): %s - Invalid ACPI Object %#08lx\n",
  164. Irp,
  165. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  166. acpiObject
  167. ) );
  168. //
  169. // Fail the IRP.
  170. //
  171. return STATUS_INVALID_PARAMETER;
  172. }
  173. //
  174. // Detect which PDOs are missing
  175. //
  176. detectStatus = ACPIDetectPdoDevices(
  177. DeviceObject,
  178. PdeviceRelations
  179. );
  180. //
  181. // If something went well along the way, yell a bit
  182. //
  183. if ( !NT_SUCCESS(detectStatus) ) {
  184. ACPIDevPrint( (
  185. ACPI_PRINT_WARNING,
  186. deviceExtension,
  187. "(%#08lx): %s - Enum Failed %#08lx\n",
  188. Irp,
  189. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  190. detectStatus
  191. ) );
  192. }
  193. //
  194. // Detect which profile providers are missing
  195. //
  196. if ( NT_SUCCESS(detectStatus)) {
  197. detectStatus = ACPIDetectDockDevices(
  198. deviceExtension,
  199. PdeviceRelations
  200. );
  201. //
  202. // If something went well along the way, yell a bit
  203. //
  204. if ( !NT_SUCCESS(detectStatus) ) {
  205. ACPIDevPrint( (
  206. ACPI_PRINT_WARNING,
  207. deviceExtension,
  208. "(%#08lx): %s - Dock Enum Failed "
  209. "%#08lx\n",
  210. Irp,
  211. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  212. detectStatus
  213. ) );
  214. }
  215. }
  216. //
  217. // Done
  218. //
  219. return detectStatus;
  220. }
  221. NTSTATUS
  222. ACPIRootIrpQueryCapabilities(
  223. IN PDEVICE_OBJECT DeviceObject,
  224. IN PIRP Irp
  225. )
  226. /*++
  227. Routine Description:
  228. This routine fills in the capabilities for the root device
  229. Arguments:
  230. DeviceObject - The object whose capabilities to get
  231. Irp - The request
  232. Return Value:
  233. NTSTATUS
  234. --*/
  235. {
  236. KEVENT event;
  237. NTSTATUS status = STATUS_SUCCESS;
  238. PDEVICE_CAPABILITIES capabilities;
  239. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  240. PIO_STACK_LOCATION irpStack;
  241. UCHAR minorFunction;
  242. PAGED_CODE();
  243. //
  244. // Setup the Event so that we are notified of when this done
  245. //
  246. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  247. //
  248. // Copy the stack location
  249. //
  250. IoCopyCurrentIrpStackLocationToNext( Irp );
  251. //
  252. // We want our completion routine to fire...
  253. //
  254. IoSetCompletionRoutine(
  255. Irp,
  256. ACPIRootIrpCompleteRoutine,
  257. &event,
  258. TRUE,
  259. TRUE,
  260. TRUE
  261. );
  262. //
  263. // Let the IRP execute
  264. //
  265. status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
  266. if (status == STATUS_PENDING) {
  267. //
  268. // Wait for it
  269. //
  270. KeWaitForSingleObject(
  271. &event,
  272. Executive,
  273. KernelMode,
  274. FALSE,
  275. NULL
  276. );
  277. //
  278. // Grab the 'real' status
  279. //
  280. status = Irp->IoStatus.Status;
  281. }
  282. //
  283. // Look at the current stack location
  284. //
  285. irpStack = IoGetCurrentIrpStackLocation( Irp );
  286. minorFunction = irpStack->MinorFunction;
  287. //
  288. // What happened?
  289. //
  290. if (!NT_SUCCESS(status)) {
  291. //
  292. // Failure
  293. //
  294. goto ACPIRootIrpQueryCapabilitiesExit;
  295. }
  296. //
  297. // Grab a pointer to the capabilitites
  298. //
  299. capabilities = irpStack->Parameters.DeviceCapabilities.Capabilities;
  300. #ifndef HANDLE_BOGUS_CAPS
  301. if (capabilities->Version < 1) {
  302. //
  303. // do not touch irp!
  304. //
  305. goto ACPIRootIrpQueryCapabilitiesExit;
  306. }
  307. #endif
  308. //
  309. // Set the capabilities that we know about
  310. //
  311. capabilities->LockSupported = FALSE;
  312. capabilities->EjectSupported = FALSE;
  313. capabilities->Removable = FALSE;
  314. capabilities->UINumber = (ULONG) -1;
  315. capabilities->UniqueID = TRUE;
  316. capabilities->RawDeviceOK = FALSE;
  317. capabilities->SurpriseRemovalOK = FALSE;
  318. capabilities->Address = (ULONG) -1;
  319. capabilities->DeviceWake = PowerDeviceUnspecified;
  320. capabilities->SystemWake = PowerDeviceUnspecified;
  321. //
  322. // build the power table properly yet?
  323. //
  324. status = ACPISystemPowerInitializeRootMapping(
  325. deviceExtension,
  326. capabilities
  327. );
  328. if (!NT_SUCCESS(status)) {
  329. ACPIDevPrint( (
  330. ACPI_PRINT_CRITICAL,
  331. deviceExtension,
  332. "(0x%08lx): %s - InitializeRootMapping = %08lx\n",
  333. Irp,
  334. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  335. status
  336. ) );
  337. goto ACPIRootIrpQueryCapabilitiesExit;
  338. }
  339. ACPIRootIrpQueryCapabilitiesExit:
  340. //
  341. // Have happily finished with this irp
  342. //
  343. Irp->IoStatus.Status = status;
  344. //
  345. // Complete the Irp
  346. //
  347. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  348. //
  349. // Done
  350. //
  351. ACPIDevPrint( (
  352. ACPI_PRINT_IRP,
  353. deviceExtension,
  354. "(%#08lx): %s = %#08lx\n",
  355. Irp,
  356. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  357. status
  358. ) );
  359. return status;
  360. }
  361. NTSTATUS
  362. ACPIRootIrpQueryDeviceRelations(
  363. IN PDEVICE_OBJECT DeviceObject,
  364. IN PIRP Irp
  365. )
  366. /*++
  367. Routine Description:
  368. This routine is the dispatch point for the IRP_MN_QUERY_DEVICE_RELATIONS
  369. requests sent to the Root or Filter Device Objects
  370. Arguments:
  371. DeviceObject - Pointer to the device object we received the request for
  372. Irp - Pointer to the request
  373. Return Value:
  374. NTSTATUS
  375. --*/
  376. {
  377. BOOLEAN checkForFilters = FALSE;
  378. KEVENT queryEvent;
  379. NTSTATUS status;
  380. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  381. PDEVICE_RELATIONS deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
  382. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  383. UCHAR minorFunction = irpStack->MinorFunction;
  384. NTSTATUS detectStatus;
  385. PAGED_CODE();
  386. switch(irpStack->Parameters.QueryDeviceRelations.Type) {
  387. case BusRelations:
  388. //
  389. // Remember to check for filters later on...
  390. //
  391. checkForFilters = TRUE;
  392. //
  393. // Get the real bus relations
  394. //
  395. status = ACPIRootIrpQueryBusRelations(
  396. DeviceObject,
  397. Irp,
  398. &deviceRelations
  399. );
  400. break ;
  401. default:
  402. status = STATUS_NOT_SUPPORTED ;
  403. ACPIDevPrint( (
  404. ACPI_PRINT_WARNING,
  405. deviceExtension,
  406. "(%#08lx): %s - Unhandled Type %d\n",
  407. Irp,
  408. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  409. irpStack->Parameters.QueryDeviceRelations.Type
  410. ) );
  411. break ;
  412. }
  413. ACPIDevPrint( (
  414. ACPI_PRINT_IRP,
  415. deviceExtension,
  416. "(%#08lx): %s (d) = %#08lx\n",
  417. Irp,
  418. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  419. status
  420. ) );
  421. if (NT_SUCCESS(status)) {
  422. //
  423. // Pass the IRP status along
  424. //
  425. Irp->IoStatus.Status = status;
  426. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  427. } else if ((status != STATUS_NOT_SUPPORTED) && (deviceRelations == NULL)) {
  428. //
  429. // If we haven't succeed the irp, then we can also fail it
  430. //
  431. Irp->IoStatus.Status = status;
  432. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  433. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  434. return status;
  435. } else {
  436. //
  437. // Either someone above us added an entry or we did not have anything
  438. // to add. Therefore, we do not touch this IRP, but simply pass it down.
  439. //
  440. }
  441. //
  442. // Initialize an event so that we can block
  443. //
  444. KeInitializeEvent( &queryEvent, SynchronizationEvent, FALSE );
  445. //
  446. // If we succeeded, then we must set a completion routine so that we
  447. // can do some post-processing
  448. //
  449. IoCopyCurrentIrpStackLocationToNext( Irp );
  450. IoSetCompletionRoutine(
  451. Irp,
  452. ACPIRootIrpCompleteRoutine,
  453. &queryEvent,
  454. TRUE,
  455. TRUE,
  456. TRUE
  457. );
  458. //
  459. // Pass the irp along
  460. //
  461. status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
  462. //
  463. // Wait for it to come back...
  464. //
  465. if (status == STATUS_PENDING) {
  466. KeWaitForSingleObject(
  467. &queryEvent,
  468. Executive,
  469. KernelMode,
  470. FALSE,
  471. NULL
  472. );
  473. //
  474. // Grab the 'real' status
  475. //
  476. status = Irp->IoStatus.Status;
  477. }
  478. //
  479. // Read back the device relations (they may have changed)
  480. //
  481. deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
  482. //
  483. // If we succeeded, then we should try to load the filters
  484. //
  485. if ( (NT_SUCCESS(status) || (status == STATUS_NOT_SUPPORTED) ) &&
  486. checkForFilters == TRUE) {
  487. //
  488. // Grab the device relations
  489. //
  490. detectStatus = ACPIDetectFilterDevices(
  491. DeviceObject,
  492. deviceRelations
  493. );
  494. ACPIDevPrint( (
  495. ACPI_PRINT_IRP,
  496. deviceExtension,
  497. "(0x%08lx): %s (u) = %#08lx\n",
  498. Irp,
  499. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  500. detectStatus
  501. ) );
  502. }
  503. //
  504. // Done with the IRP
  505. //
  506. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  507. //
  508. // Done
  509. //
  510. return status;
  511. }
  512. NTSTATUS
  513. ACPIRootIrpQueryInterface(
  514. IN PDEVICE_OBJECT DeviceObject,
  515. IN PIRP Irp
  516. )
  517. /*++
  518. Routine Description:
  519. This routine handles IRP_MN_QUERY_INTERFACE requests for the ACPI FDO.
  520. It will eject an arbiter interface for interrupts.
  521. Arguments:
  522. DeviceObject - Pointer to the device object we received the request for
  523. Irp - Pointer to the request
  524. Return Value:
  525. NTSTATUS
  526. --*/
  527. {
  528. ARBITER_INTERFACE ArbiterTable;
  529. CM_RESOURCE_TYPE resource;
  530. NTSTATUS status;
  531. GUID *interfaceType;
  532. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  533. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  534. ULONG count;
  535. UCHAR minorFunction = irpStack->MinorFunction;
  536. PAGED_CODE();
  537. //
  538. // Obtain the info we will need from the irp
  539. //
  540. resource = (CM_RESOURCE_TYPE)
  541. PtrToUlong(irpStack->Parameters.QueryInterface.InterfaceSpecificData);
  542. interfaceType = (LPGUID) irpStack->Parameters.QueryInterface.InterfaceType;
  543. #if DBG
  544. {
  545. NTSTATUS status2;
  546. UNICODE_STRING guidString;
  547. status2 = RtlStringFromGUID( interfaceType, &guidString );
  548. if (NT_SUCCESS(status2)) {
  549. ACPIDevPrint( (
  550. ACPI_PRINT_IRP,
  551. deviceExtension,
  552. "(0x%08lx): %s - Res %x Type = %wZ\n",
  553. Irp,
  554. ACPIDebugGetIrpText(IRP_MJ_PNP, irpStack->MinorFunction),
  555. resource,
  556. &guidString
  557. ) );
  558. RtlFreeUnicodeString( &guidString );
  559. }
  560. }
  561. #endif
  562. //
  563. // *Only* Handle the Guids that we know about. Do Not Ever touch
  564. // any other GUID
  565. //
  566. if ((CompareGuid(interfaceType, (PVOID) &GUID_ARBITER_INTERFACE_STANDARD)) &&
  567. (resource == CmResourceTypeInterrupt)){
  568. //
  569. // Only copy up to current size of the ARBITER_INTERFACE structure
  570. //
  571. if (irpStack->Parameters.QueryInterface.Size >
  572. sizeof (ARBITER_INTERFACE) ) {
  573. count = sizeof (ARBITER_INTERFACE);
  574. } else {
  575. count = irpStack->Parameters.QueryInterface.Size;
  576. }
  577. ArbiterTable.Size = sizeof(ARBITER_INTERFACE);
  578. ArbiterTable.Version = 1;
  579. ArbiterTable.InterfaceReference = AcpiNullReference;
  580. ArbiterTable.InterfaceDereference = AcpiNullReference;
  581. ArbiterTable.ArbiterHandler = &ArbArbiterHandler;
  582. ArbiterTable.Context = &AcpiArbiter.ArbiterState;
  583. ArbiterTable.Flags = 0; // Do not set ARBITER_PARTIAL here
  584. //
  585. // Copy the arbiter table.
  586. //
  587. RtlCopyMemory(irpStack->Parameters.QueryInterface.Interface,
  588. &ArbiterTable,
  589. count);
  590. Irp->IoStatus.Status = STATUS_SUCCESS;
  591. }
  592. //
  593. // Done
  594. //
  595. ACPIDevPrint( (
  596. ACPI_PRINT_IRP,
  597. deviceExtension,
  598. "(%#08lx): %s = %#08lx\n",
  599. Irp,
  600. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  601. Irp->IoStatus.Status
  602. ) );
  603. return ACPIDispatchForwardIrp( DeviceObject, Irp );
  604. }
  605. NTSTATUS
  606. ACPIRootIrpQueryPower(
  607. IN PDEVICE_OBJECT DeviceObject,
  608. IN PIRP Irp
  609. )
  610. /*++
  611. Routine Description:
  612. This routine handles the QUERY_POWER sent to the root FDO. It succeeds
  613. the query if ACPI supports the listed system state
  614. Arguments:
  615. DeviceObject - The Target
  616. Irp - The Request
  617. Return Value:
  618. NTSTATUS
  619. --*/
  620. {
  621. BOOLEAN passDown = TRUE;
  622. NTSTATUS status = Irp->IoStatus.Status;
  623. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  624. PIO_STACK_LOCATION irpSp;
  625. PNSOBJ object;
  626. SYSTEM_POWER_STATE systemState;
  627. ULONG objectName;
  628. //
  629. // Get the Current stack location to determine if we are a system
  630. // irp or a device irp. We ignore device irps here.
  631. //
  632. irpSp = IoGetCurrentIrpStackLocation(Irp);
  633. if (irpSp->Parameters.Power.Type != SystemPowerState) {
  634. //
  635. // We don't handle this irp
  636. //
  637. goto ACPIRootIrpQueryPowerExit;
  638. }
  639. if (irpSp->Parameters.Power.ShutdownType == PowerActionWarmEject) {
  640. //
  641. // We definately don't allow the ejection of this node
  642. //
  643. passDown = FALSE;
  644. status = STATUS_INVALID_DEVICE_REQUEST;
  645. goto ACPIRootIrpQueryPowerExit;
  646. }
  647. //
  648. // What system state are we looking at?
  649. //
  650. systemState = irpSp->Parameters.Power.State.SystemState;
  651. switch (systemState) {
  652. case PowerSystemWorking: objectName = PACKED_S0; break;
  653. case PowerSystemSleeping1: objectName = PACKED_S1; break;
  654. case PowerSystemSleeping2: objectName = PACKED_S2; break;
  655. case PowerSystemSleeping3: objectName = PACKED_S3; break;
  656. case PowerSystemHibernate:
  657. case PowerSystemShutdown:
  658. status = STATUS_SUCCESS;
  659. goto ACPIRootIrpQueryPowerExit;
  660. default:
  661. //
  662. // We don't handle this IRP
  663. //
  664. passDown = FALSE;
  665. status = STATUS_INVALID_DEVICE_REQUEST;
  666. goto ACPIRootIrpQueryPowerExit;
  667. }
  668. //
  669. // Does the object exist?
  670. //
  671. object = ACPIAmliGetNamedChild(
  672. deviceExtension->AcpiObject->pnsParent,
  673. objectName
  674. );
  675. if (object != NULL) {
  676. status = STATUS_SUCCESS;
  677. } else {
  678. passDown = FALSE;
  679. status = STATUS_INVALID_DEVICE_REQUEST;
  680. }
  681. ACPIRootIrpQueryPowerExit:
  682. //
  683. // Let the system know what we support and what we don't
  684. //
  685. Irp->IoStatus.Status = status;
  686. ACPIDevPrint( (
  687. ACPI_PRINT_IRP,
  688. deviceExtension,
  689. "(0x%08lx): ACPIRootIrpQueryPower = %08lx\n",
  690. Irp,
  691. status
  692. ) );
  693. //
  694. // Should we pass the irp down or fail it?
  695. //
  696. if (passDown) {
  697. //
  698. // If we support the request then pass it down and give someone else a
  699. // chance to veto it
  700. //
  701. return ACPIDispatchForwardPowerIrp( DeviceObject, Irp );
  702. } else {
  703. //
  704. // If we failed the irp for whatever reason, the we should just complete
  705. // the request now and continue along
  706. //
  707. PoStartNextPowerIrp( Irp );
  708. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  709. return status;
  710. }
  711. }
  712. NTSTATUS
  713. ACPIRootIrpQueryRemoveOrStopDevice(
  714. IN PDEVICE_OBJECT DeviceObject,
  715. IN PIRP Irp
  716. )
  717. /*++
  718. Routine Description:
  719. This routine transitions the device to the inactive state
  720. Arguments:
  721. DeviceObject - The target
  722. Irp - The Request
  723. Return Value:
  724. NTSTATUS
  725. --*/
  726. {
  727. NTSTATUS status;
  728. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  729. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  730. UCHAR minorFunction = irpStack->MinorFunction;
  731. PAGED_CODE();
  732. //
  733. // Are we allowed to stop the device?
  734. //
  735. if (deviceExtension->Flags & DEV_CAP_NO_STOP) {
  736. //
  737. // No, then fail the irp
  738. //
  739. Irp->IoStatus.Status = status = STATUS_INVALID_DEVICE_REQUEST;
  740. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  741. } else {
  742. //
  743. // Mark the device state as inactive...
  744. //
  745. deviceExtension->PreviousState = deviceExtension->DeviceState;
  746. deviceExtension->DeviceState = Inactive;
  747. //
  748. // Pass the Irp Along
  749. //
  750. IoSkipCurrentIrpStackLocation( Irp );
  751. status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
  752. }
  753. //
  754. // Done
  755. //
  756. ACPIDevPrint( (
  757. ACPI_PRINT_IRP,
  758. deviceExtension,
  759. "(%#08lx): %s = %#08lx\n",
  760. Irp,
  761. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  762. status
  763. ) );
  764. return status;
  765. }
  766. NTSTATUS
  767. ACPIRootIrpRemoveDevice(
  768. IN PDEVICE_OBJECT DeviceObject,
  769. IN PIRP Irp
  770. )
  771. /*++
  772. Routine Description:
  773. This routine is called when a filter object must remove itself...
  774. Arguments:
  775. DeviceObject - The DeviceObject that must be removed
  776. Irp - The request to remove ourselves
  777. Return Value:
  778. --*/
  779. {
  780. LONG oldReferenceCount;
  781. KIRQL oldIrql;
  782. NTSTATUS status;
  783. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  784. PDEVICE_OBJECT targetObject;
  785. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  786. UCHAR minorFunction = irpStack->MinorFunction;
  787. //
  788. // Set the device state as 'removed' ...
  789. //
  790. deviceExtension->DeviceState = Removed;
  791. //
  792. // Send on the remove IRP
  793. //
  794. IoSkipCurrentIrpStackLocation( Irp );
  795. status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
  796. ACPIDevPrint( (
  797. ACPI_PRINT_IRP,
  798. deviceExtension,
  799. "(%#08lx): %s = %#08lx\n",
  800. Irp,
  801. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  802. status
  803. ) );
  804. //
  805. // Attempt to stop the device (if possible)
  806. //
  807. ACPIInitStopACPI( DeviceObject );
  808. //
  809. // Unregister WMI
  810. //
  811. #ifdef WMI_TRACING
  812. ACPIWmiUnRegisterLog(DeviceObject);
  813. #endif // WMI_TRACING
  814. //
  815. // Delete the useless set of resources
  816. //
  817. if (deviceExtension->ResourceList != NULL) {
  818. ExFreePool( deviceExtension->ResourceList );
  819. }
  820. //
  821. // Update the device extension ---
  822. // we need to hold the lock for this
  823. //
  824. KeAcquireSpinLock( &AcpiDeviceTreeLock, &oldIrql );
  825. //
  826. // Step one is to zero out the things that we no longer care
  827. // about
  828. //
  829. DeviceObject->DeviceExtension = NULL;
  830. targetObject = deviceExtension->TargetDeviceObject;
  831. deviceExtension->TargetDeviceObject = NULL;
  832. deviceExtension->PhysicalDeviceObject = NULL;
  833. deviceExtension->DeviceObject = NULL;
  834. //
  835. // Mark the node as being fresh and untouched
  836. //
  837. ACPIInternalUpdateFlags( &(deviceExtension->Flags), DEV_MASK_TYPE, TRUE );
  838. ACPIInternalUpdateFlags( &(deviceExtension->Flags), DEV_TYPE_NOT_FOUND, FALSE );
  839. ACPIInternalUpdateFlags( &(deviceExtension->Flags), DEV_TYPE_REMOVED, FALSE );
  840. //
  841. // The reference count should have value >= 1
  842. //
  843. oldReferenceCount = InterlockedDecrement(
  844. &(deviceExtension->ReferenceCount)
  845. );
  846. ASSERT( oldReferenceCount >= 0 );
  847. //
  848. // Do we have to delete the node?
  849. //
  850. if (oldReferenceCount == 0) {
  851. //
  852. // Delete the extension
  853. //
  854. ACPIInitDeleteDeviceExtension( deviceExtension );
  855. }
  856. //
  857. // Done with the lock
  858. //
  859. KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
  860. //
  861. // Detach the device and delete the object
  862. //
  863. ASSERT( targetObject );
  864. IoDetachDevice( targetObject );
  865. IoDeleteDevice( DeviceObject );
  866. //
  867. // done
  868. //
  869. return STATUS_SUCCESS;
  870. }
  871. NTSTATUS
  872. ACPIRootIrpSetPower (
  873. IN PDEVICE_OBJECT DeviceObject,
  874. IN PIRP Irp
  875. )
  876. /*++
  877. Routine Description:
  878. This routine is called to tell the Root device that the system is
  879. going to sleep
  880. Arguments:
  881. DeviceObject - Device which represents the root of the ACPI tree
  882. Irp - The request in question
  883. Return Value:
  884. NTSTATUS
  885. --*/
  886. {
  887. KIRQL oldIrql;
  888. NTSTATUS status;
  889. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  890. PIO_STACK_LOCATION irpSp;
  891. //
  892. // See if we need to bugcheck
  893. //
  894. if (AcpiSystemInitialized == FALSE) {
  895. ACPIInternalError( ACPI_ROOT );
  896. }
  897. //
  898. // Get the Current stack location to determine if we are a system
  899. // irp or a device irp. We ignore device irps here.
  900. //
  901. irpSp = IoGetCurrentIrpStackLocation(Irp);
  902. if (irpSp->Parameters.Power.Type != SystemPowerState) {
  903. //
  904. // We don't handle this irp
  905. //
  906. return ACPIDispatchForwardPowerIrp( DeviceObject, Irp );
  907. }
  908. //
  909. // We are going to work on the Irp, so mark it as being SUCCESS
  910. // for now
  911. //
  912. Irp->IoStatus.Status = STATUS_SUCCESS;
  913. ACPIDevPrint( (
  914. ACPI_PRINT_IRP,
  915. deviceExtension,
  916. "(0x%08lx): ACPIRootIrpSetPower - S%d\n",
  917. Irp,
  918. irpSp->Parameters.Power.State.SystemState - PowerSystemWorking
  919. ) );
  920. //
  921. // Mark the irp as pending, and increment the irp count because a
  922. // completion is going to be set
  923. //
  924. IoMarkIrpPending( Irp );
  925. InterlockedIncrement( &(deviceExtension->OutstandingIrpCount) );
  926. //
  927. // Queue the request
  928. //
  929. status = ACPIDeviceIrpSystemRequest(
  930. DeviceObject,
  931. Irp,
  932. ACPIDeviceIrpForwardRequest
  933. );
  934. //
  935. // Did we return STATUS_MORE_PROCESSING_REQUIRED (which we used if
  936. // we overloaded STATUS_PENDING)
  937. //
  938. if (status == STATUS_MORE_PROCESSING_REQUIRED) {
  939. status = STATUS_PENDING;
  940. }
  941. //
  942. // Done. Note: the callback function always gets called, so we don't
  943. // have to worry about doing clean-up work here.
  944. //
  945. return status;
  946. }
  947. NTSTATUS
  948. ACPIRootIrpStartDevice(
  949. IN PDEVICE_OBJECT DeviceObject,
  950. IN PIRP Irp
  951. )
  952. /*++
  953. Routine Description:
  954. This routine is the dispatch point for the IRP_MN_START_DEVICE requests sent
  955. to the Root (or FDO, take your pick, they are the same thing) device object
  956. Arguments:
  957. DeviceObject - Pointer to the device object we received the request for
  958. Irp - Pointer to the request
  959. Return Value:
  960. NTSTATUS
  961. --*/
  962. {
  963. KEVENT event;
  964. NTSTATUS status = STATUS_SUCCESS;
  965. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  966. PIO_STACK_LOCATION irpStack;
  967. UCHAR minorFunction;
  968. PAGED_CODE();
  969. //
  970. // Request to start the device. The rule is that we must pass
  971. // this down to the PDO before we can start the device ourselves
  972. //
  973. ACPIDevPrint( (
  974. ACPI_PRINT_IRP,
  975. deviceExtension,
  976. "(0x%08lx): ACPIRootIrpStartDevice\n",
  977. Irp
  978. ) );
  979. //
  980. // Setup the Event so that we are notified of when this done
  981. //
  982. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  983. //
  984. // Copy the stack location
  985. //
  986. IoCopyCurrentIrpStackLocationToNext( Irp );
  987. //
  988. // We want our completion routine to fire...
  989. //
  990. IoSetCompletionRoutine(
  991. Irp,
  992. ACPIRootIrpCompleteRoutine,
  993. &event,
  994. TRUE,
  995. TRUE,
  996. TRUE
  997. );
  998. //
  999. // Let the IRP execute
  1000. //
  1001. status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
  1002. if (status == STATUS_PENDING) {
  1003. //
  1004. // Wait for it
  1005. //
  1006. KeWaitForSingleObject(
  1007. &event,
  1008. Executive,
  1009. KernelMode,
  1010. FALSE,
  1011. NULL
  1012. );
  1013. //
  1014. // Grab the 'real' status
  1015. //
  1016. status = Irp->IoStatus.Status;
  1017. }
  1018. //
  1019. // Get the current irp stack location
  1020. //
  1021. irpStack = IoGetCurrentIrpStackLocation( Irp );
  1022. minorFunction = irpStack->MinorFunction;
  1023. //
  1024. // What happened?
  1025. //
  1026. if (!NT_SUCCESS(status)) {
  1027. //
  1028. // Failure
  1029. //
  1030. goto ACPIRootIrpStartDeviceExit;
  1031. }
  1032. //
  1033. // Grab the translatted resource allocated for this device
  1034. //
  1035. deviceExtension->ResourceList =
  1036. (irpStack->Parameters.StartDevice.AllocatedResourcesTranslated ==
  1037. NULL) ? NULL:
  1038. RtlDuplicateCmResourceList(
  1039. NonPagedPool,
  1040. irpStack->Parameters.StartDevice.AllocatedResourcesTranslated,
  1041. ACPI_RESOURCE_POOLTAG
  1042. );
  1043. if (deviceExtension->ResourceList == NULL) {
  1044. ACPIDevPrint( (
  1045. ACPI_PRINT_CRITICAL,
  1046. deviceExtension,
  1047. " - Did not find a resource list!\n"
  1048. ) );
  1049. KeBugCheckEx(
  1050. ACPI_BIOS_ERROR,
  1051. ACPI_ROOT_RESOURCES_FAILURE,
  1052. (ULONG_PTR) deviceExtension,
  1053. 0,
  1054. 0
  1055. );
  1056. }
  1057. //
  1058. // Start ACPI
  1059. //
  1060. status = ACPIInitStartACPI( DeviceObject );
  1061. //
  1062. // Update the status of the device
  1063. //
  1064. if (NT_SUCCESS(status)) {
  1065. deviceExtension->DeviceState = Started;
  1066. }
  1067. #if 0
  1068. status = ACPIRootUpdateRootResourcesWithHalResources();
  1069. if (!NT_SUCCESS(status)) {
  1070. ACPIDevPrint( (
  1071. ACPI_PRINT_CRITICAL,
  1072. deviceExtension,
  1073. "(0x%08lx): ACPIRootUpdateRootResourcesWithHalResources = %08lx\n",
  1074. Irp,
  1075. status
  1076. ) );
  1077. }
  1078. #endif
  1079. ACPIRootIrpStartDeviceExit:
  1080. //
  1081. // Store and return the result
  1082. //
  1083. Irp->IoStatus.Status = status;
  1084. //
  1085. // Complete the Irp
  1086. //
  1087. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1088. //
  1089. // Done
  1090. //
  1091. ACPIDevPrint( (
  1092. ACPI_PRINT_IRP,
  1093. deviceExtension,
  1094. "(%#08lx): %s = %#08lx\n",
  1095. Irp,
  1096. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  1097. status
  1098. ) );
  1099. return status;
  1100. }
  1101. NTSTATUS
  1102. ACPIRootIrpStopDevice(
  1103. IN PDEVICE_OBJECT DeviceObject,
  1104. IN PIRP Irp
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. This handles a request to stop the device
  1109. Arguments:
  1110. DeviceObject - The device to stop
  1111. Irp - The request to tell us how to do it...
  1112. Return Value:
  1113. NTSTATUS
  1114. --*/
  1115. {
  1116. NTSTATUS status;
  1117. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  1118. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  1119. UCHAR minorFunction = irpStack->MinorFunction;
  1120. PAGED_CODE();
  1121. //
  1122. // Note: we can only stop a device from within the Inactive state...
  1123. //
  1124. if (deviceExtension->DeviceState != Inactive) {
  1125. ASSERT( deviceExtension->DeviceState == Inactive );
  1126. Irp->IoStatus.Status = status = STATUS_INVALID_DEVICE_REQUEST;
  1127. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1128. goto ACPIRootIrpStopDeviceExit;
  1129. }
  1130. //
  1131. // Set the device as 'Stopped'
  1132. deviceExtension->DeviceState = Stopped;
  1133. //
  1134. // Send on the Stop IRP
  1135. //
  1136. IoSkipCurrentIrpStackLocation( Irp );
  1137. status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
  1138. //
  1139. // Attempt to stop the device (if possible)
  1140. //
  1141. #if 1
  1142. ACPIInitStopACPI( DeviceObject );
  1143. #endif
  1144. ACPIRootIrpStopDeviceExit:
  1145. //
  1146. // done
  1147. //
  1148. ACPIDevPrint( (
  1149. ACPI_PRINT_IRP,
  1150. deviceExtension,
  1151. "(%#08lx): %s = %#08lx\n",
  1152. Irp,
  1153. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  1154. status
  1155. ) );
  1156. return status;
  1157. }
  1158. NTSTATUS
  1159. ACPIRootIrpUnhandled(
  1160. IN PDEVICE_OBJECT DeviceObject,
  1161. IN PIRP Irp
  1162. )
  1163. /*++
  1164. Routine Description:
  1165. This routine is the dispatch point for the unhandled requests sent to a filter
  1166. Arguments:
  1167. DeviceObject - Pointer to the device object we received the request for
  1168. Irp - Pointer to the request
  1169. Return Value:
  1170. NTSTATUS
  1171. --*/
  1172. {
  1173. NTSTATUS status;
  1174. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  1175. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  1176. //
  1177. // Let the debugger know
  1178. //
  1179. ACPIDevPrint( (
  1180. ACPI_PRINT_WARNING,
  1181. deviceExtension,
  1182. "(%#08lx): %s - Unhandled\n",
  1183. Irp,
  1184. ACPIDebugGetIrpText(IRP_MJ_PNP, irpStack->MinorFunction)
  1185. ) );
  1186. //
  1187. // Skip current stack location
  1188. //
  1189. IoSkipCurrentIrpStackLocation( Irp );
  1190. //
  1191. // Call the driver below us
  1192. //
  1193. status = IoCallDriver( deviceExtension->TargetDeviceObject, Irp );
  1194. //
  1195. // Done
  1196. //
  1197. return status;
  1198. }
  1199. //
  1200. // Some data structures used by the AML interpreter. We need to be able
  1201. // to read/write these globals to keep track of the number of contexts
  1202. // allocated by the interpreter...
  1203. //
  1204. extern ULONG gdwcCTObjsMax;
  1205. extern ULONG AMLIMaxCTObjs;
  1206. extern KSPIN_LOCK gdwGContextSpinLock;
  1207. VOID
  1208. ACPIRootPowerCallBack(
  1209. IN PVOID CallBackContext,
  1210. IN PVOID Argument1,
  1211. IN PVOID Argument2
  1212. )
  1213. /*++
  1214. Routine Description:
  1215. This routine is called when the system changes power states
  1216. Arguments:
  1217. CallBackContext - The device extension for the root device
  1218. Argument1
  1219. --*/
  1220. {
  1221. HANDLE pKey;
  1222. HANDLE wKey;
  1223. KIRQL oldIrql;
  1224. NTSTATUS status;
  1225. ULONG action = PtrToUlong( Argument1 );
  1226. ULONG value = PtrToUlong( Argument2 );
  1227. ULONG num;
  1228. //
  1229. // We are looking for a PO_CB_SYSTEM_STATE_LOCK
  1230. //
  1231. if (action != PO_CB_SYSTEM_STATE_LOCK) {
  1232. return;
  1233. }
  1234. //
  1235. // We need to remember if we are going to S0 or we are leaving S0
  1236. //
  1237. KeAcquireSpinLock( &GpeTableLock, &oldIrql );
  1238. AcpiPowerLeavingS0 = (value != 1);
  1239. KeReleaseSpinLock( &GpeTableLock, oldIrql );
  1240. //
  1241. // We have to update the GPE masks now. Before we can do that, we need
  1242. // to hold the cancel spinlock and the power lock to make sure that
  1243. // everything is synchronized okay
  1244. //
  1245. IoAcquireCancelSpinLock( &oldIrql );
  1246. KeAcquireSpinLockAtDpcLevel( &AcpiPowerLock );
  1247. //
  1248. // Update the GPE masks
  1249. //
  1250. ACPIWakeRemoveDevicesAndUpdate( NULL, NULL );
  1251. //
  1252. // Done with the locks
  1253. //
  1254. KeReleaseSpinLockFromDpcLevel( &AcpiPowerLock );
  1255. IoReleaseCancelSpinLock( oldIrql );
  1256. if (value == 0) {
  1257. //
  1258. // We need to reset the max number of context objects allocated
  1259. //
  1260. KeAcquireSpinLock( &gdwGContextSpinLock, &oldIrql );
  1261. gdwcCTObjsMax = 0;
  1262. KeReleaseSpinLock( &gdwGContextSpinLock, oldIrql );
  1263. //
  1264. // Return now otherwise we will execute that we normally
  1265. // would execute on wake-up
  1266. //
  1267. return;
  1268. }
  1269. //
  1270. // Open the correct handle to the registry
  1271. //
  1272. status = OSCreateHandle(ACPI_PARAMETERS_REGISTRY_KEY, NULL, &pKey);
  1273. if (!NT_SUCCESS(status)) {
  1274. return;
  1275. }
  1276. //
  1277. // Grab the max number of contexts allocated and write it to
  1278. // the registry, but only if it exceeds the last value store
  1279. // in the registry
  1280. //
  1281. KeAcquireSpinLock( &gdwGContextSpinLock, &oldIrql );
  1282. if (gdwcCTObjsMax > AMLIMaxCTObjs) {
  1283. AMLIMaxCTObjs = gdwcCTObjsMax;
  1284. }
  1285. num = AMLIMaxCTObjs;
  1286. KeReleaseSpinLock( &gdwGContextSpinLock, oldIrql );
  1287. OSWriteRegValue(
  1288. "AMLIMaxCTObjs",
  1289. pKey,
  1290. &num,
  1291. sizeof(num)
  1292. );
  1293. //
  1294. // If we are leaving the sleep state, and re-entering the running
  1295. // state, then we had better write to the registery that we think
  1296. // woke up the computer
  1297. //
  1298. status = OSCreateHandle("WakeUp",pKey,&wKey);
  1299. OSCloseHandle(pKey);
  1300. if (!NT_SUCCESS(status)) {
  1301. OSCloseHandle(pKey);
  1302. return;
  1303. }
  1304. //
  1305. // Store the PM1 Fixed Register Mask
  1306. //
  1307. OSWriteRegValue(
  1308. "FixedEventMask",
  1309. wKey,
  1310. &(AcpiInformation->pm1_wake_mask),
  1311. sizeof(AcpiInformation->pm1_wake_mask)
  1312. );
  1313. //
  1314. // Store the PM1 Fixed Register Status
  1315. //
  1316. OSWriteRegValue(
  1317. "FixedEventStatus",
  1318. wKey,
  1319. &(AcpiInformation->pm1_wake_status),
  1320. sizeof(AcpiInformation->pm1_wake_status)
  1321. );
  1322. //
  1323. // Store the GPE Mask
  1324. //
  1325. OSWriteRegValue(
  1326. "GenericEventMask",
  1327. wKey,
  1328. GpeSavedWakeMask,
  1329. AcpiInformation->GpeSize
  1330. );
  1331. //
  1332. // Store the GPE Status
  1333. //
  1334. OSWriteRegValue(
  1335. "GenericEventStatus",
  1336. wKey,
  1337. GpeSavedWakeStatus,
  1338. AcpiInformation->GpeSize
  1339. );
  1340. //
  1341. // Done with the key
  1342. //
  1343. OSCloseHandle( wKey );
  1344. }
  1345. NTSTATUS
  1346. ACPIRootUpdateRootResourcesWithBusResources(
  1347. VOID
  1348. )
  1349. /*++
  1350. Routine Description:
  1351. This routine is called when ACPI is started. Its purpose is to change
  1352. the resources reported to ACPI for its own use to include those resources
  1353. used by direct childs which are not buses. In other words, it updates
  1354. its resource list so that buses do not prevent direct children from
  1355. starting.
  1356. This is black magic
  1357. Arguments:
  1358. None
  1359. Return Value:
  1360. NTSTATUS
  1361. --*/
  1362. {
  1363. KIRQL oldIrql;
  1364. LONG oldReferenceCount;
  1365. NTSTATUS status;
  1366. PCM_RESOURCE_LIST cmList;
  1367. PDEVICE_EXTENSION deviceExtension;
  1368. PDEVICE_EXTENSION oldExtension;
  1369. PIO_RESOURCE_REQUIREMENTS_LIST currentList = NULL;
  1370. PIO_RESOURCE_REQUIREMENTS_LIST globalList = NULL;
  1371. PUCHAR crsBuf;
  1372. //
  1373. // First take the ACPI CM Res List and turn *that* into an Io ResList. This
  1374. // is the list that we will add things to
  1375. //
  1376. status = PnpCmResourceListToIoResourceList(
  1377. RootDeviceExtension->ResourceList,
  1378. &globalList
  1379. );
  1380. if (!NT_SUCCESS(status)) {
  1381. //
  1382. // Oops
  1383. //
  1384. return status;
  1385. }
  1386. //
  1387. // We must walk the tree at Dispatch level <sigh>
  1388. //
  1389. KeAcquireSpinLock( &AcpiDeviceTreeLock, &oldIrql );
  1390. //
  1391. // Is the list empty?
  1392. //
  1393. if (IsListEmpty( &(RootDeviceExtension->ChildDeviceList) ) ) {
  1394. //
  1395. // We have nothing to do here
  1396. //
  1397. KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
  1398. ExFreePool( globalList );
  1399. return STATUS_SUCCESS;
  1400. }
  1401. //
  1402. // Get the first child
  1403. //
  1404. deviceExtension = CONTAINING_RECORD(
  1405. RootDeviceExtension->ChildDeviceList.Flink,
  1406. DEVICE_EXTENSION,
  1407. SiblingDeviceList
  1408. );
  1409. //
  1410. // Always update the reference count to make sure that one will ever
  1411. // delete the node without our knowing about it
  1412. //
  1413. InterlockedIncrement( &(deviceExtension->ReferenceCount) );
  1414. //
  1415. // Release the lock
  1416. //
  1417. KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
  1418. //
  1419. // loop until we get to the parent
  1420. //
  1421. while (deviceExtension != NULL ) {
  1422. //
  1423. // Check to see if we are a bus, and if we are, we will skip this
  1424. // node
  1425. //
  1426. if (!(deviceExtension->Flags & DEV_MASK_BUS) &&
  1427. !(deviceExtension->Flags & DEV_PROP_NO_OBJECT) ) {
  1428. //
  1429. // At this point, see if there is a _CRS
  1430. //
  1431. ACPIGetBufferSync(
  1432. deviceExtension,
  1433. PACKED_CRS,
  1434. &crsBuf,
  1435. NULL
  1436. );
  1437. if (crsBuf != NULL) {
  1438. //
  1439. // Try to turn the crs into an IO_RESOURCE_REQUIREMENTS_LIST
  1440. //
  1441. status = PnpBiosResourcesToNtResources(
  1442. crsBuf,
  1443. 0,
  1444. &currentList
  1445. );
  1446. //
  1447. // If we didn't succeed, then we skip the list
  1448. //
  1449. if (NT_SUCCESS(status)) {
  1450. //
  1451. // Add this list to the global list
  1452. //
  1453. status = ACPIRangeAdd(
  1454. &globalList,
  1455. currentList
  1456. );
  1457. //
  1458. // We are done with the local IO res list
  1459. //
  1460. ExFreePool( currentList );
  1461. }
  1462. ACPIDevPrint( (
  1463. ACPI_PRINT_RESOURCES_1,
  1464. deviceExtension,
  1465. "ACPIRootUpdateResources = %08lx\n",
  1466. status
  1467. ) );
  1468. //
  1469. // Done with local crs
  1470. //
  1471. ExFreePool( crsBuf );
  1472. }
  1473. }
  1474. //
  1475. // We need the lock to walk the next resource in the tree
  1476. //
  1477. KeAcquireSpinLock( &AcpiDeviceTreeLock, &oldIrql );
  1478. //
  1479. // Remember the old extension
  1480. //
  1481. oldExtension = deviceExtension;
  1482. //
  1483. // Get the next device extension
  1484. //
  1485. if (deviceExtension->SiblingDeviceList.Flink !=
  1486. &(RootDeviceExtension->ChildDeviceList) ) {
  1487. //
  1488. // Next Element
  1489. //
  1490. deviceExtension = CONTAINING_RECORD(
  1491. deviceExtension->SiblingDeviceList.Flink,
  1492. DEVICE_EXTENSION,
  1493. SiblingDeviceList
  1494. );
  1495. //
  1496. // Reference count the device
  1497. //
  1498. InterlockedIncrement( &(deviceExtension->ReferenceCount) );
  1499. } else {
  1500. deviceExtension = NULL;
  1501. }
  1502. //
  1503. // Decrement the reference count on this node
  1504. //
  1505. oldReferenceCount = InterlockedDecrement(
  1506. &(oldExtension->ReferenceCount)
  1507. );
  1508. //
  1509. // Is this the last reference?
  1510. //
  1511. if (oldReferenceCount == 0) {
  1512. //
  1513. // Free the memory allocated by the extension
  1514. //
  1515. ACPIInitDeleteDeviceExtension( oldExtension );
  1516. }
  1517. //
  1518. // Done with the lock
  1519. //
  1520. KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
  1521. }
  1522. //
  1523. // Do we have any resources that we care to update?
  1524. //
  1525. if (globalList == NULL) {
  1526. //
  1527. // No, then we are done
  1528. //
  1529. return STATUS_SUCCESS;
  1530. }
  1531. //
  1532. // Turn the global list into a CM_RES_LIST
  1533. //
  1534. status = PnpIoResourceListToCmResourceList( globalList, &cmList );
  1535. //
  1536. // No matter what, we are done with the global list
  1537. //
  1538. ExFreePool( globalList );
  1539. //
  1540. // Check to see if we succeeded
  1541. //
  1542. if (!NT_SUCCESS(status)) {
  1543. //
  1544. // Oops
  1545. //
  1546. return status;
  1547. }
  1548. //
  1549. // Now, set this as the resources consumed by ACPI. The previous list
  1550. // was created by the system manager, so freeing it is bad.
  1551. //
  1552. RootDeviceExtension->ResourceList = cmList;
  1553. //
  1554. // Done
  1555. //
  1556. return STATUS_SUCCESS;
  1557. }
  1558. NTSTATUS
  1559. ACPIRootUpdateRootResourcesWithHalResources(
  1560. VOID
  1561. )
  1562. /*++
  1563. Routine Description:
  1564. This routine will read from the registry the resources that cannot
  1565. be allocated by ACPI and store them in the resourceList for PnP0C08
  1566. This is black magic
  1567. Arguments:
  1568. None
  1569. Return Value:
  1570. NTSTATUS
  1571. --*/
  1572. {
  1573. HANDLE classKeyHandle;
  1574. HANDLE driverKeyHandle;
  1575. HANDLE resourceMap;
  1576. NTSTATUS status;
  1577. OBJECT_ATTRIBUTES resourceObject;
  1578. PCM_FULL_RESOURCE_DESCRIPTOR cmFullResList;
  1579. PCM_RESOURCE_LIST globalResList;
  1580. PCM_RESOURCE_LIST cmResList;
  1581. PUCHAR lastAddr;
  1582. ULONG bufferSize;
  1583. ULONG busTranslatedLength;
  1584. ULONG classKeyIndex;
  1585. ULONG driverKeyIndex;
  1586. ULONG driverValueIndex;
  1587. ULONG i;
  1588. ULONG j;
  1589. ULONG length;
  1590. ULONG temp;
  1591. ULONG translatedLength;
  1592. union {
  1593. PVOID buffer;
  1594. PKEY_BASIC_INFORMATION keyBasicInf;
  1595. PKEY_FULL_INFORMATION keyFullInf;
  1596. PKEY_VALUE_FULL_INFORMATION valueKeyFullInf;
  1597. } u;
  1598. UNICODE_STRING keyName;
  1599. WCHAR rgzTranslated[] = L".Translated";
  1600. WCHAR rgzBusTranslated[] = L".Bus.Translated";
  1601. WCHAR rgzResourceMap[] =
  1602. L"\\REGISTRY\\MACHINE\\HARDWARE\\RESOURCEMAP";
  1603. #define INVALID_HANDLE (HANDLE) -1
  1604. //
  1605. // Start out with one page of buffer
  1606. //
  1607. bufferSize = PAGE_SIZE;
  1608. //
  1609. // Allocate this buffer
  1610. //
  1611. u.buffer = ExAllocatePoolWithTag(
  1612. PagedPool,
  1613. bufferSize,
  1614. ACPI_MISC_POOLTAG
  1615. );
  1616. if (u.buffer == NULL) {
  1617. return STATUS_INSUFFICIENT_RESOURCES;
  1618. }
  1619. //
  1620. // Add the current global res list to the working list
  1621. //
  1622. globalResList = NULL;
  1623. status = ACPIRangeAddCmList(
  1624. &globalResList,
  1625. RootDeviceExtension->ResourceList
  1626. );
  1627. if (!NT_SUCCESS(status)) {
  1628. ExFreePool( u.buffer );
  1629. return status;
  1630. }
  1631. ExFreePool( RootDeviceExtension->ResourceList );
  1632. RootDeviceExtension->ResourceList = NULL;
  1633. //
  1634. // count the constant string lengths
  1635. //
  1636. for (translatedLength = 0;
  1637. rgzTranslated[translatedLength];
  1638. translatedLength++);
  1639. for (busTranslatedLength = 0;
  1640. rgzBusTranslated[busTranslatedLength];
  1641. busTranslatedLength++);
  1642. translatedLength *= sizeof(WCHAR);
  1643. busTranslatedLength *= sizeof(WCHAR);
  1644. //
  1645. // Initialize the registry path information
  1646. //
  1647. RtlInitUnicodeString( &keyName, rgzResourceMap );
  1648. //
  1649. // Open the registry key for this information
  1650. //
  1651. InitializeObjectAttributes(
  1652. &resourceObject,
  1653. &keyName,
  1654. OBJ_CASE_INSENSITIVE,
  1655. NULL,
  1656. NULL
  1657. );
  1658. status = ZwOpenKey(
  1659. &resourceMap,
  1660. KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  1661. &resourceObject
  1662. );
  1663. if (!NT_SUCCESS(status)) {
  1664. //
  1665. // Failed:
  1666. //
  1667. ACPIPrint( (
  1668. ACPI_PRINT_CRITICAL,
  1669. "ACPIRootUpdateRootResourcesWithHalResources: ZwOpenKey = 0x%08lx\n",
  1670. status
  1671. ) );
  1672. ExFreePool( u.buffer );
  1673. return status;
  1674. }
  1675. //
  1676. // Walk resource map and collect any in-use resources
  1677. //
  1678. classKeyIndex = 0;
  1679. classKeyHandle = INVALID_HANDLE;
  1680. driverKeyHandle = INVALID_HANDLE;
  1681. status = STATUS_SUCCESS;
  1682. //
  1683. // loop until failure
  1684. //
  1685. while (NT_SUCCESS(status)) {
  1686. //
  1687. // Get the class information
  1688. //
  1689. status = ZwEnumerateKey(
  1690. resourceMap,
  1691. classKeyIndex++,
  1692. KeyBasicInformation,
  1693. u.keyBasicInf,
  1694. bufferSize,
  1695. &temp
  1696. );
  1697. if (!NT_SUCCESS(status)) {
  1698. break;
  1699. }
  1700. //
  1701. // Create a unicode string using the counted string passed back to
  1702. // us in the information structure, and open the class key
  1703. //
  1704. keyName.Buffer = (PWSTR) u.keyBasicInf->Name;
  1705. keyName.Length = (USHORT) u.keyBasicInf->NameLength;
  1706. keyName.MaximumLength = (USHORT) u.keyBasicInf->NameLength;
  1707. InitializeObjectAttributes(
  1708. &resourceObject,
  1709. &keyName,
  1710. OBJ_CASE_INSENSITIVE,
  1711. resourceMap,
  1712. NULL
  1713. );
  1714. status = ZwOpenKey(
  1715. &classKeyHandle,
  1716. KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  1717. &resourceObject
  1718. );
  1719. if (!NT_SUCCESS(status)) {
  1720. break;
  1721. }
  1722. //
  1723. // Loop until failure
  1724. //
  1725. driverKeyIndex = 0;
  1726. while (NT_SUCCESS(status)) {
  1727. //
  1728. // Get the class information
  1729. //
  1730. status = ZwEnumerateKey(
  1731. classKeyHandle,
  1732. driverKeyIndex++,
  1733. KeyBasicInformation,
  1734. u.keyBasicInf,
  1735. bufferSize,
  1736. &temp
  1737. );
  1738. if (!NT_SUCCESS(status)) {
  1739. break;
  1740. }
  1741. //
  1742. // Create a unicode string using the counted string passed back
  1743. // to us in the information structure, and open the class key
  1744. //
  1745. keyName.Buffer = (PWSTR) u.keyBasicInf->Name;
  1746. keyName.Length = (USHORT) u.keyBasicInf->NameLength;
  1747. keyName.MaximumLength = (USHORT) u.keyBasicInf->NameLength;
  1748. InitializeObjectAttributes(
  1749. &resourceObject,
  1750. &keyName,
  1751. OBJ_CASE_INSENSITIVE,
  1752. classKeyHandle,
  1753. NULL
  1754. );
  1755. status = ZwOpenKey(
  1756. &driverKeyHandle,
  1757. KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  1758. &resourceObject
  1759. );
  1760. if (!NT_SUCCESS(status)) {
  1761. break;
  1762. }
  1763. //
  1764. // Get full information for that key so we can get the information
  1765. // about the data stored in the key
  1766. //
  1767. status = ZwQueryKey(
  1768. driverKeyHandle,
  1769. KeyFullInformation,
  1770. u.keyFullInf,
  1771. bufferSize,
  1772. &temp
  1773. );
  1774. if (!NT_SUCCESS(status)) {
  1775. break;
  1776. }
  1777. //
  1778. // How long is the key?
  1779. //
  1780. length = sizeof( KEY_VALUE_FULL_INFORMATION) +
  1781. u.keyFullInf->MaxValueNameLen +
  1782. u.keyFullInf->MaxValueDataLen +
  1783. sizeof(UNICODE_NULL);
  1784. if (length > bufferSize) {
  1785. PVOID tempBuffer;
  1786. //
  1787. // Grow the buffer
  1788. //
  1789. tempBuffer = ExAllocatePoolWithTag(
  1790. PagedPool,
  1791. length,
  1792. ACPI_MISC_POOLTAG
  1793. );
  1794. if (tempBuffer == NULL) {
  1795. status = STATUS_INSUFFICIENT_RESOURCES;
  1796. break;
  1797. }
  1798. ExFreePool( u.buffer );
  1799. u.buffer = tempBuffer;
  1800. bufferSize = length;
  1801. }
  1802. //
  1803. // Look at all the values
  1804. //
  1805. driverValueIndex = 0;
  1806. for(;;) {
  1807. PCM_RESOURCE_LIST tempCmList;
  1808. status = ZwEnumerateValueKey(
  1809. driverKeyHandle,
  1810. driverValueIndex++,
  1811. KeyValueFullInformation,
  1812. u.valueKeyFullInf,
  1813. bufferSize,
  1814. &temp
  1815. );
  1816. if (!NT_SUCCESS(status)) {
  1817. break;
  1818. }
  1819. //
  1820. // If this is not a translated resource list, skip it
  1821. //
  1822. i = u.valueKeyFullInf->NameLength;
  1823. if (i < translatedLength ||
  1824. RtlCompareMemory(
  1825. ((PUCHAR) u.valueKeyFullInf->Name) + i - translatedLength,
  1826. rgzTranslated,
  1827. translatedLength) != translatedLength
  1828. ) {
  1829. //
  1830. // Does not end in rgzTranslated
  1831. //
  1832. continue;
  1833. }
  1834. //
  1835. // Is this a bus translated resource list???
  1836. //
  1837. if (i >= busTranslatedLength &&
  1838. RtlCompareMemory(
  1839. ((PUCHAR) u.valueKeyFullInf->Name) + i - busTranslatedLength,
  1840. rgzBusTranslated,
  1841. busTranslatedLength) != busTranslatedLength
  1842. ) {
  1843. //
  1844. // Ends in rgzBusTranslated
  1845. //
  1846. continue;
  1847. }
  1848. //
  1849. // we now have a pointer to the cm resource list
  1850. //
  1851. cmResList = (PCM_RESOURCE_LIST) ( (PUCHAR) u.valueKeyFullInf +
  1852. u.valueKeyFullInf->DataOffset);
  1853. lastAddr = (PUCHAR) cmResList + u.valueKeyFullInf->DataLength;
  1854. //
  1855. // We must flatten this list down to one level, so lets
  1856. // figure out how many descriptors we need
  1857. //
  1858. cmFullResList = cmResList->List;
  1859. for (temp = i = 0; i < cmResList->Count; i++) {
  1860. if ( (PUCHAR) cmFullResList > lastAddr) {
  1861. break;
  1862. }
  1863. temp += cmFullResList->PartialResourceList.Count;
  1864. //
  1865. // next CM_FULL_RESOURCE_DESCRIPTOR
  1866. //
  1867. cmFullResList =
  1868. (PCM_FULL_RESOURCE_DESCRIPTOR) ( (PUCHAR) cmFullResList
  1869. + sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
  1870. (cmFullResList->PartialResourceList.Count - 1) *
  1871. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) );
  1872. }
  1873. //
  1874. // Now that we have the number of descriptors, allocate this
  1875. // much space
  1876. //
  1877. tempCmList = ExAllocatePool(
  1878. PagedPool,
  1879. sizeof(CM_RESOURCE_LIST) + (temp - 1) *
  1880. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
  1881. );
  1882. if (tempCmList == NULL) {
  1883. status = STATUS_INSUFFICIENT_RESOURCES;
  1884. break;
  1885. }
  1886. //
  1887. // Now, fill up the flatened list
  1888. //
  1889. RtlCopyMemory(
  1890. tempCmList,
  1891. cmResList,
  1892. sizeof(CM_RESOURCE_LIST) -
  1893. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
  1894. );
  1895. tempCmList->Count = 1;
  1896. tempCmList->List->PartialResourceList.Count = temp;
  1897. //
  1898. // This is a brute force approach
  1899. //
  1900. cmFullResList = cmResList->List;
  1901. for (temp = i = 0; i < cmResList->Count; i++) {
  1902. if ( (PUCHAR) cmFullResList > lastAddr) {
  1903. break;
  1904. }
  1905. //
  1906. // Copy the current descriptors over
  1907. //
  1908. RtlCopyMemory(
  1909. &(tempCmList->List->PartialResourceList.PartialDescriptors[temp]),
  1910. cmFullResList->PartialResourceList.PartialDescriptors,
  1911. cmFullResList->PartialResourceList.Count *
  1912. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
  1913. );
  1914. temp += cmFullResList->PartialResourceList.Count;
  1915. //
  1916. // next CM_FULL_RESOURCE_DESCRIPTOR
  1917. //
  1918. cmFullResList =
  1919. (PCM_FULL_RESOURCE_DESCRIPTOR) ( (PUCHAR) cmFullResList
  1920. + sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
  1921. (cmFullResList->PartialResourceList.Count - 1) *
  1922. sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) );
  1923. }
  1924. //
  1925. // Add it to the global list
  1926. //
  1927. status = ACPIRangeAddCmList(
  1928. &globalResList,
  1929. tempCmList
  1930. );
  1931. if (!NT_SUCCESS(status)) {
  1932. ACPIPrint( (
  1933. ACPI_PRINT_CRITICAL,
  1934. "ACPIRootUpdateRootResourcesWithHalResources: "
  1935. "ACPIRangeAddCmList = 0x%08lx\n",
  1936. status
  1937. ) );
  1938. ExFreePool( tempCmList );
  1939. break;
  1940. }
  1941. ExFreePool( tempCmList );
  1942. } // for -- Next driverValueIndex
  1943. if (driverKeyHandle != INVALID_HANDLE) {
  1944. ZwClose( driverKeyHandle);
  1945. driverKeyHandle = INVALID_HANDLE;
  1946. }
  1947. if (status == STATUS_NO_MORE_ENTRIES) {
  1948. status = STATUS_SUCCESS;
  1949. }
  1950. } // while -- Next driverKeyIndex
  1951. if (classKeyHandle != INVALID_HANDLE) {
  1952. ZwClose( classKeyHandle );
  1953. classKeyHandle = INVALID_HANDLE;
  1954. }
  1955. if (status == STATUS_NO_MORE_ENTRIES) {
  1956. status = STATUS_SUCCESS;
  1957. }
  1958. } // while -- next classKeyIndex
  1959. if (status == STATUS_NO_MORE_ENTRIES) {
  1960. status = STATUS_SUCCESS;
  1961. }
  1962. ZwClose( resourceMap );
  1963. ExFreePool( u.buffer );
  1964. //
  1965. // Remember the new global list
  1966. //
  1967. RootDeviceExtension->ResourceList = globalResList;
  1968. return status;
  1969. }