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.

1149 lines
37 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. ideReg->bReserved = ATA_PTFLAGS_NO_OP | ATA_PTFLAGS_URGENT;
  423. status = IssueAsyncAtaPassThroughSafe (
  424. context->PdoExtension->ParentDeviceExtension,
  425. context->PdoExtension,
  426. &context->AtaPassThroughData,
  427. FALSE,
  428. IdePowerCheckBusyCompletion,
  429. context,
  430. TRUE,
  431. DEFAULT_ATA_PASS_THROUGH_TIMEOUT,
  432. FALSE
  433. );
  434. } else {
  435. //
  436. // parent woke up
  437. //
  438. status = IssueAsyncAtaPassThroughSafe (
  439. context->PdoExtension->ParentDeviceExtension,
  440. context->PdoExtension,
  441. &context->AtaPassThroughData,
  442. FALSE,
  443. IdePowerPassThroughCompletion,
  444. context,
  445. TRUE,
  446. DEFAULT_ATA_PASS_THROUGH_TIMEOUT,
  447. FALSE
  448. );
  449. }
  450. } else {
  451. status = ParentPowerUpStatus;
  452. }
  453. if (!NT_SUCCESS(status)) {
  454. context->PowerIrp->IoStatus.Status = status;
  455. IdePortPdoCompletePowerIrp (
  456. context->PdoExtension->DeviceObject,
  457. context->PowerIrp
  458. );
  459. ASSERT(InterlockedCompareExchange(&(context->PdoExtension->PowerContextLock), 0, 1) == 1);
  460. //ExFreePool (context);
  461. }
  462. return status;
  463. }
  464. VOID
  465. IdePortPdoRequestPowerCompletionRoutine (
  466. IN PDEVICE_OBJECT DeviceObject,
  467. IN UCHAR MinorFunction,
  468. IN POWER_STATE PowerState,
  469. IN PVOID Context,
  470. IN PIO_STATUS_BLOCK IoStatus
  471. )
  472. {
  473. PPDO_EXTENSION pdoExtension;
  474. PIO_STACK_LOCATION irpStack;
  475. PIRP irp = Context;
  476. pdoExtension = (PPDO_EXTENSION) DeviceObject->DeviceExtension;
  477. irp->IoStatus.Status = IoStatus->Status;
  478. IdePortPdoCompletePowerIrp (
  479. pdoExtension->DeviceObject,
  480. irp
  481. );
  482. return;
  483. }
  484. VOID
  485. IdePortPdoCompletePowerIrp (
  486. IN PDEVICE_OBJECT DeviceObject,
  487. IN PIRP Irp
  488. )
  489. {
  490. PPDO_EXTENSION pdoExtension;
  491. PFDO_EXTENSION fdoExtension;
  492. PIO_STACK_LOCATION irpStack;
  493. BOOLEAN callPoSetPowerState;
  494. KIRQL currentIrql;
  495. NTSTATUS status;
  496. POWER_ACTION shutdownType;
  497. irpStack = IoGetCurrentIrpStackLocation (Irp);
  498. pdoExtension = DeviceObject->DeviceExtension;
  499. //shutdownType = irpStack->Parameters.Power.ShutdownType;
  500. fdoExtension = pdoExtension->ParentDeviceExtension;
  501. status = Irp->IoStatus.Status;
  502. if (NT_SUCCESS(status)) {
  503. callPoSetPowerState = TRUE;
  504. Irp->IoStatus.Information = irpStack->Parameters.Power.State.DeviceState;
  505. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  506. if (pdoExtension->SystemPowerState != irpStack->Parameters.Power.State.SystemState) {
  507. DebugPrint ((DBG_POWER,
  508. "ATAPI: 0x%x target%d completing power Irp 0x%x with a new system state 0x%x\n",
  509. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  510. pdoExtension->TargetId,
  511. Irp,
  512. irpStack->Parameters.Power.State.SystemState));
  513. if (pdoExtension->SystemPowerState == PowerSystemWorking) {
  514. KeAcquireSpinLock(&fdoExtension->SpinLock, &currentIrql);
  515. //
  516. // got out of S0, block the device queue
  517. //
  518. pdoExtension->PdoState |= PDOS_QUEUE_FROZEN_BY_SLEEPING_SYSTEM;
  519. DebugPrint ((DBG_POWER,
  520. "IdePort: 0x%x target %d is powered down with 0x%x items queued\n",
  521. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  522. pdoExtension->TargetId,
  523. pdoExtension->NumberOfIrpQueued));
  524. KeReleaseSpinLock(&fdoExtension->SpinLock, currentIrql);
  525. }
  526. if (irpStack->Parameters.Power.State.SystemState == PowerSystemWorking) {
  527. KeAcquireSpinLock(&fdoExtension->SpinLock, &currentIrql);
  528. //
  529. // got into S0, unblock and restart the device queue
  530. //
  531. CLRMASK (pdoExtension->PdoState, PDOS_QUEUE_FROZEN_BY_SLEEPING_SYSTEM);
  532. DebugPrint ((DBG_POWER,
  533. "IdePort: 0x%x target %d is power up with 0x%x items queued\n",
  534. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  535. pdoExtension->TargetId,
  536. pdoExtension->NumberOfIrpQueued));
  537. GetNextLuPendingRequest (fdoExtension, pdoExtension);
  538. KeLowerIrql(currentIrql);
  539. }
  540. pdoExtension->SystemPowerState = (int)Irp->IoStatus.Information;
  541. }
  542. pdoExtension->PendingPowerDownSystemIrp = NULL;
  543. } else /* if (irpStack->Parameters.Power.Type == DevicePowerState) */ {
  544. if (pdoExtension->DevicePowerState == PowerDeviceD0) {
  545. //
  546. // PoSetPowerState is called before we power down
  547. //
  548. callPoSetPowerState = FALSE;
  549. }
  550. if (pdoExtension->DevicePowerState != irpStack->Parameters.Power.State.DeviceState) {
  551. DebugPrint ((DBG_POWER,
  552. "ATAPI: 0x%x target %d completing power Irp 0x%x with a new device state 0x%x\n",
  553. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  554. pdoExtension->TargetId,
  555. Irp,
  556. irpStack->Parameters.Power.State.DeviceState));
  557. if (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD3) {
  558. #if 0
  559. if (shutdownType == PowerActionHibernate) {
  560. DebugPrint((0, "Don't power down the controller yet\n"));
  561. } else {
  562. #endif
  563. //
  564. // should never do that if we are crashdump pointer
  565. // tell parent that we just fell to sleep
  566. //
  567. FdoChildReportPowerDown (
  568. fdoExtension,
  569. pdoExtension
  570. );
  571. #if 0
  572. }
  573. #endif
  574. KeAcquireSpinLock(&fdoExtension->SpinLock, &currentIrql);
  575. //
  576. // device is powered down. block the device queue
  577. //
  578. SETMASK(pdoExtension->PdoState, PDOS_QUEUE_FROZEN_BY_POWER_DOWN);
  579. DebugPrint ((DBG_POWER,
  580. "IdePort: 0x%x target %d is powered down with 0x%x items queued\n",
  581. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  582. pdoExtension->TargetId,
  583. pdoExtension->NumberOfIrpQueued));
  584. KeReleaseSpinLock(&fdoExtension->SpinLock, currentIrql);
  585. if (pdoExtension->PendingPowerDownSystemIrp) {
  586. //
  587. // We get this power down irp
  588. // because we are going to non-working state
  589. // block the device queue
  590. //
  591. KeAcquireSpinLock(&fdoExtension->SpinLock, &currentIrql);
  592. DebugPrint ((DBG_POWER,
  593. "ATAPI: blocking 0x%x target %d device queue\n",
  594. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  595. pdoExtension->TargetId));
  596. pdoExtension->PdoState |= PDOS_QUEUE_FROZEN_BY_SLEEPING_SYSTEM;
  597. KeReleaseSpinLock(&fdoExtension->SpinLock, currentIrql);
  598. }
  599. }
  600. if (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD3) {
  601. //
  602. // get ready to reinit. the device via acpi data when
  603. // we get out of D3
  604. //
  605. InterlockedIncrement (&pdoExtension->InitDeviceWithAcpiGtf);
  606. }
  607. if (pdoExtension->DevicePowerState == PowerDeviceD3) {
  608. //
  609. // just get out out D3, re-init. pdo
  610. //
  611. DebugPrint((DBG_POWER, "Calling DeviceInitDeviceState for irp 0x%x\n",
  612. Irp));
  613. status = DeviceInitDeviceState (
  614. pdoExtension,
  615. DevicePowerUpInitCompletionRoutine,
  616. Irp
  617. );
  618. if (!NT_SUCCESS(status)) {
  619. DevicePowerUpInitCompletionRoutine (
  620. Irp,
  621. status
  622. );
  623. }
  624. return;
  625. }
  626. pdoExtension->DevicePowerState = (int) Irp->IoStatus.Information;
  627. }
  628. }
  629. if ((callPoSetPowerState) && NT_SUCCESS(status)) {
  630. //
  631. // we didn't get out of device D0 state. calling PoSetPowerState now
  632. //
  633. PoSetPowerState (
  634. pdoExtension->DeviceObject,
  635. irpStack->Parameters.Power.Type,
  636. irpStack->Parameters.Power.State
  637. );
  638. }
  639. } else {
  640. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  641. if (pdoExtension->SystemPowerState != irpStack->Parameters.Power.State.SystemState) {
  642. if (pdoExtension->SystemPowerState == PowerSystemWorking) {
  643. //
  644. // failed a system power down irp
  645. //
  646. KeAcquireSpinLock(&fdoExtension->SpinLock, &currentIrql);
  647. //
  648. // got into S0, unblock and restart the device queue
  649. //
  650. if (pdoExtension->PdoState & PDOS_QUEUE_FROZEN_BY_SLEEPING_SYSTEM) {
  651. CLRMASK (pdoExtension->PdoState, PDOS_QUEUE_FROZEN_BY_SLEEPING_SYSTEM);
  652. GetNextLuPendingRequest (fdoExtension, pdoExtension);
  653. KeLowerIrql(currentIrql);
  654. } else {
  655. KeReleaseSpinLock(&fdoExtension->SpinLock, currentIrql);
  656. }
  657. }
  658. }
  659. pdoExtension->PendingPowerDownSystemIrp = NULL;
  660. }
  661. }
  662. if (!NT_SUCCESS(status)) {
  663. DebugPrint ((DBG_ALWAYS,
  664. "ATAPI: 0x%x target %d failed power Irp 0x%x. status = 0x%x\n",
  665. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  666. pdoExtension->TargetId,
  667. Irp,
  668. Irp->IoStatus.Status));
  669. if (irpStack->Parameters.Power.Type == DevicePowerState) {
  670. //
  671. // ISSUE: 08/20/2000: Just failed a power D0 request...fail all pending irp
  672. //
  673. //ASSERT (irpStack->Parameters.Power.State.DeviceState != PowerDeviceD0);
  674. //
  675. // we will fail all the pending irps if we failed with status
  676. // no such device
  677. //
  678. if (status == STATUS_NO_SUCH_DEVICE) {
  679. DebugPrint ((0,
  680. "Restarting the Lu queue after marking the device dead\n"
  681. ));
  682. DebugPrint((0,
  683. "Device Power up irp failed with status 0x%x\n",
  684. status
  685. ));
  686. //
  687. // mark the pdo as dead
  688. // ISSUE: 12/19/2001. We should update deadmeat reason
  689. // for ease of debugging.
  690. //
  691. KeAcquireSpinLock(&pdoExtension->PdoSpinLock, &currentIrql);
  692. SETMASK (pdoExtension->PdoState, PDOS_DEADMEAT);
  693. KeReleaseSpinLock(&pdoExtension->PdoSpinLock, currentIrql);
  694. //
  695. // ISSUE: 12/19/2001: Should we call IoInvalidateDeviceRelations?
  696. // we should get a remove irp in this case anyway.
  697. //
  698. IoInvalidateDeviceRelations (
  699. fdoExtension->AttacheePdo,
  700. BusRelations
  701. );
  702. //
  703. // start any pending requests
  704. // ISSUE: 12/19/2001: We should hold the pdospinlock at
  705. // this time. But in the other routines we seem to be
  706. // holding just the fdospinlock before modifying the
  707. // pdostate. We will leave it as such to minimise regressions.
  708. //
  709. KeAcquireSpinLock(&fdoExtension->SpinLock, &currentIrql);
  710. if (pdoExtension->PdoState & PDOS_QUEUE_FROZEN_BY_POWER_DOWN) {
  711. //
  712. // ISSUE: 12/19/2001: We are not updating the device power
  713. // state to D0. This would cause all the further requests
  714. // to ask for a new power up irp. The system would be slow
  715. // if we get too many requests. The remove irp should arrive
  716. // eventually and end the misery.
  717. //
  718. CLRMASK (pdoExtension->PdoState, PDOS_QUEUE_FROZEN_BY_POWER_DOWN);
  719. //
  720. // restart the lu queue (on an lu that is marked dead)
  721. // we didn't run GTF or do any of the other initialization.
  722. // Since we marked the device dead above, we can restart the
  723. // queue.They will get completed with status
  724. // device_does_not_exist.
  725. //
  726. GetNextLuPendingRequest (fdoExtension, pdoExtension);
  727. KeLowerIrql(currentIrql);
  728. } else {
  729. KeReleaseSpinLock(&fdoExtension->SpinLock, currentIrql);
  730. }
  731. } else {
  732. //
  733. // ISSUE: 12/192001: we handle only status_no_such device
  734. //
  735. ASSERT (irpStack->Parameters.Power.State.DeviceState != PowerDeviceD0);
  736. }
  737. }
  738. }
  739. #if DBG
  740. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  741. DebugPrint ((DBG_POWER, "IdePortPdoCompletePowerIrp: 0x%x target %d completing a SYSTEM power irp 0x%x for system state 0x%x \n",
  742. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  743. pdoExtension->TargetId,
  744. Irp,
  745. irpStack->Parameters.Power.State.SystemState));
  746. ASSERT (pdoExtension->PendingSystemPowerIrp == Irp);
  747. pdoExtension->PendingSystemPowerIrp = NULL;
  748. } else if (irpStack->Parameters.Power.Type == DevicePowerState) {
  749. DebugPrint ((DBG_POWER, "IdePortPdoCompletePowerIrp: 0x%x target %d completing a DEVICE power irp 0x%x for device state 0x%x \n",
  750. pdoExtension->ParentDeviceExtension->IdeResource.TranslatedCommandBaseAddress,
  751. pdoExtension->TargetId,
  752. Irp,
  753. irpStack->Parameters.Power.State.SystemState));
  754. ASSERT (pdoExtension->PendingDevicePowerIrp == Irp);
  755. pdoExtension->PendingDevicePowerIrp = NULL;
  756. }
  757. #endif
  758. PoStartNextPowerIrp (Irp);
  759. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  760. }
  761. VOID
  762. IdePowerCheckBusyCompletion (
  763. IN PDEVICE_OBJECT DeviceObject,
  764. IN PIDE_POWER_CONTEXT Context,
  765. IN NTSTATUS Status
  766. )
  767. /*++
  768. Routine Description
  769. Completion routine for ide pass through that would check if the
  770. device is busy. This is typically done before a reset to salvage
  771. drives that hang when a reset is issued while they are busy (due
  772. to a hardware reset)
  773. Arguments:
  774. DeviceObject
  775. Context
  776. Status : Not used
  777. Return Value
  778. None.
  779. --*/
  780. {
  781. PATA_PASS_THROUGH ataPassThrough;
  782. PIDEREGS ideReg;
  783. NTSTATUS status;
  784. ataPassThrough = &Context->AtaPassThroughData;
  785. ideReg = &ataPassThrough->IdeReg;
  786. //
  787. // send down the reset
  788. //
  789. RtlZeroMemory(ideReg, sizeof(IDEREGS));
  790. ideReg->bReserved = ATA_PTFLAGS_BUS_RESET | ATA_PTFLAGS_URGENT;
  791. status = IssueAsyncAtaPassThroughSafe (
  792. Context->PdoExtension->ParentDeviceExtension,
  793. Context->PdoExtension,
  794. &Context->AtaPassThroughData,
  795. FALSE,
  796. IdePowerPassThroughCompletion,
  797. Context,
  798. TRUE,
  799. DEFAULT_ATA_PASS_THROUGH_TIMEOUT,
  800. FALSE
  801. );
  802. return;
  803. }
  804. VOID
  805. IdePowerPassThroughCompletion (
  806. IN PDEVICE_OBJECT DeviceObject,
  807. IN PIDE_POWER_CONTEXT Context,
  808. IN NTSTATUS Status
  809. )
  810. {
  811. if (!NT_SUCCESS(Status)) {
  812. //
  813. // device failed power management command
  814. // will not try it anymore
  815. //
  816. KIRQL currentIrql;
  817. KeAcquireSpinLock(&Context->PdoExtension->PdoSpinLock, &currentIrql);
  818. SETMASK (Context->PdoExtension->PdoState, PDOS_NO_POWER_DOWN);
  819. KeReleaseSpinLock(&Context->PdoExtension->PdoSpinLock, currentIrql);
  820. Status = STATUS_SUCCESS;
  821. }
  822. Context->PowerIrp->IoStatus.Status = Status;
  823. IdePortPdoCompletePowerIrp (
  824. DeviceObject,
  825. Context->PowerIrp
  826. );
  827. ASSERT(InterlockedCompareExchange(&(Context->PdoExtension->PowerContextLock), 0, 1) == 1);
  828. //ExFreePool (Context);
  829. }
  830. VOID
  831. DevicePowerUpInitCompletionRoutine (
  832. PVOID Context,
  833. NTSTATUS Status
  834. )
  835. {
  836. PIRP irp = Context;
  837. PIO_STACK_LOCATION irpStack;
  838. PPDO_EXTENSION pdoExtension;
  839. KIRQL currentIrql;
  840. irpStack = IoGetCurrentIrpStackLocation (irp);
  841. pdoExtension = (PPDO_EXTENSION) irpStack->DeviceObject->DeviceExtension;
  842. if (!NT_SUCCESS(Status)) {
  843. //ASSERT (!"DevicePowerUpInitCompletionRoutine Failed\n");
  844. DebugPrint((DBG_ALWAYS, "ATAPI: ERROR: DevicePowerUpInitComplete failed with status %x\n",
  845. Status));
  846. }
  847. ASSERT (pdoExtension->PendingDevicePowerIrp == irp);
  848. pdoExtension->PendingDevicePowerIrp = NULL;
  849. pdoExtension->DevicePowerState = (ULONG)irp->IoStatus.Information;
  850. PoSetPowerState (
  851. pdoExtension->DeviceObject,
  852. irpStack->Parameters.Power.Type,
  853. irpStack->Parameters.Power.State
  854. );
  855. KeAcquireSpinLock(&pdoExtension->ParentDeviceExtension->SpinLock, &currentIrql);
  856. //
  857. // got into D0, restart device queue
  858. //
  859. DebugPrint((DBG_POWER, "Clearing QUEUE_FROZEN_BY_POWER_DOWN flag\n"));
  860. CLRMASK(pdoExtension->PdoState, PDOS_QUEUE_FROZEN_BY_POWER_DOWN);
  861. GetNextLuPendingRequest (pdoExtension->ParentDeviceExtension, pdoExtension);
  862. KeLowerIrql(currentIrql);
  863. PoStartNextPowerIrp (irp);
  864. IoCompleteRequest(irp, IO_NO_INCREMENT);
  865. }