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.

825 lines
23 KiB

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