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.

1152 lines
36 KiB

  1. /*++
  2. Copyright (C) 1997-99 Microsoft Corporation
  3. Module Name:
  4. pdopower.c
  5. Abstract:
  6. --*/
  7. #include "ideport.h"
  8. VOID
  9. IdePowerCheckBusyCompletion (
  10. IN PDEVICE_OBJECT DeviceObject,
  11. IN PIDE_POWER_CONTEXT Context,
  12. IN NTSTATUS Status
  13. );
  14. NTSTATUS
  15. DeviceQueryPowerState (
  16. IN PDEVICE_OBJECT DeviceObject,
  17. IN OUT PIRP Irp
  18. )
  19. {
  20. PIO_STACK_LOCATION irpStack;
  21. PPDO_EXTENSION pdoExtension;
  22. pdoExtension = RefPdoWithTag(
  23. DeviceObject,
  24. FALSE,
  25. Irp
  26. );
  27. if (pdoExtension) {
  28. #if defined (DONT_POWER_DOWN_PAGING_DEVICE)
  29. irpStack = IoGetCurrentIrpStackLocation (Irp);
  30. if (!pdoExtension->CrashDumpPathCount ||
  31. ((irpStack->Parameters.Power.Type == SystemPowerState) &&
  32. (irpStack->Parameters.Power.State.SystemState == PowerSystemWorking)) ||
  33. ((irpStack->Parameters.Power.Type == DevicePowerState) &&
  34. (irpStack->Parameters.Power.State.SystemState == PowerDeviceD0))) {
  35. Irp->IoStatus.Status = STATUS_SUCCESS;
  36. } else {
  37. Irp->IoStatus.Status = STATUS_DEVICE_POWER_FAILURE;
  38. }
  39. #else
  40. Irp->IoStatus.Status = STATUS_SUCCESS;
  41. #endif // DONT_POWER_DOWN_PAGING_DEVICE
  42. UnrefPdoWithTag (pdoExtension, Irp);
  43. } else {
  44. Irp->IoStatus.Status = STATUS_SUCCESS;
  45. }
  46. PoStartNextPowerIrp (Irp);
  47. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  48. //
  49. // Do not send this Irp down
  50. //
  51. return STATUS_SUCCESS;
  52. }
  53. NTSTATUS
  54. IdePortSetPdoPowerState (
  55. IN PDEVICE_OBJECT DeviceObject,
  56. IN OUT PIRP Irp
  57. )
  58. {
  59. NTSTATUS status;
  60. PIO_STACK_LOCATION irpStack;
  61. PPDO_EXTENSION pdoExtension;
  62. irpStack = IoGetCurrentIrpStackLocation (Irp);
  63. pdoExtension = DeviceObject->DeviceExtension;
  64. DebugPrint ((DBG_POWER,
  65. "0x%x target %d got power irp 0x%x\n",
  66. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  67. pdoExtension->TargetId,
  68. Irp
  69. ));
  70. DebugPrint ((DBG_POWER,
  71. "IdePort: 0x%x device %d: current System Power State = 0x%x\n",
  72. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  73. pdoExtension->TargetId,
  74. pdoExtension->SystemPowerState));
  75. DebugPrint ((DBG_POWER,
  76. "IdePort: 0x%x device %d: current Device Power State = 0x%x\n",
  77. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  78. pdoExtension->TargetId,
  79. pdoExtension->DevicePowerState));
  80. IoMarkIrpPending(Irp);
  81. // if (!(pdoExtension->LuFlags & PD_LOGICAL_UNIT_POWER_OK)) {
  82. //
  83. // //
  84. // // The device does support power management commands
  85. // // just STATUS_SUCCESS everything. If ACPI is around,
  86. // // it will power manage our device
  87. // //
  88. // status = STATUS_SUCCESS;
  89. //
  90. // } else
  91. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  92. DebugPrint ((DBG_POWER, "IdePortSetPdoPowerState: 0x%x target %d got a SYSTEM power irp 0x%x for system state 0x%x \n",
  93. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  94. pdoExtension->TargetId,
  95. Irp,
  96. irpStack->Parameters.Power.State.SystemState));
  97. ASSERT (pdoExtension->PendingSystemPowerIrp == NULL);
  98. #if DBG
  99. pdoExtension->PendingSystemPowerIrp = Irp;
  100. ASSERT (pdoExtension->PendingSystemPowerIrp);
  101. #endif // DBG
  102. status = IdePortSetPdoSystemPowerState (DeviceObject, Irp);
  103. } else if (irpStack->Parameters.Power.Type == DevicePowerState) {
  104. DebugPrint ((DBG_POWER, "IdePortSetPdoPowerState: 0x%x target %d got a DEVICE power irp 0x%x for device state 0x%x \n",
  105. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  106. pdoExtension->TargetId,
  107. Irp,
  108. irpStack->Parameters.Power.State.DeviceState));
  109. ASSERT (pdoExtension->PendingDevicePowerIrp == NULL);
  110. #if DBG
  111. pdoExtension->PendingDevicePowerIrp = Irp;
  112. ASSERT (pdoExtension->PendingDevicePowerIrp);
  113. #endif // DBG
  114. status = IdePortSetPdoDevicePowerState (DeviceObject, Irp);
  115. } else {
  116. status = STATUS_NOT_IMPLEMENTED;
  117. }
  118. if (status != STATUS_PENDING) {
  119. Irp->IoStatus.Status = status;
  120. IdePortPdoCompletePowerIrp (
  121. DeviceObject,
  122. Irp
  123. );
  124. }
  125. return STATUS_PENDING;
  126. }
  127. NTSTATUS
  128. IdePortSetPdoSystemPowerState (
  129. IN PDEVICE_OBJECT DeviceObject,
  130. IN OUT PIRP Irp
  131. )
  132. {
  133. NTSTATUS status;
  134. PIO_STACK_LOCATION irpStack;
  135. PPDO_EXTENSION pdoExtension;
  136. SYSTEM_POWER_STATE newSystemState;
  137. POWER_STATE powerState;
  138. POWER_ACTION shutdownType;
  139. pdoExtension = DeviceObject->DeviceExtension;
  140. status = STATUS_SUCCESS;
  141. irpStack = IoGetCurrentIrpStackLocation (Irp);
  142. newSystemState = irpStack->Parameters.Power.State.SystemState;
  143. shutdownType = irpStack->Parameters.Power.ShutdownType;
  144. if (pdoExtension->SystemPowerState != newSystemState) {
  145. //
  146. // new system state request
  147. //
  148. if (pdoExtension->SystemPowerState == PowerSystemWorking) {
  149. //
  150. // Getting out of working state.
  151. //
  152. if ((newSystemState == PowerSystemShutdown) &&
  153. (shutdownType == PowerActionShutdownReset)) {
  154. //
  155. // spin up for BIOS POST
  156. //
  157. powerState.DeviceState = PowerDeviceD0;
  158. } else {
  159. //
  160. // put the device to D3 and freeze the device queue
  161. //
  162. //
  163. // Issue a D3 to top of my drive stack
  164. //
  165. powerState.DeviceState = PowerDeviceD3;
  166. pdoExtension->PendingPowerDownSystemIrp = Irp;
  167. }
  168. status = PoRequestPowerIrp (
  169. pdoExtension->DeviceObject,
  170. IRP_MN_SET_POWER,
  171. powerState,
  172. IdePortPdoRequestPowerCompletionRoutine,
  173. Irp,
  174. NULL
  175. );
  176. if (NT_SUCCESS(status)) {
  177. status = STATUS_PENDING;
  178. }
  179. } else {
  180. if (newSystemState == PowerSystemHibernate) {
  181. //
  182. // we can't hibernate when we are in some sleep state
  183. //
  184. ASSERT (FALSE);
  185. }
  186. }
  187. }
  188. return status;
  189. }
  190. NTSTATUS
  191. IdePortSetPdoDevicePowerState (
  192. IN PDEVICE_OBJECT DeviceObject,
  193. IN OUT PIRP Irp
  194. )
  195. {
  196. PPDO_EXTENSION pdoExtension;
  197. PIO_STACK_LOCATION irpStack;
  198. NTSTATUS status;
  199. DEVICE_POWER_STATE newDeviceState;
  200. POWER_ACTION shutdownType;
  201. BOOLEAN issueIdeCommand;
  202. IDEREGS ideReg;
  203. PIDE_POWER_CONTEXT context;
  204. BOOLEAN powerUpParent;
  205. BOOLEAN noopPassThrough;
  206. pdoExtension = DeviceObject->DeviceExtension;
  207. status = STATUS_SUCCESS;
  208. irpStack = IoGetCurrentIrpStackLocation (Irp);
  209. newDeviceState = irpStack->Parameters.Power.State.DeviceState;
  210. shutdownType = irpStack->Parameters.Power.ShutdownType;
  211. powerUpParent = FALSE;
  212. issueIdeCommand = FALSE;
  213. RtlZeroMemory (&ideReg, sizeof(ideReg));
  214. if (pdoExtension->DevicePowerState != newDeviceState) {
  215. if (pdoExtension->DevicePowerState == PowerDeviceD0) {
  216. POWER_STATE newPowerState;
  217. newPowerState.DeviceState = newDeviceState;
  218. //
  219. // getting out of D0 state, better call PoSetPowerState now
  220. // this gives the system a chance to flush before we
  221. // get out of D0
  222. //
  223. PoSetPowerState (
  224. pdoExtension->DeviceObject,
  225. DevicePowerState,
  226. newPowerState
  227. );
  228. }
  229. if (pdoExtension->DevicePowerState < newDeviceState) {
  230. KIRQL currentIrql;
  231. //
  232. // we are powering down, try to clean out the Lu device queue
  233. //
  234. KeAcquireSpinLock(&pdoExtension->ParentDeviceExtension->SpinLock, &currentIrql);
  235. pdoExtension->CurrentKey = 0;
  236. KeReleaseSpinLock(&pdoExtension->ParentDeviceExtension->SpinLock, currentIrql);
  237. }
  238. if ((newDeviceState == PowerDeviceD0) ||
  239. (newDeviceState == PowerDeviceD1)) {
  240. //
  241. // spinning up to D0 or D1...
  242. //
  243. DebugPrint ((DBG_POWER, "IdePort: Irp 0x%x to spin UP 0x%x %d...\n",
  244. Irp,
  245. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  246. pdoExtension->TargetId));
  247. if (pdoExtension->DevicePowerState == PowerDeviceD1) {
  248. //
  249. // D0-->D1
  250. // can't do much here
  251. DebugPrint ((DBG_POWER, "ATAPI: reqeust for PowerDeviceD1 to PowerDeviceD0\n"));
  252. } else if ((pdoExtension->DevicePowerState == PowerDeviceD0) ||
  253. (pdoExtension->DevicePowerState == PowerDeviceD2)) {
  254. //
  255. // D1-->D0 or
  256. // D2-->D0 or D1
  257. //
  258. issueIdeCommand = TRUE;
  259. if (pdoExtension->ScsiDeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) {
  260. ideReg.bCommandReg = IDE_COMMAND_ATAPI_RESET;
  261. ideReg.bReserved = ATA_PTFLAGS_URGENT;
  262. } else {
  263. ideReg.bCommandReg = IDE_COMMAND_IDLE_IMMEDIATE;
  264. ideReg.bReserved = ATA_PTFLAGS_URGENT | ATA_PTFLAGS_STATUS_DRDY_REQUIRED;
  265. }
  266. } else {
  267. PFDO_EXTENSION fdoExtension = pdoExtension->ParentDeviceExtension;
  268. //
  269. // D3-->D0 or D1
  270. //
  271. issueIdeCommand = TRUE;
  272. ideReg.bReserved = ATA_PTFLAGS_BUS_RESET | ATA_PTFLAGS_URGENT;
  273. //
  274. // wait for busy to clear
  275. //
  276. if (fdoExtension->WaitOnPowerUp) {
  277. ideReg.bSectorNumberReg = 3;
  278. }
  279. //
  280. // we are coming out of deeeeep sleep, make sure our parent
  281. // is awake (power up) before we can wake up
  282. //
  283. powerUpParent = TRUE;
  284. }
  285. } else if ((newDeviceState == PowerDeviceD2) ||
  286. (newDeviceState == PowerDeviceD3)) {
  287. //
  288. // spinning down to D2 or D3...
  289. //
  290. DebugPrint ((DBG_POWER, "IdePort: Irp 0x%x to spin DOWN 0x%x %d...\n",
  291. Irp,
  292. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  293. pdoExtension->TargetId));
  294. if ((pdoExtension->DevicePowerState == PowerDeviceD0) ||
  295. (pdoExtension->DevicePowerState == PowerDeviceD1) ||
  296. (pdoExtension->DevicePowerState == PowerDeviceD2)) {
  297. //
  298. // going to D3
  299. //
  300. if ((pdoExtension->PdoState & PDOS_NO_POWER_DOWN) ||
  301. (shutdownType == PowerActionHibernate)) {
  302. //
  303. // send an no-op command to block the queue
  304. //
  305. issueIdeCommand = TRUE;
  306. ideReg.bReserved = ATA_PTFLAGS_NO_OP;
  307. } else {
  308. //
  309. // spin down
  310. //
  311. issueIdeCommand = TRUE;
  312. ideReg.bCommandReg = IDE_COMMAND_STANDBY_IMMEDIATE;
  313. ideReg.bReserved = ATA_PTFLAGS_STATUS_DRDY_REQUIRED;
  314. }
  315. } else if (pdoExtension->DevicePowerState == PowerDeviceD3) {
  316. //
  317. // PowerDeviceD3 -> PowerDeviceD2
  318. //
  319. // need to do a bus reset (spin up) and issue IDE_COMMAND_STANDBY_IMMEDIATE
  320. // (spin down). this will cause uncessary INRUSH current. bad
  321. // idea. fail the request for now
  322. DebugPrint ((DBG_POWER, "ATAPI: reqeust for PowerDeviceD3 to PowerDeviceD2\n"));
  323. status = STATUS_INVALID_DEVICE_STATE;
  324. } else {
  325. status = STATUS_INVALID_DEVICE_STATE;
  326. }
  327. } else {
  328. status = STATUS_INVALID_DEVICE_STATE;
  329. }
  330. }
  331. /*************
  332. else if ( pdoExtension->DevicePowerState == PowerDeviceD0) {
  333. //
  334. // Send a no-op so that it can drain the device queue
  335. //
  336. issueIdeCommand = TRUE;
  337. ideReg.bSectorCountReg = 1;
  338. ideReg.bReserved = ATA_PTFLAGS_NO_OP;
  339. }
  340. ***************/
  341. if (issueIdeCommand && NT_SUCCESS(status)) {
  342. if ((pdoExtension->PdoState & PDOS_DEADMEAT) ||
  343. (!(pdoExtension->PdoState & PDOS_STARTED))) {
  344. DebugPrint ((DBG_ALWAYS,
  345. "ATAPI: power irp 0x%x for not-yet-started or deadmeat device 0x%x\n",
  346. Irp, DeviceObject));
  347. //
  348. // even the device may not be ready to be
  349. // "power-managed", we still need to go
  350. // through all the power code so that all
  351. // the flags/states will be consistent
  352. //
  353. RtlZeroMemory (&ideReg, sizeof(ideReg));
  354. ideReg.bReserved = ATA_PTFLAGS_NO_OP | ATA_PTFLAGS_URGENT;
  355. }
  356. //context = ExAllocatePool (NonPagedPool, sizeof(IDE_POWER_CONTEXT));
  357. ASSERT(InterlockedCompareExchange(&(pdoExtension->PowerContextLock), 1, 0) == 0);
  358. context = &(pdoExtension->PdoPowerContext);
  359. if (context) {
  360. context->PdoExtension = pdoExtension;
  361. context->PowerIrp = Irp;
  362. RtlZeroMemory (&context->AtaPassThroughData, sizeof(ATA_PASS_THROUGH));
  363. RtlMoveMemory (&context->AtaPassThroughData.IdeReg, &ideReg, sizeof(ideReg));
  364. } else {
  365. status = STATUS_NO_MEMORY;
  366. issueIdeCommand = FALSE;
  367. }
  368. }
  369. if (issueIdeCommand && NT_SUCCESS(status)) {
  370. if (powerUpParent) {
  371. status = FdoChildRequestPowerUp (
  372. pdoExtension->ParentDeviceExtension,
  373. pdoExtension,
  374. context
  375. );
  376. ASSERT (NT_SUCCESS(status));
  377. //
  378. // the pass through will be issued by FdoChildRequestPowerUp() callback
  379. //
  380. issueIdeCommand = FALSE;
  381. status = STATUS_PENDING;
  382. }
  383. }
  384. if (issueIdeCommand && NT_SUCCESS(status)) {
  385. status = PdoRequestParentPowerUpCompletionRoutine (
  386. context,
  387. STATUS_SUCCESS
  388. );
  389. //
  390. // this call will complete the power irp
  391. // always return STATUS_PENDING so that out callee
  392. // will not try to complete the same irp
  393. //
  394. status = STATUS_PENDING;
  395. }
  396. return status;
  397. }
  398. NTSTATUS
  399. PdoRequestParentPowerUpCompletionRoutine (
  400. PVOID Context,
  401. NTSTATUS ParentPowerUpStatus
  402. )
  403. {
  404. PIDE_POWER_CONTEXT context = Context;
  405. NTSTATUS status;
  406. if (NT_SUCCESS(ParentPowerUpStatus)) {
  407. PIDEREGS ideReg;
  408. PATA_PASS_THROUGH ataPassThrough;
  409. DebugPrint ((DBG_POWER, "PdoRequestParentPowerUpCompletionRoutine: calling IssueAsyncAtaPassThrough for pdo 0x%x\n", context->PdoExtension));
  410. //
  411. // hack. We need to check if the device is busy before we issue
  412. // the reset. Since there are no bits left in the bReserved
  413. // register, we use the sectorCount register. It serves 2 purposes.
  414. // If it is non zero (and reserved has NO_OP set) then we would
  415. // perform a waitForBusy. It also indicates the time to wiat
  416. // in seconds.
  417. //
  418. ataPassThrough = &context->AtaPassThroughData;
  419. ideReg = &ataPassThrough->IdeReg;
  420. if ((ideReg->bReserved & ATA_PTFLAGS_BUS_RESET) &&
  421. (ideReg->bSectorNumberReg != 0)) {
  422. //
  423. // busy check
  424. //
  425. ideReg->bReserved = ATA_PTFLAGS_NO_OP | ATA_PTFLAGS_URGENT;
  426. status = IssueAsyncAtaPassThroughSafe (
  427. context->PdoExtension->ParentDeviceExtension,
  428. context->PdoExtension,
  429. &context->AtaPassThroughData,
  430. FALSE,
  431. IdePowerCheckBusyCompletion,
  432. context,
  433. TRUE,
  434. DEFAULT_ATA_PASS_THROUGH_TIMEOUT,
  435. FALSE
  436. );
  437. } else {
  438. //
  439. // parent woke up
  440. //
  441. status = IssueAsyncAtaPassThroughSafe (
  442. context->PdoExtension->ParentDeviceExtension,
  443. context->PdoExtension,
  444. &context->AtaPassThroughData,
  445. FALSE,
  446. IdePowerPassThroughCompletion,
  447. context,
  448. TRUE,
  449. DEFAULT_ATA_PASS_THROUGH_TIMEOUT,
  450. FALSE
  451. );
  452. }
  453. } else {
  454. status = ParentPowerUpStatus;
  455. }
  456. if (!NT_SUCCESS(status)) {
  457. context->PowerIrp->IoStatus.Status = status;
  458. IdePortPdoCompletePowerIrp (
  459. context->PdoExtension->DeviceObject,
  460. context->PowerIrp
  461. );
  462. ASSERT(InterlockedCompareExchange(&(context->PdoExtension->PowerContextLock), 0, 1) == 1);
  463. //ExFreePool (context);
  464. }
  465. return status;
  466. }
  467. VOID
  468. IdePortPdoRequestPowerCompletionRoutine (
  469. IN PDEVICE_OBJECT DeviceObject,
  470. IN UCHAR MinorFunction,
  471. IN POWER_STATE PowerState,
  472. IN PVOID Context,
  473. IN PIO_STATUS_BLOCK IoStatus
  474. )
  475. {
  476. PPDO_EXTENSION pdoExtension;
  477. PIO_STACK_LOCATION irpStack;
  478. PIRP irp = Context;
  479. pdoExtension = (PPDO_EXTENSION) DeviceObject->DeviceExtension;
  480. irp->IoStatus.Status = IoStatus->Status;
  481. IdePortPdoCompletePowerIrp (
  482. pdoExtension->DeviceObject,
  483. irp
  484. );
  485. return;
  486. }
  487. VOID
  488. IdePortPdoCompletePowerIrp (
  489. IN PDEVICE_OBJECT DeviceObject,
  490. IN PIRP Irp
  491. )
  492. {
  493. PPDO_EXTENSION pdoExtension;
  494. PFDO_EXTENSION fdoExtension;
  495. PIO_STACK_LOCATION irpStack;
  496. BOOLEAN callPoSetPowerState;
  497. KIRQL currentIrql;
  498. NTSTATUS status;
  499. POWER_ACTION shutdownType;
  500. irpStack = IoGetCurrentIrpStackLocation (Irp);
  501. pdoExtension = DeviceObject->DeviceExtension;
  502. //shutdownType = irpStack->Parameters.Power.ShutdownType;
  503. fdoExtension = pdoExtension->ParentDeviceExtension;
  504. status = Irp->IoStatus.Status;
  505. if (NT_SUCCESS(status)) {
  506. callPoSetPowerState = TRUE;
  507. Irp->IoStatus.Information = irpStack->Parameters.Power.State.DeviceState;
  508. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  509. if (pdoExtension->SystemPowerState != irpStack->Parameters.Power.State.SystemState) {
  510. DebugPrint ((DBG_POWER,
  511. "ATAPI: 0x%x target%d completing power Irp 0x%x with a new system state 0x%x\n",
  512. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  513. pdoExtension->TargetId,
  514. Irp,
  515. irpStack->Parameters.Power.State.SystemState));
  516. if (pdoExtension->SystemPowerState == PowerSystemWorking) {
  517. KeAcquireSpinLock(&fdoExtension->SpinLock, &currentIrql);
  518. //
  519. // got out of S0, block the device queue
  520. //
  521. pdoExtension->PdoState |= PDOS_QUEUE_FROZEN_BY_SLEEPING_SYSTEM;
  522. DebugPrint ((DBG_POWER,
  523. "IdePort: 0x%x target %d is powered down with 0x%x items queued\n",
  524. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  525. pdoExtension->TargetId,
  526. pdoExtension->NumberOfIrpQueued));
  527. KeReleaseSpinLock(&fdoExtension->SpinLock, currentIrql);
  528. }
  529. if (irpStack->Parameters.Power.State.SystemState == PowerSystemWorking) {
  530. KeAcquireSpinLock(&fdoExtension->SpinLock, &currentIrql);
  531. //
  532. // got into S0, unblock and restart the device queue
  533. //
  534. CLRMASK (pdoExtension->PdoState, PDOS_QUEUE_FROZEN_BY_SLEEPING_SYSTEM);
  535. DebugPrint ((DBG_POWER,
  536. "IdePort: 0x%x target %d is power up with 0x%x items queued\n",
  537. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  538. pdoExtension->TargetId,
  539. pdoExtension->NumberOfIrpQueued));
  540. GetNextLuPendingRequest (fdoExtension, pdoExtension);
  541. KeLowerIrql(currentIrql);
  542. }
  543. pdoExtension->SystemPowerState = (int)Irp->IoStatus.Information;
  544. }
  545. pdoExtension->PendingPowerDownSystemIrp = NULL;
  546. } else /* if (irpStack->Parameters.Power.Type == DevicePowerState) */ {
  547. if (pdoExtension->DevicePowerState == PowerDeviceD0) {
  548. //
  549. // PoSetPowerState is called before we power down
  550. //
  551. callPoSetPowerState = FALSE;
  552. }
  553. if (pdoExtension->DevicePowerState != irpStack->Parameters.Power.State.DeviceState) {
  554. DebugPrint ((DBG_POWER,
  555. "ATAPI: 0x%x target %d completing power Irp 0x%x with a new device state 0x%x\n",
  556. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  557. pdoExtension->TargetId,
  558. Irp,
  559. irpStack->Parameters.Power.State.DeviceState));
  560. if (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD3) {
  561. #if 0
  562. if (shutdownType == PowerActionHibernate) {
  563. DebugPrint((0, "Don't power down the controller yet\n"));
  564. } else {
  565. #endif
  566. //
  567. // should never do that if we are crashdump pointer
  568. // tell parent that we just fell to sleep
  569. //
  570. FdoChildReportPowerDown (
  571. fdoExtension,
  572. pdoExtension
  573. );
  574. #if 0
  575. }
  576. #endif
  577. KeAcquireSpinLock(&fdoExtension->SpinLock, &currentIrql);
  578. //
  579. // device is powered down. block the device queue
  580. //
  581. SETMASK(pdoExtension->PdoState, PDOS_QUEUE_FROZEN_BY_POWER_DOWN);
  582. DebugPrint ((DBG_POWER,
  583. "IdePort: 0x%x target %d is powered down with 0x%x items queued\n",
  584. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  585. pdoExtension->TargetId,
  586. pdoExtension->NumberOfIrpQueued));
  587. KeReleaseSpinLock(&fdoExtension->SpinLock, currentIrql);
  588. if (pdoExtension->PendingPowerDownSystemIrp) {
  589. //
  590. // We get this power down irp
  591. // because we are going to non-working state
  592. // block the device queue
  593. //
  594. KeAcquireSpinLock(&fdoExtension->SpinLock, &currentIrql);
  595. DebugPrint ((DBG_POWER,
  596. "ATAPI: blocking 0x%x target %d device queue\n",
  597. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  598. pdoExtension->TargetId));
  599. pdoExtension->PdoState |= PDOS_QUEUE_FROZEN_BY_SLEEPING_SYSTEM;
  600. KeReleaseSpinLock(&fdoExtension->SpinLock, currentIrql);
  601. }
  602. }
  603. if (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD3) {
  604. //
  605. // get ready to reinit. the device via acpi data when
  606. // we get out of D3
  607. //
  608. InterlockedIncrement (&pdoExtension->InitDeviceWithAcpiGtf);
  609. }
  610. if (pdoExtension->DevicePowerState == PowerDeviceD3) {
  611. //
  612. // just get out out D3, re-init. pdo
  613. //
  614. DebugPrint((DBG_POWER, "Calling DeviceInitDeviceState for irp 0x%x\n",
  615. Irp));
  616. status = DeviceInitDeviceState (
  617. pdoExtension,
  618. DevicePowerUpInitCompletionRoutine,
  619. Irp
  620. );
  621. if (!NT_SUCCESS(status)) {
  622. DevicePowerUpInitCompletionRoutine (
  623. Irp,
  624. status
  625. );
  626. }
  627. return;
  628. }
  629. pdoExtension->DevicePowerState = (int) Irp->IoStatus.Information;
  630. }
  631. }
  632. if ((callPoSetPowerState) && NT_SUCCESS(status)) {
  633. //
  634. // we didn't get out of device D0 state. calling PoSetPowerState now
  635. //
  636. PoSetPowerState (
  637. pdoExtension->DeviceObject,
  638. irpStack->Parameters.Power.Type,
  639. irpStack->Parameters.Power.State
  640. );
  641. }
  642. } else {
  643. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  644. if (pdoExtension->SystemPowerState != irpStack->Parameters.Power.State.SystemState) {
  645. if (pdoExtension->SystemPowerState == PowerSystemWorking) {
  646. //
  647. // failed a system power down irp
  648. //
  649. KeAcquireSpinLock(&fdoExtension->SpinLock, &currentIrql);
  650. //
  651. // got into S0, unblock and restart the device queue
  652. //
  653. if (pdoExtension->PdoState & PDOS_QUEUE_FROZEN_BY_SLEEPING_SYSTEM) {
  654. CLRMASK (pdoExtension->PdoState, PDOS_QUEUE_FROZEN_BY_SLEEPING_SYSTEM);
  655. GetNextLuPendingRequest (fdoExtension, pdoExtension);
  656. KeLowerIrql(currentIrql);
  657. } else {
  658. KeReleaseSpinLock(&fdoExtension->SpinLock, currentIrql);
  659. }
  660. }
  661. }
  662. pdoExtension->PendingPowerDownSystemIrp = NULL;
  663. }
  664. }
  665. if (!NT_SUCCESS(status)) {
  666. DebugPrint ((DBG_ALWAYS,
  667. "ATAPI: 0x%x target %d failed power Irp 0x%x. status = 0x%x\n",
  668. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  669. pdoExtension->TargetId,
  670. Irp,
  671. Irp->IoStatus.Status));
  672. if (irpStack->Parameters.Power.Type == DevicePowerState) {
  673. //
  674. // ISSUE: 08/20/2000: Just failed a power D0 request...fail all pending irp
  675. //
  676. //ASSERT (irpStack->Parameters.Power.State.DeviceState != PowerDeviceD0);
  677. //
  678. // we will fail all the pending irps if we failed with status
  679. // no such device
  680. //
  681. if (status == STATUS_NO_SUCH_DEVICE) {
  682. DebugPrint ((0,
  683. "Restarting the Lu queue after marking the device dead\n"
  684. ));
  685. DebugPrint((0,
  686. "Device Power up irp failed with status 0x%x\n",
  687. status
  688. ));
  689. //
  690. // mark the pdo as dead
  691. // ISSUE: 12/19/2001. We should update deadmeat reason
  692. // for ease of debugging.
  693. //
  694. KeAcquireSpinLock(&pdoExtension->PdoSpinLock, &currentIrql);
  695. SETMASK (pdoExtension->PdoState, PDOS_DEADMEAT);
  696. KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
  697. //
  698. // ISSUE: 12/19/2001: Should we call IoInvalidateDeviceRelations?
  699. // we should get a remove irp in this case anyway.
  700. //
  701. IoInvalidateDeviceRelations (
  702. fdoExtension->AttacheePdo,
  703. BusRelations
  704. );
  705. //
  706. // start any pending requests
  707. // ISSUE: 12/19/2001: We should hold the pdospinlock at
  708. // this time. But in the other routines we seem to be
  709. // holding just the fdospinlock before modifying the
  710. // pdostate. We will leave it as such to minimise regressions.
  711. //
  712. KeAcquireSpinLock(&fdoExtension->SpinLock, &currentIrql);
  713. if (pdoExtension->PdoState & PDOS_QUEUE_FROZEN_BY_POWER_DOWN) {
  714. //
  715. // ISSUE: 12/19/2001: We are not updating the device power
  716. // state to D0. This would cause all the further requests
  717. // to ask for a new power up irp. The system would be slow
  718. // if we get too many requests. The remove irp should arrive
  719. // eventually and end the misery.
  720. //
  721. CLRMASK (pdoExtension->PdoState, PDOS_QUEUE_FROZEN_BY_POWER_DOWN);
  722. //
  723. // restart the lu queue (on an lu that is marked dead)
  724. // we didn't run GTF or do any of the other initialization.
  725. // Since we marked the device dead above, we can restart the
  726. // queue.They will get completed with status
  727. // device_does_not_exist.
  728. //
  729. GetNextLuPendingRequest (fdoExtension, pdoExtension);
  730. KeLowerIrql(currentIrql);
  731. } else {
  732. KeReleaseSpinLock(&fdoExtension->SpinLock, currentIrql);
  733. }
  734. } else {
  735. //
  736. // ISSUE: 12/192001: we handle only status_no_such device
  737. //
  738. ASSERT (irpStack->Parameters.Power.State.DeviceState != PowerDeviceD0);
  739. }
  740. }
  741. }
  742. #if DBG
  743. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  744. DebugPrint ((DBG_POWER, "IdePortPdoCompletePowerIrp: 0x%x target %d completing a SYSTEM power irp 0x%x for system state 0x%x \n",
  745. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  746. pdoExtension->TargetId,
  747. Irp,
  748. irpStack->Parameters.Power.State.SystemState));
  749. ASSERT (pdoExtension->PendingSystemPowerIrp == Irp);
  750. pdoExtension->PendingSystemPowerIrp = NULL;
  751. } else if (irpStack->Parameters.Power.Type == DevicePowerState) {
  752. DebugPrint ((DBG_POWER, "IdePortPdoCompletePowerIrp: 0x%x target %d completing a DEVICE power irp 0x%x for device state 0x%x \n",
  753. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  754. pdoExtension->TargetId,
  755. Irp,
  756. irpStack->Parameters.Power.State.SystemState));
  757. ASSERT (pdoExtension->PendingDevicePowerIrp == Irp);
  758. pdoExtension->PendingDevicePowerIrp = NULL;
  759. }
  760. #endif
  761. PoStartNextPowerIrp (Irp);
  762. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  763. }
  764. VOID
  765. IdePowerCheckBusyCompletion (
  766. IN PDEVICE_OBJECT DeviceObject,
  767. IN PIDE_POWER_CONTEXT Context,
  768. IN NTSTATUS Status
  769. )
  770. /*++
  771. Routine Description
  772. Completion routine for ide pass through that would check if the
  773. device is busy. This is typically done before a reset to salvage
  774. drives that hang when a reset is issued while they are busy (due
  775. to a hardware reset)
  776. Arguments:
  777. DeviceObject
  778. Context
  779. Status : Not used
  780. Return Value
  781. None.
  782. --*/
  783. {
  784. PATA_PASS_THROUGH ataPassThrough;
  785. PIDEREGS ideReg;
  786. NTSTATUS status;
  787. ataPassThrough = &Context->AtaPassThroughData;
  788. ideReg = &ataPassThrough->IdeReg;
  789. //
  790. // send down the reset
  791. //
  792. RtlZeroMemory(ideReg, sizeof(IDEREGS));
  793. ideReg->bReserved = ATA_PTFLAGS_BUS_RESET | ATA_PTFLAGS_URGENT;
  794. status = IssueAsyncAtaPassThroughSafe (
  795. Context->PdoExtension->ParentDeviceExtension,
  796. Context->PdoExtension,
  797. &Context->AtaPassThroughData,
  798. FALSE,
  799. IdePowerPassThroughCompletion,
  800. Context,
  801. TRUE,
  802. DEFAULT_ATA_PASS_THROUGH_TIMEOUT,
  803. FALSE
  804. );
  805. return;
  806. }
  807. VOID
  808. IdePowerPassThroughCompletion (
  809. IN PDEVICE_OBJECT DeviceObject,
  810. IN PIDE_POWER_CONTEXT Context,
  811. IN NTSTATUS Status
  812. )
  813. {
  814. if (!NT_SUCCESS(Status)) {
  815. //
  816. // device failed power management command
  817. // will not try it anymore
  818. //
  819. KIRQL currentIrql;
  820. KeAcquireSpinLock(&Context->PdoExtension->PdoSpinLock, &currentIrql);
  821. SETMASK (Context->PdoExtension->PdoState, PDOS_NO_POWER_DOWN);
  822. KeReleaseSpinLock(&Context->PdoExtension->PdoSpinLock, currentIrql);
  823. Status = STATUS_SUCCESS;
  824. }
  825. Context->PowerIrp->IoStatus.Status = Status;
  826. IdePortPdoCompletePowerIrp (
  827. DeviceObject,
  828. Context->PowerIrp
  829. );
  830. ASSERT(InterlockedCompareExchange(&(Context->PdoExtension->PowerContextLock), 0, 1) == 1);
  831. //ExFreePool (Context);
  832. }
  833. VOID
  834. DevicePowerUpInitCompletionRoutine (
  835. PVOID Context,
  836. NTSTATUS Status
  837. )
  838. {
  839. PIRP irp = Context;
  840. PIO_STACK_LOCATION irpStack;
  841. PPDO_EXTENSION pdoExtension;
  842. KIRQL currentIrql;
  843. irpStack = IoGetCurrentIrpStackLocation (irp);
  844. pdoExtension = (PPDO_EXTENSION) irpStack->DeviceObject->DeviceExtension;
  845. if (!NT_SUCCESS(Status)) {
  846. //ASSERT (!"DevicePowerUpInitCompletionRoutine Failed\n");
  847. DebugPrint((DBG_ALWAYS, "ATAPI: ERROR: DevicePowerUpInitComplete failed with status %x\n",
  848. Status));
  849. }
  850. ASSERT (pdoExtension->PendingDevicePowerIrp == irp);
  851. pdoExtension->PendingDevicePowerIrp = NULL;
  852. pdoExtension->DevicePowerState = (ULONG)irp->IoStatus.Information;
  853. PoSetPowerState (
  854. pdoExtension->DeviceObject,
  855. irpStack->Parameters.Power.Type,
  856. irpStack->Parameters.Power.State
  857. );
  858. KeAcquireSpinLock(&pdoExtension->ParentDeviceExtension->SpinLock, &currentIrql);
  859. //
  860. // got into D0, restart device queue
  861. //
  862. DebugPrint((DBG_POWER, "Clearing QUEUE_FROZEN_BY_POWER_DOWN flag\n"));
  863. CLRMASK(pdoExtension->PdoState, PDOS_QUEUE_FROZEN_BY_POWER_DOWN);
  864. GetNextLuPendingRequest (pdoExtension->ParentDeviceExtension, pdoExtension);
  865. KeLowerIrql(currentIrql);
  866. PoStartNextPowerIrp (irp);
  867. IoCompleteRequest(irp, IO_NO_INCREMENT);
  868. }