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.

800 lines
22 KiB

  1. /*++
  2. Copyright (C) 1997-99 Microsoft Corporation
  3. Module Name:
  4. fdopower.c
  5. Abstract:
  6. --*/
  7. #include "ideport.h"
  8. //POWER_STATE
  9. NTSTATUS
  10. IdePortIssueSetPowerState (
  11. IN PDEVICE_EXTENSION_HEADER DoExtension,
  12. IN POWER_STATE_TYPE Type,
  13. IN POWER_STATE State,
  14. IN BOOLEAN Sync
  15. )
  16. {
  17. PIRP irp = NULL;
  18. PIO_STACK_LOCATION irpStack;
  19. NTSTATUS status;
  20. CCHAR stackSize;
  21. SET_POWER_STATE_CONTEXT context;
  22. if (Sync) {
  23. KeInitializeEvent(
  24. &context.Event,
  25. NotificationEvent,
  26. FALSE
  27. );
  28. }
  29. stackSize = (CCHAR) (DoExtension->DeviceObject->StackSize);
  30. irp = IoAllocateIrp(
  31. stackSize,
  32. FALSE
  33. );
  34. if (irp == NULL) {
  35. status = STATUS_NO_MEMORY;
  36. goto GetOut;
  37. }
  38. irpStack = IoGetNextIrpStackLocation(irp);
  39. irpStack->MajorFunction = IRP_MJ_POWER;
  40. irpStack->MinorFunction = IRP_MN_SET_POWER;
  41. irpStack->Parameters.Power.SystemContext = 0;
  42. irpStack->Parameters.Power.Type = Type;
  43. irpStack->Parameters.Power.State = State;
  44. IoSetCompletionRoutine(irp,
  45. IdePortPowerCompletionRoutine,
  46. Sync ? &context : NULL,
  47. TRUE,
  48. TRUE,
  49. TRUE);
  50. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  51. status = PoCallDriver(
  52. DoExtension->DeviceObject,
  53. irp
  54. );
  55. //
  56. // Wait for the completion routine. It will be called anyway
  57. //
  58. //if ((status == STATUS_PENDING) && (Sync)) {
  59. if (Sync) {
  60. KeWaitForSingleObject(&context.Event,
  61. Executive,
  62. KernelMode,
  63. FALSE,
  64. NULL);
  65. status = context.Status;
  66. }
  67. GetOut:
  68. return status;
  69. }
  70. NTSTATUS
  71. IdePortPowerCompletionRoutine (
  72. IN PDEVICE_OBJECT DeviceObject,
  73. IN PIRP Irp,
  74. IN PVOID Context
  75. )
  76. {
  77. PSET_POWER_STATE_CONTEXT context = Context;
  78. if (context) {
  79. context->Status = Irp->IoStatus.Status;
  80. KeSetEvent(
  81. &context->Event,
  82. EVENT_INCREMENT,
  83. FALSE
  84. );
  85. }
  86. IoFreeIrp (Irp);
  87. return STATUS_MORE_PROCESSING_REQUIRED;
  88. }
  89. NTSTATUS
  90. IdePortSetFdoPowerState (
  91. IN PDEVICE_OBJECT DeviceObject,
  92. IN OUT PIRP Irp
  93. )
  94. {
  95. PFDO_EXTENSION fdoExtension;
  96. PIO_STACK_LOCATION irpStack;
  97. NTSTATUS status = STATUS_SUCCESS;
  98. PFDO_POWER_CONTEXT context;
  99. BOOLEAN powerStateChange;
  100. BOOLEAN systemPowerContext = FALSE;
  101. BOOLEAN devicePowerContext = FALSE;
  102. DebugPrint ((DBG_POWER,
  103. "FDO devobj 0x%x got power irp 0x%x\n",
  104. DeviceObject,
  105. Irp
  106. ));
  107. fdoExtension = DeviceObject->DeviceExtension;
  108. irpStack = IoGetCurrentIrpStackLocation (Irp);
  109. //context = ExAllocatePool (NonPagedPool, sizeof(FDO_POWER_CONTEXT));
  110. //
  111. // We need two pre-alloced context structures. This is because a system power irp
  112. // would result in a device power irp to be issued before the former is completed.
  113. //
  114. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  115. ASSERT(InterlockedCompareExchange(&(fdoExtension->PowerContextLock[0]), 1, 0) == 0);
  116. context = &(fdoExtension->FdoPowerContext[0]);
  117. systemPowerContext = TRUE;
  118. } else {
  119. ASSERT(InterlockedCompareExchange(&(fdoExtension->PowerContextLock[1]), 1, 0) == 0);
  120. context = &(fdoExtension->FdoPowerContext[1]);
  121. devicePowerContext = TRUE;
  122. }
  123. if (context == NULL) {
  124. ASSERT(context);
  125. status = STATUS_NO_MEMORY;
  126. } else {
  127. RtlZeroMemory (context, sizeof(FDO_POWER_CONTEXT));
  128. powerStateChange = TRUE;
  129. context->OriginalPowerIrp = Irp;
  130. context->newPowerType = irpStack->Parameters.Power.Type;
  131. context->newPowerState = irpStack->Parameters.Power.State;
  132. if (irpStack->Parameters.Power.Type == SystemPowerState) {
  133. if (fdoExtension->SystemPowerState != irpStack->Parameters.Power.State.SystemState) {
  134. #if DBG
  135. ASSERT (fdoExtension->PendingSystemPowerIrp == NULL);
  136. fdoExtension->PendingSystemPowerIrp = Irp;
  137. ASSERT (fdoExtension->PendingSystemPowerIrp);
  138. #endif
  139. if (fdoExtension->SystemPowerState == PowerSystemWorking) {
  140. POWER_STATE powerState;
  141. //
  142. // Getting out of working state.
  143. //
  144. if ((irpStack->Parameters.Power.State.SystemState == PowerSystemShutdown) &&
  145. (irpStack->Parameters.Power.ShutdownType == PowerActionShutdownReset)) {
  146. //
  147. // spin up for BIOS POST
  148. //
  149. powerState.DeviceState = PowerDeviceD0;
  150. } else {
  151. //
  152. // power down for sleep
  153. //
  154. powerState.DeviceState = PowerDeviceD3;
  155. }
  156. IoMarkIrpPending(Irp);
  157. PoRequestPowerIrp (
  158. fdoExtension->DeviceObject,
  159. IRP_MN_SET_POWER,
  160. powerState,
  161. FdoContingentPowerCompletionRoutine,
  162. context,
  163. NULL
  164. );
  165. return STATUS_PENDING;
  166. }
  167. } else {
  168. //
  169. // We are already in the given state
  170. //
  171. powerStateChange = FALSE;
  172. }
  173. } else if (irpStack->Parameters.Power.Type == DevicePowerState) {
  174. if (fdoExtension->DevicePowerState != irpStack->Parameters.Power.State.DeviceState) {
  175. DebugPrint ((
  176. DBG_POWER,
  177. "IdePort: New Fdo 0x%x device power state 0x%x\n",
  178. fdoExtension->IdeResource.TranslatedCommandBaseAddress,
  179. irpStack->Parameters.Power.State.DeviceState
  180. ));
  181. ASSERT (fdoExtension->PendingDevicePowerIrp == NULL);
  182. #if DBG
  183. fdoExtension->PendingDevicePowerIrp = Irp;
  184. ASSERT (fdoExtension->PendingDevicePowerIrp);
  185. #endif //DBG
  186. if (fdoExtension->DevicePowerState == PowerDeviceD0) {
  187. //
  188. // getting out of D0 state, better call PoSetPowerState now
  189. //
  190. PoSetPowerState (
  191. DeviceObject,
  192. DevicePowerState,
  193. irpStack->Parameters.Power.State
  194. );
  195. }
  196. } else {
  197. //
  198. // We are already in the given state
  199. //
  200. powerStateChange = FALSE;
  201. }
  202. } else {
  203. ASSERT (FALSE);
  204. status = STATUS_NOT_IMPLEMENTED;
  205. }
  206. }
  207. if (NT_SUCCESS(status)) {
  208. IoMarkIrpPending(Irp);
  209. IoCopyCurrentIrpStackLocationToNext (Irp);
  210. if (powerStateChange) {
  211. IoSetCompletionRoutine(Irp,
  212. FdoPowerCompletionRoutine,
  213. context,
  214. TRUE,
  215. TRUE,
  216. TRUE);
  217. } else {
  218. if (systemPowerContext) {
  219. ASSERT(devicePowerContext == FALSE);
  220. ASSERT(InterlockedCompareExchange(&(fdoExtension->PowerContextLock[0]), 0, 1) == 1);
  221. }
  222. if (devicePowerContext) {
  223. ASSERT(systemPowerContext == FALSE);
  224. ASSERT(InterlockedCompareExchange(&(fdoExtension->PowerContextLock[1]), 0, 1) == 1);
  225. }
  226. //ExFreePool (context);
  227. PoStartNextPowerIrp (Irp);
  228. }
  229. PoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  230. return STATUS_PENDING;
  231. } else {
  232. Irp->IoStatus.Information = 0;
  233. Irp->IoStatus.Status = status;
  234. if (context) {
  235. if (systemPowerContext) {
  236. ASSERT(devicePowerContext == FALSE);
  237. ASSERT(InterlockedCompareExchange(&(fdoExtension->PowerContextLock[0]), 0, 1) == 1);
  238. }
  239. if (devicePowerContext) {
  240. ASSERT(systemPowerContext == FALSE);
  241. ASSERT(InterlockedCompareExchange(&(fdoExtension->PowerContextLock[1]), 0, 1) == 1);
  242. }
  243. //ExFreePool (context);
  244. }
  245. PoStartNextPowerIrp (Irp);
  246. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  247. return status;
  248. }
  249. }
  250. NTSTATUS
  251. FdoContingentPowerCompletionRoutine (
  252. IN PDEVICE_OBJECT DeviceObject,
  253. IN UCHAR MinorFunction,
  254. IN POWER_STATE PowerState,
  255. IN PVOID Context,
  256. IN PIO_STATUS_BLOCK IoStatus
  257. )
  258. {
  259. PFDO_POWER_CONTEXT context = Context;
  260. PFDO_EXTENSION fdoExtension;
  261. PIRP irp;
  262. irp = context->OriginalPowerIrp;
  263. fdoExtension = DeviceObject->DeviceExtension;
  264. if (NT_SUCCESS(IoStatus->Status)) {
  265. IoCopyCurrentIrpStackLocationToNext (irp);
  266. IoSetCompletionRoutine(irp,
  267. FdoPowerCompletionRoutine,
  268. context,
  269. TRUE,
  270. TRUE,
  271. TRUE);
  272. PoCallDriver (fdoExtension->AttacheeDeviceObject, irp);
  273. } else {
  274. irp->IoStatus.Information = 0;
  275. irp->IoStatus.Status = IoStatus->Status;
  276. //
  277. // This should happen only for system power irps
  278. //
  279. ASSERT(context->newPowerType == SystemPowerState);
  280. ASSERT(InterlockedCompareExchange(&(fdoExtension->PowerContextLock[0]), 0, 1) == 1);
  281. //ExFreePool (context);
  282. PoStartNextPowerIrp (irp);
  283. IoCompleteRequest(irp, IO_NO_INCREMENT);
  284. }
  285. return IoStatus->Status;
  286. }
  287. NTSTATUS
  288. FdoPowerCompletionRoutine (
  289. IN PDEVICE_OBJECT DeviceObject,
  290. IN PIRP Irp,
  291. IN PVOID Context
  292. )
  293. {
  294. PFDO_POWER_CONTEXT context = Context;
  295. BOOLEAN callPoSetPowerState;
  296. PFDO_EXTENSION fdoExtension;
  297. POWER_STATE newPowerState;
  298. POWER_STATE_TYPE newPowerType;
  299. BOOLEAN unlocked = FALSE;
  300. BOOLEAN moreProcessingRequired = FALSE;
  301. NTSTATUS status;
  302. fdoExtension = DeviceObject->DeviceExtension;
  303. newPowerType = context->newPowerType;
  304. newPowerState = context->newPowerState;
  305. if ((NT_SUCCESS(Irp->IoStatus.Status))) {
  306. callPoSetPowerState = TRUE;
  307. if (context->newPowerType == SystemPowerState) {
  308. fdoExtension->SystemPowerState = context->newPowerState.SystemState;
  309. if (fdoExtension->SystemPowerState == PowerSystemWorking) {
  310. POWER_STATE powerState;
  311. //
  312. // I don't need the context any more
  313. //
  314. ASSERT(InterlockedCompareExchange(&(fdoExtension->PowerContextLock[0]), 0, 1) == 1);
  315. unlocked = TRUE;
  316. moreProcessingRequired = TRUE;
  317. ASSERT(fdoExtension->PendingSystemPowerIrp == Irp);
  318. //
  319. // initiate a D0 here to cause a re-enumuration
  320. //
  321. powerState.DeviceState = PowerDeviceD0;
  322. status = PoRequestPowerIrp (
  323. fdoExtension->DeviceObject,
  324. IRP_MN_SET_POWER,
  325. powerState,
  326. FdoSystemPowerUpCompletionRoutine,
  327. Irp,
  328. NULL
  329. );
  330. ASSERT(status == STATUS_PENDING);
  331. }
  332. DebugPrint ((
  333. DBG_POWER, "IdePort: New Fdo 0x%x system power state 0x%x\n",
  334. fdoExtension->IdeResource.TranslatedCommandBaseAddress,
  335. fdoExtension->SystemPowerState));
  336. #if DBG
  337. if (moreProcessingRequired == FALSE) {
  338. fdoExtension->PendingSystemPowerIrp = NULL;
  339. }
  340. #endif
  341. } else if (context->newPowerType == DevicePowerState) {
  342. if (context->newPowerState.DeviceState == PowerDeviceD0) {
  343. if (fdoExtension->panasonicController) {
  344. //
  345. // this will loop 20000 * 100 us (2000ms) the most.
  346. //
  347. ULONG i = 20000;
  348. while (i) {
  349. //
  350. // the panasonic controller needs a special way to kick start
  351. //
  352. WRITE_PORT_UCHAR (fdoExtension->HwDeviceExtension->BaseIoAddress1.RegistersBaseAddress + 0x207, 0x81);
  353. WRITE_PORT_UCHAR (fdoExtension->HwDeviceExtension->BaseIoAddress1.RegistersBaseAddress, 0xa0);
  354. WRITE_PORT_UCHAR (fdoExtension->HwDeviceExtension->BaseIoAddress1.DriveSelect, 0xa0);
  355. if (0xa0 == READ_PORT_UCHAR (fdoExtension->HwDeviceExtension->BaseIoAddress1.DriveSelect)) {
  356. DebugPrint ((0, "panasonicController wait start count = %u\n", i));
  357. //
  358. // done
  359. //
  360. i = 0;
  361. } else {
  362. KeStallExecutionProcessor(100);
  363. i--;
  364. }
  365. }
  366. }
  367. }
  368. if ((context->newPowerState.DeviceState == PowerDeviceD0) &&
  369. (!context->TimingRestored)) {
  370. NTSTATUS status;
  371. status = ChannelRestoreTiming (
  372. fdoExtension,
  373. ChannelRestoreTimingCompletionRoutine,
  374. context
  375. );
  376. if (!NT_SUCCESS(status)) {
  377. ChannelRestoreTimingCompletionRoutine(
  378. fdoExtension->DeviceObject,
  379. status,
  380. context
  381. );
  382. }
  383. return STATUS_MORE_PROCESSING_REQUIRED;
  384. }
  385. ASSERT (fdoExtension->PendingDevicePowerIrp == Irp);
  386. fdoExtension->PendingDevicePowerIrp = NULL;
  387. if (fdoExtension->DevicePowerState == PowerDeviceD0) {
  388. //
  389. // PoSetPowerState is called before we get out of D0
  390. //
  391. callPoSetPowerState = FALSE;
  392. }
  393. fdoExtension->DevicePowerState = context->newPowerState.DeviceState;
  394. if ((fdoExtension->DevicePowerState == PowerDeviceD0) &&
  395. (fdoExtension->FdoState & FDOS_STARTED)) {
  396. IoInvalidateDeviceRelations (
  397. fdoExtension->AttacheePdo,
  398. BusRelations
  399. );
  400. }
  401. }
  402. if (callPoSetPowerState) {
  403. PoSetPowerState (
  404. DeviceObject,
  405. newPowerType,
  406. newPowerState
  407. );
  408. }
  409. } else {
  410. DebugPrint ((DBG_ALWAYS, "ATAPI: devobj 0x%x failed power irp 0x%x\n", fdoExtension->AttacheeDeviceObject, Irp));
  411. if (context->newPowerType == SystemPowerState) {
  412. ASSERT (fdoExtension->PendingSystemPowerIrp == Irp);
  413. fdoExtension->PendingSystemPowerIrp = NULL;
  414. } else if (context->newPowerType == DevicePowerState) {
  415. ASSERT (fdoExtension->PendingDevicePowerIrp == Irp);
  416. fdoExtension->PendingDevicePowerIrp = NULL;
  417. }
  418. }
  419. //
  420. // Done with context
  421. //
  422. if (!unlocked) {
  423. if (context->newPowerType == SystemPowerState) {
  424. ASSERT(InterlockedCompareExchange(&(fdoExtension->PowerContextLock[0]), 0, 1) == 1);
  425. } else {
  426. ASSERT(InterlockedCompareExchange(&(fdoExtension->PowerContextLock[1]), 0, 1) == 1);
  427. }
  428. }
  429. //ExFreePool (Context);
  430. //
  431. // wait for the device irp to complete
  432. //
  433. if (moreProcessingRequired) {
  434. return STATUS_MORE_PROCESSING_REQUIRED;
  435. }
  436. //
  437. // If pending has be returned for this irp then mark the current stack as
  438. // pending.
  439. //
  440. //if (Irp->PendingReturned) {
  441. // IoMarkIrpPending(Irp);
  442. //}
  443. PoStartNextPowerIrp (Irp);
  444. return Irp->IoStatus.Status;
  445. }
  446. VOID
  447. FdoChildReportPowerDown (
  448. IN PFDO_EXTENSION FdoExtension,
  449. IN PPDO_EXTENSION PdoExtension
  450. )
  451. {
  452. KIRQL currentIrql;
  453. POWER_STATE powerState;
  454. KeAcquireSpinLock(&FdoExtension->LogicalUnitListSpinLock, &currentIrql);
  455. FdoExtension->NumberOfLogicalUnitsPowerUp--;
  456. if (FdoExtension->NumberOfLogicalUnitsPowerUp == 0) {
  457. DebugPrint ((DBG_POWER, "FdoChildReportPowerDown: sleep fdo 0x%x\n", FdoExtension));
  458. //
  459. // All the children are powered down, we can now power down
  460. // the parent (the controller)
  461. //
  462. powerState.DeviceState = PowerDeviceD3;
  463. PoRequestPowerIrp (
  464. FdoExtension->DeviceObject,
  465. IRP_MN_SET_POWER,
  466. powerState,
  467. NULL,
  468. NULL,
  469. NULL
  470. );
  471. } else if (FdoExtension->NumberOfLogicalUnitsPowerUp < 0) {
  472. //
  473. // should never happen. If it did, pretend it didn't
  474. //
  475. ASSERT (FALSE);
  476. FdoExtension->NumberOfLogicalUnitsPowerUp = 0;
  477. }
  478. KeReleaseSpinLock(&FdoExtension->LogicalUnitListSpinLock, currentIrql);
  479. return;
  480. }
  481. NTSTATUS
  482. FdoChildRequestPowerUp (
  483. IN PFDO_EXTENSION FdoExtension,
  484. IN PPDO_EXTENSION PdoExtension,
  485. IN PVOID Context
  486. )
  487. {
  488. KIRQL currentIrql;
  489. NTSTATUS status;
  490. POWER_STATE powerState;
  491. KeAcquireSpinLock(&FdoExtension->LogicalUnitListSpinLock, &currentIrql);
  492. status = STATUS_SUCCESS;
  493. if (FdoExtension->NumberOfLogicalUnitsPowerUp == 0) {
  494. DebugPrint ((DBG_POWER, "FdoChildRequestPowerUp: wake up fdo 0x%x\n", FdoExtension));
  495. KeReleaseSpinLock(&FdoExtension->LogicalUnitListSpinLock, currentIrql);
  496. //
  497. // One of the children is coming out of sleep,
  498. // we need to power up the parent (the controller)
  499. //
  500. powerState.DeviceState = PowerDeviceD0;
  501. status = PoRequestPowerIrp (
  502. FdoExtension->DeviceObject,
  503. IRP_MN_SET_POWER,
  504. powerState,
  505. FdoChildRequestPowerUpCompletionRoutine,
  506. Context,
  507. NULL
  508. );
  509. ASSERT (NT_SUCCESS(status));
  510. status = STATUS_PENDING;
  511. } else {
  512. FdoExtension->NumberOfLogicalUnitsPowerUp++;
  513. if (FdoExtension->NumberOfLogicalUnitsPowerUp > FdoExtension->NumberOfLogicalUnits) {
  514. //
  515. // should never happen. If it did, pretend it didn't
  516. //
  517. ASSERT (FALSE);
  518. FdoExtension->NumberOfLogicalUnitsPowerUp = FdoExtension->NumberOfLogicalUnits;
  519. }
  520. KeReleaseSpinLock(&FdoExtension->LogicalUnitListSpinLock, currentIrql);
  521. PdoRequestParentPowerUpCompletionRoutine (
  522. Context,
  523. STATUS_SUCCESS
  524. );
  525. }
  526. return status;
  527. }
  528. NTSTATUS
  529. FdoChildRequestPowerUpCompletionRoutine (
  530. IN PDEVICE_OBJECT DeviceObject,
  531. IN UCHAR MinorFunction,
  532. IN POWER_STATE PowerState,
  533. IN PVOID Context,
  534. IN PIO_STATUS_BLOCK IoStatus
  535. )
  536. {
  537. PFDO_EXTENSION fdoExtension;
  538. fdoExtension = DeviceObject->DeviceExtension;
  539. if (NT_SUCCESS(IoStatus->Status)) {
  540. KIRQL currentIrql;
  541. KeAcquireSpinLock(&fdoExtension->LogicalUnitListSpinLock, &currentIrql);
  542. fdoExtension->NumberOfLogicalUnitsPowerUp++;
  543. KeReleaseSpinLock(&fdoExtension->LogicalUnitListSpinLock, currentIrql);
  544. }
  545. PdoRequestParentPowerUpCompletionRoutine (
  546. Context,
  547. IoStatus->Status
  548. );
  549. return IoStatus->Status;
  550. }
  551. NTSTATUS
  552. ChannelQueryPowerState (
  553. IN PDEVICE_OBJECT DeviceObject,
  554. IN OUT PIRP Irp
  555. )
  556. {
  557. PIO_STACK_LOCATION irpStack;
  558. PFDO_EXTENSION fdoExtension;
  559. fdoExtension = DeviceObject->DeviceExtension;
  560. #if defined (DONT_POWER_DOWN_PAGING_DEVICE)
  561. irpStack = IoGetCurrentIrpStackLocation (Irp);
  562. if (!fdoExtension->CrashDumpPathCount ||
  563. ((irpStack->Parameters.Power.Type == SystemPowerState) &&
  564. (irpStack->Parameters.Power.State.SystemState == PowerSystemWorking)) ||
  565. ((irpStack->Parameters.Power.Type == DevicePowerState) &&
  566. (irpStack->Parameters.Power.State.SystemState == PowerDeviceD0))) {
  567. Irp->IoStatus.Status = STATUS_SUCCESS;
  568. } else {
  569. Irp->IoStatus.Status = STATUS_DEVICE_POWER_FAILURE;
  570. }
  571. #else
  572. Irp->IoStatus.Status = STATUS_SUCCESS;
  573. #endif // DONT_POWER_DOWN_PAGING_DEVICE
  574. IoCopyCurrentIrpStackLocationToNext (Irp);
  575. PoStartNextPowerIrp (Irp);
  576. return PoCallDriver (fdoExtension->AttacheeDeviceObject, Irp);
  577. }
  578. NTSTATUS
  579. FdoSystemPowerUpCompletionRoutine (
  580. IN PDEVICE_OBJECT DeviceObject,
  581. IN UCHAR MinorFunction,
  582. IN POWER_STATE PowerState,
  583. IN PVOID Context,
  584. IN PIO_STATUS_BLOCK IoStatus
  585. )
  586. {
  587. PFDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  588. PIRP irp = Context;
  589. #if DBG
  590. fdoExtension->PendingSystemPowerIrp = NULL;
  591. #endif
  592. //
  593. // start the next system power irp
  594. //
  595. PoStartNextPowerIrp (irp);
  596. if (!NT_SUCCESS(IoStatus->Status)) {
  597. irp->IoStatus.Status = IoStatus->Status;
  598. }
  599. IoCompleteRequest(irp, IO_NO_INCREMENT);
  600. return STATUS_SUCCESS;
  601. }