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.

3835 lines
89 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. bus.c
  5. Abstract:
  6. This module contains the bus dispatcher for the ACPI driver, NT version
  7. Author:
  8. Stephane Plante (splante)
  9. Environment:
  10. NT Kernel Model Driver only
  11. --*/
  12. #include "pch.h"
  13. extern ACPI_INTERFACE_STANDARD ACPIInterfaceTable;
  14. LIST_ENTRY AcpiUnresolvedEjectList;
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, ACPIBusAndFilterIrpEject)
  17. #pragma alloc_text(PAGE, ACPIBusAndFilterIrpQueryCapabilities)
  18. #pragma alloc_text(PAGE, ACPIBusAndFilterIrpQueryEjectRelations)
  19. #pragma alloc_text(PAGE, ACPIBusAndFilterIrpQueryPnpDeviceState)
  20. #pragma alloc_text(PAGE, ACPIBusAndFilterIrpSetLock)
  21. #pragma alloc_text(PAGE, ACPIBusIrpCancelRemoveOrStopDevice)
  22. #pragma alloc_text(PAGE, ACPIBusIrpDeviceUsageNotification)
  23. #pragma alloc_text(PAGE, ACPIBusIrpEject)
  24. #pragma alloc_text(PAGE, ACPIBusIrpQueryBusInformation)
  25. #pragma alloc_text(PAGE, ACPIBusIrpQueryBusRelations)
  26. #pragma alloc_text(PAGE, ACPIBusIrpQueryCapabilities)
  27. #pragma alloc_text(PAGE, ACPIBusIrpQueryDeviceRelations)
  28. #pragma alloc_text(PAGE, ACPIBusIrpQueryId)
  29. #pragma alloc_text(PAGE, ACPIBusIrpQueryInterface)
  30. #pragma alloc_text(PAGE, ACPIBusIrpQueryPnpDeviceState)
  31. #pragma alloc_text(PAGE, ACPIBusIrpQueryRemoveOrStopDevice)
  32. #pragma alloc_text(PAGE, ACPIBusIrpQueryResourceRequirements)
  33. #pragma alloc_text(PAGE, ACPIBusIrpQueryResources)
  34. #pragma alloc_text(PAGE, ACPIBusIrpQueryTargetRelation)
  35. #pragma alloc_text(PAGE, ACPIBusIrpSetLock)
  36. #pragma alloc_text(PAGE, ACPIBusIrpStartDevice)
  37. #pragma alloc_text(PAGE, ACPIBusIrpStartDeviceWorker)
  38. #pragma alloc_text(PAGE, ACPIBusIrpStopDevice)
  39. #pragma alloc_text(PAGE, SmashInterfaceQuery)
  40. #endif
  41. PDEVICE_EXTENSION DebugExtension = NULL;
  42. NTSTATUS
  43. ACPIBusAndFilterIrpEject(
  44. IN PDEVICE_OBJECT DeviceObject,
  45. IN PIRP Irp,
  46. IN PVOID Context,
  47. IN BOOLEAN ProcessingFilterIrp
  48. )
  49. /*++
  50. Routine Description:
  51. This routine is the dispatch point for the IRP_MN_EJECT requests sent to
  52. the PDO.
  53. Arguments:
  54. DeviceObject - Pointer to the device object we received the request for
  55. Irp - Pointer to the request
  56. Return Value:
  57. NTSTATUS
  58. --*/
  59. {
  60. NTSTATUS status = Irp->IoStatus.Status;
  61. PDEVICE_EXTENSION deviceExtension;
  62. PNSOBJ acpiObject;
  63. PDEVICE_EXTENSION parentExtension = NULL;
  64. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  65. UCHAR minorFunction = irpStack->MinorFunction;
  66. ULONG i;
  67. KIRQL oldIrql;
  68. PAGED_CODE();
  69. //
  70. // Get the device extension and acpi object
  71. //
  72. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  73. acpiObject = deviceExtension->AcpiObject;
  74. if ( acpiObject == NULL) {
  75. //
  76. // Don't touch this one
  77. //
  78. status = STATUS_NOT_SUPPORTED;
  79. goto ACPIBusAndFilterIrpEjectExit ;
  80. }
  81. if ( (deviceExtension->DeviceState != Inactive) &&
  82. (deviceExtension->DeviceState != Stopped) ) {
  83. //
  84. // We got called to eject a live node! Yuck, how did this happen?!
  85. //
  86. ACPIDevPrint( (
  87. ACPI_PRINT_FAILURE,
  88. deviceExtension,
  89. "(0x%08lx): ACPIBusAndFilterIrpEject: Active node!\n",
  90. Irp
  91. ) );
  92. status = STATUS_UNSUCCESSFUL ;
  93. goto ACPIBusAndFilterIrpEjectExit ;
  94. }
  95. //
  96. // Bye bye card.
  97. //
  98. ACPIGetNothingEvalIntegerSync(
  99. deviceExtension,
  100. PACKED_EJ0,
  101. 1
  102. );
  103. //
  104. // If this is an eject in S0, make the device go away immediately
  105. // by getting the currrent device status
  106. //
  107. status = ACPIGetDevicePresenceSync(
  108. deviceExtension,
  109. (PVOID *) &i,
  110. NULL
  111. );
  112. if (NT_SUCCESS(status) &&
  113. (!ProcessingFilterIrp) &&
  114. (!(deviceExtension->Flags & DEV_TYPE_NOT_PRESENT))) {
  115. ACPIDevPrint( (
  116. ACPI_PRINT_FAILURE,
  117. deviceExtension,
  118. "(0x%08lx): ACPIBusAndFilterIrpEject: "
  119. "device is still listed as present after _EJ0!\n",
  120. Irp
  121. ) );
  122. //
  123. // The device did not go away. Let us fail this IRP.
  124. //
  125. status = STATUS_UNSUCCESSFUL;
  126. }
  127. ACPIBusAndFilterIrpEjectExit:
  128. //
  129. // done
  130. //
  131. ACPIDevPrint( (
  132. ACPI_PRINT_IRP,
  133. deviceExtension,
  134. "(%#08lx): %s = %#08lx\n",
  135. Irp,
  136. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  137. status
  138. ) );
  139. return status;
  140. }
  141. NTSTATUS
  142. ACPIBusAndFilterIrpQueryCapabilities(
  143. IN PDEVICE_OBJECT DeviceObject,
  144. IN PIRP Irp,
  145. IN PVOID Context,
  146. IN BOOLEAN ProcessingFilterIrp
  147. )
  148. /*++
  149. Routine Description:
  150. This routine handles the IRP_MN_QUERY_CAPABILITIES requests for both
  151. bus and filter devnodes.
  152. Arguments:
  153. DeviceObject - Pointer to the device object we received the request for
  154. Irp - Pointer to the request
  155. Return Value:
  156. NTSTATUS
  157. --*/
  158. {
  159. NTSTATUS status;
  160. PDEVICE_CAPABILITIES capabilities;
  161. PDEVICE_EXTENSION deviceExtension;
  162. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  163. PNSOBJ acpiObject, rmvObject;
  164. UCHAR minorFunction = irpStack->MinorFunction;
  165. ULONG deviceStatus;
  166. ULONG slotUniqueNumber, rmvValue;
  167. PAGED_CODE();
  168. //
  169. // Get the device extension and acpi object
  170. //
  171. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  172. acpiObject = deviceExtension->AcpiObject;
  173. //
  174. // Grab a pointer to the capabilities
  175. //
  176. capabilities = irpStack->Parameters.DeviceCapabilities.Capabilities;
  177. #ifndef HANDLE_BOGUS_CAPS
  178. if (capabilities->Version < 1) {
  179. //
  180. // do not touch irp!
  181. //
  182. status = STATUS_NOT_SUPPORTED;
  183. goto ACPIBusAndFilterIrpQueryCapabilitiesExit;
  184. }
  185. #endif
  186. #if !defined(ACPI_INTERNAL_LOCKING)
  187. //
  188. // An object of this name signifies the node is lockable
  189. //
  190. if (ACPIAmliGetNamedChild( acpiObject, PACKED_LCK) != NULL) {
  191. capabilities->LockSupported = TRUE;
  192. }
  193. #endif
  194. //
  195. // Note presence of _RMV and _EJx methods unless there is a
  196. // capability on the object to the contrary.
  197. //
  198. if ((deviceExtension->Flags & DEV_CAP_NO_REMOVE_OR_EJECT) == 0) {
  199. //
  200. // An object of this name signifies the node is removable,
  201. // unless it's a method which might be trying to tell us the
  202. // device *isn't* removable.
  203. //
  204. rmvObject = ACPIAmliGetNamedChild( acpiObject, PACKED_RMV);
  205. if (rmvObject != NULL) {
  206. if (NSGETOBJTYPE(rmvObject) == OBJTYPE_METHOD) {
  207. //
  208. // Execute the RMV method.
  209. //
  210. status = ACPIGetIntegerSyncValidate(
  211. deviceExtension,
  212. PACKED_RMV,
  213. &rmvValue,
  214. NULL
  215. );
  216. if (NT_SUCCESS(status)) {
  217. capabilities->Removable = rmvValue ? TRUE : FALSE;
  218. } else {
  219. capabilities->Removable = TRUE;
  220. }
  221. } else {
  222. //
  223. // If it's anything other than a method, it means the device is
  224. // removable (even if it's _RMV = 0)
  225. //
  226. capabilities->Removable = TRUE;
  227. }
  228. }
  229. //
  230. // An object of this name signifies the node is ejectable, but we strip
  231. // that away for docks (the profile provider can present these)
  232. //
  233. if (!ACPIDockIsDockDevice(acpiObject)) {
  234. if (ACPIAmliGetNamedChild( acpiObject, PACKED_EJ0) != NULL) {
  235. capabilities->EjectSupported = TRUE;
  236. capabilities->Removable = TRUE;
  237. }
  238. if (ACPIAmliGetNamedChild( acpiObject, PACKED_EJ1) ||
  239. ACPIAmliGetNamedChild( acpiObject, PACKED_EJ2) ||
  240. ACPIAmliGetNamedChild( acpiObject, PACKED_EJ3) ||
  241. ACPIAmliGetNamedChild( acpiObject, PACKED_EJ4)) {
  242. capabilities->WarmEjectSupported = TRUE;
  243. capabilities->Removable = TRUE;
  244. }
  245. }
  246. }
  247. //
  248. // An object of this name will signifies inrush
  249. //
  250. if (ACPIAmliGetNamedChild( acpiObject, PACKED_IRC) != NULL) {
  251. DeviceObject->Flags |= DO_POWER_INRUSH;
  252. }
  253. //
  254. // Is the device disabled?
  255. //
  256. status = ACPIGetDevicePresenceSync(
  257. deviceExtension,
  258. (PVOID *) &deviceStatus,
  259. NULL
  260. );
  261. if (!NT_SUCCESS(status)) {
  262. goto ACPIBusAndFilterIrpQueryCapabilitiesExit;
  263. }
  264. if (!(deviceExtension->Flags & DEV_PROP_DEVICE_ENABLED)) {
  265. if (ACPIAmliGetNamedChild( acpiObject, PACKED_CRS) != NULL &&
  266. ACPIAmliGetNamedChild( acpiObject, PACKED_SRS) == NULL) {
  267. capabilities->HardwareDisabled = 1;
  268. } else if (ProcessingFilterIrp) {
  269. capabilities->HardwareDisabled = 0;
  270. }
  271. } else if (!ProcessingFilterIrp) {
  272. //
  273. // For machines with this attribute set, this means that the
  274. // hardware REALLY isn't present and should always be reported
  275. // as disabled
  276. //
  277. if (AcpiOverrideAttributes & ACPI_OVERRIDE_STA_CHECK) {
  278. capabilities->HardwareDisabled = 1;
  279. } else {
  280. capabilities->HardwareDisabled = 0;
  281. }
  282. }
  283. //
  284. // If we fail the START_DEVICE, then there are some cases where we don't
  285. // want the device to show up in the Device Manager. So try to report this
  286. // capability based on the information from the device presence...
  287. //
  288. if (!(deviceStatus & STA_STATUS_USER_INTERFACE)) {
  289. //
  290. // See the bit that says that we shouldn't the device in the UI if
  291. // the Start Device Fails
  292. //
  293. capabilities->NoDisplayInUI = 1;
  294. }
  295. //
  296. // Determine the slot number
  297. //
  298. if (ACPIAmliGetNamedChild( acpiObject, PACKED_SUN) != NULL) {
  299. //
  300. // If we have UINumber information, use it.
  301. //
  302. status = ACPIGetIntegerSync(
  303. deviceExtension,
  304. PACKED_SUN,
  305. &slotUniqueNumber,
  306. NULL
  307. );
  308. if (NT_SUCCESS(status)) {
  309. capabilities->UINumber = slotUniqueNumber;
  310. }
  311. }
  312. //
  313. // Is there an address?
  314. //
  315. if (ACPIAmliGetNamedChild( acpiObject, PACKED_ADR) != NULL) {
  316. status = ACPIGetAddressSync(
  317. deviceExtension,
  318. &(capabilities->Address),
  319. NULL
  320. );
  321. if (!NT_SUCCESS(status)) {
  322. ACPIDevPrint( (
  323. ACPI_PRINT_CRITICAL,
  324. deviceExtension,
  325. " - Could query device address - %08lx",
  326. status
  327. ) );
  328. goto ACPIBusAndFilterIrpQueryCapabilitiesExit;
  329. }
  330. }
  331. //
  332. // Do the power capabilities
  333. //
  334. status = ACPISystemPowerQueryDeviceCapabilities(
  335. deviceExtension,
  336. capabilities
  337. );
  338. if (!NT_SUCCESS(status)) {
  339. ACPIDevPrint( (
  340. ACPI_PRINT_CRITICAL,
  341. deviceExtension,
  342. " - Could query device capabilities - %08lx",
  343. status
  344. ) );
  345. goto ACPIBusAndFilterIrpQueryCapabilitiesExit;
  346. }
  347. //
  348. // Set the current flags for the capabilities
  349. //
  350. if (!ProcessingFilterIrp) {
  351. //
  352. // Set some rather boolean capabilities
  353. //
  354. capabilities->SilentInstall = TRUE;
  355. capabilities->RawDeviceOK =
  356. (deviceExtension->Flags & DEV_CAP_RAW) ? TRUE : FALSE;
  357. capabilities->UniqueID =
  358. (deviceExtension->InstanceID == NULL ? FALSE : TRUE);
  359. //
  360. // In the filter case, we will just let the underlying pdo determine the
  361. // success or failure of the irp.
  362. //
  363. status = STATUS_SUCCESS;
  364. }
  365. ACPIBusAndFilterIrpQueryCapabilitiesExit:
  366. ACPIDevPrint( (
  367. ACPI_PRINT_IRP,
  368. deviceExtension,
  369. "(0x%08lx): %s = 0x%08lx\n",
  370. Irp,
  371. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  372. status
  373. ) );
  374. return status;
  375. }
  376. NTSTATUS
  377. ACPIBusAndFilterIrpQueryEjectRelations(
  378. IN PDEVICE_OBJECT DeviceObject,
  379. IN PIRP Irp,
  380. IN OUT PDEVICE_RELATIONS *DeviceRelations
  381. )
  382. {
  383. PDEVICE_EXTENSION deviceExtension, additionalExtension;
  384. PNSOBJ acpiObject;
  385. NTSTATUS status ;
  386. PAGED_CODE();
  387. //
  388. // Get the device extension and acpi object
  389. //
  390. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  391. acpiObject = deviceExtension->AcpiObject;
  392. //
  393. // lets look at the ACPIObject that we have so can see if it is valid...
  394. //
  395. if (acpiObject == NULL) {
  396. //
  397. // Invalid name space object <bad>
  398. //
  399. ACPIDevPrint( (
  400. ACPI_PRINT_CRITICAL,
  401. deviceExtension,
  402. "(0x%08lx): ACPIBusAndFilterIrpQueryEjectRelations: "
  403. "invalid ACPIObject (0x%08lx)\n",
  404. Irp,
  405. acpiObject
  406. ) );
  407. //
  408. // Mark the irp as very bad...
  409. //
  410. return STATUS_INVALID_PARAMETER;
  411. }
  412. //
  413. // Mark sure _DCK nodes have ejection relations that include their fake
  414. // dock nodes.
  415. //
  416. if (ACPIDockIsDockDevice(acpiObject)) {
  417. additionalExtension = ACPIDockFindCorrespondingDock( deviceExtension );
  418. } else {
  419. additionalExtension = NULL;
  420. }
  421. status = ACPIDetectEjectDevices(
  422. deviceExtension,
  423. DeviceRelations,
  424. additionalExtension
  425. );
  426. //
  427. // If something went wrong...
  428. //
  429. if (!NT_SUCCESS(status)) {
  430. //
  431. // That's not nice..
  432. //
  433. ACPIDevPrint( (
  434. ACPI_PRINT_CRITICAL,
  435. deviceExtension,
  436. "ACPIBusAndFilterIrpQueryEjectRelations: enum = 0x%08lx\n",
  437. Irp,
  438. status
  439. ) );
  440. }
  441. //
  442. // Done
  443. //
  444. return status ;
  445. }
  446. NTSTATUS
  447. ACPIBusAndFilterIrpQueryPnpDeviceState(
  448. IN PDEVICE_OBJECT DeviceObject,
  449. IN PIRP Irp,
  450. IN PVOID Context,
  451. IN BOOLEAN ProcessingFilterIrp
  452. )
  453. /*++
  454. Routine Description:
  455. This routines tells the system what PNP state the device is in
  456. Arguments:
  457. DeviceObject - The device whose state we want to know
  458. Irp - The request
  459. ProcessingFilterIrp - Are we a filter or not?
  460. Return Value:
  461. NTSTATUS
  462. --*/
  463. {
  464. BOOLEAN staPresent;
  465. NTSTATUS status = STATUS_SUCCESS;
  466. PDEVICE_EXTENSION deviceExtension;
  467. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  468. PNSOBJ nsObj = NULL;
  469. UCHAR minorFunction = irpStack->MinorFunction;
  470. ULONG deviceStatus;
  471. PAGED_CODE();
  472. //
  473. // Get the device extension
  474. //
  475. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  476. //
  477. // We base some of the decisions on wether or not a _STA is *really*
  478. // present or not. Determine that now
  479. //
  480. if ( !(deviceExtension->Flags & DEV_PROP_NO_OBJECT) ) {
  481. nsObj = ACPIAmliGetNamedChild(
  482. deviceExtension->AcpiObject,
  483. PACKED_STA
  484. );
  485. }
  486. staPresent = (nsObj == NULL ? FALSE : TRUE);
  487. //
  488. // Get the device status
  489. //
  490. status = ACPIGetDevicePresenceSync(
  491. deviceExtension,
  492. (PVOID *) &deviceStatus,
  493. NULL
  494. );
  495. if (!NT_SUCCESS(status)) {
  496. goto ACPIBusAndFilterIrpQueryPnpDeviceStateExit;
  497. }
  498. //
  499. // do we show this in the UI?
  500. //
  501. if (deviceExtension->Flags & DEV_CAP_NEVER_SHOW_IN_UI) {
  502. Irp->IoStatus.Information |= PNP_DEVICE_DONT_DISPLAY_IN_UI;
  503. } else if (deviceExtension->Flags & DEV_CAP_NO_SHOW_IN_UI) {
  504. Irp->IoStatus.Information |= PNP_DEVICE_DONT_DISPLAY_IN_UI;
  505. } else if (staPresent || !ProcessingFilterIrp) {
  506. Irp->IoStatus.Information &= ~PNP_DEVICE_DONT_DISPLAY_IN_UI;
  507. }
  508. //
  509. // Is the device not working?
  510. //
  511. if (deviceExtension->Flags & DEV_PROP_DEVICE_FAILED) {
  512. Irp->IoStatus.Information |= PNP_DEVICE_FAILED;
  513. } else if (staPresent && !ProcessingFilterIrp) {
  514. Irp->IoStatus.Information &= ~PNP_DEVICE_FAILED;
  515. }
  516. //
  517. // Can we disable this device?
  518. // Note that anything that isn't a regular device should be
  519. // marked as disableable...
  520. //
  521. if (!(deviceExtension->Flags & DEV_PROP_NO_OBJECT) &&
  522. !(deviceExtension->Flags & DEV_CAP_PROCESSOR) &&
  523. !(deviceExtension->Flags & DEV_CAP_THERMAL_ZONE) &&
  524. !(deviceExtension->Flags & DEV_CAP_BUTTON) ) {
  525. if (!ProcessingFilterIrp) {
  526. //
  527. // Can we actually disable the device?
  528. // Note --- this requires an _DIS, a _PS3, or a _PR0
  529. //
  530. nsObj = ACPIAmliGetNamedChild(
  531. deviceExtension->AcpiObject,
  532. PACKED_DIS
  533. );
  534. if (nsObj == NULL) {
  535. nsObj = ACPIAmliGetNamedChild(
  536. deviceExtension->AcpiObject,
  537. PACKED_PS3
  538. );
  539. }
  540. if (nsObj == NULL) {
  541. nsObj = ACPIAmliGetNamedChild(
  542. deviceExtension->AcpiObject,
  543. PACKED_PR0
  544. );
  545. }
  546. if (deviceExtension->Flags & DEV_CAP_NO_STOP) {
  547. nsObj = NULL;
  548. }
  549. if (nsObj == NULL) {
  550. Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
  551. }
  552. } else {
  553. //
  554. // Can we actually disable the device?
  555. // Note --- this requires an _DIS, a _PS3, or a _PR0
  556. //
  557. nsObj = ACPIAmliGetNamedChild(
  558. deviceExtension->AcpiObject,
  559. PACKED_DIS
  560. );
  561. if (nsObj == NULL) {
  562. nsObj = ACPIAmliGetNamedChild(
  563. deviceExtension->AcpiObject,
  564. PACKED_PS3
  565. );
  566. }
  567. if (nsObj == NULL) {
  568. nsObj = ACPIAmliGetNamedChild(
  569. deviceExtension->AcpiObject,
  570. PACKED_PR0
  571. );
  572. }
  573. if (deviceExtension->Flags & DEV_CAP_NO_STOP) {
  574. nsObj = NULL;
  575. }
  576. if (nsObj != NULL) {
  577. Irp->IoStatus.Information &= ~PNP_DEVICE_NOT_DISABLEABLE;
  578. }
  579. }
  580. } else {
  581. //
  582. // If we have no device object...
  583. //
  584. if (deviceExtension->Flags & DEV_CAP_NO_STOP) {
  585. Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
  586. }
  587. }
  588. ACPIBusAndFilterIrpQueryPnpDeviceStateExit:
  589. ACPIDevPrint( (
  590. ACPI_PRINT_PNP_STATE,
  591. deviceExtension,
  592. ":%s%s%s%s%s%s\n",
  593. ( (Irp->IoStatus.Information & PNP_DEVICE_DISABLED) ? " Disabled" : ""),
  594. ( (Irp->IoStatus.Information & PNP_DEVICE_DONT_DISPLAY_IN_UI) ? " NoShowInUi" : ""),
  595. ( (Irp->IoStatus.Information & PNP_DEVICE_FAILED) ? " Failed" : ""),
  596. ( (Irp->IoStatus.Information & PNP_DEVICE_REMOVED) ? " Removed" : ""),
  597. ( (Irp->IoStatus.Information & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED) ? " ResourceChanged" : ""),
  598. ( (Irp->IoStatus.Information & PNP_DEVICE_NOT_DISABLEABLE) ? " NoDisable" : "")
  599. ) );
  600. //
  601. // Done
  602. //
  603. ACPIDevPrint( (
  604. ACPI_PRINT_IRP,
  605. deviceExtension,
  606. "(0x%08lx): %s = 0x%08lx\n",
  607. Irp,
  608. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  609. status
  610. ) );
  611. return status;
  612. }
  613. NTSTATUS
  614. ACPIBusAndFilterIrpSetLock(
  615. IN PDEVICE_OBJECT DeviceObject,
  616. IN PIRP Irp,
  617. IN PVOID Context,
  618. IN BOOLEAN ProcessingFilterIrp
  619. )
  620. /*++
  621. Routine Description:
  622. This handles lock and unlock requests for PDO's or filters...
  623. Arguments:
  624. DeviceObject - The device to stop
  625. Irp - The request to tell us how to do it...
  626. Return Value:
  627. NTSTATUS
  628. --*/
  629. {
  630. NTSTATUS status = Irp->IoStatus.Status;
  631. PDEVICE_EXTENSION deviceExtension;
  632. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  633. UCHAR minorFunction = irpStack->MinorFunction;
  634. BOOLEAN lockParameter = irpStack->Parameters.SetLock.Lock;
  635. ULONG acpiLockArg ;
  636. NTSTATUS lockStatus ;
  637. PAGED_CODE();
  638. //
  639. // Get the device extension
  640. //
  641. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  642. #if !defined(ACPI_INTERNAL_LOCKING)
  643. //
  644. // Attempt to lock/unlock the device as appropriate
  645. //
  646. acpiLockArg = ((lockParameter) ? 1 : 0) ;
  647. //
  648. // Here we go...
  649. //
  650. #if 0
  651. lockStatus = ACPIGetNothingEvalIntegerSync(
  652. deviceExtension,
  653. PACKED_LCK,
  654. acpiLockArg
  655. );
  656. #endif
  657. if (status == STATUS_NOT_SUPPORTED) {
  658. status = STATUS_SUCCESS ;
  659. }
  660. #endif
  661. //
  662. // done
  663. //
  664. ACPIDevPrint( (
  665. ACPI_PRINT_IRP,
  666. deviceExtension,
  667. "(%#08lx): %s = %#08lx\n",
  668. Irp,
  669. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  670. status
  671. ) );
  672. return status;
  673. }
  674. NTSTATUS
  675. ACPIBusIrpCancelRemoveOrStopDevice(
  676. IN PDEVICE_OBJECT DeviceObject,
  677. IN PIRP Irp
  678. )
  679. /*++
  680. Routine Description:
  681. This routine is called when we no longer wish to remove or stop the device
  682. object
  683. Arguments:
  684. DeviceObject - The device object to be removed
  685. Irp - The request
  686. Return Value:
  687. NTSTATUS
  688. --*/
  689. {
  690. NTSTATUS status = STATUS_SUCCESS;
  691. PDEVICE_EXTENSION deviceExtension;
  692. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  693. UCHAR minorFunction = irpStack->MinorFunction;
  694. PAGED_CODE();
  695. //
  696. // Get the device extension and acpi object
  697. //
  698. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  699. //
  700. // Were we allowed to stop the device?
  701. //
  702. if (!(deviceExtension->Flags & DEV_CAP_NO_STOP) ) {
  703. //
  704. // Check to see if we have placed this device in the inactive state
  705. //
  706. if (deviceExtension->DeviceState == Inactive) {
  707. //
  708. // Mark the device extension as being started
  709. //
  710. deviceExtension->DeviceState = deviceExtension->PreviousState;
  711. }
  712. }
  713. //
  714. // Complete the irp
  715. //
  716. Irp->IoStatus.Status = status;
  717. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  718. //
  719. // Done
  720. //
  721. ACPIDevPrint( (
  722. ACPI_PRINT_IRP,
  723. deviceExtension,
  724. "(0x%08lx): %s = 0x%08lx\n",
  725. Irp,
  726. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  727. status
  728. ) );
  729. return status;
  730. }
  731. NTSTATUS
  732. ACPIBusIrpDeviceUsageNotification(
  733. IN PDEVICE_OBJECT DeviceObject,
  734. IN PIRP Irp
  735. )
  736. /*++
  737. Routine Description:
  738. This routine is called to let ACPI know that the device is on one
  739. particular type of path
  740. Arguments:
  741. DeviceObject - Pointer to the device object we received the request for
  742. Irp - Pointer to the request
  743. Return Value:
  744. NTSTATUS
  745. --*/
  746. {
  747. NTSTATUS status = STATUS_SUCCESS;
  748. PDEVICE_EXTENSION deviceExtension;
  749. PDEVICE_OBJECT parentObject;
  750. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  751. PAGED_CODE();
  752. //
  753. // Get the device extension
  754. //
  755. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  756. //
  757. // Do we have a parent extension?
  758. //
  759. if (deviceExtension->ParentExtension != NULL) {
  760. //
  761. // Get the parents stack
  762. //
  763. parentObject = deviceExtension->ParentExtension->DeviceObject;
  764. if (parentObject == NULL) {
  765. //
  766. // Fail because we don't have a device object
  767. //
  768. status = STATUS_NO_SUCH_DEVICE;
  769. goto ACPIBusIrpDeviceUsageNotificationExit;
  770. }
  771. //
  772. // Send a synchronous irp down and wait for the result
  773. //
  774. status = ACPIInternalSendSynchronousIrp(
  775. parentObject,
  776. irpSp,
  777. NULL
  778. );
  779. }
  780. //
  781. // Did we succeed
  782. //
  783. if (NT_SUCCESS(status)) {
  784. //
  785. // Do we care about the usage type?
  786. //
  787. if (irpSp->Parameters.UsageNotification.Type ==
  788. DeviceUsageTypeHibernation) {
  789. //
  790. // Yes --- then perform the addition or subtraction required
  791. //
  792. IoAdjustPagingPathCount(
  793. &(deviceExtension->HibernatePathCount),
  794. irpSp->Parameters.UsageNotification.InPath
  795. );
  796. }
  797. }
  798. ACPIBusIrpDeviceUsageNotificationExit:
  799. //
  800. // Complete the request
  801. //
  802. Irp->IoStatus.Status = status;
  803. Irp->IoStatus.Information = 0;
  804. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  805. ACPIDevPrint( (
  806. ACPI_PRINT_IRP,
  807. deviceExtension,
  808. "(0x%08lx): %s = 0x%08lx\n",
  809. Irp,
  810. ACPIDebugGetIrpText(IRP_MJ_PNP, IRP_MN_DEVICE_USAGE_NOTIFICATION),
  811. status
  812. ) );
  813. //
  814. // Done
  815. //
  816. return status;
  817. }
  818. NTSTATUS
  819. ACPIBusIrpEject(
  820. IN PDEVICE_OBJECT DeviceObject,
  821. IN PIRP Irp
  822. )
  823. /*++
  824. Routine Description:
  825. This routine is the dispatch point for the IRP_MN_EJECT requests sent to
  826. the PDO.
  827. Arguments:
  828. DeviceObject - Pointer to the device object we received the request for
  829. Irp - Pointer to the request
  830. Return Value:
  831. NTSTATUS
  832. --*/
  833. {
  834. PAGED_CODE();
  835. return ACPIIrpInvokeDispatchRoutine(
  836. DeviceObject,
  837. Irp,
  838. NULL,
  839. ACPIBusAndFilterIrpEject,
  840. FALSE,
  841. TRUE
  842. );
  843. }
  844. NTSTATUS
  845. ACPIBusIrpQueryBusInformation(
  846. IN PDEVICE_OBJECT DeviceObject,
  847. IN PIRP Irp
  848. )
  849. /*++
  850. Routine Description:
  851. This is only called if the device is of the special type PNP0A06
  852. (EIO Bus). This is because we need to tell the system that this is
  853. the ISA bus
  854. Arguments:
  855. DeviceObject - Pointer to the device object we received the request for
  856. Irp - Pointer to the request
  857. Return Value:
  858. NTSTATUS
  859. --*/
  860. {
  861. NTSTATUS status = STATUS_SUCCESS;
  862. PPNP_BUS_INFORMATION busInfo = NULL;
  863. PAGED_CODE();
  864. //
  865. // Allocate some memory to return the information
  866. //
  867. busInfo = ExAllocatePoolWithTag(
  868. PagedPool,
  869. sizeof(PNP_BUS_INFORMATION),
  870. ACPI_MISC_POOLTAG
  871. );
  872. if (busInfo != NULL) {
  873. //
  874. // The BusNumber = 0 might come back and haunt us
  875. //
  876. // Fill in the record
  877. //
  878. busInfo->BusTypeGuid = GUID_BUS_TYPE_ISAPNP;
  879. busInfo->LegacyBusType = Isa;
  880. busInfo->BusNumber = 0;
  881. } else {
  882. ACPIDevPrint( (
  883. ACPI_PRINT_CRITICAL,
  884. DeviceObject->DeviceExtension,
  885. "ACPIBusIrpQueryBusInformation: Could not allocate 0x%08lx bytes\n",
  886. sizeof(PNP_BUS_INFORMATION)
  887. ) );
  888. status = STATUS_INSUFFICIENT_RESOURCES;
  889. }
  890. //
  891. // Done with the request
  892. //
  893. Irp->IoStatus.Status = status;
  894. Irp->IoStatus.Information = (ULONG_PTR) busInfo;
  895. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  896. //
  897. // Done
  898. //
  899. return status;
  900. }
  901. NTSTATUS
  902. ACPIBusIrpQueryBusRelations(
  903. IN PDEVICE_OBJECT DeviceObject,
  904. IN PIRP Irp,
  905. OUT PDEVICE_RELATIONS *DeviceRelations
  906. )
  907. /*++
  908. Routine Description:
  909. This handles DeviceRelations requests sent onto the ACPI driver
  910. Arguments:
  911. DeviceObject - The object that we care about...
  912. Irp - The request in question
  913. Return Value:
  914. NTSTATUS
  915. --*/
  916. {
  917. NTSTATUS filterStatus;
  918. PDEVICE_EXTENSION deviceExtension;
  919. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  920. PNSOBJ acpiObject;
  921. UCHAR minorFunction = irpStack->MinorFunction;
  922. NTSTATUS status ;
  923. PAGED_CODE();
  924. //
  925. // Get the device extension and acpi object
  926. //
  927. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  928. acpiObject = deviceExtension->AcpiObject;
  929. //
  930. // lets look at the ACPIObject that we have so can see if it is valid...
  931. //
  932. if (acpiObject == NULL) {
  933. //
  934. // Invalid name space object <bad>
  935. //
  936. ACPIDevPrint( (
  937. ACPI_PRINT_CRITICAL,
  938. deviceExtension,
  939. "(0x%08lx): ACPIBusIrpQueryDeviceRelations: "
  940. "invalid ACPIObject (0x%08lx)\n",
  941. Irp,
  942. acpiObject
  943. ) );
  944. //
  945. // Mark the irp as very bad...
  946. //
  947. return STATUS_INVALID_PARAMETER;
  948. }
  949. //
  950. // Active the code to detect unenumerated devices...
  951. //
  952. status = ACPIDetectPdoDevices(
  953. DeviceObject,
  954. DeviceRelations
  955. );
  956. //
  957. // If something went wrong...
  958. //
  959. if (!NT_SUCCESS(status)) {
  960. //
  961. // Ouch bad..
  962. //
  963. ACPIDevPrint( (
  964. ACPI_PRINT_CRITICAL,
  965. deviceExtension,
  966. "(0x%08lx): ACPIBusIrpQueryDeviceRelations: enum = 0x%08lx\n",
  967. Irp,
  968. status
  969. ) );
  970. } else {
  971. //
  972. // Load the filters
  973. //
  974. filterStatus = ACPIDetectFilterDevices(
  975. DeviceObject,
  976. *DeviceRelations
  977. );
  978. if (!NT_SUCCESS(filterStatus)) {
  979. //
  980. // Filter Operation failed
  981. //
  982. ACPIDevPrint( (
  983. ACPI_PRINT_CRITICAL,
  984. deviceExtension,
  985. "(0x%08lx): ACPIBusIrpQueryDeviceRelations: filter = 0x%08lx\n",
  986. Irp,
  987. filterStatus
  988. ) );
  989. }
  990. }
  991. //
  992. // Done
  993. //
  994. return status ;
  995. }
  996. NTSTATUS
  997. ACPIBusIrpQueryCapabilities(
  998. IN PDEVICE_OBJECT DeviceObject,
  999. IN PIRP Irp
  1000. )
  1001. /*++
  1002. Routine Description:
  1003. This routine is the dispatch point for the IRP_MN_QUERY_CAPABILITIES requests sent
  1004. to the PDO
  1005. Arguments:
  1006. DeviceObject - Pointer to the device object we received the request for
  1007. Irp - Pointer to the request
  1008. Return Value:
  1009. NTSTATUS
  1010. --*/
  1011. {
  1012. PAGED_CODE();
  1013. ACPIDebugEnter( "ACPIBusIrpQueryCapabilities" );
  1014. return ACPIIrpInvokeDispatchRoutine(
  1015. DeviceObject,
  1016. Irp,
  1017. NULL,
  1018. ACPIBusAndFilterIrpQueryCapabilities,
  1019. TRUE,
  1020. TRUE
  1021. );
  1022. ACPIDebugExit( "ACPIBusIrpQueryCapabilities" );
  1023. }
  1024. NTSTATUS
  1025. ACPIBusIrpQueryDeviceRelations(
  1026. IN PDEVICE_OBJECT DeviceObject,
  1027. IN PIRP Irp
  1028. )
  1029. /*++
  1030. Routine Description:
  1031. This handles DeviceRelations requests sent onto the ACPI driver
  1032. Arguments:
  1033. DeviceObject - The object that we care about...
  1034. Irp - The request in question
  1035. Return Value:
  1036. NTSTATUS
  1037. --*/
  1038. {
  1039. NTSTATUS status ;
  1040. PDEVICE_EXTENSION deviceExtension;
  1041. PDEVICE_RELATIONS deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
  1042. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  1043. UCHAR minorFunction = irpStack->MinorFunction;
  1044. PAGED_CODE();
  1045. //
  1046. // Get the device extension
  1047. //
  1048. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  1049. //
  1050. // Fork off to the appropriate query relations subtype function
  1051. //
  1052. switch(irpStack->Parameters.QueryDeviceRelations.Type) {
  1053. case TargetDeviceRelation:
  1054. status = ACPIBusIrpQueryTargetRelation(
  1055. DeviceObject,
  1056. Irp,
  1057. &deviceRelations
  1058. );
  1059. break ;
  1060. case BusRelations:
  1061. status = ACPIBusIrpQueryBusRelations(
  1062. DeviceObject,
  1063. Irp,
  1064. &deviceRelations
  1065. );
  1066. break ;
  1067. case EjectionRelations:
  1068. status = ACPIBusAndFilterIrpQueryEjectRelations(
  1069. DeviceObject,
  1070. Irp,
  1071. &deviceRelations
  1072. );
  1073. break ;
  1074. default:
  1075. status = STATUS_NOT_SUPPORTED;
  1076. ACPIDevPrint( (
  1077. ACPI_PRINT_IRP,
  1078. deviceExtension,
  1079. "(0x%08lx): %s - Unhandled Type %d\n",
  1080. Irp,
  1081. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  1082. irpStack->Parameters.QueryDeviceRelations.Type
  1083. ) );
  1084. break ;
  1085. }
  1086. //
  1087. // If we succeeds, then we can always write to the irp
  1088. //
  1089. if (NT_SUCCESS(status)) {
  1090. Irp->IoStatus.Status = status;
  1091. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  1092. } else if ( (status != STATUS_NOT_SUPPORTED) &&
  1093. (deviceRelations == NULL) ) {
  1094. //
  1095. // We explicitely failed the irp, and nobody above us had anything to
  1096. // add.
  1097. //
  1098. Irp->IoStatus.Status = status;
  1099. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  1100. } else {
  1101. //
  1102. // Either we haven't touched the IRP or existing children were already
  1103. // present (placed there by an FDO). Grab our status from what is
  1104. // already present.
  1105. //
  1106. status = Irp->IoStatus.Status;
  1107. }
  1108. //
  1109. // Done with the irp
  1110. //
  1111. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1112. //
  1113. // Done
  1114. //
  1115. ACPIDevPrint( (
  1116. ACPI_PRINT_IRP,
  1117. deviceExtension,
  1118. "(0x%08lx): %s = 0x%08lx\n",
  1119. Irp,
  1120. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  1121. status
  1122. ) );
  1123. return status;
  1124. }
  1125. NTSTATUS
  1126. ACPIBusIrpQueryId(
  1127. IN PDEVICE_OBJECT DeviceObject,
  1128. IN PIRP Irp
  1129. )
  1130. /*++
  1131. Routine Description:
  1132. This routine is the dispatch point for the IRP_MN_QUERY_ID PNP
  1133. minor function
  1134. Note: This is what the returned strings from this function should look
  1135. like. This is from mail that lonny sent.
  1136. DeviceID = ACPI\PNPxxxx
  1137. InstanceID = yyyy
  1138. HardwareID = ACPI\PNPxxxx,*PNPxxxx
  1139. Arguments:
  1140. DeviceObject - The object that we care about
  1141. Irp - The request in question
  1142. Return Value:
  1143. NTSTATUS
  1144. --*/
  1145. {
  1146. BUS_QUERY_ID_TYPE type;
  1147. NTSTATUS status = Irp->IoStatus.Status;
  1148. PDEVICE_EXTENSION deviceExtension;
  1149. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  1150. PUCHAR baseBuffer;
  1151. ULONG baseBufferSize;
  1152. UCHAR minorFunction = irpStack->MinorFunction;
  1153. PAGED_CODE();
  1154. //
  1155. // Get the device extension
  1156. //
  1157. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  1158. //
  1159. // What we do is based on the IdType of the Request...
  1160. //
  1161. type = irpStack->Parameters.QueryId.IdType;
  1162. switch (type) {
  1163. case BusQueryCompatibleIDs:
  1164. //
  1165. // This returns a MULTI-SZ wide string...
  1166. //
  1167. status = ACPIGetCompatibleIDSyncWide(
  1168. deviceExtension,
  1169. &baseBuffer,
  1170. &baseBufferSize
  1171. );
  1172. if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  1173. status = STATUS_NOT_SUPPORTED;
  1174. break;
  1175. } else if (!NT_SUCCESS(status)) {
  1176. ACPIDevPrint( (
  1177. ACPI_PRINT_FAILURE,
  1178. deviceExtension,
  1179. " (0x%08lx): IRP_MN_QUERY_ID( %d - CID) = 0x%08lx\n",
  1180. Irp,
  1181. type,
  1182. status
  1183. ) );
  1184. break;
  1185. }
  1186. //
  1187. // Store the result in the Irp
  1188. //
  1189. Irp->IoStatus.Information = (ULONG_PTR) baseBuffer;
  1190. break;
  1191. case BusQueryInstanceID:
  1192. //
  1193. // In this case, we have to build the instance id
  1194. //
  1195. status = ACPIGetInstanceIDSyncWide(
  1196. deviceExtension,
  1197. &baseBuffer,
  1198. &baseBufferSize
  1199. );
  1200. if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  1201. status = STATUS_NOT_SUPPORTED;
  1202. break;
  1203. } else if (!NT_SUCCESS(status)) {
  1204. ACPIDevPrint( (
  1205. ACPI_PRINT_FAILURE,
  1206. deviceExtension,
  1207. " (0x%08lx): IRP_MN_QUERY_ID( %d - UID) = 0x%08lx\n",
  1208. Irp,
  1209. type,
  1210. status
  1211. ) );
  1212. break;
  1213. }
  1214. //
  1215. // Store the result in the Irp
  1216. //
  1217. Irp->IoStatus.Information = (ULONG_PTR) baseBuffer;
  1218. break;
  1219. case BusQueryDeviceID:
  1220. //
  1221. // Get the Device ID as a wide string
  1222. //
  1223. status = ACPIGetDeviceIDSyncWide(
  1224. deviceExtension,
  1225. &baseBuffer,
  1226. &baseBufferSize
  1227. );
  1228. if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  1229. status = STATUS_NOT_SUPPORTED;
  1230. break;
  1231. } else if (!NT_SUCCESS(status)) {
  1232. ACPIDevPrint( (
  1233. ACPI_PRINT_FAILURE,
  1234. deviceExtension,
  1235. " (0x%08lx): IRP_MN_QUERY_ID( %d - HID) = 0x%08lx\n",
  1236. Irp,
  1237. type,
  1238. status
  1239. ) );
  1240. break;
  1241. }
  1242. //
  1243. // Store the result in the Irp
  1244. //
  1245. Irp->IoStatus.Information = (ULONG_PTR) baseBuffer;
  1246. break;
  1247. case BusQueryHardwareIDs:
  1248. //
  1249. // Get the device ID as a normal string
  1250. //
  1251. status = ACPIGetHardwareIDSyncWide(
  1252. deviceExtension,
  1253. &baseBuffer,
  1254. &baseBufferSize
  1255. );
  1256. if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
  1257. status = STATUS_NOT_SUPPORTED;
  1258. break;
  1259. } else if (!NT_SUCCESS(status)) {
  1260. ACPIDevPrint( (
  1261. ACPI_PRINT_FAILURE,
  1262. deviceExtension,
  1263. " (0x%08lx): IRP_MN_QUERY_ID( %d - UID) = 0x%08lx\n",
  1264. Irp,
  1265. type,
  1266. status
  1267. ) );
  1268. break;
  1269. }
  1270. //
  1271. // Store the result in the Irp
  1272. //
  1273. Irp->IoStatus.Information = (ULONG_PTR) baseBuffer;
  1274. break;
  1275. default:
  1276. ACPIDevPrint( (
  1277. ACPI_PRINT_IRP,
  1278. deviceExtension,
  1279. "(0x%08lx): %s - Unhandled Id %d\n",
  1280. Irp,
  1281. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  1282. type
  1283. ) );
  1284. break;
  1285. } // switch
  1286. //
  1287. // Store the status result of the request and complete it
  1288. //
  1289. Irp->IoStatus.Status = status;
  1290. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1291. ACPIDevPrint( (
  1292. ACPI_PRINT_IRP,
  1293. deviceExtension,
  1294. "(0x%08lx): %s(%d) = 0x%08lx\n",
  1295. Irp,
  1296. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  1297. type,
  1298. status
  1299. ) );
  1300. return status;
  1301. }
  1302. NTSTATUS
  1303. ACPIBusIrpQueryInterface(
  1304. IN PDEVICE_OBJECT DeviceObject,
  1305. IN PIRP Irp
  1306. )
  1307. /*++
  1308. Routine Description:
  1309. This routine handles IRP_MN_QUERY_INTERFACE requests for PDOs owned
  1310. by the ACPI driver. It will eject an 'ACPI' interface and it will
  1311. smash Translator Interfaces for interrupts that have been provided
  1312. by the devnode's FDO.
  1313. Arguments:
  1314. DeviceObject - Pointer to the device object we received the request for
  1315. Irp - Pointer to the request
  1316. Return Value:
  1317. NTSTATUS
  1318. --*/
  1319. {
  1320. CM_RESOURCE_TYPE resource;
  1321. GUID *interfaceType;
  1322. NTSTATUS status = STATUS_NOT_SUPPORTED;
  1323. PDEVICE_EXTENSION deviceExtension;
  1324. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  1325. ULONG count;
  1326. PAGED_CODE();
  1327. //
  1328. // Get the device extension
  1329. //
  1330. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  1331. //
  1332. // Obtain the info we will need from the irp
  1333. //
  1334. resource = (CM_RESOURCE_TYPE)
  1335. PtrToUlong(irpStack->Parameters.QueryInterface.InterfaceSpecificData);
  1336. interfaceType = (LPGUID) irpStack->Parameters.QueryInterface.InterfaceType;
  1337. #if DBG
  1338. {
  1339. NTSTATUS status2;
  1340. UNICODE_STRING guidString;
  1341. status2 = RtlStringFromGUID( interfaceType, &guidString );
  1342. if (NT_SUCCESS(status2)) {
  1343. ACPIDevPrint( (
  1344. ACPI_PRINT_IRP,
  1345. deviceExtension,
  1346. "(0x%08lx): %s - Res %x Type = %wZ\n",
  1347. Irp,
  1348. ACPIDebugGetIrpText(IRP_MJ_PNP, irpStack->MinorFunction),
  1349. resource,
  1350. &guidString
  1351. ) );
  1352. RtlFreeUnicodeString( &guidString );
  1353. }
  1354. }
  1355. #endif
  1356. //
  1357. // *Only* Handle the Guids that we know about. Do Not Ever touch
  1358. // any other GUID
  1359. //
  1360. if (CompareGuid(interfaceType, (PVOID) &GUID_ACPI_INTERFACE_STANDARD)) {
  1361. PACPI_INTERFACE_STANDARD interfaceDestination;
  1362. //
  1363. // Only copy up to current size of the ACPI_INTERFACE structure
  1364. //
  1365. if (irpStack->Parameters.QueryInterface.Size >
  1366. sizeof (ACPI_INTERFACE_STANDARD) ) {
  1367. count = sizeof (ACPI_INTERFACE_STANDARD);
  1368. } else {
  1369. count = irpStack->Parameters.QueryInterface.Size;
  1370. }
  1371. //
  1372. // Find where we will store the interface
  1373. //
  1374. interfaceDestination = (PACPI_INTERFACE_STANDARD)
  1375. irpStack->Parameters.QueryInterface.Interface;
  1376. //
  1377. // Copy from the global table to the caller's table, using size
  1378. // specified. Give caller only what was asked for, for
  1379. // backwards compatibility.
  1380. //
  1381. RtlCopyMemory(
  1382. interfaceDestination,
  1383. &ACPIInterfaceTable,
  1384. count
  1385. );
  1386. //
  1387. // Make sure that we can give the user back the correct context. To do
  1388. // this we need to calculate that the number of bytes we are giving back
  1389. // is at least more than that is required to store a pointer at the
  1390. // correct place in the structure
  1391. //
  1392. if (count > (FIELD_OFFSET(ACPI_INTERFACE_STANDARD, Context) + sizeof(PVOID) ) ) {
  1393. interfaceDestination->Context = DeviceObject;
  1394. }
  1395. //
  1396. // Done with the irp
  1397. //
  1398. status = STATUS_SUCCESS;
  1399. } else if (CompareGuid(interfaceType, (PVOID) &GUID_TRANSLATOR_INTERFACE_STANDARD)) {
  1400. if (resource == CmResourceTypeInterrupt) {
  1401. //
  1402. // Smash any interface that has already been reported because we
  1403. // want to arbitrate UNTRANSLATED resources. We can be certain
  1404. // that the HAL underneath will provide the translator interface that
  1405. // has to be there.
  1406. //
  1407. // TEMPTEMP HACKHACK This should last only as long as the PCI
  1408. // driver is building its IRQ translator.
  1409. //
  1410. // EFN: Remove this HACKHACK on Alpha
  1411. //
  1412. #ifndef _ALPHA_
  1413. if (IsPciBus(DeviceObject)) {
  1414. SmashInterfaceQuery(Irp);
  1415. }
  1416. #endif // _ALPHA_
  1417. } else if ((resource == CmResourceTypePort) || (resource == CmResourceTypeMemory)) {
  1418. //
  1419. // For root PCI buses, determine whether we need to eject a translator or not.
  1420. // This decision will be based on the contents of the _CRS.
  1421. //
  1422. if (IsPciBus(DeviceObject)) {
  1423. status = TranslateEjectInterface(DeviceObject, Irp);
  1424. }
  1425. }
  1426. } else if (CompareGuid(interfaceType, (PVOID) &GUID_PCI_BUS_INTERFACE_STANDARD)) {
  1427. if (IsPciBus(DeviceObject)) {
  1428. status = PciBusEjectInterface(DeviceObject, Irp);
  1429. }
  1430. } else if (CompareGuid(interfaceType, (PVOID) &GUID_BUS_INTERFACE_STANDARD)) {
  1431. //
  1432. // Fail the irp unless we have the correct interface
  1433. //
  1434. Irp->IoStatus.Status = STATUS_NOINTERFACE;
  1435. //
  1436. // Is there are parent to this PDO?
  1437. //
  1438. if (deviceExtension->ParentExtension != NULL) {
  1439. PDEVICE_OBJECT parentObject =
  1440. deviceExtension->ParentExtension->DeviceObject;
  1441. //
  1442. // Make a new irp and send it ownward.
  1443. // Note: Because the Interface pointer is in the IO Stack,
  1444. // by passing down the current stack as the one to copy into
  1445. // the new irp, we effectively get to pass the interfaces for free
  1446. //
  1447. if (parentObject != NULL) {
  1448. Irp->IoStatus.Status = ACPIInternalSendSynchronousIrp(
  1449. parentObject,
  1450. irpStack,
  1451. NULL
  1452. );
  1453. }
  1454. }
  1455. }
  1456. if (status != STATUS_NOT_SUPPORTED) {
  1457. //
  1458. // Set the status code in the Irp to what we will return
  1459. //
  1460. Irp->IoStatus.Status = status;
  1461. } else {
  1462. //
  1463. // Use the status code from the Irp to determine what we will return
  1464. //
  1465. status = Irp->IoStatus.Status;
  1466. }
  1467. //
  1468. // Complete the request
  1469. //
  1470. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1471. return status;
  1472. }
  1473. NTSTATUS
  1474. ACPIBusIrpQueryPnpDeviceState(
  1475. IN PDEVICE_OBJECT DeviceObject,
  1476. IN PIRP Irp
  1477. )
  1478. /*++
  1479. Routine Description:
  1480. This routine is the dispatch point for the IRP_MN_QUERY_DEVICE_STATE
  1481. requests sent to the Physical Device Objects
  1482. Arguments:
  1483. DeviceObject - Pointer to the device object we received the request for
  1484. Irp - Pointer to the request
  1485. Return Value:
  1486. NTSTATUS
  1487. --*/
  1488. {
  1489. PAGED_CODE();
  1490. return ACPIIrpInvokeDispatchRoutine(
  1491. DeviceObject,
  1492. Irp,
  1493. NULL,
  1494. ACPIBusAndFilterIrpQueryPnpDeviceState,
  1495. TRUE,
  1496. TRUE
  1497. );
  1498. }
  1499. NTSTATUS
  1500. ACPIBusIrpQueryPower(
  1501. IN PDEVICE_OBJECT DeviceObject,
  1502. IN PIRP Irp
  1503. )
  1504. /*++
  1505. Routine Description:
  1506. This routines tells the system what PNP state the device is in
  1507. Arguments:
  1508. DeviceObject - The device whose state we want to know
  1509. Irp - The request
  1510. Return Value:
  1511. NTSTATUS
  1512. --*/
  1513. {
  1514. NTSTATUS status;
  1515. PDEVICE_EXTENSION deviceExtension;
  1516. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  1517. PNSOBJ acpiObject;
  1518. PNSOBJ ejectObject;
  1519. SYSTEM_POWER_STATE systemState;
  1520. ULONG packedEJx;
  1521. //
  1522. // Get the device extension
  1523. //
  1524. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  1525. //
  1526. // Get the Current stack location to determine if we are a system
  1527. // irp or a device irp. We ignore device irps here and any system
  1528. // irp that isn't of type PowerActionWarmEject
  1529. //
  1530. if (irpSp->Parameters.Power.Type != SystemPowerState) {
  1531. //
  1532. // We don't handle this irp
  1533. //
  1534. return ACPIDispatchPowerIrpSuccess( DeviceObject, Irp );
  1535. }
  1536. if (irpSp->Parameters.Power.ShutdownType != PowerActionWarmEject) {
  1537. //
  1538. // No eject work - just complete the IRP.
  1539. //
  1540. return ACPIDispatchPowerIrpSuccess( DeviceObject, Irp );
  1541. }
  1542. if (deviceExtension->Flags & DEV_PROP_NO_OBJECT) {
  1543. //
  1544. // If we don't have an ACPI object, then we can't succeed this request
  1545. //
  1546. return ACPIDispatchPowerIrpFailure( DeviceObject, Irp );
  1547. }
  1548. //
  1549. // Restrict power states to those possible during a warm eject...
  1550. //
  1551. acpiObject = deviceExtension->AcpiObject ;
  1552. if (ACPIDockIsDockDevice(acpiObject)) {
  1553. //
  1554. // Don't touch this device, the profile provider manages eject
  1555. // transitions.
  1556. //
  1557. return ACPIDispatchPowerIrpSuccess( DeviceObject, Irp );
  1558. }
  1559. //
  1560. // What system state are we looking at?
  1561. //
  1562. systemState = irpSp->Parameters.Power.State.SystemState;
  1563. switch (irpSp->Parameters.Power.State.SystemState) {
  1564. case PowerSystemSleeping1: packedEJx = PACKED_EJ1; break;
  1565. case PowerSystemSleeping2: packedEJx = PACKED_EJ2; break;
  1566. case PowerSystemSleeping3: packedEJx = PACKED_EJ3; break;
  1567. case PowerSystemHibernate: packedEJx = PACKED_EJ4; break;
  1568. default: return ACPIDispatchPowerIrpFailure( DeviceObject, Irp );
  1569. }
  1570. //
  1571. // Does the appropriate object exist for this device?
  1572. //
  1573. ejectObject = ACPIAmliGetNamedChild( acpiObject, packedEJx) ;
  1574. if (ejectObject == NULL) {
  1575. //
  1576. // Fail the request, as we cannot eject in this case.
  1577. //
  1578. return ACPIDispatchPowerIrpFailure( DeviceObject, Irp );
  1579. }
  1580. //
  1581. // Succeed the request
  1582. //
  1583. return ACPIDispatchPowerIrpSuccess( DeviceObject, Irp );
  1584. }
  1585. NTSTATUS
  1586. ACPIBusIrpQueryRemoveOrStopDevice(
  1587. IN PDEVICE_OBJECT DeviceObject,
  1588. IN PIRP Irp
  1589. )
  1590. /*++
  1591. Routine Description:
  1592. This routine transitions a device to the Inactive State
  1593. Arguments:
  1594. DeviceObject - The device that is to become inactive
  1595. Irp - The request
  1596. Return Value:
  1597. NTSTATUS
  1598. --*/
  1599. {
  1600. NTSTATUS status;
  1601. PDEVICE_EXTENSION deviceExtension;
  1602. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  1603. UCHAR minorFunction = irpStack->MinorFunction;
  1604. PAGED_CODE();
  1605. //
  1606. // Get the device extension and acpi object
  1607. //
  1608. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  1609. //
  1610. // Are we allowed to stop this device?
  1611. //
  1612. if (deviceExtension->Flags & DEV_CAP_NO_STOP) {
  1613. //
  1614. // No, then fail the irp
  1615. //
  1616. status = STATUS_INVALID_DEVICE_REQUEST;
  1617. } else {
  1618. //
  1619. // Mark the device extension as being inactive
  1620. //
  1621. deviceExtension->PreviousState = deviceExtension->DeviceState;
  1622. deviceExtension->DeviceState = Inactive;
  1623. status = STATUS_SUCCESS;
  1624. }
  1625. //
  1626. // Complete the irp
  1627. //
  1628. Irp->IoStatus.Status = status;
  1629. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1630. //
  1631. // Done processing
  1632. //
  1633. ACPIDevPrint( (
  1634. ACPI_PRINT_IRP,
  1635. deviceExtension,
  1636. "(0x%08lx): %s = 0x%08lx\n",
  1637. Irp,
  1638. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  1639. status
  1640. ) );
  1641. return status;
  1642. }
  1643. NTSTATUS
  1644. ACPIBusIrpQueryResources(
  1645. IN PDEVICE_OBJECT DeviceObject,
  1646. IN PIRP Irp
  1647. )
  1648. /*++
  1649. Routine Description:
  1650. This routine is the dispatch point for the IRP_MN_QUERY_RESOURCES requests sent
  1651. to PDO device objects
  1652. Arguments:
  1653. DeviceObject - Pointer to the device object we received the request for
  1654. Irp - Pointer to the request
  1655. Return Value:
  1656. NTSTATUS
  1657. --*/
  1658. {
  1659. NTSTATUS status;
  1660. PDEVICE_EXTENSION deviceExtension;
  1661. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  1662. PCM_RESOURCE_LIST cmList = NULL;
  1663. PIO_RESOURCE_REQUIREMENTS_LIST ioList = NULL;
  1664. PUCHAR crsBuf = NULL;
  1665. UCHAR minorFunction = irpStack->MinorFunction;
  1666. ULONG deviceStatus;
  1667. ULONG crsBufSize;
  1668. PAGED_CODE();
  1669. //
  1670. // Get the device extension
  1671. //
  1672. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  1673. //
  1674. // Note that at this point, we must evaluate the _DDN for the
  1675. // object and store that in the registry
  1676. //
  1677. ACPIInitDosDeviceName( deviceExtension );
  1678. //
  1679. // The first thing to look for is wether or not the device is present and
  1680. // decoding its resources. We do this by getting the device status and
  1681. // looking at Bit #1
  1682. //
  1683. status = ACPIGetDevicePresenceSync(
  1684. deviceExtension,
  1685. (PVOID *) &deviceStatus,
  1686. NULL
  1687. );
  1688. if (!NT_SUCCESS(status)) {
  1689. goto ACPIBusIrpQueryResourcesExit;
  1690. }
  1691. if ( !(deviceExtension->Flags & DEV_PROP_DEVICE_ENABLED) ) {
  1692. //
  1693. // The device isn't decoding any resources. So asking it for its
  1694. // current resources is doomed to failure
  1695. //
  1696. ACPIDevPrint( (
  1697. ACPI_PRINT_WARNING,
  1698. deviceExtension,
  1699. "(0x%08lx) : ACPIBusIrpQueryResources - Device not Enabled\n",
  1700. Irp
  1701. ) );
  1702. status = STATUS_INVALID_DEVICE_STATE;
  1703. goto ACPIBusIrpQueryResourcesExit;
  1704. }
  1705. //
  1706. // Container objects do not claim resources. So, don't even bother
  1707. // trying to obtain a _CRS
  1708. //
  1709. if (!(deviceExtension->Flags & DEV_CAP_CONTAINER)) {
  1710. //
  1711. // Here we try to find the current resource set
  1712. //
  1713. status = ACPIGetBufferSync(
  1714. deviceExtension,
  1715. PACKED_CRS,
  1716. &crsBuf,
  1717. &crsBufSize
  1718. );
  1719. } else {
  1720. //
  1721. // This is the status code returned if there is no _CRS. It actually
  1722. // doesn't matter what code we use since in the failure case, we
  1723. // should return whatever code was already present in the IRP
  1724. //
  1725. status = STATUS_OBJECT_NAME_NOT_FOUND;
  1726. }
  1727. if (!NT_SUCCESS(status)) {
  1728. //
  1729. // If this is the PCI device, then we *must* succeed, otherwise the OS
  1730. // will not boot.
  1731. //
  1732. if (! (deviceExtension->Flags & DEV_CAP_PCI) ) {
  1733. //
  1734. // Abort. Complete the irp with whatever status code is present
  1735. //
  1736. status = Irp->IoStatus.Status;
  1737. }
  1738. goto ACPIBusIrpQueryResourcesExit;
  1739. }
  1740. //
  1741. // Build a IO_RESOURCE_REQUIREMENT_LISTS
  1742. //
  1743. status = PnpBiosResourcesToNtResources(
  1744. crsBuf,
  1745. (deviceExtension->Flags & DEV_CAP_PCI ?
  1746. PNP_BIOS_TO_IO_NO_CONSUMED_RESOURCES : 0),
  1747. &ioList );
  1748. //
  1749. // Whatever happens, we are done with the buffer
  1750. //
  1751. ExFreePool(crsBuf);
  1752. if (!NT_SUCCESS(status)) {
  1753. //
  1754. // Abort. We failed the irp for a reason. Remember that
  1755. //
  1756. goto ACPIBusIrpQueryResourcesExit;
  1757. }
  1758. //
  1759. // Make sure that if the DEVICE is PCI, that we subtract out the
  1760. // resource that should not be there
  1761. //
  1762. if (deviceExtension->Flags & DEV_CAP_PCI) {
  1763. status = ACPIRangeSubtract(
  1764. &ioList,
  1765. RootDeviceExtension->ResourceList
  1766. );
  1767. if (!NT_SUCCESS(status)) {
  1768. ACPIDevPrint( (
  1769. ACPI_PRINT_CRITICAL,
  1770. deviceExtension,
  1771. "(0x%08lx) : ACPIBusIrpQueryResources "
  1772. "Subtract = 0x%08lx\n",
  1773. Irp,
  1774. status
  1775. ) );
  1776. ExFreePool( ioList );
  1777. goto ACPIBusIrpQueryResourcesExit;
  1778. }
  1779. //
  1780. // Make sure our range is the proper size
  1781. //
  1782. ACPIRangeValidatePciResources( deviceExtension, ioList );
  1783. } else if (deviceExtension->Flags & DEV_CAP_PIC_DEVICE) {
  1784. //
  1785. // Strip out the PIC resources
  1786. //
  1787. status = ACPIRangeFilterPICInterrupt(
  1788. ioList
  1789. );
  1790. if (!NT_SUCCESS(status)) {
  1791. ACPIDevPrint( (
  1792. ACPI_PRINT_CRITICAL,
  1793. deviceExtension,
  1794. "(0x%08lx): ACPIBusIrpQueryResources "
  1795. "FilterPIC = 0x%08lx\n",
  1796. Irp,
  1797. status
  1798. ) );
  1799. ExFreePool( ioList );
  1800. goto ACPIBusIrpQueryResourcesExit;
  1801. }
  1802. }
  1803. //
  1804. // Turn the list into a CM_RESOURCE_LIST
  1805. //
  1806. if (NT_SUCCESS(status)) {
  1807. status = PnpIoResourceListToCmResourceList(
  1808. ioList,
  1809. &cmList
  1810. );
  1811. if (!NT_SUCCESS(status)) {
  1812. ExFreePool( ioList );
  1813. goto ACPIBusIrpQueryResourcesExit;
  1814. }
  1815. }
  1816. //
  1817. // Whatever happens, we are done with the IO list
  1818. //
  1819. ExFreePool(ioList);
  1820. ACPIBusIrpQueryResourcesExit:
  1821. //
  1822. // If this is the PCI device, then we *must* succeed, otherwise the OS
  1823. // will not boot.
  1824. //
  1825. if (!NT_SUCCESS(status) && status != STATUS_INSUFFICIENT_RESOURCES &&
  1826. (deviceExtension->Flags & DEV_CAP_PCI) ) {
  1827. KeBugCheckEx(
  1828. ACPI_BIOS_ERROR,
  1829. ACPI_ROOT_PCI_RESOURCE_FAILURE,
  1830. (ULONG_PTR) deviceExtension,
  1831. 0,
  1832. (ULONG_PTR) Irp
  1833. );
  1834. }
  1835. //
  1836. // Done with Irp
  1837. //
  1838. Irp->IoStatus.Status = status;
  1839. Irp->IoStatus.Information = (ULONG_PTR) ( NT_SUCCESS(status) ? cmList : NULL );
  1840. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1841. //
  1842. // Done
  1843. //
  1844. ACPIDevPrint( (
  1845. ACPI_PRINT_IRP,
  1846. deviceExtension,
  1847. "(0x%08lx): %s = 0x%08lx\n",
  1848. Irp,
  1849. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  1850. status
  1851. ) );
  1852. return status;
  1853. }
  1854. NTSTATUS
  1855. ACPIBusIrpQueryResourceRequirements(
  1856. IN PDEVICE_OBJECT DeviceObject,
  1857. IN PIRP Irp
  1858. )
  1859. /*++
  1860. Routine Description:
  1861. This routine is the dispatch point for the IRP_MN_QUERY_RESOURCES requests sent
  1862. to PDO device objects
  1863. Arguments:
  1864. DeviceObject - Pointer to the device object we received the request for
  1865. Irp - Pointer to the request
  1866. Return Value:
  1867. NTSTATUS
  1868. --*/
  1869. {
  1870. NTSTATUS crsStat;
  1871. NTSTATUS prsStat;
  1872. NTSTATUS status = Irp->IoStatus.Status;
  1873. PCM_RESOURCE_LIST cmList = NULL;
  1874. PDEVICE_EXTENSION deviceExtension;
  1875. PIO_RESOURCE_REQUIREMENTS_LIST resList = NULL;
  1876. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  1877. PUCHAR crsBuf = NULL;
  1878. PUCHAR prsBuf = NULL;
  1879. UCHAR minorFunction = irpStack->MinorFunction;
  1880. ULONG crsBufSize;
  1881. ULONG prsBufSize;
  1882. PAGED_CODE();
  1883. //
  1884. // Get the device extension
  1885. //
  1886. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  1887. //
  1888. // Here we must return a PIO_RESOURCE_REQUIREMENTS_LIST. For
  1889. // now, we will simply obtain some interesting pointers
  1890. // and fall through
  1891. //
  1892. //
  1893. // Container objects are special in that they have _CRS/_PRS but do not
  1894. // claim resources. Rather, they are used to specify a resource
  1895. // translation
  1896. //
  1897. if (!(deviceExtension->Flags & DEV_CAP_CONTAINER)) {
  1898. //
  1899. // Fetch the buffers, as appropriate
  1900. //
  1901. crsStat = ACPIGetBufferSync(
  1902. deviceExtension,
  1903. PACKED_CRS,
  1904. &crsBuf,
  1905. &crsBufSize
  1906. );
  1907. prsStat = ACPIGetBufferSync(
  1908. deviceExtension,
  1909. PACKED_PRS,
  1910. &prsBuf,
  1911. &prsBufSize
  1912. );
  1913. } else {
  1914. //
  1915. // Pretend that there is no _CRS/_PRS present
  1916. //
  1917. crsStat = STATUS_OBJECT_NAME_NOT_FOUND;
  1918. prsStat = STATUS_OBJECT_NAME_NOT_FOUND;
  1919. }
  1920. //
  1921. // If there is a _CRS, then remember to clear the irp-generated status
  1922. // we will want to fall through
  1923. //
  1924. if (NT_SUCCESS(crsStat)) {
  1925. status = STATUS_NOT_SUPPORTED;
  1926. } else if (!NT_SUCCESS(prsStat)) {
  1927. //
  1928. // This is the case where there isn't a _PRS. We jump directly to
  1929. // the point where we complete the irp, note that the irp will
  1930. // be completed with whatever status code is currently present.
  1931. // The only exception to this is if we discovered that we didn't
  1932. // have enough memory to fulfill either operation..
  1933. //
  1934. if (prsStat == STATUS_INSUFFICIENT_RESOURCES ||
  1935. crsStat == STATUS_INSUFFICIENT_RESOURCES) {
  1936. status = STATUS_INSUFFICIENT_RESOURCES;
  1937. }
  1938. goto ACPIBusIrpQueryResourceRequirementsExit;
  1939. }
  1940. //
  1941. // Did we find a PRS?
  1942. //
  1943. if (NT_SUCCESS(prsStat)) {
  1944. //
  1945. // Our first step is to try to use these resources to build the
  1946. // information...
  1947. //
  1948. status = PnpBiosResourcesToNtResources(
  1949. prsBuf,
  1950. 0,
  1951. &resList
  1952. );
  1953. ASSERT(NT_SUCCESS(status));
  1954. ACPIDevPrint( (
  1955. ACPI_PRINT_IRP,
  1956. deviceExtension,
  1957. "(0x%08lx): %s - ResourcesToNtResources = 0x%08lx\n",
  1958. Irp,
  1959. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  1960. status
  1961. ) );
  1962. //
  1963. // Done with PRS buffer
  1964. //
  1965. ExFreePool(prsBuf);
  1966. //
  1967. // Fall through!!!
  1968. //
  1969. }
  1970. //
  1971. // Earlier, we cleared the status bit if the crsStat was successful. So
  1972. // we should succeed the following this if there was no _PRS, or if there
  1973. // was one but an error occured. Of course, there would have to be
  1974. // a _CRS...
  1975. //
  1976. if (!NT_SUCCESS(status) && NT_SUCCESS(crsStat) ) {
  1977. status = PnpBiosResourcesToNtResources(
  1978. crsBuf,
  1979. (deviceExtension->Flags & DEV_CAP_PCI ?
  1980. PNP_BIOS_TO_IO_NO_CONSUMED_RESOURCES : 0),
  1981. &resList
  1982. );
  1983. ASSERT(NT_SUCCESS(status));
  1984. }
  1985. //
  1986. // Free the _CRS memory, if appropriate
  1987. //
  1988. if (NT_SUCCESS(crsStat)) {
  1989. ExFreePool( crsBuf );
  1990. }
  1991. //
  1992. // Make sure that if the DEVICE is PCI, that we subtract out the
  1993. // resource that should not be there
  1994. //
  1995. if (deviceExtension->Flags & DEV_CAP_PCI) {
  1996. //
  1997. // Make sure our resources are the proper size
  1998. //
  1999. ACPIRangeValidatePciResources( deviceExtension, resList );
  2000. //
  2001. // Subtract out the resources that conflict with the HAL...
  2002. //
  2003. status = ACPIRangeSubtract(
  2004. &resList,
  2005. RootDeviceExtension->ResourceList
  2006. );
  2007. ASSERT(NT_SUCCESS(status));
  2008. if (!NT_SUCCESS(status)) {
  2009. ACPIDevPrint( (
  2010. ACPI_PRINT_CRITICAL,
  2011. deviceExtension,
  2012. "(0x%08lx) : ACPIBusIrpQueryResourceRequirements "
  2013. "Subtract = 0x%08lx\n",
  2014. Irp,
  2015. status
  2016. ) );
  2017. ExFreePool( resList );
  2018. resList = NULL;
  2019. }
  2020. //
  2021. // Make sure our resources are *still* correct
  2022. //
  2023. ACPIRangeValidatePciResources( deviceExtension, resList );
  2024. } else if (deviceExtension->Flags & DEV_CAP_PIC_DEVICE) {
  2025. //
  2026. // Strip out the PIC resources
  2027. //
  2028. status = ACPIRangeFilterPICInterrupt(
  2029. resList
  2030. );
  2031. if (!NT_SUCCESS(status)) {
  2032. ACPIDevPrint( (
  2033. ACPI_PRINT_CRITICAL,
  2034. deviceExtension,
  2035. "(0x%08lx): ACPIBusIrpQueryResources "
  2036. "FilterPIC = 0x%08lx\n",
  2037. Irp,
  2038. status
  2039. ) );
  2040. ExFreePool( resList );
  2041. resList = NULL;
  2042. }
  2043. }
  2044. //
  2045. // Dump the list
  2046. //
  2047. #if DBG
  2048. if (NT_SUCCESS(status)) {
  2049. ACPIDebugResourceRequirementsList( resList, deviceExtension );
  2050. }
  2051. #endif
  2052. //
  2053. // Remember the resource list
  2054. //
  2055. Irp->IoStatus.Information = (ULONG_PTR)
  2056. ( NT_SUCCESS(status) ? resList : NULL );
  2057. ACPIBusIrpQueryResourceRequirementsExit:
  2058. //
  2059. // If this is the PCI device, then we *must* succeed, otherwise the OS
  2060. // will not boot.
  2061. //
  2062. if (!NT_SUCCESS(status) && status != STATUS_INSUFFICIENT_RESOURCES &&
  2063. (deviceExtension->Flags & DEV_CAP_PCI)) {
  2064. ASSERT(NT_SUCCESS(status));
  2065. ACPIDevPrint( (
  2066. ACPI_PRINT_CRITICAL,
  2067. deviceExtension,
  2068. "(0x%08lx): %s = 0x%08lx\n",
  2069. Irp,
  2070. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  2071. status
  2072. ) );
  2073. KeBugCheckEx(
  2074. ACPI_BIOS_ERROR,
  2075. ACPI_ROOT_PCI_RESOURCE_FAILURE,
  2076. (ULONG_PTR) deviceExtension,
  2077. 1,
  2078. (ULONG_PTR) Irp
  2079. );
  2080. }
  2081. //
  2082. // Done Processing Irp
  2083. //
  2084. Irp->IoStatus.Status = status;
  2085. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  2086. //
  2087. // Done
  2088. //
  2089. ACPIDevPrint( (
  2090. ACPI_PRINT_IRP,
  2091. deviceExtension,
  2092. "(0x%08lx): %s = 0x%08lx\n",
  2093. Irp,
  2094. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  2095. status
  2096. ) );
  2097. return status;
  2098. }
  2099. NTSTATUS
  2100. ACPIBusIrpQueryTargetRelation(
  2101. IN PDEVICE_OBJECT DeviceObject,
  2102. IN PIRP Irp,
  2103. OUT PDEVICE_RELATIONS *DeviceRelations
  2104. )
  2105. /*++
  2106. Routine Description:
  2107. This handles DeviceRelations requests sent onto the ACPI driver
  2108. Arguments:
  2109. DeviceObject - The object that we care about...
  2110. Irp - The request in question
  2111. Return Value:
  2112. NTSTATUS
  2113. --*/
  2114. {
  2115. PDEVICE_EXTENSION deviceExtension;
  2116. NTSTATUS status ;
  2117. PAGED_CODE();
  2118. //
  2119. // Nobody should have answered this IRP and sent it down to us. That would
  2120. // be immensely bad...
  2121. //
  2122. ASSERT(*DeviceRelations == NULL) ;
  2123. //
  2124. // Get the device extension
  2125. //
  2126. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  2127. //
  2128. // Allocate some memory for the return buffer
  2129. //
  2130. *DeviceRelations = ExAllocatePoolWithTag(
  2131. NonPagedPool,
  2132. sizeof(DEVICE_RELATIONS),
  2133. ACPI_IRP_POOLTAG
  2134. );
  2135. if (*DeviceRelations == NULL) {
  2136. ACPIDevPrint( (
  2137. ACPI_PRINT_CRITICAL,
  2138. deviceExtension,
  2139. "(0x%08lx): ACPIBusIrpQueryTargetRelation: cannot "
  2140. "allocate %x bytes\n",
  2141. Irp,
  2142. sizeof(DEVICE_RELATIONS)
  2143. ) );
  2144. return STATUS_INSUFFICIENT_RESOURCES;
  2145. }
  2146. //
  2147. // Reference the object
  2148. //
  2149. status = ObReferenceObjectByPointer(
  2150. DeviceObject,
  2151. 0,
  2152. NULL,
  2153. KernelMode
  2154. );
  2155. if (!NT_SUCCESS(status)) {
  2156. ACPIDevPrint( (
  2157. ACPI_PRINT_CRITICAL,
  2158. deviceExtension,
  2159. "(0x%08lx): ACPIBusIrpQueryDeviceRelations: ObReference = %08lx\n",
  2160. Irp,
  2161. status
  2162. ) );
  2163. ExFreePool( *DeviceRelations );
  2164. return status ;
  2165. }
  2166. //
  2167. // Setup the relations
  2168. //
  2169. (*DeviceRelations)->Count = 1;
  2170. (*DeviceRelations)->Objects[0] = DeviceObject;
  2171. //
  2172. // Done
  2173. //
  2174. return status ;
  2175. }
  2176. NTSTATUS
  2177. ACPIBusIrpRemoveDevice(
  2178. IN PDEVICE_OBJECT DeviceObject,
  2179. IN PIRP Irp
  2180. )
  2181. /*++
  2182. Routine Description:
  2183. This routine is called when we need to remove the device object...
  2184. Arguments:
  2185. DeviceObject - The device object to be removed
  2186. Irp - The request
  2187. Return Value:
  2188. NTSTATUS
  2189. --*/
  2190. {
  2191. KIRQL oldIrql;
  2192. LONG oldReferenceCount;
  2193. NTSTATUS status = STATUS_SUCCESS;
  2194. PDEVICE_EXTENSION deviceExtension;
  2195. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  2196. UCHAR minorFunction = irpStack->MinorFunction;
  2197. //
  2198. // Get the device extension.
  2199. //
  2200. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  2201. if (!(deviceExtension->Flags & DEV_TYPE_NOT_ENUMERATED)) {
  2202. //
  2203. // If the device is still physically present, so must the PDO be.
  2204. // This case is essentially a stop.
  2205. //
  2206. deviceExtension->DeviceState = Stopped;
  2207. //
  2208. // Delete the children of this device
  2209. //
  2210. ACPIInitDeleteChildDeviceList( deviceExtension );
  2211. //
  2212. // Mark the request as complete...
  2213. //
  2214. Irp->IoStatus.Status = status;
  2215. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  2216. if (NT_SUCCESS(status)) {
  2217. //
  2218. // Attempt to stop the device, and unlock the device.
  2219. //
  2220. ACPIInitStopDevice( deviceExtension , TRUE);
  2221. }
  2222. return status ;
  2223. }
  2224. //
  2225. // If the device has already been removed, then hhmm...
  2226. //
  2227. if (deviceExtension->DeviceState == Removed) {
  2228. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE ;
  2229. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  2230. return STATUS_NO_SUCH_DEVICE ;
  2231. }
  2232. //
  2233. // Otherwise, try to stop the device
  2234. //
  2235. if (deviceExtension->DeviceState != SurpriseRemoved) {
  2236. if (IsPciBus(deviceExtension->DeviceObject)) {
  2237. //
  2238. // If this is PCI bridge, then we
  2239. // may have _REG methods to evaluate.
  2240. //
  2241. EnableDisableRegions(deviceExtension->AcpiObject, FALSE);
  2242. }
  2243. //
  2244. // Attempt to stop the device (if possible)
  2245. //
  2246. ACPIInitStopDevice( deviceExtension, TRUE );
  2247. }
  2248. //
  2249. // Delete the children of this device
  2250. //
  2251. ACPIInitDeleteChildDeviceList( deviceExtension );
  2252. //
  2253. // Set the device state as removed
  2254. //
  2255. deviceExtension->DeviceState = Removed;
  2256. //
  2257. // Complete the request
  2258. //
  2259. Irp->IoStatus.Status = STATUS_SUCCESS;
  2260. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  2261. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  2262. //
  2263. // After this point, the device extension is GONE
  2264. //
  2265. ACPIDevPrint( (
  2266. ACPI_PRINT_REMOVE,
  2267. deviceExtension,
  2268. "(0x%08lx): %s = 0x%08lx\n",
  2269. Irp,
  2270. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  2271. STATUS_SUCCESS
  2272. ) );
  2273. //
  2274. // Reset the device extension
  2275. //
  2276. ACPIInitResetDeviceExtension( deviceExtension );
  2277. return STATUS_SUCCESS;
  2278. }
  2279. NTSTATUS
  2280. ACPIBusIrpSetLock(
  2281. IN PDEVICE_OBJECT DeviceObject,
  2282. IN PIRP Irp
  2283. )
  2284. /*++
  2285. Routine Description:
  2286. This routine is the dispatch point for the IRP_MN_SET_LOCK
  2287. requests sent to the PDO.
  2288. Arguments:
  2289. DeviceObject - Pointer to the device object we received the request for
  2290. Irp - Pointer to the request
  2291. Return Value:
  2292. NTSTATUS
  2293. --*/
  2294. {
  2295. PAGED_CODE();
  2296. return ACPIIrpInvokeDispatchRoutine(
  2297. DeviceObject,
  2298. Irp,
  2299. NULL,
  2300. ACPIBusAndFilterIrpSetLock,
  2301. TRUE,
  2302. TRUE
  2303. );
  2304. }
  2305. NTSTATUS
  2306. ACPIBusIrpSetDevicePower(
  2307. IN PDEVICE_OBJECT DeviceObject,
  2308. IN PIRP Irp,
  2309. IN PIO_STACK_LOCATION IrpStack
  2310. )
  2311. /*++
  2312. Routine Description:
  2313. This routine handles device power request for a PDO
  2314. Arguments:
  2315. DeviceObject - The PDO target
  2316. DeviceExtension - The real extension to the target
  2317. Irp - The request
  2318. IrpStack - The current request
  2319. Return Value:
  2320. NTSTATUS
  2321. --*/
  2322. {
  2323. NTSTATUS status;
  2324. PDEVICE_EXTENSION deviceExtension;
  2325. UNREFERENCED_PARAMETER( IrpStack );
  2326. //
  2327. // Get the device extension
  2328. //
  2329. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  2330. //
  2331. // We are going to do some work on the irp, so mark it as being
  2332. // successfull for now
  2333. //
  2334. Irp->IoStatus.Status = STATUS_SUCCESS;
  2335. //
  2336. // Mark the irp as pending
  2337. //
  2338. IoMarkIrpPending( Irp );
  2339. //
  2340. // We might queue up the irp, so this counts as a completion routine.
  2341. // Which means we need to incr the ref count
  2342. //
  2343. InterlockedIncrement( &deviceExtension->OutstandingIrpCount );
  2344. //
  2345. // Queue the irp up. Note that we will *always* call the completion
  2346. // routine, so we don't really care what was returned directly by
  2347. // this call --- the callback gets a chance to execute.
  2348. //
  2349. status = ACPIDeviceIrpDeviceRequest(
  2350. DeviceObject,
  2351. Irp,
  2352. ACPIDeviceIrpCompleteRequest
  2353. );
  2354. //
  2355. // Did we return STATUS_MORE_PROCESSING_REQUIRED (which we used
  2356. // if we overload STATUS_PENDING)
  2357. //
  2358. if (status == STATUS_MORE_PROCESSING_REQUIRED) {
  2359. status = STATUS_PENDING;
  2360. }
  2361. //
  2362. // Note: We called the completion routine, which should have completed
  2363. // the IRP with the same STATUS code as is being returned here (okay, if
  2364. // it is STATUS_PENDING, obviously we haven't completed the IRP, but that
  2365. // is okay).
  2366. //
  2367. return status;
  2368. }
  2369. NTSTATUS
  2370. ACPIBusIrpSetPower (
  2371. IN PDEVICE_OBJECT DeviceObject,
  2372. IN PIRP Irp
  2373. )
  2374. /*++
  2375. Routine Description:
  2376. This routine handles request to set the power state for a Physical
  2377. Device object
  2378. Arguments:
  2379. DeviceObject - The PDO target of the request
  2380. Irp - The request
  2381. Return Value:
  2382. NTSTATUS
  2383. --*/
  2384. {
  2385. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  2386. //
  2387. // Look to see who should actually handle this request
  2388. //
  2389. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  2390. //
  2391. // This is a system request
  2392. //
  2393. return ACPIBusIrpSetSystemPower( DeviceObject, Irp, irpStack );
  2394. } else {
  2395. //
  2396. // This is a device request
  2397. //
  2398. return ACPIBusIrpSetDevicePower( DeviceObject, Irp, irpStack );
  2399. }
  2400. }
  2401. NTSTATUS
  2402. ACPIBusIrpSetSystemPower(
  2403. IN PDEVICE_OBJECT DeviceObject,
  2404. IN PIRP Irp,
  2405. IN PIO_STACK_LOCATION IrpStack
  2406. )
  2407. /*++
  2408. Routine Description:
  2409. This handles request for a system set power irp sent to a PDO
  2410. Arguments:
  2411. DeviceObject - The PDO target of the request
  2412. Irp - The current request
  2413. IrpStack - The current arguments
  2414. Return Value:
  2415. NTSTATUS
  2416. --*/
  2417. {
  2418. DEVICE_POWER_STATE deviceState;
  2419. NTSTATUS status;
  2420. PDEVICE_EXTENSION deviceExtension;
  2421. POWER_STATE powerState;
  2422. SYSTEM_POWER_STATE systemState;
  2423. //
  2424. // Get the device extension
  2425. //
  2426. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  2427. //
  2428. // Grab these two values. They are required for further calculations
  2429. //
  2430. systemState= IrpStack->Parameters.Power.State.SystemState;
  2431. deviceState = deviceExtension->PowerInfo.DevicePowerMatrix[systemState];
  2432. //
  2433. // If our ShutdownAction is PowerActionWarmEject, then we have a special
  2434. // case, and we don't need to request a D-irp for the device
  2435. //
  2436. if (IrpStack->Parameters.Power.ShutdownType == PowerActionWarmEject) {
  2437. ASSERT(!(deviceExtension->Flags & DEV_PROP_NO_OBJECT));
  2438. ASSERT(!ACPIDockIsDockDevice(deviceExtension->AcpiObject));
  2439. //
  2440. // We are going to do some work on the irp, so mark it as being
  2441. // successfull for now
  2442. //
  2443. Irp->IoStatus.Status = STATUS_SUCCESS;
  2444. //
  2445. // Mark the irp as pending
  2446. //
  2447. IoMarkIrpPending( Irp );
  2448. //
  2449. // We might queue up the irp, so this counts as a completion routine.
  2450. // Which means we need to incr the ref count
  2451. //
  2452. InterlockedIncrement( &deviceExtension->OutstandingIrpCount );
  2453. ACPIDevPrint( (
  2454. ACPI_PRINT_REMOVE,
  2455. deviceExtension,
  2456. "(0x%08lx) ACPIBusIrpSetSystemPower: Eject from S%d!\n",
  2457. Irp,
  2458. systemState - PowerSystemWorking
  2459. ) );
  2460. //
  2461. // Request the warm eject
  2462. //
  2463. status = ACPIDeviceIrpWarmEjectRequest(
  2464. deviceExtension,
  2465. Irp,
  2466. ACPIDeviceIrpCompleteRequest,
  2467. FALSE
  2468. );
  2469. //
  2470. // If we got back STATUS_MORE_PROCESSING_REQUIRED, then that is
  2471. // just an alias for STATUS_PENDING, so we make that change now
  2472. //
  2473. if (status == STATUS_MORE_PROCESSING_REQUIRED) {
  2474. status = STATUS_PENDING;
  2475. }
  2476. return status;
  2477. }
  2478. //
  2479. // Look at the device extension and determine if we need to send a
  2480. // D-irp in respond. The rule is that if the device is RAW driven or
  2481. // the current D state of the device is numerically lower then the
  2482. // known D state for the given S state, then we should send the request
  2483. //
  2484. if ( !(deviceExtension->Flags & DEV_CAP_RAW) ) {
  2485. return ACPIDispatchPowerIrpSuccess( DeviceObject, Irp );
  2486. } // if
  2487. if ( (deviceExtension->PowerInfo.PowerState == deviceState) ) {
  2488. return ACPIDispatchPowerIrpSuccess( DeviceObject, Irp );
  2489. } // if
  2490. ACPIDevPrint( (
  2491. ACPI_PRINT_POWER,
  2492. deviceExtension,
  2493. "(0x%08lx) ACPIBusIrpSetSystemPower: send D%d irp!\n",
  2494. Irp,
  2495. deviceState - PowerDeviceD0
  2496. ) );
  2497. //
  2498. // We are going to do some work on the irp, so mark it as being
  2499. // successfull for now
  2500. //
  2501. Irp->IoStatus.Status = STATUS_SUCCESS;
  2502. //
  2503. // Mark the irp as pending
  2504. //
  2505. IoMarkIrpPending( Irp );
  2506. //
  2507. // We might queue up the irp, so this counts as a completion routine.
  2508. // Which means we need to incr the ref count
  2509. //
  2510. InterlockedIncrement( &deviceExtension->OutstandingIrpCount );
  2511. //
  2512. // We need to actually use a PowerState to send the request down, not
  2513. // a device state
  2514. //
  2515. powerState.DeviceState = deviceState;
  2516. //
  2517. // Make the request
  2518. //
  2519. PoRequestPowerIrp(
  2520. DeviceObject,
  2521. IRP_MN_SET_POWER,
  2522. powerState,
  2523. ACPIBusIrpSetSystemPowerComplete,
  2524. Irp,
  2525. NULL
  2526. );
  2527. //
  2528. // Always return pending
  2529. //
  2530. return STATUS_PENDING;
  2531. }
  2532. NTSTATUS
  2533. ACPIBusIrpSetSystemPowerComplete(
  2534. IN PDEVICE_OBJECT DeviceObject,
  2535. IN UCHAR MinorFunction,
  2536. IN POWER_STATE PowerState,
  2537. IN PVOID Context,
  2538. IN PIO_STATUS_BLOCK IoStatus
  2539. )
  2540. /*++
  2541. Routine Description:
  2542. This routine is called when the created D-irp has been sent throughout
  2543. the stack
  2544. Arguments:
  2545. DeviceObject - The device that received the request
  2546. MinorFunction - The function that was requested of the device
  2547. PowerState - The power state the device was sent to
  2548. Context - The original system irp
  2549. IoStatus - The result of the request
  2550. Return Value:
  2551. NTSTATUS
  2552. --*/
  2553. {
  2554. PIRP irp = (PIRP) Context;
  2555. PDEVICE_EXTENSION deviceExtension;
  2556. //
  2557. // Get the device extension
  2558. //
  2559. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  2560. //
  2561. // Make sure that we have cleared the information field
  2562. //
  2563. irp->IoStatus.Information = 0;
  2564. //
  2565. // Call this wrapper function so that we don't have to duplicated code
  2566. //
  2567. ACPIDeviceIrpCompleteRequest(
  2568. deviceExtension,
  2569. (PVOID) irp,
  2570. IoStatus->Status
  2571. );
  2572. //
  2573. // Done
  2574. //
  2575. return IoStatus->Status;
  2576. }
  2577. typedef struct {
  2578. KEVENT Event;
  2579. PIRP Irp;
  2580. } START_DEVICE_CONTEXT, *PSTART_DEVICE_CONTEXT;
  2581. NTSTATUS
  2582. ACPIBusIrpStartDevice(
  2583. IN PDEVICE_OBJECT DeviceObject,
  2584. IN PIRP Irp
  2585. )
  2586. /*++
  2587. Routine Description:
  2588. This handles a request to start the device
  2589. Arguments:
  2590. DeviceObject - The device to start
  2591. Irp - The request to the device to tell it to stop
  2592. Return Value:
  2593. NTSTATUS
  2594. --*/
  2595. {
  2596. NTSTATUS status = STATUS_SUCCESS;
  2597. PDEVICE_EXTENSION deviceExtension;
  2598. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  2599. UCHAR minorFunction = irpStack->MinorFunction;
  2600. PAGED_CODE();
  2601. //
  2602. // Get the device extension and acpi object
  2603. //
  2604. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  2605. //
  2606. // If this is a PCI root bus (the only way that it can be here is if
  2607. // we enumerated this as a PNP0A03 device object) then we need to do
  2608. // a few extra things
  2609. //
  2610. if (deviceExtension->Flags & DEV_CAP_PCI) {
  2611. //
  2612. // The IRQ Arbiter needs to have the FDO of the PCI
  2613. // bus. So here is a PDO. From this, can be gotten
  2614. // the FDO. And only do it once.
  2615. //
  2616. if (!PciInterfacesInstantiated) {
  2617. AcpiArbInitializePciRouting( DeviceObject );
  2618. }
  2619. //
  2620. // We need to get the PME interface as well
  2621. //
  2622. if (!PciPmeInterfaceInstantiated) {
  2623. ACPIWakeInitializePmeRouting( DeviceObject );
  2624. }
  2625. }
  2626. //
  2627. // Pass the real work off to this function
  2628. //
  2629. status = ACPIInitStartDevice(
  2630. DeviceObject,
  2631. irpStack->Parameters.StartDevice.AllocatedResources,
  2632. ACPIBusIrpStartDeviceCompletion,
  2633. Irp,
  2634. Irp
  2635. );
  2636. if (NT_SUCCESS(status)) {
  2637. return STATUS_PENDING;
  2638. } else {
  2639. return status;
  2640. }
  2641. }
  2642. VOID
  2643. ACPIBusIrpStartDeviceCompletion(
  2644. IN PDEVICE_EXTENSION DeviceExtension,
  2645. IN PVOID Context,
  2646. IN NTSTATUS Status
  2647. )
  2648. /*++
  2649. Routine Description:
  2650. This is the call back routine that is invoked when we have finished
  2651. programming the resources
  2652. This routine completes the irp
  2653. Arguments:
  2654. DeviceExtension - Extension of the device that was started
  2655. Context - The Irp
  2656. Status - The result
  2657. Return Value:
  2658. None
  2659. --*/
  2660. {
  2661. PIRP irp = (PIRP) Context;
  2662. PWORK_QUEUE_CONTEXT workContext = &(DeviceExtension->Pdo.WorkContext);
  2663. irp->IoStatus.Status = Status;
  2664. if (NT_SUCCESS(Status)) {
  2665. DeviceExtension->DeviceState = Started;
  2666. } else {
  2667. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( irp );
  2668. UCHAR minorFunction = irpStack->MinorFunction;
  2669. //
  2670. // Complete the irp --- we can do this at DPC level without problem
  2671. //
  2672. IoCompleteRequest( irp, IO_NO_INCREMENT );
  2673. //
  2674. // Let the world know
  2675. //
  2676. ACPIDevPrint( (
  2677. ACPI_PRINT_IRP,
  2678. DeviceExtension,
  2679. "(0x%08lx): %s = 0x%08lx\n",
  2680. irp,
  2681. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  2682. Status
  2683. ) );
  2684. return;
  2685. }
  2686. //
  2687. // We can't run EnableDisableRegions at DPC level,
  2688. // so queue a worker item.
  2689. //
  2690. ExInitializeWorkItem(
  2691. &(workContext->Item),
  2692. ACPIBusIrpStartDeviceWorker,
  2693. workContext
  2694. );
  2695. workContext->DeviceObject = DeviceExtension->DeviceObject;
  2696. workContext->Irp = irp;
  2697. ExQueueWorkItem(
  2698. &(workContext->Item),
  2699. DelayedWorkQueue
  2700. );
  2701. }
  2702. VOID
  2703. ACPIBusIrpStartDeviceWorker(
  2704. IN PVOID Context
  2705. )
  2706. /*++
  2707. Routine Description:
  2708. This routine is called at PASSIVE_LEVEL after we after turned on the
  2709. device
  2710. Arguments:
  2711. Context - Contains the arguments passed to the START_DEVICE function
  2712. Return Value:
  2713. None
  2714. --*/
  2715. {
  2716. NTSTATUS status;
  2717. PDEVICE_EXTENSION deviceExtension;
  2718. PDEVICE_OBJECT deviceObject;
  2719. PIRP irp;
  2720. PIO_STACK_LOCATION irpStack;
  2721. PWORK_QUEUE_CONTEXT workContext = (PWORK_QUEUE_CONTEXT) Context;
  2722. UCHAR minorFunction;
  2723. PAGED_CODE();
  2724. //
  2725. // Grab the parameters that we need out of the Context
  2726. //
  2727. deviceObject = workContext->DeviceObject;
  2728. deviceExtension = ACPIInternalGetDeviceExtension( deviceObject );
  2729. irp = workContext->Irp;
  2730. irpStack = IoGetCurrentIrpStackLocation( irp );
  2731. minorFunction = irpStack->MinorFunction;
  2732. status = irp->IoStatus.Status;
  2733. //
  2734. // Update the status of the device
  2735. //
  2736. if (NT_SUCCESS(status)) {
  2737. if (IsNsobjPciBus(deviceExtension->AcpiObject)) {
  2738. //
  2739. // This may be a PCI bridge, so we
  2740. // may have _REG methods to evaluate.
  2741. // N.B. This work is done here, instead
  2742. // of in ACPIBusIrpStartDevice because we
  2743. // need to wait until after the resources
  2744. // have been programmed.
  2745. //
  2746. EnableDisableRegions(deviceExtension->AcpiObject, TRUE);
  2747. }
  2748. }
  2749. //
  2750. // Complete the request
  2751. //
  2752. irp->IoStatus.Status = status;
  2753. irp->IoStatus.Information = (ULONG_PTR) NULL;
  2754. IoCompleteRequest( irp, IO_NO_INCREMENT );
  2755. //
  2756. // Let the world know
  2757. //
  2758. ACPIDevPrint( (
  2759. ACPI_PRINT_IRP,
  2760. deviceExtension,
  2761. "(0x%08lx): %s = 0x%08lx\n",
  2762. irp,
  2763. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  2764. status
  2765. ) );
  2766. }
  2767. NTSTATUS
  2768. ACPIBusIrpStopDevice(
  2769. IN PDEVICE_OBJECT DeviceObject,
  2770. IN PIRP Irp
  2771. )
  2772. /*++
  2773. Routine Description:
  2774. This handles a request to stop the device...
  2775. Arguments:
  2776. DeviceObject - The device to stop
  2777. Irp - The request to the device to tell it to stop..
  2778. Return Value:
  2779. NTSTATUS
  2780. --*/
  2781. {
  2782. NTSTATUS status = STATUS_SUCCESS;
  2783. PDEVICE_EXTENSION deviceExtension;
  2784. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  2785. PNSOBJ acpiObject;
  2786. UCHAR minorFunction = irpStack->MinorFunction;
  2787. PAGED_CODE();
  2788. //
  2789. // Get the device extension and acpi object
  2790. //
  2791. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  2792. acpiObject = deviceExtension->AcpiObject;
  2793. //
  2794. // We are trying to be intelligent here. If we got a stop without being
  2795. // in the inactive state, then we should remember what state we where in
  2796. //
  2797. if (deviceExtension->DeviceState != Inactive) {
  2798. deviceExtension->DeviceState = deviceExtension->PreviousState;
  2799. }
  2800. if (IsPciBus(deviceExtension->DeviceObject)) {
  2801. //
  2802. // If this is PCI bridge, then we
  2803. // may have _REG methods to evaluate.
  2804. //
  2805. EnableDisableRegions(deviceExtension->AcpiObject, FALSE);
  2806. }
  2807. //
  2808. // Set the device as 'Stopped'
  2809. //
  2810. deviceExtension->DeviceState = Stopped;
  2811. //
  2812. // Mark the request as complete...
  2813. //
  2814. Irp->IoStatus.Status = status;
  2815. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  2816. if (NT_SUCCESS(status)) {
  2817. //
  2818. // Attempt to stop the device
  2819. //
  2820. ACPIInitStopDevice( deviceExtension, FALSE );
  2821. }
  2822. //
  2823. // Done
  2824. //
  2825. ACPIDevPrint( (
  2826. ACPI_PRINT_IRP,
  2827. deviceExtension,
  2828. "(0x%08lx): %s = 0x%08lx\n",
  2829. Irp,
  2830. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  2831. status
  2832. ) );
  2833. return status;
  2834. }
  2835. NTSTATUS
  2836. ACPIBusIrpSurpriseRemoval(
  2837. IN PDEVICE_OBJECT DeviceObject,
  2838. IN PIRP Irp
  2839. )
  2840. /*++
  2841. Routine Description:
  2842. This routine is the dispatch point for surprise remove
  2843. Arguments:
  2844. DeviceObject - The device object
  2845. Irp - The request in question
  2846. Return Value:
  2847. NTSTATUS
  2848. --*/
  2849. {
  2850. KIRQL oldIrql;
  2851. NTSTATUS status = STATUS_SUCCESS;
  2852. PDEVICE_EXTENSION deviceExtension;
  2853. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  2854. PNSOBJ acpiObject;
  2855. UCHAR minorFunction = irpStack->MinorFunction;
  2856. PDEVICE_EXTENSION newDeviceExtension ;
  2857. //
  2858. // Get the device extension and acpi object.
  2859. //
  2860. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  2861. acpiObject = deviceExtension->AcpiObject;
  2862. //
  2863. // If we are already removed, then this isn't a valid request
  2864. //
  2865. if (deviceExtension->DeviceState == Removed) {
  2866. return ACPIDispatchIrpSurpriseRemoved( DeviceObject, Irp );
  2867. }
  2868. if ( !ACPIInternalIsReportedMissing(deviceExtension) ) {
  2869. //
  2870. // If the device is still physically present, then an FDO used
  2871. // IoInvalidatePnpDeviceState to set the device to disabled. No
  2872. // QueryRemove/Remove combination happens here, we just get a
  2873. // SurpriseRemove as we are already started. It is actually appropriate
  2874. // to set it to stop as we may get restarted after remove strips the
  2875. // complaining FDO off.
  2876. //
  2877. deviceExtension->DeviceState = Stopped;
  2878. //
  2879. // Mark the request as complete...
  2880. //
  2881. Irp->IoStatus.Status = status;
  2882. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  2883. if (NT_SUCCESS(status)) {
  2884. //
  2885. // Attempt to stop the device
  2886. //
  2887. ACPIInitStopDevice( deviceExtension, TRUE );
  2888. }
  2889. return status;
  2890. }
  2891. if (IsPciBus(deviceExtension->DeviceObject)) {
  2892. //
  2893. // If this is PCI bridge, then we
  2894. // may have _REG methods to evaluate.
  2895. //
  2896. EnableDisableRegions(deviceExtension->AcpiObject, FALSE);
  2897. }
  2898. //
  2899. // Set the device state as surprise removed
  2900. //
  2901. deviceExtension->DeviceState = SurpriseRemoved;
  2902. //
  2903. // Attempt to stop the device (if possible)
  2904. //
  2905. ACPIInitStopDevice( deviceExtension, TRUE );
  2906. //
  2907. // Is the device really gone? In other words, did ACPI not see it the
  2908. // last time that it was enumerated?
  2909. //
  2910. ACPIBuildSurpriseRemovedExtension(deviceExtension);
  2911. //
  2912. // Complete the request
  2913. //
  2914. Irp->IoStatus.Status = status ;
  2915. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  2916. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  2917. //
  2918. // Done
  2919. //
  2920. ACPIDevPrint( (
  2921. ACPI_PRINT_REMOVE,
  2922. deviceExtension,
  2923. "(0x%08lx): %s = 0x%08lx\n",
  2924. Irp,
  2925. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  2926. status
  2927. ) );
  2928. return status ;
  2929. }
  2930. NTSTATUS
  2931. ACPIBusIrpUnhandled(
  2932. IN PDEVICE_OBJECT DeviceObject,
  2933. IN PIRP Irp
  2934. )
  2935. /*++
  2936. Routine Description:
  2937. This routine is the dispatch point for all unhandled irps
  2938. Arguments:
  2939. DeviceObject - The device object that we (do not) care about
  2940. Irp - The request in question
  2941. Return Value:
  2942. NTSTATUS
  2943. --*/
  2944. {
  2945. NTSTATUS status;
  2946. PDEVICE_EXTENSION deviceExtension;
  2947. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  2948. UCHAR minorFunction = irpStack->MinorFunction;
  2949. //
  2950. // Get the device extension
  2951. //
  2952. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  2953. //
  2954. // Auto-complete the IRP as something we don't handle...
  2955. //
  2956. status = Irp->IoStatus.Status;
  2957. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  2958. //
  2959. // Done
  2960. //
  2961. ACPIDevPrint( (
  2962. ACPI_PRINT_IRP,
  2963. deviceExtension,
  2964. "(0x%08lx): %s = 0x%08lx\n",
  2965. Irp,
  2966. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  2967. status
  2968. ) );
  2969. return status;
  2970. }
  2971. VOID
  2972. SmashInterfaceQuery(
  2973. IN OUT PIRP Irp
  2974. )
  2975. {
  2976. GUID *interfaceType;
  2977. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  2978. PAGED_CODE();
  2979. interfaceType = (LPGUID) irpStack->Parameters.QueryInterface.InterfaceType;
  2980. RtlZeroMemory(interfaceType, sizeof(GUID));
  2981. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
  2982. }