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.

1966 lines
53 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. power.c
  5. Abstract:
  6. This module contains the routines for port driver power support
  7. Authors:
  8. Peter Wieland
  9. Environment:
  10. Kernel mode only
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "port.h"
  15. PUCHAR PowerMinorStrings[] = {
  16. "IRP_MN_WAIT_WAKE",
  17. "IRP_MN_POWER_SEQUENCE",
  18. "IRP_MN_SET_POWER",
  19. "IRP_MN_QUERY_POWER"
  20. };
  21. VOID
  22. SpProcessAdapterSystemState(
  23. IN PDEVICE_OBJECT DeviceObject,
  24. IN PIRP Irp
  25. );
  26. VOID
  27. SpProcessAdapterDeviceState(
  28. IN PDEVICE_OBJECT DeviceObject,
  29. IN PIRP Irp
  30. );
  31. NTSTATUS
  32. SpQueryTargetPower(
  33. IN PDEVICE_OBJECT DeviceObject,
  34. IN PIRP Irp,
  35. IN POWER_STATE_TYPE Type,
  36. IN POWER_STATE State
  37. );
  38. NTSTATUS
  39. SpQueryAdapterPower(
  40. IN PDEVICE_OBJECT DeviceObject,
  41. IN PIRP Irp,
  42. IN POWER_STATE_TYPE Type,
  43. IN POWER_STATE State
  44. );
  45. NTSTATUS
  46. SpSetTargetDeviceState(
  47. IN PDEVICE_OBJECT DeviceObject,
  48. IN PIRP Irp,
  49. IN DEVICE_POWER_STATE DeviceState
  50. );
  51. VOID
  52. SpSetTargetDeviceStateLockedCompletion(
  53. IN PDEVICE_OBJECT DeviceObject,
  54. IN NTSTATUS Status,
  55. IN PIRP OriginalIrp
  56. );
  57. VOID
  58. SpSetTargetDeviceStateUnlockedCompletion(
  59. IN PDEVICE_OBJECT DeviceObject,
  60. IN NTSTATUS Status,
  61. IN PIRP OriginalIrp
  62. );
  63. NTSTATUS
  64. SpSetTargetSystemState(
  65. IN PDEVICE_OBJECT DeviceObject,
  66. IN PIRP Irp,
  67. IN SYSTEM_POWER_STATE SystemState
  68. );
  69. VOID
  70. SpSetTargetSystemStateLockedCompletion(
  71. IN PDEVICE_OBJECT DeviceObject,
  72. IN NTSTATUS Status,
  73. IN PIRP OriginalIrp
  74. );
  75. VOID
  76. SpSetTargetSystemStateUnlockedCompletion(
  77. IN PDEVICE_OBJECT DeviceObject,
  78. IN NTSTATUS Status,
  79. IN PIRP OriginalIrp
  80. );
  81. VOID
  82. SpSetTargetDeviceStateForSystemStateCompletion(
  83. IN PDEVICE_OBJECT DeviceObject,
  84. IN UCHAR MinorFunction,
  85. IN POWER_STATE PowerState,
  86. IN PIRP OriginalIrp,
  87. IN PIO_STATUS_BLOCK IoStatus
  88. );
  89. NTSTATUS
  90. SpSetAdapterPower(
  91. IN PDEVICE_OBJECT DeviceObject,
  92. IN PIRP Irp,
  93. IN POWER_STATE_TYPE Type,
  94. IN POWER_STATE State
  95. );
  96. VOID
  97. SpRequestAdapterPowerCompletion(
  98. IN PDEVICE_OBJECT DeviceObject,
  99. IN UCHAR MinorFunction,
  100. IN POWER_STATE PowerState,
  101. IN PIRP OriginalIrp,
  102. IN PIO_STATUS_BLOCK IoStatus
  103. );
  104. VOID
  105. SpPowerAdapterForTargetCompletion(
  106. IN PDEVICE_OBJECT DeviceObject,
  107. IN UCHAR MinorFunction,
  108. IN POWER_STATE PowerState,
  109. IN PIRP OriginalIrp,
  110. IN PIO_STATUS_BLOCK IoStatus
  111. );
  112. NTSTATUS
  113. SpSetLowerPowerCompletion(
  114. IN PDEVICE_OBJECT DeviceObject,
  115. IN PIRP Irp,
  116. IN PVOID Context
  117. );
  118. VOID
  119. SpSetTargetDesiredPowerCompletion(
  120. IN PDEVICE_OBJECT DeviceObject,
  121. IN UCHAR MinorFunction,
  122. IN POWER_STATE PowerState,
  123. IN PIRP OriginalIrp,
  124. IN PIO_STATUS_BLOCK IoStatus
  125. );
  126. VOID
  127. SpRequestValidPowerStateCompletion (
  128. IN PDEVICE_OBJECT DeviceObject,
  129. IN UCHAR MinorFunction,
  130. IN POWER_STATE PowerState,
  131. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  132. IN PIO_STATUS_BLOCK IoStatus
  133. );
  134. typedef struct {
  135. NTSTATUS Status;
  136. KEVENT Event;
  137. } SP_SIGNAL_POWER_COMPLETION_CONTEXT, *PSP_SIGNAL_POWER_COMPLETION_CONTEXT;
  138. VOID
  139. SpSignalPowerCompletion(
  140. IN PDEVICE_OBJECT DeviceObject,
  141. IN UCHAR MinorFunction,
  142. IN POWER_STATE PowerState,
  143. IN PSP_SIGNAL_POWER_COMPLETION_CONTEXT Context,
  144. IN PIO_STATUS_BLOCK IoStatus
  145. );
  146. #pragma alloc_text(PAGE, SpRequestValidAdapterPowerStateSynchronous)
  147. NTSTATUS
  148. ScsiPortDispatchPower(
  149. IN PDEVICE_OBJECT DeviceObject,
  150. IN OUT PIRP Irp
  151. )
  152. /*++
  153. Routine Description:
  154. This routine handles all IRP_MJ_POWER IRPs for the target device objects.
  155. N.B. This routine is NOT pageable as it may be called at dispatch level.
  156. Arguments:
  157. DeviceObject - Pointer to the device object for which this IRP applies.
  158. Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
  159. Return Value:
  160. NT status.
  161. --*/
  162. {
  163. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  164. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  165. BOOLEAN isPdo = commonExtension->IsPdo;
  166. NTSTATUS status;
  167. //
  168. // Get the current status of the request.
  169. //
  170. status = Irp->IoStatus.Status;
  171. DebugPrint((4, "ScsiPortDispatchPower: irp %p is %s for %s %p\n",
  172. Irp,
  173. PowerMinorStrings[irpStack->MinorFunction],
  174. isPdo ? "pdo" : "fdo",
  175. DeviceObject));
  176. switch (irpStack->MinorFunction) {
  177. case IRP_MN_SET_POWER: {
  178. POWER_STATE_TYPE type = irpStack->Parameters.Power.Type;
  179. POWER_STATE state = irpStack->Parameters.Power.State;
  180. DebugPrint((4, "ScsiPortDispatchPower: SET_POWER type %d state %d\n",
  181. type, state));
  182. #if DBG
  183. if (type == SystemPowerState) {
  184. ASSERT(state.SystemState >= PowerSystemUnspecified);
  185. ASSERT(state.SystemState < PowerSystemMaximum);
  186. } else {
  187. ASSERT(state.DeviceState >= PowerDeviceUnspecified);
  188. ASSERT(state.DeviceState < PowerDeviceMaximum);
  189. }
  190. #endif
  191. //
  192. // If this is a power-down request then call PoSetPowerState now
  193. // while we're not actually holding any resources or locks.
  194. //
  195. if ((state.SystemState != PowerSystemWorking) ||
  196. (state.DeviceState != PowerDeviceD0)) {
  197. PoSetPowerState(DeviceObject, type, state);
  198. }
  199. //
  200. // Special case system shutdown request.
  201. //
  202. if ((type == SystemPowerState) &&
  203. (state.SystemState > PowerSystemHibernate)) {
  204. if (isPdo) {
  205. //
  206. // Do not pwer-downdown PDOs on shutdown. There is no
  207. // reliable way to ensure that disks will spin up on restart.
  208. //
  209. status = STATUS_SUCCESS;
  210. break;
  211. } else {
  212. PADAPTER_EXTENSION adapter;
  213. //
  214. // If the adapter is not configured to receive power-down
  215. // requests at shutdown, just pass the request down.
  216. //
  217. adapter = (PADAPTER_EXTENSION)commonExtension;
  218. if (adapter->NeedsShutdown == FALSE) {
  219. PoStartNextPowerIrp(Irp);
  220. IoCopyCurrentIrpStackLocationToNext(Irp);
  221. return PoCallDriver(commonExtension->LowerDeviceObject, Irp);
  222. }
  223. }
  224. }
  225. if (isPdo) {
  226. if (type == DevicePowerState) {
  227. status = SpSetTargetDeviceState(DeviceObject,
  228. Irp,
  229. state.DeviceState);
  230. } else {
  231. status = SpSetTargetSystemState(DeviceObject,
  232. Irp,
  233. state.SystemState);
  234. }
  235. } else {
  236. PADAPTER_EXTENSION adapter = DeviceObject->DeviceExtension;
  237. //
  238. // If we have disabled power then ignore any non-working power irps.
  239. //
  240. if ((adapter->DisablePower) &&
  241. ((state.DeviceState != PowerDeviceD0) ||
  242. (state.SystemState != PowerSystemWorking))) {
  243. status = STATUS_SUCCESS;
  244. break;
  245. } else {
  246. status = SpSetAdapterPower(DeviceObject, Irp, type, state);
  247. }
  248. }
  249. if(status == STATUS_PENDING) {
  250. return status;
  251. }
  252. break;
  253. }
  254. case IRP_MN_QUERY_POWER: {
  255. POWER_STATE_TYPE type = irpStack->Parameters.Power.Type;
  256. POWER_STATE state = irpStack->Parameters.Power.State;
  257. DebugPrint((4, "ScsiPortDispatchPower: QUERY_POWER type %d "
  258. "state %d\n",
  259. type, state));
  260. if ((type == SystemPowerState) &&
  261. (state.SystemState > PowerSystemHibernate)) {
  262. //
  263. // Ignore shutdown irps.
  264. //
  265. DebugPrint((4, "ScsiPortDispatch power - ignoring shutdown "
  266. "query irp for level %d\n",
  267. state.SystemState));
  268. status = STATUS_SUCCESS;
  269. break;
  270. }
  271. if (isPdo) {
  272. if ((type == SystemPowerState) &&
  273. (state.SystemState > PowerSystemHibernate)) {
  274. //
  275. // Ignore shutdown irps.
  276. //
  277. DebugPrint((4, "ScsiPortDispatch power - ignoring shutdown "
  278. "query irp for level %d\n",
  279. state.SystemState));
  280. status = STATUS_SUCCESS;
  281. } else {
  282. status = SpQueryTargetPower(DeviceObject,
  283. Irp,
  284. type,
  285. state);
  286. }
  287. } else {
  288. PADAPTER_EXTENSION adapter = (PADAPTER_EXTENSION)commonExtension;
  289. //
  290. // If we don't support power for this adapter then fail all
  291. // queries.
  292. //
  293. if (adapter->DisablePower) {
  294. status = STATUS_NOT_SUPPORTED;
  295. break;
  296. }
  297. status = SpQueryAdapterPower(DeviceObject, Irp, type, state);
  298. if (NT_SUCCESS(status)) {
  299. //
  300. // See what the lower driver wants to do.
  301. //
  302. PoStartNextPowerIrp(Irp);
  303. IoCopyCurrentIrpStackLocationToNext(Irp);
  304. return PoCallDriver(commonExtension->LowerDeviceObject, Irp);
  305. }
  306. }
  307. break;
  308. }
  309. case IRP_MN_WAIT_WAKE: {
  310. if (isPdo) {
  311. //
  312. // We don't support WAIT WAKE, so just fail the request.
  313. //
  314. status = STATUS_INVALID_DEVICE_REQUEST;
  315. PoStartNextPowerIrp(Irp);
  316. Irp->IoStatus.Status = status;
  317. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  318. } else {
  319. //
  320. // Pass the request down.
  321. //
  322. PoStartNextPowerIrp(Irp);
  323. IoSkipCurrentIrpStackLocation(Irp);
  324. status = PoCallDriver(commonExtension->LowerDeviceObject, Irp);
  325. }
  326. return status;
  327. }
  328. default: {
  329. //
  330. // We pass down FDO requests we don't handle.
  331. //
  332. if (!isPdo) {
  333. PoStartNextPowerIrp(Irp);
  334. IoSkipCurrentIrpStackLocation(Irp);
  335. return PoCallDriver(commonExtension->LowerDeviceObject, Irp);
  336. }
  337. break;
  338. }
  339. }
  340. //
  341. // Complete the request.
  342. //
  343. PoStartNextPowerIrp(Irp);
  344. Irp->IoStatus.Status = status;
  345. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  346. return status;
  347. }
  348. NTSTATUS
  349. SpSetAdapterPower(
  350. IN PDEVICE_OBJECT DeviceObject,
  351. IN PIRP Irp,
  352. IN POWER_STATE_TYPE Type,
  353. IN POWER_STATE State
  354. )
  355. /*++
  356. Routine Description:
  357. Wrapper routine to dump adapter power requests into the device i/o queue.
  358. Power requests are processed by the StartIo routine which calls
  359. SpProcessAdapterPower to do the actual work.
  360. Arguments:
  361. DeviceObject - the device object being power managed.
  362. Irp - the power management irp.
  363. Type - the type of set_power irp (device or system)
  364. State - the state the adapter is being put into.
  365. Return Value:
  366. STATUS_PENDING
  367. --*/
  368. {
  369. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  370. PADAPTER_EXTENSION adapter = DeviceObject->DeviceExtension;
  371. NTSTATUS status;
  372. ASSERT_FDO(DeviceObject);
  373. DebugPrint((2, "SpSetAdapterPower - starting packet\n"));
  374. if(SpIsAdapterControlTypeSupported(adapter, ScsiStopAdapter)) {
  375. IoMarkIrpPending(Irp);
  376. IoStartPacket(DeviceObject, Irp, 0L, FALSE);
  377. return STATUS_PENDING;
  378. } else if((commonExtension->CurrentPnpState != IRP_MN_START_DEVICE) &&
  379. (commonExtension->PreviousPnpState != IRP_MN_START_DEVICE)) {
  380. //
  381. // Fine, we're in a low power state. If we get a start or a remove
  382. // then there's an implicit power transition there so we don't really
  383. // need to set our current power state.
  384. //
  385. IoMarkIrpPending(Irp);
  386. IoCopyCurrentIrpStackLocationToNext(Irp);
  387. PoStartNextPowerIrp(Irp);
  388. PoCallDriver(commonExtension->LowerDeviceObject, Irp);
  389. return STATUS_PENDING;
  390. } else {
  391. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  392. return Irp->IoStatus.Status;
  393. }
  394. }
  395. VOID
  396. SpPowerAdapterForTargetCompletion(
  397. IN PDEVICE_OBJECT DeviceObject,
  398. IN UCHAR MinorFunction,
  399. IN POWER_STATE PowerState,
  400. IN PIRP OriginalIrp,
  401. IN PIO_STATUS_BLOCK IoStatus
  402. )
  403. /*++
  404. Routine Description:
  405. This routine is called for a D0 request to a target device after it's
  406. adapter has been powered back on. The routine will call back into
  407. SpSetTargetDeviceState to restart the power request or complete the
  408. target D request if the adapter power up was not successful.
  409. Arguments:
  410. DeviceObject - the adapter which was powered up.
  411. MinorFunction - IRP_MN_SET_POWER
  412. PowerState - PowerDeviceD0
  413. OriginalIrp - The original target D0 irp. This is the irp which will
  414. be reprocessed.
  415. IoStatus - the status of the adapter power up request.
  416. Return Value:
  417. none.
  418. --*/
  419. {
  420. PADAPTER_EXTENSION adapter = DeviceObject->DeviceExtension;
  421. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(OriginalIrp);
  422. POWER_STATE_TYPE type = irpStack->Parameters.Power.Type;
  423. POWER_STATE state = irpStack->Parameters.Power.State;
  424. NTSTATUS status = IoStatus->Status;
  425. DebugPrint((1, "SpPowerAdapterForTargetCompletion: DevObj %#p, Irp "
  426. "%#p, Status %#08lx\n",
  427. DeviceObject, OriginalIrp, IoStatus));
  428. ASSERT_FDO(DeviceObject);
  429. ASSERT_PDO(irpStack->DeviceObject);
  430. ASSERT(type == DevicePowerState);
  431. ASSERT(state.DeviceState == PowerDeviceD0);
  432. ASSERT(NT_SUCCESS(status));
  433. if(NT_SUCCESS(status)) {
  434. ASSERT(adapter->CommonExtension.CurrentDeviceState == PowerDeviceD0);
  435. status = SpSetTargetDeviceState(irpStack->DeviceObject,
  436. OriginalIrp,
  437. PowerDeviceD0);
  438. }
  439. if(status != STATUS_PENDING) {
  440. PoStartNextPowerIrp(OriginalIrp);
  441. OriginalIrp->IoStatus.Status = status;
  442. IoCompleteRequest(OriginalIrp, IO_NO_INCREMENT);
  443. }
  444. return;
  445. }
  446. NTSTATUS
  447. SpQueryAdapterPower(
  448. IN PDEVICE_OBJECT DeviceObject,
  449. IN PIRP Irp,
  450. IN POWER_STATE_TYPE Type,
  451. IN POWER_STATE State
  452. )
  453. {
  454. PADAPTER_EXTENSION adapter = DeviceObject->DeviceExtension;
  455. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  456. NTSTATUS status;
  457. if((adapter->HwAdapterControl != NULL) && (adapter->IsPnp)) {
  458. status = STATUS_SUCCESS;
  459. } else if((commonExtension->CurrentPnpState != IRP_MN_START_DEVICE) &&
  460. (commonExtension->PreviousPnpState != IRP_MN_START_DEVICE)) {
  461. //
  462. // If the adapter's not been started yet then we can blindly go to
  463. // a lower power state - START irps imply a transition into the D0 state
  464. //
  465. status = STATUS_SUCCESS;
  466. } else {
  467. status = STATUS_NOT_SUPPORTED;
  468. }
  469. return status;
  470. }
  471. NTSTATUS
  472. SpQueryTargetPower(
  473. IN PDEVICE_OBJECT DeviceObject,
  474. IN PIRP Irp,
  475. IN POWER_STATE_TYPE Type,
  476. IN POWER_STATE State
  477. )
  478. {
  479. return STATUS_SUCCESS;
  480. }
  481. NTSTATUS
  482. SpRequestValidPowerState(
  483. IN PADAPTER_EXTENSION Adapter,
  484. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  485. IN PSCSI_REQUEST_BLOCK Srb
  486. )
  487. {
  488. PCOMMON_EXTENSION commonExtension = &(LogicalUnit->CommonExtension);
  489. PSRB_DATA srbData = Srb->OriginalRequest;
  490. BOOLEAN needsPower = SpSrbRequiresPower(Srb);
  491. NTSTATUS status = STATUS_SUCCESS;
  492. //
  493. // Make sure we're at a power level which can process this request. If
  494. // we aren't then make this a pending request, lock the queues and
  495. // ask the power system to bring us up to a more energetic level.
  496. //
  497. if((Srb->Function == SRB_FUNCTION_UNLOCK_QUEUE) ||
  498. (Srb->Function == SRB_FUNCTION_LOCK_QUEUE)) {
  499. //
  500. // Lock and unlock commands don't require power and will work
  501. // regardless of the current power state.
  502. //
  503. return status;
  504. }
  505. //
  506. // Even if this is a bypass request, the class driver may not request
  507. // actual miniport operations on the unpowered side of a power sequence.
  508. // This means that this is either:
  509. // * a request to an idle device - powering up the device will power
  510. // up the adapter if necessary.
  511. // * a request to power down a device - adapter cannot have powered
  512. // off until this is done.
  513. // * a part of a power up sequence - the only real SCSI commands come
  514. // after the power up irp has been processed and that irp will
  515. // already have turned the adapter on.
  516. // This boils down to - we don't need to do anything special here to
  517. // power up the adapter. The device power sequences will take care of
  518. // it automatically.
  519. //
  520. //
  521. // If the device or system isn't working AND this is not a request to
  522. // unlock the queue then let it go through. The class driver is going
  523. // to unlock the queue after sending us a power request so we need to
  524. // be able to handle one.
  525. //
  526. if((commonExtension->CurrentDeviceState != PowerDeviceD0) ||
  527. ((commonExtension->CurrentSystemState != PowerSystemWorking) &&
  528. (!TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_BYPASS_LOCKED_QUEUE)))) {
  529. //
  530. // This request cannot be executed now. Mark it as pending
  531. // in the logical unit structure and return.
  532. // GetNextLogicalUnit will restart the commnad after all of the
  533. // active commands have completed.
  534. //
  535. ASSERT(!TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_BYPASS_LOCKED_QUEUE));
  536. ASSERT(!(LogicalUnit->LuFlags & LU_PENDING_LU_REQUEST));
  537. DebugPrint((4, "ScsiPortStartIo: logical unit (%d,%d,%d) [%#p] is "
  538. "in power state (%d,%d) - must power up for irp "
  539. "%#p\n",
  540. Srb->PathId,
  541. Srb->TargetId,
  542. Srb->Lun,
  543. commonExtension->DeviceObject,
  544. commonExtension->CurrentDeviceState,
  545. commonExtension->CurrentSystemState,
  546. srbData->CurrentIrp));
  547. ASSERT(LogicalUnit->PendingRequest == NULL);
  548. LogicalUnit->PendingRequest = Srb->OriginalRequest;
  549. //
  550. // Indicate that the logical unit is still active so that the
  551. // request will get processed when the request list is empty.
  552. //
  553. SET_FLAG(LogicalUnit->LuFlags, LU_PENDING_LU_REQUEST |
  554. LU_LOGICAL_UNIT_IS_ACTIVE);
  555. if(commonExtension->CurrentSystemState != PowerSystemWorking) {
  556. DebugPrint((1, "SpRequestValidPowerState: can't power up target "
  557. "since it's in system state %d\n",
  558. commonExtension->CurrentSystemState));
  559. //
  560. // Set the desired D state in the device extension. This is
  561. // necessary when we're in a low system state as well as useful for
  562. // debugging when we're in low D states.
  563. //
  564. commonExtension->DesiredDeviceState = PowerDeviceD0;
  565. //
  566. // If we aren't in a valid system state then just release the
  567. // spinlock and return. The next time we receive a system
  568. // state irp we'll issue the appropriate D state irp as well.
  569. //
  570. return STATUS_PENDING;
  571. } else if(commonExtension->DesiredDeviceState == PowerDeviceD0) {
  572. //
  573. // Scsiport is already asking to power up this lun. Once that's
  574. // happened this request will be restarted. For now just leave
  575. // it as the pending request.
  576. //
  577. return STATUS_PENDING;
  578. }
  579. //
  580. // Tell Po that we're not idle in case this was stuck in the queue
  581. // for some reason.
  582. //
  583. if(commonExtension->IdleTimer != NULL) {
  584. PoSetDeviceBusy(commonExtension->IdleTimer);
  585. }
  586. //
  587. // Get PO to send a power request to this device stack to put it
  588. // back into the D0 state.
  589. //
  590. {
  591. POWER_STATE powerState;
  592. powerState.DeviceState = PowerDeviceD0;
  593. status = PoRequestPowerIrp(
  594. commonExtension->DeviceObject,
  595. IRP_MN_SET_POWER,
  596. powerState,
  597. NULL,
  598. NULL,
  599. NULL);
  600. }
  601. //
  602. // CODEWORK - if we can't power up the device here we'll need to
  603. // hang around in the tick handler for a while and try to do
  604. // it from there.
  605. //
  606. ASSERT(NT_SUCCESS(status));
  607. return STATUS_PENDING;
  608. }
  609. ASSERT(Adapter->CommonExtension.CurrentDeviceState == PowerDeviceD0);
  610. ASSERT(Adapter->CommonExtension.CurrentSystemState == PowerSystemWorking);
  611. return status;
  612. }
  613. NTSTATUS
  614. SpSetLowerPowerCompletion(
  615. IN PDEVICE_OBJECT DeviceObject,
  616. IN PIRP Irp,
  617. IN PVOID Context
  618. )
  619. {
  620. PADAPTER_EXTENSION adapter = DeviceObject->DeviceExtension;
  621. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  622. POWER_STATE_TYPE type = irpStack->Parameters.Power.Type;
  623. POWER_STATE state = irpStack->Parameters.Power.State;
  624. DebugPrint((2, "SpSetLowerPowerCompletion: DevObj %#p Irp %#p "
  625. "%sState %d\n",
  626. DeviceObject, Irp,
  627. ((type == SystemPowerState) ? "System" : "Device"),
  628. state.DeviceState - 1));
  629. if(NT_SUCCESS(Irp->IoStatus.Status)) {
  630. if(type == SystemPowerState) {
  631. DebugPrint((2, "SpSetLowerPowerCompletion: Lower device succeeded "
  632. "the system state transition. Reprocessing power "
  633. "irp\n"));
  634. SpProcessAdapterSystemState(DeviceObject, Irp);
  635. } else {
  636. DebugPrint((2, "SpSetLowerPowerCompletion: Lower device power up "
  637. "was successful. Reprocessing power irp\n"));
  638. SpProcessAdapterDeviceState(DeviceObject, Irp);
  639. }
  640. return STATUS_MORE_PROCESSING_REQUIRED;
  641. } else {
  642. DebugPrint((1, "SpSetLowerPowerCompletion: Lower device power operation"
  643. "failed - completing power irp with status %#08lx\n",
  644. Irp->IoStatus.Status));
  645. PoStartNextPowerIrp(Irp);
  646. SpStartNextPacket(DeviceObject, FALSE);
  647. return STATUS_SUCCESS;
  648. }
  649. }
  650. VOID
  651. SpProcessAdapterSystemState(
  652. IN PDEVICE_OBJECT DeviceObject,
  653. IN PIRP Irp
  654. )
  655. /*++
  656. Routine Description:
  657. This routine handles a system power IRP for the adapter.
  658. Arguments:
  659. DeviceObject - the device object for the adapter.
  660. Irp - the power irp.
  661. Return Value:
  662. none
  663. --*/
  664. {
  665. PADAPTER_EXTENSION adapterExtension = DeviceObject->DeviceExtension;
  666. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  667. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  668. SYSTEM_POWER_STATE state = irpStack->Parameters.Power.State.SystemState;
  669. SYSTEM_POWER_STATE originalSystemState;
  670. NTSTATUS status = STATUS_SUCCESS;
  671. ASSERT_FDO(DeviceObject);
  672. ASSERT(irpStack->Parameters.Power.Type == SystemPowerState);
  673. DebugPrint((2, "SpProcessAdapterSystemState: DevObj %#p Irp %#p "
  674. "SystemState %d\n",
  675. DeviceObject, Irp, state));
  676. originalSystemState = commonExtension->CurrentSystemState;
  677. try {
  678. POWER_STATE newDeviceState;
  679. if(((commonExtension->CurrentSystemState != PowerSystemWorking) &&
  680. (state != PowerSystemWorking)) ||
  681. (commonExtension->CurrentSystemState == state)) {
  682. DebugPrint((2, "SpProcessAdapterSystemState: no work required for "
  683. "transition from system state %d to %d\n",
  684. commonExtension->CurrentSystemState,
  685. state));
  686. commonExtension->CurrentSystemState = state;
  687. leave;
  688. }
  689. //
  690. // Set the new system state. We'll back it out if any errors occur.
  691. //
  692. commonExtension->CurrentSystemState = state;
  693. if(state != PowerSystemWorking) {
  694. //
  695. // Going into a non-working state - power down the device.
  696. //
  697. DebugPrint((1, "SpProcessAdapterSystemState: need to power "
  698. "down adapter for non-working system state "
  699. "%d\n", state));
  700. newDeviceState.DeviceState = PowerDeviceD3;
  701. //
  702. // This system irp cannot be completed until we've successfully
  703. // powered the adapter off (or on).
  704. //
  705. status = PoRequestPowerIrp(DeviceObject,
  706. IRP_MN_SET_POWER,
  707. newDeviceState,
  708. SpRequestAdapterPowerCompletion,
  709. Irp,
  710. NULL);
  711. DebugPrint((2, "SpProcessAdapterSystemState: PoRequestPowerIrp "
  712. "returned %#08lx\n", status));
  713. } else {
  714. //
  715. // Transitioning the device into a system working state. Just
  716. // do the enable. When a child device is put into S0 and has
  717. // work to process it will request a D0 of the child which will
  718. // in turn request a D0 of the parent (ie. the adapter). We can
  719. // defer adapter power on until that occurs.
  720. //
  721. // Going into a working device state. When the targets are
  722. // powered on and we have work to do they will request an
  723. // adapter power up for us.
  724. //
  725. DebugPrint((1, "SpProcessAdapterSystemState: going to working "
  726. "state - no need to take adapter out of power "
  727. "state %d\n",
  728. commonExtension->CurrentDeviceState));
  729. ASSERT(state == PowerSystemWorking);
  730. status = SpEnableDisableAdapter(adapterExtension, TRUE);
  731. ASSERT(status != STATUS_PENDING);
  732. DebugPrint((1, "SpProcessAdapterSystemState: SpEnableDisableAd. "
  733. "returned %#08lx\n", status));
  734. }
  735. } finally {
  736. SpStartNextPacket(DeviceObject, FALSE);
  737. if(status != STATUS_PENDING) {
  738. if(!NT_SUCCESS(status)) {
  739. //
  740. // Something went wrong above. Restore the original system
  741. // state.
  742. //
  743. commonExtension->CurrentSystemState = originalSystemState;
  744. }
  745. Irp->IoStatus.Status = status;
  746. PoStartNextPowerIrp(Irp);
  747. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  748. }
  749. }
  750. return;
  751. }
  752. VOID
  753. SpProcessAdapterDeviceState(
  754. IN PDEVICE_OBJECT DeviceObject,
  755. IN PIRP Irp
  756. )
  757. /*++
  758. Routine Description:
  759. This routine handles a device power IRP for the adapter.
  760. Arguments:
  761. DeviceObject - the device object for the adapter.
  762. Irp - the power irp.
  763. Return Value:
  764. none
  765. --*/
  766. {
  767. PADAPTER_EXTENSION adapterExtension = DeviceObject->DeviceExtension;
  768. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  769. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  770. DEVICE_POWER_STATE state = irpStack->Parameters.Power.State.DeviceState;
  771. NTSTATUS status = STATUS_SUCCESS;
  772. ASSERT_FDO(DeviceObject);
  773. ASSERT(irpStack->Parameters.Power.Type == DevicePowerState);
  774. DebugPrint((1, "SpProcessAdapterDevicePower: DevObj %#p Irp %#p "
  775. "State %d\n",
  776. DeviceObject, Irp, state));
  777. //
  778. // First check to see if we actually need to touch the queue.
  779. // If both the current and new state are working or non-working then
  780. // we don't have a thing to do.
  781. //
  782. if(((commonExtension->CurrentDeviceState != PowerDeviceD0) &&
  783. (state != PowerDeviceD0)) ||
  784. (commonExtension->CurrentDeviceState == state)) {
  785. DebugPrint((2, "SpProcessAdapterDeviceState: no work required "
  786. "for transition from device state %d to %d\n",
  787. commonExtension->CurrentDeviceState,
  788. state));
  789. } else {
  790. BOOLEAN enable = (state == PowerDeviceD0);
  791. status = SpEnableDisableAdapter(adapterExtension, enable);
  792. ASSERT(status != STATUS_PENDING);
  793. DebugPrint((2, "SpProcessAdapterDeviceState: SpEnableDisableAd. "
  794. "returned %#08lx\n", status));
  795. }
  796. ASSERT(status != STATUS_PENDING);
  797. if(NT_SUCCESS(status)) {
  798. commonExtension->CurrentDeviceState = state;
  799. }
  800. //
  801. // If this is not a D0 irp then throw it down to the lower driver,
  802. // otherwise complete it.
  803. //
  804. SpStartNextPacket(DeviceObject, FALSE);
  805. Irp->IoStatus.Status = status;
  806. PoStartNextPowerIrp(Irp);
  807. if(irpStack->Parameters.Power.State.DeviceState != PowerDeviceD0) {
  808. IoCopyCurrentIrpStackLocationToNext(Irp);
  809. PoCallDriver(commonExtension->LowerDeviceObject, Irp);
  810. } else {
  811. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  812. }
  813. //
  814. // If we successfully powered up the adapter, initiate a rescan so our child
  815. // device state is accurate.
  816. //
  817. if (NT_SUCCESS(status) && (state == PowerDeviceD0)) {
  818. DebugPrint((1, "SpProcessAdapterDeviceState: powered up.. rescan %p\n",
  819. adapterExtension->LowerPdo));
  820. IoInvalidateDeviceRelations(
  821. adapterExtension->LowerPdo,
  822. BusRelations);
  823. }
  824. return;
  825. }
  826. VOID
  827. ScsiPortProcessAdapterPower(
  828. IN PDEVICE_OBJECT DeviceObject,
  829. IN PIRP Irp
  830. )
  831. {
  832. PADAPTER_EXTENSION adapter = DeviceObject->DeviceExtension;
  833. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  834. ASSERT(irpStack->MajorFunction == IRP_MJ_POWER);
  835. ASSERT(irpStack->MinorFunction == IRP_MN_SET_POWER);
  836. ASSERT_FDO(DeviceObject);
  837. //
  838. // Determine if the irp should be sent to the lower driver first.
  839. // If so send it down without calling SpStartNextPacket so we'll
  840. // still have synchronization in the completion routine.
  841. //
  842. // The completion routine calls ScsiPortProcessAdapterPower for this
  843. // irp.
  844. //
  845. if(irpStack->Parameters.Power.Type == SystemPowerState) {
  846. //
  847. // Process system state irps before we send them down.
  848. //
  849. SpProcessAdapterSystemState(DeviceObject, Irp);
  850. } else if(irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0) {
  851. NTSTATUS status;
  852. //
  853. // System power IRP or a power-up request. These should be
  854. // processed by the lower driver before being processed by
  855. // scsiport.
  856. //
  857. IoCopyCurrentIrpStackLocationToNext(Irp);
  858. IoSetCompletionRoutine(Irp,
  859. SpSetLowerPowerCompletion,
  860. NULL,
  861. TRUE,
  862. TRUE,
  863. TRUE);
  864. status = PoCallDriver(
  865. adapter->CommonExtension.LowerDeviceObject,
  866. Irp);
  867. } else {
  868. SpProcessAdapterDeviceState(DeviceObject, Irp);
  869. }
  870. return;
  871. }
  872. VOID
  873. SpRequestAdapterPowerCompletion(
  874. IN PDEVICE_OBJECT DeviceObject,
  875. IN UCHAR MinorFunction,
  876. IN POWER_STATE PowerState,
  877. IN PIRP SystemIrp,
  878. IN PIO_STATUS_BLOCK IoStatus
  879. )
  880. {
  881. PADAPTER_EXTENSION adapter = DeviceObject->DeviceExtension;
  882. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(SystemIrp);
  883. SYSTEM_POWER_STATE state = irpStack->Parameters.Power.State.SystemState;
  884. BOOLEAN enable = FALSE;
  885. NTSTATUS status = IoStatus->Status;
  886. ASSERT_FDO(DeviceObject);
  887. ASSERT(IoGetCurrentIrpStackLocation(SystemIrp)->Parameters.Power.Type ==
  888. SystemPowerState);
  889. DebugPrint((2, "SpRequestAdapterPowerCompletion: Adapter %#p, "
  890. "Irp %#p, State %d, Status %#08lx\n",
  891. adapter,
  892. SystemIrp,
  893. PowerState.DeviceState,
  894. IoStatus->Status));
  895. SystemIrp->IoStatus.Status = IoStatus->Status;
  896. if(NT_SUCCESS(status)) {
  897. enable = (state == PowerSystemWorking);
  898. status = SpEnableDisableAdapter(adapter, enable);
  899. DebugPrint((1, "SpRequestAdapterPowerCompletion: %s adapter call "
  900. "returned %#08lx\n",
  901. enable ? "Enable" : "Disable",
  902. status));
  903. ASSERT(status != STATUS_PENDING);
  904. if((NT_SUCCESS(status)) && enable) {
  905. POWER_STATE setState;
  906. setState.SystemState = PowerSystemWorking;
  907. PoSetPowerState(DeviceObject,
  908. SystemPowerState,
  909. setState);
  910. }
  911. }
  912. IoCopyCurrentIrpStackLocationToNext(SystemIrp);
  913. PoStartNextPowerIrp(SystemIrp);
  914. PoCallDriver(adapter->CommonExtension.LowerDeviceObject, SystemIrp);
  915. return;
  916. }
  917. VOID
  918. SpSetTargetDesiredPowerCompletion(
  919. IN PDEVICE_OBJECT DeviceObject,
  920. IN UCHAR MinorFunction,
  921. IN POWER_STATE PowerState,
  922. IN PIRP OriginalIrp,
  923. IN PIO_STATUS_BLOCK IoStatus
  924. )
  925. {
  926. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  927. ASSERT_PDO(DeviceObject);
  928. ASSERT(MinorFunction == IRP_MN_SET_POWER);
  929. ASSERT(NT_SUCCESS(IoStatus->Status));
  930. ASSERT(PowerState.DeviceState == PowerDeviceD0);
  931. ASSERT(commonExtension->CurrentDeviceState == PowerDeviceD0);
  932. ASSERT(commonExtension->DesiredDeviceState == PowerState.DeviceState);
  933. ASSERT(OriginalIrp == NULL);
  934. DebugPrint((4, "SpSetTargetDesiredPowerCompletion: power irp completed "
  935. "with status %#08lx\n", IoStatus->Status));
  936. commonExtension->DesiredDeviceState = PowerDeviceUnspecified;
  937. return;
  938. }
  939. VOID
  940. SpSetTargetDeviceStateLockedCompletion(
  941. IN PDEVICE_OBJECT DeviceObject,
  942. IN NTSTATUS Status,
  943. IN PIRP OriginalIrp
  944. )
  945. /*++
  946. Routine Description:
  947. This routine is called after locking the queue for handling of a device
  948. state. The proper device state is set and an unlock request is sent
  949. to the queue. The OriginalIrp (whatever it may have been) will be
  950. completed after the unlock has been completed.
  951. Arguments:
  952. DeviceObject - the device object
  953. Status - the status of the enable/disable operation
  954. OriginalIrp - the original power irp.
  955. Return Value:
  956. none
  957. --*/
  958. {
  959. PLOGICAL_UNIT_EXTENSION logicalUnit = DeviceObject->DeviceExtension;
  960. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  961. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(OriginalIrp);
  962. ASSERT(irpStack->Parameters.Power.Type == DevicePowerState);
  963. DebugPrint((4, "SpSetTargetDeviceStateLockedCompletion: DO %#p Irp %#p "
  964. "Status %#08lx\n",
  965. DeviceObject, OriginalIrp, Status));
  966. if(NT_SUCCESS(Status)) {
  967. DEVICE_POWER_STATE newState =
  968. irpStack->Parameters.Power.State.DeviceState;
  969. DebugPrint((4, "SpSetTargetDeviceStateLockedCompletion: old device state "
  970. "was %d - new device state is %d\n",
  971. commonExtension->CurrentDeviceState,
  972. irpStack->Parameters.Power.State.DeviceState));
  973. SpAdjustDisabledBit(logicalUnit,
  974. (BOOLEAN) ((newState == PowerDeviceD0) ? TRUE :
  975. FALSE));
  976. commonExtension->CurrentDeviceState = newState;
  977. SpEnableDisableLogicalUnit(
  978. logicalUnit,
  979. TRUE,
  980. SpSetTargetDeviceStateUnlockedCompletion,
  981. OriginalIrp);
  982. return;
  983. }
  984. OriginalIrp->IoStatus.Status = Status;
  985. PoStartNextPowerIrp(OriginalIrp);
  986. IoCompleteRequest(OriginalIrp, IO_NO_INCREMENT);
  987. return;
  988. }
  989. VOID
  990. SpSetTargetDeviceStateUnlockedCompletion(
  991. IN PDEVICE_OBJECT DeviceObject,
  992. IN NTSTATUS Status,
  993. IN PIRP OriginalIrp
  994. )
  995. /*++
  996. Routine Description:
  997. This routine is called after unlocking the queue following the setting
  998. of the new device state. It simply completes the original power request.
  999. Arguments:
  1000. DeviceObject - the device object
  1001. Status - the status of the enable/disable operation
  1002. OriginalIrp - the original power irp.
  1003. Return Value:
  1004. none
  1005. --*/
  1006. {
  1007. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(OriginalIrp);
  1008. ASSERT(irpStack->Parameters.Power.Type == DevicePowerState);
  1009. DebugPrint((4, "SpSetTargetDeviceStateUnlockedCompletion: DO %#p Irp %#p "
  1010. "Status %#08lx\n",
  1011. DeviceObject, OriginalIrp, Status));
  1012. if(NT_SUCCESS(Status) &&
  1013. (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0)) {
  1014. //
  1015. // Power up completed - fire notifications.
  1016. //
  1017. PoSetPowerState(DeviceObject,
  1018. DevicePowerState,
  1019. irpStack->Parameters.Power.State);
  1020. }
  1021. OriginalIrp->IoStatus.Status = Status;
  1022. PoStartNextPowerIrp(OriginalIrp);
  1023. IoCompleteRequest(OriginalIrp, IO_NO_INCREMENT);
  1024. return;
  1025. }
  1026. NTSTATUS
  1027. SpSetTargetDeviceState(
  1028. IN PDEVICE_OBJECT DeviceObject,
  1029. IN PIRP Irp,
  1030. IN DEVICE_POWER_STATE DeviceState
  1031. )
  1032. /*++
  1033. Routine Description:
  1034. Arguments:
  1035. Return Value:
  1036. --*/
  1037. {
  1038. PLOGICAL_UNIT_EXTENSION logicalUnit = DeviceObject->DeviceExtension;
  1039. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  1040. PADAPTER_EXTENSION adapter = logicalUnit->AdapterExtension;
  1041. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1042. BOOLEAN isHibernation;
  1043. NTSTATUS status = STATUS_SUCCESS;
  1044. ASSERT_PDO(DeviceObject);
  1045. ASSERT(irpStack->Parameters.Power.Type == DevicePowerState);
  1046. DebugPrint((4, "SpSetTargetDeviceState: device %#p irp %#p\n",
  1047. DeviceObject, Irp));
  1048. //
  1049. // First check to see if we actually need to touch the queue.
  1050. // If both the current and new state are working or non-working then
  1051. // we don't have a thing to do.
  1052. //
  1053. if(((commonExtension->CurrentDeviceState != PowerDeviceD0) &&
  1054. (DeviceState != PowerDeviceD0)) ||
  1055. (commonExtension->CurrentDeviceState == DeviceState)) {
  1056. DebugPrint((4, "SpSetTargetDeviceState: Transition from D%d to D%d "
  1057. "requires no extra work\n",
  1058. commonExtension->CurrentDeviceState,
  1059. DeviceState));
  1060. commonExtension->CurrentDeviceState = DeviceState;
  1061. return STATUS_SUCCESS;
  1062. }
  1063. //
  1064. // We can't power up the target device if the adapter isn't already
  1065. // powered up.
  1066. //
  1067. if((DeviceState == PowerDeviceD0) &&
  1068. (adapter->CommonExtension.CurrentDeviceState != PowerDeviceD0)) {
  1069. POWER_STATE newAdapterState;
  1070. DebugPrint((1, "SpSetTargetPower: Unable to power up target "
  1071. "before adapter - requesting adapter %#p "
  1072. "powerup\n",
  1073. adapter));
  1074. irpStack->DeviceObject = DeviceObject;
  1075. newAdapterState.DeviceState = PowerDeviceD0;
  1076. return PoRequestPowerIrp(adapter->DeviceObject,
  1077. IRP_MN_SET_POWER,
  1078. newAdapterState,
  1079. SpPowerAdapterForTargetCompletion,
  1080. Irp,
  1081. NULL);
  1082. }
  1083. //
  1084. // Device power operations use queue locks to ensure
  1085. // synchronization with i/o requests. However they never leave
  1086. // the logical unit queue permenantly locked - otherwise we'd be
  1087. // unable to power-up the device when i/o came in. Lock the queue
  1088. // so we can set the power state.
  1089. //
  1090. IoMarkIrpPending(Irp);
  1091. SpEnableDisableLogicalUnit(
  1092. logicalUnit,
  1093. FALSE,
  1094. SpSetTargetDeviceStateLockedCompletion,
  1095. Irp);
  1096. return STATUS_PENDING;
  1097. }
  1098. NTSTATUS
  1099. SpSetTargetSystemState(
  1100. IN PDEVICE_OBJECT DeviceObject,
  1101. IN PIRP Irp,
  1102. IN SYSTEM_POWER_STATE SystemState
  1103. )
  1104. /*++
  1105. Routine Description:
  1106. Arguments:
  1107. Return Value:
  1108. --*/
  1109. {
  1110. PLOGICAL_UNIT_EXTENSION logicalUnit = DeviceObject->DeviceExtension;
  1111. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  1112. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1113. POWER_STATE newDeviceState;
  1114. NTSTATUS status = STATUS_SUCCESS;
  1115. ASSERT_PDO(DeviceObject);
  1116. ASSERT(irpStack->Parameters.Power.Type == SystemPowerState);
  1117. DebugPrint((2, "SpSetTargetSystemState: device %#p irp %#p\n",
  1118. DeviceObject, Irp));
  1119. //
  1120. // First check to see if we actually need to touch the queue.
  1121. // If both the current and new state are working or non-working then
  1122. // we don't have a thing to do.
  1123. //
  1124. if(((commonExtension->CurrentSystemState != PowerSystemWorking) &&
  1125. (SystemState != PowerSystemWorking)) ||
  1126. (commonExtension->CurrentSystemState == SystemState)) {
  1127. DebugPrint((2, "SpSetTargetPower: Transition from S%d to S%d "
  1128. "requires no extra work\n",
  1129. commonExtension->CurrentSystemState,
  1130. SystemState));
  1131. commonExtension->CurrentSystemState = SystemState;
  1132. return STATUS_SUCCESS;
  1133. }
  1134. //
  1135. // Disable the logical unit so we can set it's power state safely.
  1136. //
  1137. IoMarkIrpPending(Irp);
  1138. SpEnableDisableLogicalUnit(
  1139. logicalUnit,
  1140. FALSE,
  1141. SpSetTargetSystemStateLockedCompletion,
  1142. Irp);
  1143. return STATUS_PENDING;
  1144. }
  1145. VOID
  1146. SpSetTargetSystemStateLockedCompletion(
  1147. IN PDEVICE_OBJECT DeviceObject,
  1148. IN NTSTATUS Status,
  1149. IN PIRP PowerIrp
  1150. )
  1151. /*++
  1152. Routine Description:
  1153. This routine is called after the logical unit has been locked and is
  1154. responsible for setting the new system state of the logical unit. If
  1155. the logical unit currently has a desired power state (other than
  1156. unspecified) this routine will request that the device be put into that
  1157. power state after the logical unit is re-enabled.
  1158. Once the work is done this routine will request that the logical unit
  1159. be re-enabled. After that the power irp will be completed.
  1160. Arguments:
  1161. DeviceObject - the device object which has been disabled
  1162. Status - the status of the disable request
  1163. PowerIrp - the power irp we are processing
  1164. Return Value:
  1165. none
  1166. --*/
  1167. {
  1168. PLOGICAL_UNIT_EXTENSION logicalUnit = DeviceObject->DeviceExtension;
  1169. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  1170. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(PowerIrp);
  1171. POWER_STATE_TYPE type = irpStack->Parameters.Power.Type;
  1172. SYSTEM_POWER_STATE state = irpStack->Parameters.Power.State.SystemState;
  1173. POWER_STATE powerState;
  1174. ASSERT_PDO(DeviceObject);
  1175. ASSERT(type == SystemPowerState);
  1176. ASSERT(PowerIrp != NULL);
  1177. DebugPrint((2, "SpSetTargetSystemStateLockedCompletion: DevObj %#p, "
  1178. "Status %#08lx PowerIrp %#p\n",
  1179. DeviceObject, Status, PowerIrp));
  1180. //
  1181. // If the enable/disable failed then the power operation is obviously
  1182. // unsuccessful. Fail the power irp.
  1183. //
  1184. if(!NT_SUCCESS(Status)) {
  1185. ASSERT(FALSE);
  1186. PowerIrp->IoStatus.Status = Status;
  1187. PoStartNextPowerIrp(PowerIrp);
  1188. IoCompleteRequest(PowerIrp, IO_NO_INCREMENT);
  1189. return;
  1190. }
  1191. SpAdjustDisabledBit(
  1192. logicalUnit,
  1193. (BOOLEAN) ((state == PowerSystemWorking) ? TRUE : FALSE));
  1194. commonExtension->CurrentSystemState = state;
  1195. DebugPrint((2, "SpSetTargetSystemStateLockedCompletion: new system state %d "
  1196. "set - desired device state is %d\n",
  1197. state,
  1198. commonExtension->DesiredDeviceState));
  1199. //
  1200. // Re-enable the logical unit. We'll put it into the correct D state
  1201. // after it's been turned back on.
  1202. //
  1203. SpEnableDisableLogicalUnit(logicalUnit,
  1204. TRUE,
  1205. SpSetTargetSystemStateUnlockedCompletion,
  1206. PowerIrp);
  1207. return;
  1208. }
  1209. VOID
  1210. SpSetTargetSystemStateUnlockedCompletion(
  1211. IN PDEVICE_OBJECT DeviceObject,
  1212. IN NTSTATUS Status,
  1213. IN PIRP PowerIrp
  1214. )
  1215. /*++
  1216. Routine Description:
  1217. This routine is called after the system state of the logical unit has been
  1218. set and it has been re-enabled. If the device has a desired power state
  1219. or if it needs to be turned off (or on) for hibernation the power irp
  1220. will be sent from here.
  1221. Arguments:
  1222. DeviceObject - the logical unit which has been unlocked
  1223. Status - the status of the unlock request
  1224. PowerIrp - the original power irp.
  1225. Return Value:
  1226. none
  1227. --*/
  1228. {
  1229. PLOGICAL_UNIT_EXTENSION logicalUnit = DeviceObject->DeviceExtension;
  1230. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  1231. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(PowerIrp);
  1232. POWER_STATE_TYPE type = irpStack->Parameters.Power.Type;
  1233. SYSTEM_POWER_STATE state = irpStack->Parameters.Power.State.SystemState;
  1234. POWER_STATE powerState;
  1235. ASSERT_PDO(DeviceObject);
  1236. ASSERT(type == SystemPowerState);
  1237. ASSERT(PowerIrp != NULL);
  1238. DebugPrint((2, "SpSetTargetSystemStateUnlockedCompletion: DevObj %#p, "
  1239. "Status %#08lx PowerIrp %#p\n",
  1240. DeviceObject, Status, PowerIrp));
  1241. if(!NT_SUCCESS(Status)) {
  1242. //
  1243. // Oh dear - this device couldn't be re-enabled. The logical unit is
  1244. // useless until this can be done.
  1245. //
  1246. //
  1247. // CODEWORK - figure out a way to deal with this case.
  1248. //
  1249. ASSERT(FALSE);
  1250. PowerIrp->IoStatus.Status = Status;
  1251. PoStartNextPowerIrp(PowerIrp);
  1252. IoCompleteRequest(PowerIrp, IO_NO_INCREMENT);
  1253. return;
  1254. }
  1255. if(state == PowerSystemWorking) {
  1256. //
  1257. // We're waking up the system. Check to see if the device needs
  1258. // to be powered immediately as well.
  1259. //
  1260. //
  1261. // Power up - fire notifications.
  1262. //
  1263. powerState.SystemState = state;
  1264. PoSetPowerState(DeviceObject,
  1265. SystemPowerState,
  1266. powerState);
  1267. if(commonExtension->DesiredDeviceState != PowerDeviceUnspecified) {
  1268. //
  1269. // Request a power up of the target device now. We'll complete
  1270. // the system irp immediately without waiting for the device irp
  1271. // to finish.
  1272. //
  1273. powerState.DeviceState = commonExtension->DesiredDeviceState;
  1274. DebugPrint((1, "SpSetTargetSystemStateUnlockedCompletion: Target has "
  1275. "desired device state of %d - issuing irp to "
  1276. "request transition\n",
  1277. powerState.DeviceState));
  1278. Status = PoRequestPowerIrp(DeviceObject,
  1279. IRP_MN_SET_POWER,
  1280. powerState,
  1281. SpSetTargetDesiredPowerCompletion,
  1282. NULL,
  1283. NULL);
  1284. ASSERT(Status == STATUS_PENDING);
  1285. }
  1286. if(Status != STATUS_PENDING) {
  1287. PowerIrp->IoStatus.Status = Status;
  1288. } else {
  1289. PowerIrp->IoStatus.Status = STATUS_SUCCESS;
  1290. }
  1291. PoStartNextPowerIrp(PowerIrp);
  1292. IoCompleteRequest(PowerIrp, IO_NO_INCREMENT);
  1293. } else {
  1294. //
  1295. // We're going to put the device into a D state based on the current
  1296. // S state.
  1297. //
  1298. DebugPrint((2, "SpSetTargetSystemStateUnlockedCompletion: power down "
  1299. "target for non-working system state "
  1300. "transition\n"));
  1301. powerState.DeviceState = PowerDeviceD3;
  1302. //
  1303. // Request the appropriate D irp. We'll block the S irp until the
  1304. // D transition has been completed.
  1305. //
  1306. Status = PoRequestPowerIrp(
  1307. DeviceObject,
  1308. IRP_MN_SET_POWER,
  1309. powerState,
  1310. SpSetTargetDeviceStateForSystemStateCompletion,
  1311. PowerIrp,
  1312. NULL);
  1313. if(!NT_SUCCESS(Status)) {
  1314. //
  1315. // STATUS_PENDING is still successful.
  1316. //
  1317. PowerIrp->IoStatus.Status = Status;
  1318. PoStartNextPowerIrp(PowerIrp);
  1319. IoCompleteRequest(PowerIrp, IO_NO_INCREMENT);
  1320. }
  1321. }
  1322. return;
  1323. }
  1324. VOID
  1325. SpSetTargetDeviceStateForSystemStateCompletion(
  1326. IN PDEVICE_OBJECT DeviceObject,
  1327. IN UCHAR MinorFunction,
  1328. IN POWER_STATE PowerState,
  1329. IN PIRP OriginalIrp,
  1330. IN PIO_STATUS_BLOCK IoStatus
  1331. )
  1332. {
  1333. PIO_STACK_LOCATION irpStack;
  1334. irpStack = IoGetCurrentIrpStackLocation(OriginalIrp);
  1335. ASSERT_PDO(DeviceObject);
  1336. ASSERT(irpStack->Parameters.Power.Type == SystemPowerState);
  1337. ASSERT(irpStack->Parameters.Power.State.SystemState != PowerSystemWorking);
  1338. DebugPrint((2, "SpSetTargetDeviceStateForSystemCompletion: DevObj %#p, "
  1339. "Irp %#p, Status %#08lx\n",
  1340. DeviceObject, OriginalIrp, IoStatus));
  1341. OriginalIrp->IoStatus.Status = IoStatus->Status;
  1342. PoStartNextPowerIrp(OriginalIrp);
  1343. IoCompleteRequest(OriginalIrp, IO_NO_INCREMENT);
  1344. return;
  1345. }
  1346. VOID
  1347. SpRequestValidPowerStateCompletion (
  1348. IN PDEVICE_OBJECT DeviceObject,
  1349. IN UCHAR MinorFunction,
  1350. IN POWER_STATE PowerState,
  1351. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  1352. IN PIO_STATUS_BLOCK IoStatus
  1353. )
  1354. {
  1355. //
  1356. // re-enable the logical unit. Don't bother with a completion routine
  1357. // because there's nothing to do.
  1358. //
  1359. ASSERT(NT_SUCCESS(IoStatus->Status));
  1360. SpEnableDisableLogicalUnit(LogicalUnit, TRUE, NULL, NULL);
  1361. return;
  1362. }
  1363. NTSTATUS
  1364. SpRequestValidAdapterPowerStateSynchronous(
  1365. IN PADAPTER_EXTENSION Adapter
  1366. )
  1367. {
  1368. PCOMMON_EXTENSION commonExtension = &(Adapter->CommonExtension);
  1369. NTSTATUS status = STATUS_SUCCESS;
  1370. //
  1371. // Interlock with other calls to this routine - there's no reason to have
  1372. // several D0 irps in flight at any given time.
  1373. //
  1374. ExAcquireFastMutex(&(Adapter->PowerMutex));
  1375. try {
  1376. //
  1377. // Check to see if we're already in a working state. If so we can just
  1378. // continue.
  1379. //
  1380. if((commonExtension->CurrentSystemState == PowerSystemWorking) &&
  1381. (commonExtension->CurrentDeviceState == PowerDeviceD0)) {
  1382. leave;
  1383. }
  1384. //
  1385. // First check the system state. If the device is in a non-working system
  1386. // state then we'll need to block waiting for the system to wake up.
  1387. //
  1388. if(commonExtension->CurrentSystemState != PowerSystemWorking) {
  1389. //
  1390. // If we're not in a system working state then fail the attempt
  1391. // to set a new device state. The caller should retry when the
  1392. // system is powered on. Ideally we won't be getting requests
  1393. // which cause us to try and power up while the system is
  1394. // suspended.
  1395. //
  1396. status = STATUS_UNSUCCESSFUL;
  1397. leave;
  1398. }
  1399. //
  1400. // Request a power change request.
  1401. //
  1402. {
  1403. POWER_STATE newAdapterState;
  1404. SP_SIGNAL_POWER_COMPLETION_CONTEXT context;
  1405. DebugPrint((1, "SpRequestValidAdapterPowerState: Requesting D0 power "
  1406. "irp for adapter %p\n", Adapter));
  1407. newAdapterState.DeviceState = PowerDeviceD0;
  1408. KeInitializeEvent(&(context.Event), SynchronizationEvent, FALSE);
  1409. status = PoRequestPowerIrp(Adapter->DeviceObject,
  1410. IRP_MN_SET_POWER,
  1411. newAdapterState,
  1412. SpSignalPowerCompletion,
  1413. &context,
  1414. NULL);
  1415. if(status == STATUS_PENDING) {
  1416. KeWaitForSingleObject(&(context.Event),
  1417. KernelMode,
  1418. Executive,
  1419. FALSE,
  1420. NULL);
  1421. }
  1422. status = context.Status;
  1423. leave;
  1424. }
  1425. } finally {
  1426. ExReleaseFastMutex(&(Adapter->PowerMutex));
  1427. }
  1428. return status;
  1429. }
  1430. VOID
  1431. SpSignalPowerCompletion(
  1432. IN PDEVICE_OBJECT DeviceObject,
  1433. IN UCHAR MinorFunction,
  1434. IN POWER_STATE PowerState,
  1435. IN PSP_SIGNAL_POWER_COMPLETION_CONTEXT Context,
  1436. IN PIO_STATUS_BLOCK IoStatus
  1437. )
  1438. {
  1439. Context->Status = IoStatus->Status;
  1440. KeSetEvent(&(Context->Event), IO_NO_INCREMENT, FALSE);
  1441. return;
  1442. }