Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2066 lines
52 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. acpidock.c
  5. Abstract:
  6. This module handles docking issues for ACPI.
  7. For each dock, we create a node off the root of ACPI called a "profile
  8. provider". This node represents that individual dock. We do this so
  9. that the OS can determine the current or upcoming hardware profile
  10. without having to start that portion of the tree which leads down to
  11. the dock. Also, as multiple simulataneous docks are supported via ACPI,
  12. we make them all children of the root so that the OS can pick up the
  13. hardware profile in just one pass.
  14. Author:
  15. Adrian J. Oney (AdriaO)
  16. Environment:
  17. Kernel mode only.
  18. Revision History:
  19. 20-Jan-98 Initial Revision
  20. --*/
  21. #include "pch.h"
  22. #include "amlreg.h"
  23. #include <stdio.h>
  24. #ifdef ALLOC_PRAGMA
  25. #pragma alloc_text(PAGE,ACPIDockIrpStartDevice)
  26. #pragma alloc_text(PAGE,ACPIDockIrpQueryCapabilities)
  27. #pragma alloc_text(PAGE,ACPIDockIrpQueryDeviceRelations)
  28. #pragma alloc_text(PAGE,ACPIDockIrpEject)
  29. #pragma alloc_text(PAGE,ACPIDockIrpQueryID)
  30. #pragma alloc_text(PAGE,ACPIDockIrpSetLock)
  31. #pragma alloc_text(PAGE,ACPIDockIrpQueryEjectRelations)
  32. #pragma alloc_text(PAGE,ACPIDockIrpQueryInterface)
  33. #pragma alloc_text(PAGE,ACPIDockIrpQueryPnpDeviceState)
  34. #pragma alloc_text(PAGE,ACPIDockIntfReference)
  35. #pragma alloc_text(PAGE,ACPIDockIntfDereference)
  36. #pragma alloc_text(PAGE,ACPIDockIntfSetMode)
  37. #pragma alloc_text(PAGE,ACPIDockIntfUpdateDeparture)
  38. #endif
  39. PDEVICE_EXTENSION
  40. ACPIDockFindCorrespondingDock(
  41. IN PDEVICE_EXTENSION DeviceExtension
  42. )
  43. /*++
  44. Routine Description:
  45. This routine takes a pointer to an ACPI object an returns the dock extension
  46. that matches it.
  47. Argument Description:
  48. DeviceExtension - The device for which we want the dock
  49. Return Value:
  50. NULL or the matching extension for the profile provider
  51. --*/
  52. {
  53. PDEVICE_EXTENSION rootChildExtension = NULL ;
  54. EXTENSIONLIST_ENUMDATA eled ;
  55. ACPIExtListSetupEnum(
  56. &eled,
  57. &(RootDeviceExtension->ChildDeviceList),
  58. &AcpiDeviceTreeLock,
  59. SiblingDeviceList,
  60. WALKSCHEME_HOLD_SPINLOCK
  61. ) ;
  62. for(rootChildExtension = ACPIExtListStartEnum(&eled);
  63. ACPIExtListTestElement(&eled, TRUE) ;
  64. rootChildExtension = ACPIExtListEnumNext(&eled)) {
  65. if (!rootChildExtension) {
  66. ACPIExtListExitEnumEarly(&eled);
  67. break;
  68. }
  69. if (!(rootChildExtension->Flags & DEV_PROP_DOCK)) {
  70. continue;
  71. }
  72. if (rootChildExtension->Dock.CorrospondingAcpiDevice ==
  73. DeviceExtension) {
  74. ACPIExtListExitEnumEarly(&eled) ;
  75. break;
  76. }
  77. }
  78. //
  79. // Done
  80. //
  81. return rootChildExtension;
  82. }
  83. NTSTATUS
  84. ACPIDockGetDockObject(
  85. IN PNSOBJ AcpiObject,
  86. OUT PNSOBJ *dckObject
  87. )
  88. /*++
  89. Routine Description:
  90. This routine gets the _DCK method object if the device has one
  91. Arguments:
  92. The ACPI Object to test.
  93. Return Value:
  94. NTSTATUS (failure if _DCK method does not exist)
  95. --*/
  96. {
  97. return AMLIGetNameSpaceObject(
  98. "_DCK",
  99. AcpiObject,
  100. dckObject,
  101. NSF_LOCAL_SCOPE
  102. );
  103. }
  104. NTSTATUS
  105. ACPIDockIrpEject(
  106. IN PDEVICE_OBJECT DeviceObject,
  107. IN PIRP Irp
  108. )
  109. /*++
  110. Routine Description:
  111. Arguments:
  112. DeviceObject - The device to get the capabilities for
  113. Irp - The request to the device to tell it to stop
  114. Return Value:
  115. NTSTATUS
  116. --*/
  117. {
  118. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  119. UCHAR minorFunction = irpStack->MinorFunction;
  120. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  121. PDEVICE_EXTENSION dockDeviceExtension;
  122. PNSOBJ ej0Object;
  123. NTSTATUS status;
  124. ULONG i, ignoredPerSpec ;
  125. PAGED_CODE();
  126. //
  127. // The dock may have failed _DCK on a start, in which case we have kept
  128. // it around for the explicit purpose of ejecting it. Now we make the dock
  129. // go away.
  130. //
  131. ACPIInternalUpdateFlags(
  132. &(deviceExtension->Flags),
  133. DEV_CAP_UNATTACHED_DOCK,
  134. TRUE
  135. );
  136. //
  137. // lets get the corrosponding dock node for this device
  138. //
  139. dockDeviceExtension = deviceExtension->Dock.CorrospondingAcpiDevice ;
  140. if (!dockDeviceExtension) {
  141. //
  142. // Invalid name space object <bad>
  143. //
  144. ACPIDevPrint( (
  145. ACPI_PRINT_FAILURE,
  146. deviceExtension,
  147. "(0x%08lx): ACPIDockIrpEject: no corresponding extension!!\n",
  148. Irp
  149. ) );
  150. ASSERT(0);
  151. //
  152. // Mark the irp as very bad...
  153. //
  154. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL ;
  155. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  156. return STATUS_UNSUCCESSFUL;
  157. }
  158. if (deviceExtension->Dock.ProfileDepartureStyle == PDS_UPDATE_ON_EJECT) {
  159. //
  160. // On the Compaq Armada 7800, we switch UARTs during an undock, thus we
  161. // lose the debugger com port programming.
  162. //
  163. KdDisableDebugger();
  164. if (deviceExtension->Dock.IsolationState != IS_ISOLATED) {
  165. status = ACPIGetIntegerEvalIntegerSync(
  166. dockDeviceExtension,
  167. PACKED_DCK,
  168. 0,
  169. &ignoredPerSpec
  170. );
  171. deviceExtension->Dock.IsolationState = IS_ISOLATED;
  172. if (!NT_SUCCESS(status)) {
  173. KdEnableDebugger();
  174. Irp->IoStatus.Status = status ;
  175. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  176. return status ;
  177. }
  178. }
  179. }
  180. ej0Object = ACPIAmliGetNamedChild(
  181. dockDeviceExtension->AcpiObject,
  182. PACKED_EJ0
  183. );
  184. if (ej0Object != NULL) {
  185. status = ACPIGetNothingEvalIntegerSync(
  186. dockDeviceExtension,
  187. PACKED_EJ0,
  188. 1
  189. );
  190. } else {
  191. status = STATUS_OBJECT_NAME_NOT_FOUND;
  192. }
  193. if (deviceExtension->Dock.ProfileDepartureStyle == PDS_UPDATE_ON_EJECT) {
  194. KdEnableDebugger() ;
  195. }
  196. //
  197. // The dock may have failed _DCK on a start, in which case we have kept
  198. // it around for the explicit purpose of ejecting it. Now we make the dock
  199. // go away.
  200. //
  201. ACPIInternalUpdateFlags(
  202. &(deviceExtension->Flags),
  203. DEV_CAP_UNATTACHED_DOCK,
  204. TRUE
  205. );
  206. if (NT_SUCCESS(status)) {
  207. //
  208. // Get the currrent device status
  209. //
  210. status = ACPIGetDevicePresenceSync(
  211. deviceExtension,
  212. (PVOID *) &i,
  213. NULL
  214. );
  215. if (NT_SUCCESS(status) &&
  216. !(deviceExtension->Flags & DEV_TYPE_NOT_PRESENT)) {
  217. ACPIDevPrint( (
  218. ACPI_PRINT_FAILURE,
  219. deviceExtension,
  220. "(0x%08lx): ACPIDockIrpEjectDevice: "
  221. "dock is still listed as present after _DCK/_EJx!\n",
  222. Irp
  223. ) );
  224. //
  225. // The device did not go away. Let us fail this
  226. //
  227. status = STATUS_UNSUCCESSFUL ;
  228. }
  229. }
  230. Irp->IoStatus.Status = status;
  231. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  232. return status ;
  233. }
  234. NTSTATUS
  235. ACPIDockIrpQueryCapabilities(
  236. IN PDEVICE_OBJECT DeviceObject,
  237. IN PIRP Irp
  238. )
  239. /*++
  240. Routine Description:
  241. This handles a request to get the capabilities of a device.
  242. Arguments:
  243. DeviceObject - The device to get the capabilities for
  244. Irp - The request to the device to tell it to stop
  245. Return Value:
  246. NTSTATUS
  247. --*/
  248. {
  249. NTSTATUS status ;
  250. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  251. PDEVICE_EXTENSION dockDeviceExtension;
  252. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  253. UCHAR minorFunction = irpStack->MinorFunction;
  254. PDEVICE_CAPABILITIES capabilities;
  255. PNSOBJ acpiObject ;
  256. PAGED_CODE();
  257. //
  258. // Grab a pointer to the capabilities
  259. //
  260. capabilities = irpStack->Parameters.DeviceCapabilities.Capabilities;
  261. dockDeviceExtension = deviceExtension->Dock.CorrospondingAcpiDevice ;
  262. if (!dockDeviceExtension) {
  263. ACPIDevPrint( (
  264. ACPI_PRINT_FAILURE,
  265. deviceExtension,
  266. "(0x%08lx): ACPIDockIrpQueryCapabilities: "
  267. "no corresponding extension!!\n",
  268. Irp
  269. ) );
  270. ASSERT(0) ;
  271. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL ;
  272. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  273. return STATUS_UNSUCCESSFUL;
  274. }
  275. acpiObject = dockDeviceExtension->AcpiObject ;
  276. //
  277. // Set the current flags for the capabilities
  278. //
  279. capabilities->SilentInstall = TRUE;
  280. capabilities->RawDeviceOK = TRUE;
  281. capabilities->DockDevice = TRUE;
  282. capabilities->Removable = TRUE;
  283. capabilities->UniqueID = TRUE;
  284. if (ACPIAmliGetNamedChild( acpiObject, PACKED_EJ0)) {
  285. capabilities->EjectSupported = TRUE;
  286. }
  287. if (ACPIAmliGetNamedChild( acpiObject, PACKED_EJ1) ||
  288. ACPIAmliGetNamedChild( acpiObject, PACKED_EJ2) ||
  289. ACPIAmliGetNamedChild( acpiObject, PACKED_EJ3) ||
  290. ACPIAmliGetNamedChild( acpiObject, PACKED_EJ4)) {
  291. capabilities->WarmEjectSupported = TRUE;
  292. }
  293. //
  294. // An object of this name signifies the node is lockable
  295. //
  296. #if !defined(ACPI_INTERNAL_LOCKING)
  297. if (ACPIAmliGetNamedChild( acpiObject, PACKED_LCK) != NULL) {
  298. capabilities->LockSupported = TRUE;
  299. }
  300. #endif
  301. //
  302. // Internally record the power capabilities
  303. //
  304. status = ACPISystemPowerQueryDeviceCapabilities(
  305. deviceExtension,
  306. capabilities
  307. );
  308. //
  309. // Round down S1-S3 to D3. This will ensure we reexamine the _STA after
  310. // resume from sleep (note that we won't actually be playing with the docks
  311. // power methods, so this is safe)
  312. //
  313. capabilities->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;
  314. capabilities->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;
  315. capabilities->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;
  316. //
  317. // We can do this slimy-like because we don't have any Wake bits or
  318. // anything else fancy.
  319. //
  320. IoCopyDeviceCapabilitiesMapping(
  321. capabilities,
  322. deviceExtension->PowerInfo.DevicePowerMatrix
  323. );
  324. //
  325. // Now update our power matrix.
  326. //
  327. if (!NT_SUCCESS(status)) {
  328. ACPIDevPrint( (
  329. ACPI_PRINT_CRITICAL,
  330. deviceExtension,
  331. " - Could query device capabilities - %08lx",
  332. status
  333. ) );
  334. }
  335. ACPIDevPrint( (
  336. ACPI_PRINT_IRP,
  337. deviceExtension,
  338. "(0x%08lx): %s = 0x%08lx\n",
  339. Irp,
  340. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  341. status
  342. ) );
  343. Irp->IoStatus.Status = status;
  344. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  345. return status;
  346. }
  347. NTSTATUS
  348. ACPIDockIrpQueryDeviceRelations(
  349. IN PDEVICE_OBJECT DeviceObject,
  350. IN PIRP Irp
  351. )
  352. /*++
  353. Routine Description:
  354. This handles a request to query device relations. Since profile providers
  355. never have children, we only need to fix up the eject relations
  356. appropriately
  357. Arguments:
  358. DeviceObject - The device to get the capabilities for
  359. Irp - The request to the device to tell it to stop
  360. Return Value:
  361. NTSTATUS
  362. --*/
  363. {
  364. NTSTATUS status = STATUS_NOT_SUPPORTED;
  365. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  366. PDEVICE_RELATIONS deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
  367. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  368. UCHAR minorFunction = irpStack->MinorFunction;
  369. PAGED_CODE();
  370. switch(irpStack->Parameters.QueryDeviceRelations.Type) {
  371. case BusRelations:
  372. break ;
  373. case TargetDeviceRelation:
  374. status = ACPIBusIrpQueryTargetRelation(
  375. DeviceObject,
  376. Irp,
  377. &deviceRelations
  378. );
  379. break ;
  380. case EjectionRelations:
  381. status = ACPIDockIrpQueryEjectRelations(
  382. DeviceObject,
  383. Irp,
  384. &deviceRelations
  385. );
  386. break ;
  387. default:
  388. ACPIDevPrint( (
  389. ACPI_PRINT_IRP,
  390. deviceExtension,
  391. "(0x%08lx): %s - Unhandled Type %d\n",
  392. Irp,
  393. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  394. irpStack->Parameters.QueryDeviceRelations.Type
  395. ) );
  396. break ;
  397. }
  398. //
  399. // If we succeeds, then we can always write to the irp
  400. //
  401. if (NT_SUCCESS(status)) {
  402. Irp->IoStatus.Status = status;
  403. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  404. } else if ((status != STATUS_NOT_SUPPORTED) && (deviceRelations == NULL)) {
  405. //
  406. // If we haven't succeed the irp, then we can also fail it, but only
  407. // if nothing else has been added.
  408. //
  409. Irp->IoStatus.Status = status;
  410. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  411. } else {
  412. //
  413. // Grab our status from what is already present
  414. //
  415. status = Irp->IoStatus.Status;
  416. }
  417. //
  418. // Done with the irp
  419. //
  420. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  421. //
  422. // Done
  423. //
  424. ACPIDevPrint( (
  425. ACPI_PRINT_IRP,
  426. deviceExtension,
  427. "(0x%08lx): %s = 0x%08lx\n",
  428. Irp,
  429. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  430. status
  431. ) );
  432. return status;
  433. }
  434. NTSTATUS
  435. ACPIDockIrpQueryEjectRelations(
  436. IN PDEVICE_OBJECT DeviceObject,
  437. IN PIRP Irp,
  438. IN OUT PDEVICE_RELATIONS *PdeviceRelations
  439. )
  440. {
  441. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  442. PDEVICE_EXTENSION dockDeviceExtension ;
  443. PNSOBJ acpiObject = NULL;
  444. NTSTATUS status ;
  445. PAGED_CODE();
  446. //
  447. // lets get the corrosponding dock node for this device
  448. //
  449. dockDeviceExtension = deviceExtension->Dock.CorrospondingAcpiDevice ;
  450. if (!dockDeviceExtension) {
  451. //
  452. // Invalid name space object <bad>
  453. //
  454. ACPIDevPrint( (
  455. ACPI_PRINT_FAILURE,
  456. deviceExtension,
  457. "(0x%08lx): ACPIDockIrpQueryEjectRelations: "
  458. "no corresponding extension!!\n",
  459. Irp
  460. ) );
  461. ASSERT(0) ;
  462. return STATUS_UNSUCCESSFUL;
  463. }
  464. //
  465. // lets look at the ACPIObject that we have so can see if it is valid...
  466. //
  467. acpiObject = dockDeviceExtension->AcpiObject;
  468. if (acpiObject == NULL) {
  469. //
  470. // Invalid name space object <bad>
  471. //
  472. ACPIDevPrint( (
  473. ACPI_PRINT_CRITICAL,
  474. deviceExtension,
  475. "(0x%08lx): ACPIDockIrpQueryEjectRelations: "
  476. "invalid ACPIObject (0x%08lx)\n",
  477. acpiObject
  478. ) );
  479. return STATUS_INVALID_PARAMETER;
  480. }
  481. status = ACPIDetectEjectDevices(
  482. dockDeviceExtension,
  483. PdeviceRelations,
  484. dockDeviceExtension
  485. );
  486. //
  487. // If something went wrong...
  488. //
  489. if (!NT_SUCCESS(status)) {
  490. //
  491. // That's not nice..
  492. //
  493. ACPIDevPrint( (
  494. ACPI_PRINT_CRITICAL,
  495. deviceExtension,
  496. "(0x%08lx): ACPIDockIrpQueryEjectRelations: enum 0x%08lx\n",
  497. Irp,
  498. status
  499. ) );
  500. }
  501. return status ;
  502. }
  503. NTSTATUS
  504. ACPIDockIrpQueryID(
  505. IN PDEVICE_OBJECT DeviceObject,
  506. IN PIRP Irp
  507. )
  508. /*++
  509. Routine Description:
  510. This routine is the dispatch point for the IRP_MN_QUERY_ID PNP
  511. minor function
  512. Note: This is what the returned strings from this function should look
  513. like.
  514. DeviceID = ACPI\DockDevice
  515. InstanceID = ACPI object node ( CDCK, etc )
  516. HardwareIDs = ACPI\DockDevice&_SB.DOCK, ACPI\DockDevice
  517. Arguments:
  518. DeviceObject - The object that we care about
  519. Irp - The request in question
  520. Return Value:
  521. NTSTATUS
  522. --*/
  523. {
  524. BUS_QUERY_ID_TYPE type;
  525. NTSTATUS status;
  526. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  527. PDEVICE_EXTENSION dockDeviceExtension;
  528. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  529. PNSOBJ acpiObject = deviceExtension->AcpiObject;
  530. PUCHAR buffer;
  531. UCHAR minorFunction = irpStack->MinorFunction;
  532. UNICODE_STRING unicodeIdString;
  533. PWCHAR serialID;
  534. ULONG firstHardwareIDLength;
  535. PAGED_CODE();
  536. //
  537. // Initilize the Unicode Structure
  538. //
  539. RtlZeroMemory( &unicodeIdString, sizeof(UNICODE_STRING) );
  540. //
  541. // What we do is based on the IdType of the Request...
  542. //
  543. type = irpStack->Parameters.QueryId.IdType;
  544. switch (type) {
  545. case BusQueryDeviceID:
  546. //
  547. // We pre-calculate this since it is so useful for debugging
  548. //
  549. status = ACPIInitUnicodeString(
  550. &unicodeIdString,
  551. deviceExtension->DeviceID
  552. );
  553. break;
  554. case BusQueryDeviceSerialNumber:
  555. //
  556. // lets get the corrosponding dock node for this device
  557. //
  558. dockDeviceExtension = deviceExtension->Dock.CorrospondingAcpiDevice;
  559. if (!dockDeviceExtension) {
  560. //
  561. // Invalid name space object <bad>
  562. //
  563. ACPIDevPrint( (
  564. ACPI_PRINT_FAILURE,
  565. deviceExtension,
  566. "(0x%08lx): ACPIDockIrpQueryID: no corresponding extension!!\n",
  567. Irp
  568. ) );
  569. ASSERT(0);
  570. //
  571. // Mark the irp as very bad...
  572. //
  573. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  574. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  575. return STATUS_UNSUCCESSFUL;
  576. }
  577. status = ACPIGetSerialIDWide(
  578. dockDeviceExtension,
  579. &serialID,
  580. NULL
  581. );
  582. if (!NT_SUCCESS(status)) {
  583. break;
  584. }
  585. //
  586. // Return the Serial Number for the DockDevice
  587. //
  588. unicodeIdString.Buffer = serialID;
  589. break;
  590. case BusQueryInstanceID:
  591. //
  592. // We pre-calculate this since it is so useful for debugging
  593. //
  594. status = ACPIInitUnicodeString(
  595. &unicodeIdString,
  596. deviceExtension->InstanceID
  597. );
  598. break;
  599. case BusQueryCompatibleIDs:
  600. status = STATUS_NOT_SUPPORTED;
  601. break;
  602. case BusQueryHardwareIDs:
  603. //
  604. // Now set our identifier. In theory, the OS could use this
  605. // string in any scenario, although in reality it will key off
  606. // of the dock ID.
  607. //
  608. // Construct the MultiSz hardware ID list:
  609. // ACPI\DockDevice&_SB.PCI0.DOCK
  610. // ACPI\DockDevice
  611. //
  612. status = ACPIInitMultiString(
  613. &unicodeIdString,
  614. "ACPI\\DockDevice",
  615. deviceExtension->InstanceID,
  616. "ACPI\\DockDevice",
  617. NULL
  618. );
  619. if (NT_SUCCESS(status)) {
  620. //
  621. // Replace first '\0' with '&'
  622. //
  623. firstHardwareIDLength = wcslen(unicodeIdString.Buffer);
  624. unicodeIdString.Buffer[firstHardwareIDLength] = L'&';
  625. }
  626. break;
  627. default:
  628. ACPIDevPrint( (
  629. ACPI_PRINT_IRP,
  630. deviceExtension,
  631. "(0x%08lx): %s - Unhandled Id %d\n",
  632. Irp,
  633. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  634. type
  635. ) );
  636. status = STATUS_NOT_SUPPORTED;
  637. break;
  638. } // switch
  639. //
  640. // Did we pass or did we fail?
  641. //
  642. if (NT_SUCCESS(status)) {
  643. Irp->IoStatus.Information = (ULONG_PTR) unicodeIdString.Buffer;
  644. } else {
  645. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  646. }
  647. Irp->IoStatus.Status = status;
  648. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  649. ACPIDevPrint( (
  650. ACPI_PRINT_IRP,
  651. deviceExtension,
  652. "(0x%08lx): %s(%d) = 0x%08lx\n",
  653. Irp,
  654. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  655. type,
  656. status
  657. ) );
  658. return status;
  659. }
  660. NTSTATUS
  661. ACPIDockIrpQueryInterface(
  662. IN PDEVICE_OBJECT DeviceObject,
  663. IN PIRP Irp
  664. )
  665. /*++
  666. Routine Description:
  667. This routine is the dispatch point for the IRP_MN_QUERY_INTERFACE minor
  668. function. The only reason we respond to this is so we can handle the
  669. dock interface which is used to solve the removal ordering problem we won't
  670. be fixing 5.0 (sigh).
  671. Arguments:
  672. DeviceObject - The object that we care about
  673. Irp - The request in question
  674. Return Value:
  675. NTSTATUS
  676. --*/
  677. {
  678. NTSTATUS status;
  679. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  680. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  681. UCHAR minorFunction = irpStack->MinorFunction;
  682. LPGUID interfaceType;
  683. PAGED_CODE();
  684. status = Irp->IoStatus.Status;
  685. interfaceType = (LPGUID) irpStack->Parameters.QueryInterface.InterfaceType;
  686. if (CompareGuid(interfaceType, (PVOID) &GUID_DOCK_INTERFACE)) {
  687. DOCK_INTERFACE dockInterface;
  688. USHORT count;
  689. //
  690. // Only copy up to current size of the ACPI_INTERFACE structure
  691. //
  692. if (irpStack->Parameters.QueryInterface.Size > sizeof(DOCK_INTERFACE)) {
  693. count = sizeof(DOCK_INTERFACE);
  694. } else {
  695. count = irpStack->Parameters.QueryInterface.Size;
  696. }
  697. //
  698. // Build up the interface structure.
  699. //
  700. dockInterface.Size = count;
  701. dockInterface.Version = DOCK_INTRF_STANDARD_VER;
  702. dockInterface.Context = DeviceObject;
  703. dockInterface.InterfaceReference = ACPIDockIntfReference;
  704. dockInterface.InterfaceDereference = ACPIDockIntfDereference;
  705. dockInterface.ProfileDepartureSetMode = ACPIDockIntfSetMode;
  706. dockInterface.ProfileDepartureUpdate = ACPIDockIntfUpdateDeparture;
  707. //
  708. // Give it a reference
  709. //
  710. dockInterface.InterfaceReference(dockInterface.Context);
  711. //
  712. // Hand back the interface
  713. //
  714. RtlCopyMemory(
  715. (PDOCK_INTERFACE) irpStack->Parameters.QueryInterface.Interface,
  716. &dockInterface,
  717. count
  718. );
  719. //
  720. // We're done with this irp
  721. //
  722. Irp->IoStatus.Status = status = STATUS_SUCCESS;
  723. }
  724. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  725. ACPIDevPrint( (
  726. ACPI_PRINT_IRP,
  727. deviceExtension,
  728. "(0x%08lx): %s = 0x%08lx\n",
  729. Irp,
  730. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  731. status
  732. ) );
  733. return status;
  734. }
  735. NTSTATUS
  736. ACPIDockIrpQueryPnpDeviceState(
  737. IN PDEVICE_OBJECT DeviceObject,
  738. IN PIRP Irp
  739. )
  740. /*++
  741. Routine Description:
  742. This routine is the dispatch point for the IRP_MN_QUERY_PNP_DEVICE_STATE
  743. minor function. The only reason we respond to this is so we can set the
  744. PNP_DEVICE_DONT_DISPLAY_IN_UI flag (we are a raw PDO that does not need
  745. to be visible)
  746. Arguments:
  747. DeviceObject - The object that we care about
  748. Irp - The request in question
  749. Return Value:
  750. NTSTATUS
  751. --*/
  752. {
  753. NTSTATUS status = STATUS_SUCCESS;
  754. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  755. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  756. UCHAR minorFunction = irpStack->MinorFunction;
  757. PAGED_CODE();
  758. Irp->IoStatus.Information |= PNP_DEVICE_DONT_DISPLAY_IN_UI ;
  759. Irp->IoStatus.Status = status;
  760. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  761. ACPIDevPrint( (
  762. ACPI_PRINT_IRP,
  763. deviceExtension,
  764. "(0x%08lx): %s = 0x%08lx\n",
  765. Irp,
  766. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  767. status
  768. ) );
  769. return status;
  770. }
  771. NTSTATUS
  772. ACPIDockIrpQueryPower(
  773. IN PDEVICE_OBJECT DeviceObject,
  774. IN PIRP Irp
  775. )
  776. /*++
  777. Routine Description:
  778. This routines tells the system what PNP state the device is in
  779. Arguments:
  780. DeviceObject - The device whose state we want to know
  781. Irp - The request
  782. Return Value:
  783. NTSTATUS
  784. --*/
  785. {
  786. NTSTATUS status;
  787. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  788. PDEVICE_EXTENSION dockDeviceExtension ;
  789. PIO_STACK_LOCATION irpSp;
  790. PNSOBJ acpiObject, ejectObject ;
  791. SYSTEM_POWER_STATE systemState;
  792. ULONG packedEJx ;
  793. dockDeviceExtension = deviceExtension->Dock.CorrospondingAcpiDevice ;
  794. if (!dockDeviceExtension) {
  795. ACPIDevPrint( (
  796. ACPI_PRINT_FAILURE,
  797. deviceExtension,
  798. "(0x%08lx): ACPIDockIrpQueryPower - "
  799. "no corresponding extension!!\n",
  800. Irp
  801. ) );
  802. ASSERT(0) ;
  803. return ACPIDispatchPowerIrpSuccess( DeviceObject, Irp );
  804. }
  805. //
  806. // Get the Current stack location to determine if we are a system
  807. // irp or a device irp. We ignore device irps here.
  808. //
  809. irpSp = IoGetCurrentIrpStackLocation(Irp);
  810. if (irpSp->Parameters.Power.Type != SystemPowerState) {
  811. //
  812. // We don't handle this irp
  813. //
  814. return ACPIDispatchPowerIrpSuccess( DeviceObject, Irp );
  815. }
  816. if (irpSp->Parameters.Power.ShutdownType != PowerActionWarmEject) {
  817. //
  818. // No eject work - complete the IRP.
  819. //
  820. return ACPIDispatchPowerIrpSuccess( DeviceObject, Irp );
  821. }
  822. //
  823. // Restrict power states to those supported.
  824. //
  825. acpiObject = dockDeviceExtension->AcpiObject;
  826. //
  827. // What system state are we looking at?
  828. //
  829. systemState = irpSp->Parameters.Power.State.SystemState;
  830. switch (irpSp->Parameters.Power.State.SystemState) {
  831. case PowerSystemSleeping1:
  832. packedEJx = PACKED_EJ1;
  833. break;
  834. case PowerSystemSleeping2:
  835. packedEJx = PACKED_EJ2;
  836. break;
  837. case PowerSystemSleeping3:
  838. packedEJx = PACKED_EJ3;
  839. break;
  840. case PowerSystemHibernate:
  841. packedEJx = PACKED_EJ4;
  842. break;
  843. case PowerSystemWorking:
  844. case PowerSystemShutdown:
  845. default:
  846. packedEJx = 0;
  847. break;
  848. }
  849. if (packedEJx) {
  850. ejectObject = ACPIAmliGetNamedChild( acpiObject, packedEJx);
  851. if (ejectObject == NULL) {
  852. //
  853. // Fail the request, as we cannot eject in this case.
  854. //
  855. PoStartNextPowerIrp( Irp );
  856. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  857. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  858. return STATUS_UNSUCCESSFUL;
  859. }
  860. }
  861. return ACPIDispatchPowerIrpSuccess( DeviceObject, Irp );
  862. }
  863. NTSTATUS
  864. ACPIDockIrpRemoveDevice(
  865. IN PDEVICE_OBJECT DeviceObject,
  866. IN PIRP Irp
  867. )
  868. /*++
  869. Routine Description:
  870. This routine is called when we need to remove the device. Note that we only
  871. delete ourselves if we have been undocked (ie, our hardware is gone)
  872. Arguments:
  873. DeviceObject - The dock device to "remove"
  874. Irp - The request to the device to tell it to go away
  875. Return Value:
  876. NTSTATUS
  877. --*/
  878. {
  879. LONG oldReferenceCount;
  880. KIRQL oldIrql;
  881. NTSTATUS status = STATUS_SUCCESS;
  882. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  883. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  884. UCHAR minorFunction = irpStack->MinorFunction;
  885. ULONG i, ignoredPerSpec;
  886. if (!(deviceExtension->Flags & DEV_MASK_NOT_PRESENT)) {
  887. //
  888. // If the device is still physically present, so must the PDO be.
  889. // This case is essentially a stop. Mark the request as complete...
  890. //
  891. Irp->IoStatus.Status = status;
  892. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  893. return status;
  894. }
  895. if (deviceExtension->DeviceState == Removed) {
  896. Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  897. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  898. return STATUS_NO_SUCH_DEVICE;
  899. }
  900. if (deviceExtension->Dock.ProfileDepartureStyle == PDS_UPDATE_ON_REMOVE) {
  901. PDEVICE_EXTENSION dockDeviceExtension;
  902. //
  903. // lets get the corrosponding dock node for this device
  904. //
  905. dockDeviceExtension = deviceExtension->Dock.CorrospondingAcpiDevice ;
  906. //
  907. // On the Compaq Armada 7800, we switch UARTs during an undock, thus we
  908. // lose the debugger com port programming.
  909. //
  910. if (deviceExtension->Dock.IsolationState != IS_ISOLATED) {
  911. KdDisableDebugger();
  912. status = ACPIGetIntegerEvalIntegerSync(
  913. dockDeviceExtension,
  914. PACKED_DCK,
  915. 0,
  916. &ignoredPerSpec
  917. );
  918. KdEnableDebugger();
  919. }
  920. }
  921. //
  922. // The device is gone. Let the isolation state reflect that.
  923. //
  924. deviceExtension->Dock.IsolationState = IS_UNKNOWN;
  925. //
  926. // Set the device state as removed
  927. //
  928. deviceExtension->DeviceState = Removed;
  929. //
  930. // Complete the request
  931. //
  932. Irp->IoStatus.Status = STATUS_SUCCESS;
  933. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  934. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  935. //
  936. // Done
  937. //
  938. ACPIDevPrint( (
  939. ACPI_PRINT_IRP,
  940. deviceExtension,
  941. "(0x%08lx): %s = 0x%08lx\n",
  942. Irp,
  943. ACPIDebugGetIrpText(IRP_MJ_PNP, minorFunction),
  944. STATUS_SUCCESS
  945. ) );
  946. //
  947. // Update the device extension
  948. //
  949. KeAcquireSpinLock( &AcpiDeviceTreeLock, &oldIrql );
  950. ASSERT(!(deviceExtension->Flags&DEV_TYPE_FILTER)) ;
  951. //
  952. // Step one is to zero out the things that we no longer care about
  953. //
  954. deviceExtension->TargetDeviceObject = NULL;
  955. deviceExtension->PhysicalDeviceObject = NULL;
  956. deviceExtension->DeviceObject = NULL;
  957. //
  958. // Mark the node as being fresh and untouched
  959. //
  960. ACPIInternalUpdateFlags( &(deviceExtension->Flags), DEV_MASK_TYPE, TRUE );
  961. ACPIInternalUpdateFlags( &(deviceExtension->Flags), DEV_TYPE_NOT_FOUND, FALSE );
  962. ACPIInternalUpdateFlags( &(deviceExtension->Flags), DEV_TYPE_REMOVED, FALSE );
  963. //
  964. // The reference count should have value > 0
  965. //
  966. oldReferenceCount = InterlockedDecrement(
  967. &(deviceExtension->ReferenceCount)
  968. );
  969. ASSERT(oldReferenceCount >= 0) ;
  970. if ( oldReferenceCount == 0) {
  971. //
  972. // Delete the extension
  973. //
  974. ACPIInitDeleteDeviceExtension( deviceExtension );
  975. }
  976. //
  977. // Done with the lock
  978. //
  979. KeReleaseSpinLock( &AcpiDeviceTreeLock, oldIrql );
  980. //
  981. // Delete the device
  982. //
  983. IoDeleteDevice( DeviceObject );
  984. //
  985. // Done
  986. //
  987. return STATUS_SUCCESS;
  988. }
  989. NTSTATUS
  990. ACPIDockIrpSetLock(
  991. IN PDEVICE_OBJECT DeviceObject,
  992. IN PIRP Irp
  993. )
  994. /*++
  995. Routine Description:
  996. Arguments:
  997. DeviceObject - The device to set the lock state for
  998. Irp - The request to the device to tell it to lock
  999. Return Value:
  1000. NTSTATUS
  1001. --*/
  1002. {
  1003. NTSTATUS status;
  1004. PAGED_CODE();
  1005. //
  1006. // We aren't a real device, so we don't do locking.
  1007. //
  1008. status = Irp->IoStatus.Status ;
  1009. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1010. return status ;
  1011. }
  1012. NTSTATUS
  1013. ACPIDockIrpStartDevice(
  1014. IN PDEVICE_OBJECT DeviceObject,
  1015. IN PIRP Irp
  1016. )
  1017. /*++
  1018. Routine Description:
  1019. This handles a request to start the device
  1020. Arguments:
  1021. DeviceObject - The device to start
  1022. Irp - The request to the device to tell it to start
  1023. Return Value:
  1024. NTSTATUS
  1025. --*/
  1026. {
  1027. NTSTATUS status = STATUS_SUCCESS;
  1028. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  1029. PDEVICE_EXTENSION dockDeviceExtension;
  1030. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation( Irp );
  1031. UCHAR minorFunction = irpStack->MinorFunction;
  1032. ULONG dockResult;
  1033. ULONG dockStatus;
  1034. PAGED_CODE();
  1035. dockDeviceExtension = deviceExtension->Dock.CorrospondingAcpiDevice ;
  1036. if (!dockDeviceExtension) {
  1037. ACPIDevPrint( (
  1038. ACPI_PRINT_FAILURE,
  1039. deviceExtension,
  1040. "(0x%08lx): ACPIDockIrpStartDevice - "
  1041. "no corresponding extension!!\n",
  1042. Irp
  1043. ) );
  1044. ASSERT(0) ;
  1045. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL ;
  1046. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1047. return STATUS_UNSUCCESSFUL;
  1048. }
  1049. if (deviceExtension->Dock.IsolationState == IS_ISOLATED) {
  1050. KdDisableDebugger();
  1051. //
  1052. // Note: the way that this is structured is that we get
  1053. // the _DCK value first, and if that succeeds, then we
  1054. // get the device presence. If that also succeeds, then
  1055. // we try to process the two. If either fail, we don't
  1056. // do any work
  1057. //
  1058. status = ACPIGetIntegerEvalIntegerSync(
  1059. dockDeviceExtension,
  1060. PACKED_DCK,
  1061. 1,
  1062. &dockResult
  1063. );
  1064. if (NT_SUCCESS(status)) {
  1065. //
  1066. // Get the device presence
  1067. //
  1068. status = ACPIGetDevicePresenceSync(
  1069. dockDeviceExtension,
  1070. (PVOID *) &dockStatus,
  1071. NULL
  1072. );
  1073. }
  1074. KdEnableDebugger();
  1075. if (NT_SUCCESS(status)) {
  1076. if (dockDeviceExtension->Flags & DEV_TYPE_NOT_PRESENT) {
  1077. if (dockResult != 0) {
  1078. ACPIDevPrint( (
  1079. ACPI_PRINT_FAILURE,
  1080. deviceExtension,
  1081. "(0x%08lx): ACPIDockIrpStartDevice: "
  1082. "Not present, but _DCK = %08lx\n",
  1083. Irp,
  1084. dockResult
  1085. ) );
  1086. } else {
  1087. ACPIDevPrint( (
  1088. ACPI_PRINT_FAILURE,
  1089. deviceExtension,
  1090. "(0x%08lx): ACPIDockIrpStartDevice: _DCK = 0\n",
  1091. Irp
  1092. ) );
  1093. }
  1094. status = STATUS_UNSUCCESSFUL ;
  1095. } else {
  1096. if (dockResult != 1) {
  1097. ACPIDevPrint( (
  1098. ACPI_PRINT_FAILURE,
  1099. deviceExtension,
  1100. "(0x%08lx): ACPIDockIrpStartDevice: _DCK = 0\n",
  1101. Irp
  1102. ) );
  1103. } else {
  1104. ACPIDevPrint( (
  1105. ACPI_PRINT_IRP,
  1106. deviceExtension,
  1107. "(0x%08lx): ACPIDockIrpStartDevice = 0x%08lx\n",
  1108. Irp,
  1109. status
  1110. ) );
  1111. }
  1112. }
  1113. }
  1114. //
  1115. // We are done. The ACPI implementers guide says we don't need to
  1116. // enumerate the entire tree here as the _DCK method should have
  1117. // notified the appropriate branches of the tree if the docking event
  1118. // was successful. Unfortunately Win2K behavior was to enumerate the
  1119. // entire tree. Specifically, it would drain starts before enums. Since
  1120. // the profile provider appeared at the top of the tree, the dock would
  1121. // start and then the enum that found it would proceed and find the
  1122. // hardware. To maintain this pseudo-behavior we queue an enum here
  1123. // (bletch.)
  1124. //
  1125. IoInvalidateDeviceRelations(
  1126. RootDeviceExtension->PhysicalDeviceObject,
  1127. BusRelations
  1128. );
  1129. //
  1130. // Now we remove the unattached dock flag, but only if we succeeded
  1131. // start. If we cleared it in the failure case, we couldn't eject the
  1132. // dock that may be physically attached. Note that this also means we
  1133. // *must* try to eject the dock after start failure! The proper code for
  1134. // this is part of the kernel.
  1135. //
  1136. if (NT_SUCCESS(status)) {
  1137. ACPIInternalUpdateFlags(
  1138. &(deviceExtension->Flags),
  1139. DEV_CAP_UNATTACHED_DOCK,
  1140. TRUE
  1141. );
  1142. }
  1143. }
  1144. if (NT_SUCCESS(status)) {
  1145. deviceExtension->Dock.IsolationState = IS_ISOLATION_DROPPED;
  1146. deviceExtension->DeviceState = Started;
  1147. }
  1148. Irp->IoStatus.Status = status;
  1149. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1150. return status;
  1151. }
  1152. BOOLEAN
  1153. ACPIDockIsDockDevice(
  1154. IN PNSOBJ AcpiObject
  1155. )
  1156. /*++
  1157. Routine Description:
  1158. This routine will tell the caller whether the given device is a dock.
  1159. Arguments:
  1160. The ACPI Object to test.
  1161. Return Value:
  1162. BOOLEAN (true iff dock)
  1163. --*/
  1164. {
  1165. PNSOBJ dckMethodObject ;
  1166. //
  1167. // ACPI dock devices are identified via _DCK methods.
  1168. //
  1169. return (NT_SUCCESS(ACPIDockGetDockObject(AcpiObject, &dckMethodObject))) ;
  1170. }
  1171. NTSTATUS
  1172. ACPIDockIrpSetPower(
  1173. IN PDEVICE_OBJECT DeviceObject,
  1174. IN PIRP Irp
  1175. )
  1176. /*++
  1177. Routine Description:
  1178. This routine handles request to set the power state for a Physical
  1179. Device object
  1180. Arguments:
  1181. DeviceObject - The PDO target of the request
  1182. Irp - The request
  1183. Return Value:
  1184. NTSTATUS
  1185. --*/
  1186. {
  1187. NTSTATUS status;
  1188. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  1189. UCHAR minorFunction = irpSp->MinorFunction;
  1190. if (irpSp->Parameters.Power.Type != SystemPowerState) {
  1191. return ACPIDockIrpSetDevicePower(DeviceObject, Irp);
  1192. } else {
  1193. return ACPIDockIrpSetSystemPower(DeviceObject, Irp);
  1194. }
  1195. }
  1196. NTSTATUS
  1197. ACPIDockIrpSetDevicePower(
  1198. IN PDEVICE_OBJECT DeviceObject,
  1199. IN PIRP Irp
  1200. )
  1201. /*++
  1202. Routine Description:
  1203. This routine handles device power request for a dock PDO
  1204. Arguments:
  1205. DeviceObject - The PDO target
  1206. Irp - The request
  1207. IrpStack - The current request
  1208. Return Value:
  1209. NTSTATUS
  1210. --*/
  1211. {
  1212. NTSTATUS status;
  1213. PDEVICE_EXTENSION deviceExtension;
  1214. //
  1215. // Get the device extension
  1216. //
  1217. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  1218. //
  1219. // We are going to do some work on the irp, so mark it as being
  1220. // successfull for now
  1221. //
  1222. Irp->IoStatus.Status = STATUS_SUCCESS;
  1223. //
  1224. // Mark the irp as pending
  1225. //
  1226. IoMarkIrpPending( Irp );
  1227. //
  1228. // We might queue up the irp, so this counts as a completion routine.
  1229. // Which means we need to incr the ref count
  1230. //
  1231. InterlockedIncrement( &deviceExtension->OutstandingIrpCount );
  1232. //
  1233. // Queue the irp up. Note that we will *always* call the completion
  1234. // routine, so we don't really care what was returned directly by
  1235. // this call --- the callback gets a chance to execute.
  1236. //
  1237. status = ACPIDeviceIrpDeviceRequest(
  1238. DeviceObject,
  1239. Irp,
  1240. ACPIDeviceIrpCompleteRequest
  1241. );
  1242. //
  1243. // Did we return STATUS_MORE_PROCESSING_REQUIRED (which we used
  1244. // if we overload STATUS_PENDING)
  1245. //
  1246. if (status == STATUS_MORE_PROCESSING_REQUIRED) {
  1247. status = STATUS_PENDING;
  1248. }
  1249. //
  1250. // Note: We called the completion routine, which should have completed
  1251. // the IRP with the same STATUS code as is being returned here (okay, if
  1252. // it is STATUS_PENDING, obviously we haven't completed the IRP, but that
  1253. // is okay).
  1254. //
  1255. return status;
  1256. }
  1257. NTSTATUS
  1258. ACPIDockIrpSetSystemPower(
  1259. IN PDEVICE_OBJECT DeviceObject,
  1260. IN PIRP Irp
  1261. )
  1262. /*++
  1263. Routine Description:
  1264. This routine handles request to set the system power state for a Physical
  1265. Device object. Here we initiate warm ejects and act as a power policy
  1266. manager for ourselves.
  1267. Arguments:
  1268. DeviceObject - The PDO target of the request
  1269. Irp - The request
  1270. Return Value:
  1271. NTSTATUS
  1272. --*/
  1273. {
  1274. NTSTATUS status;
  1275. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  1276. UCHAR minorFunction = irpSp->MinorFunction;
  1277. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(DeviceObject);
  1278. PDEVICE_EXTENSION dockDeviceExtension;
  1279. SYSTEM_POWER_STATE systemState;
  1280. DEVICE_POWER_STATE deviceState;
  1281. POWER_STATE powerState;
  1282. //
  1283. // Get the device extension
  1284. //
  1285. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  1286. //
  1287. // Grab these two values. They are required for further calculations
  1288. //
  1289. systemState= irpSp->Parameters.Power.State.SystemState;
  1290. deviceState = deviceExtension->PowerInfo.DevicePowerMatrix[systemState];
  1291. dockDeviceExtension = deviceExtension->Dock.CorrospondingAcpiDevice ;
  1292. if (!dockDeviceExtension) {
  1293. ACPIDevPrint( (
  1294. ACPI_PRINT_FAILURE,
  1295. deviceExtension,
  1296. "(0x%08lx): ACPIDockIrpSetPower - "
  1297. "no corresponding extension!!\n",
  1298. Irp
  1299. ) );
  1300. ASSERT(0) ;
  1301. return ACPIDispatchPowerIrpFailure( DeviceObject, Irp );
  1302. }
  1303. if (irpSp->Parameters.Power.ShutdownType == PowerActionWarmEject) {
  1304. //
  1305. // We are going to do some work on the irp, so mark it as being
  1306. // successful for now
  1307. //
  1308. Irp->IoStatus.Status = STATUS_SUCCESS;
  1309. //
  1310. // Mark the irp as pending
  1311. //
  1312. IoMarkIrpPending( Irp );
  1313. //
  1314. // We might queue up the irp, so this counts as a completion routine.
  1315. // Which means we need to incr the ref count
  1316. //
  1317. InterlockedIncrement( &dockDeviceExtension->OutstandingIrpCount );
  1318. ACPIDevPrint( (
  1319. ACPI_PRINT_REMOVE,
  1320. deviceExtension,
  1321. "(0x%08lx) ACPIBusIrpSetSystemPower: Eject from S%d!\n",
  1322. Irp,
  1323. systemState - PowerSystemWorking
  1324. ) );
  1325. //
  1326. // Request the warm eject
  1327. //
  1328. status = ACPIDeviceIrpWarmEjectRequest(
  1329. dockDeviceExtension,
  1330. Irp,
  1331. ACPIDeviceIrpCompleteRequest,
  1332. (BOOLEAN) (deviceExtension->Dock.ProfileDepartureStyle == PDS_UPDATE_ON_EJECT)
  1333. );
  1334. //
  1335. // If we got back STATUS_MORE_PROCESSING_REQUIRED, then that is
  1336. // just an alias for STATUS_PENDING, so we make that change now
  1337. //
  1338. if (status == STATUS_MORE_PROCESSING_REQUIRED) {
  1339. status = STATUS_PENDING;
  1340. }
  1341. return status;
  1342. }
  1343. //
  1344. // Look at the device extension and determine if we need to send a
  1345. // D-irp in respond. The rule is that if the device is RAW driven or
  1346. // the current D state of the device is numerically lower then the
  1347. // known D state for the given S state, then we should send the request
  1348. //
  1349. ASSERT(deviceExtension->Flags & DEV_CAP_RAW);
  1350. if ( (deviceExtension->PowerInfo.PowerState == deviceState) ) {
  1351. return ACPIDispatchPowerIrpSuccess( DeviceObject, Irp );
  1352. } // if
  1353. ACPIDevPrint( (
  1354. ACPI_PRINT_REMOVE,
  1355. deviceExtension,
  1356. "(0x%08lx) ACPIDockIrpSetSystemPower: send D%d irp!\n",
  1357. Irp,
  1358. deviceState - PowerDeviceD0
  1359. ) );
  1360. //
  1361. // We are going to do some work on the irp, so mark it as being
  1362. // successfull for now
  1363. //
  1364. Irp->IoStatus.Status = STATUS_SUCCESS;
  1365. //
  1366. // Mark the irp as pending
  1367. //
  1368. IoMarkIrpPending( Irp );
  1369. //
  1370. // We might queue up the irp, so this counts as a completion routine.
  1371. // Which means we need to incr the ref count
  1372. //
  1373. InterlockedIncrement( &deviceExtension->OutstandingIrpCount );
  1374. //
  1375. // We need to actually use a PowerState to send the request down, not
  1376. // a device state
  1377. //
  1378. powerState.DeviceState = deviceState;
  1379. //
  1380. // Make the request
  1381. //
  1382. PoRequestPowerIrp(
  1383. DeviceObject,
  1384. IRP_MN_SET_POWER,
  1385. powerState,
  1386. ACPIDockIrpSetSystemPowerComplete,
  1387. Irp,
  1388. NULL
  1389. );
  1390. //
  1391. // Always return pending
  1392. //
  1393. return STATUS_PENDING;
  1394. }
  1395. NTSTATUS
  1396. ACPIDockIrpSetSystemPowerComplete(
  1397. IN PDEVICE_OBJECT DeviceObject,
  1398. IN UCHAR MinorFunction,
  1399. IN POWER_STATE PowerState,
  1400. IN PVOID Context,
  1401. IN PIO_STATUS_BLOCK IoStatus
  1402. )
  1403. /*++
  1404. Routine Description:
  1405. This routine is called when the created D-irp has been sent throughout
  1406. the stack
  1407. Arguments:
  1408. DeviceObject - The device that received the request
  1409. MinorFunction - The function that was requested of the device
  1410. PowerState - The power state the device was sent to
  1411. Context - The original system irp
  1412. IoStatus - The result of the request
  1413. Return Value:
  1414. NTSTATUS
  1415. --*/
  1416. {
  1417. PIRP irp = (PIRP) Context;
  1418. PDEVICE_EXTENSION deviceExtension;
  1419. //
  1420. // Get the device extension
  1421. //
  1422. deviceExtension = ACPIInternalGetDeviceExtension( DeviceObject );
  1423. //
  1424. // Make sure that we have cleared the information field
  1425. //
  1426. irp->IoStatus.Information = 0;
  1427. //
  1428. // Call this wrapper function so that we don't have to duplicated code
  1429. //
  1430. ACPIDeviceIrpCompleteRequest(
  1431. deviceExtension,
  1432. (PVOID) irp,
  1433. IoStatus->Status
  1434. );
  1435. //
  1436. // Done
  1437. //
  1438. return IoStatus->Status;
  1439. }
  1440. VOID
  1441. ACPIDockIntfReference(
  1442. IN PVOID Context
  1443. )
  1444. /*++
  1445. Routine Description:
  1446. This routine increments the reference count for the dock interface
  1447. Arguments:
  1448. Context - The device object this interface was taken out against
  1449. Return Value:
  1450. None
  1451. --*/
  1452. {
  1453. PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT) Context;
  1454. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(deviceObject);
  1455. PAGED_CODE();
  1456. ObReferenceObject(deviceObject);
  1457. InterlockedIncrement(&deviceExtension->ReferenceCount);
  1458. if (!(deviceExtension->Flags & DEV_TYPE_SURPRISE_REMOVED)) {
  1459. InterlockedIncrement(&deviceExtension->Dock.InterfaceReferenceCount);
  1460. }
  1461. }
  1462. VOID
  1463. ACPIDockIntfDereference(
  1464. IN PVOID Context
  1465. )
  1466. /*++
  1467. Routine Description:
  1468. This routine decrements the reference count for the dock interface
  1469. Arguments:
  1470. Context - The device object this interface was taken out against
  1471. Return Value:
  1472. None
  1473. --*/
  1474. {
  1475. PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT) Context;
  1476. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(deviceObject);
  1477. ULONG oldReferenceCount;
  1478. PAGED_CODE();
  1479. if (!(deviceExtension->Flags & DEV_TYPE_SURPRISE_REMOVED)) {
  1480. oldReferenceCount = InterlockedDecrement(
  1481. &deviceExtension->Dock.InterfaceReferenceCount
  1482. );
  1483. if (oldReferenceCount == 0) {
  1484. //
  1485. // Revert back to the default used in buildsrc.c
  1486. //
  1487. deviceExtension->Dock.ProfileDepartureStyle = PDS_UPDATE_ON_EJECT;
  1488. }
  1489. }
  1490. oldReferenceCount = InterlockedDecrement(&deviceExtension->ReferenceCount);
  1491. if (oldReferenceCount == 0) {
  1492. //
  1493. // Delete the extension
  1494. //
  1495. ACPIInitDeleteDeviceExtension(deviceExtension);
  1496. }
  1497. ObDereferenceObject(deviceObject);
  1498. }
  1499. NTSTATUS
  1500. ACPIDockIntfSetMode(
  1501. IN PVOID Context,
  1502. IN PROFILE_DEPARTURE_STYLE Style
  1503. )
  1504. /*++
  1505. Routine Description:
  1506. This routine sets the manner in which profiles will be updated
  1507. Arguments:
  1508. Context - The device object this interface was taken out against
  1509. Style - PDS_UPDATE_ON_REMOVE, PDS_UPDATE_ON_EJECT,
  1510. PDS_UPDATE_ON_INTERFACE, or PDS_UPDATE_DEFAULT
  1511. Return Value:
  1512. NTSTATUS
  1513. --*/
  1514. {
  1515. PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT) Context;
  1516. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(deviceObject);
  1517. PAGED_CODE();
  1518. if (deviceExtension->Flags & DEV_TYPE_SURPRISE_REMOVED) {
  1519. return STATUS_NO_SUCH_DEVICE;
  1520. }
  1521. deviceExtension->Dock.ProfileDepartureStyle =
  1522. (Style == PDS_UPDATE_DEFAULT) ? PDS_UPDATE_ON_EJECT : Style;
  1523. ASSERT(deviceExtension->Dock.InterfaceReferenceCount);
  1524. return STATUS_SUCCESS;
  1525. }
  1526. NTSTATUS
  1527. ACPIDockIntfUpdateDeparture(
  1528. IN PVOID Context
  1529. )
  1530. /*++
  1531. Routine Description:
  1532. This routine initiates the hardware profile change portion of an undock
  1533. Arguments:
  1534. Context - The device object this interface was taken out against
  1535. Return Value:
  1536. NTSTATUS
  1537. --*/
  1538. {
  1539. PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT) Context;
  1540. PDEVICE_EXTENSION deviceExtension = ACPIInternalGetDeviceExtension(deviceObject);
  1541. NTSTATUS status;
  1542. ULONG ignoredPerSpec;
  1543. PDEVICE_EXTENSION dockDeviceExtension;
  1544. PAGED_CODE();
  1545. if (deviceExtension->Flags & DEV_TYPE_SURPRISE_REMOVED) {
  1546. return STATUS_NO_SUCH_DEVICE;
  1547. }
  1548. ASSERT(deviceExtension->Dock.InterfaceReferenceCount);
  1549. ASSERT(deviceExtension->Dock.ProfileDepartureStyle == PDS_UPDATE_ON_INTERFACE);
  1550. if (deviceExtension->Dock.ProfileDepartureStyle != PDS_UPDATE_ON_INTERFACE) {
  1551. //
  1552. // Can't do this, we may already have updated our profile!
  1553. //
  1554. return STATUS_INVALID_DEVICE_REQUEST;
  1555. }
  1556. //
  1557. // lets get the corrosponding dock node for this device
  1558. //
  1559. dockDeviceExtension = deviceExtension->Dock.CorrospondingAcpiDevice ;
  1560. //
  1561. // On the Compaq Armada 7800, we switch UARTs during an undock, thus we
  1562. // lose the debugger com port programming.
  1563. //
  1564. if (deviceExtension->Dock.IsolationState != IS_ISOLATED) {
  1565. KdDisableDebugger();
  1566. status = ACPIGetIntegerEvalIntegerSync(
  1567. dockDeviceExtension,
  1568. PACKED_DCK,
  1569. 0,
  1570. &ignoredPerSpec
  1571. );
  1572. KdEnableDebugger();
  1573. deviceExtension->Dock.IsolationState = IS_ISOLATED;
  1574. } else {
  1575. status = STATUS_SUCCESS;
  1576. }
  1577. return status;
  1578. }