PageRenderTime 57ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/storage/classpnp/power.c

https://bitbucket.org/arty/arty-newcc-reactos
C | 1602 lines | 820 code | 360 blank | 422 comment | 103 complexity | 24a06aa7e7a7a211029f3b02be5aabb1 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-3.0, CC-BY-SA-3.0, AGPL-3.0, GPL-3.0, CPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. class.c
  5. Abstract:
  6. SCSI class driver routines
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. --*/
  12. #include "classp.h"
  13. #define CLASS_TAG_POWER 'WLcS'
  14. NTSTATUS
  15. ClasspPowerHandler(
  16. IN PDEVICE_OBJECT DeviceObject,
  17. IN PIRP Irp,
  18. IN CLASS_POWER_OPTIONS Options
  19. );
  20. NTSTATUS
  21. ClasspPowerDownCompletion(
  22. IN PDEVICE_OBJECT DeviceObject,
  23. IN PIRP Irp,
  24. IN PCLASS_POWER_CONTEXT Context
  25. );
  26. NTSTATUS
  27. ClasspPowerUpCompletion(
  28. IN PDEVICE_OBJECT DeviceObject,
  29. IN PIRP Irp,
  30. IN PCLASS_POWER_CONTEXT Context
  31. );
  32. VOID
  33. RetryPowerRequest(
  34. PDEVICE_OBJECT DeviceObject,
  35. PIRP Irp,
  36. PCLASS_POWER_CONTEXT Context
  37. );
  38. NTSTATUS
  39. ClasspStartNextPowerIrpCompletion(
  40. IN PDEVICE_OBJECT DeviceObject,
  41. IN PIRP Irp,
  42. IN PVOID Context
  43. );
  44. /*++////////////////////////////////////////////////////////////////////////////
  45. ClassDispatchPower()
  46. Routine Description:
  47. This routine acquires the removelock for the irp and then calls the
  48. appropriate power callback.
  49. Arguments:
  50. DeviceObject -
  51. Irp -
  52. Return Value:
  53. --*/
  54. NTSTATUS
  55. ClassDispatchPower(
  56. IN PDEVICE_OBJECT DeviceObject,
  57. IN PIRP Irp
  58. )
  59. {
  60. PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  61. ULONG isRemoved;
  62. PCLASS_POWER_DEVICE powerRoutine = NULL;
  63. //
  64. // NOTE: This code may be called at PASSIVE or DISPATCH, depending
  65. // upon the device object it is being called for.
  66. // don't do anything that would break under either circumstance.
  67. //
  68. NTSTATUS status;
  69. isRemoved = ClassAcquireRemoveLock(DeviceObject, Irp);
  70. if(isRemoved) {
  71. ClassReleaseRemoveLock(DeviceObject, Irp);
  72. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  73. PoStartNextPowerIrp(Irp);
  74. ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
  75. return STATUS_DEVICE_DOES_NOT_EXIST;
  76. }
  77. return commonExtension->DevInfo->ClassPowerDevice(DeviceObject, Irp);
  78. } // end ClassDispatchPower()
  79. /*++////////////////////////////////////////////////////////////////////////////
  80. ClasspPowerUpCompletion()
  81. Routine Description:
  82. This routine is used for intermediate completion of a power up request.
  83. PowerUp requires four requests to be sent to the lower driver in sequence.
  84. * The queue is "power locked" to ensure that the class driver power-up
  85. work can be done before request processing resumes.
  86. * The power irp is sent down the stack for any filter drivers and the
  87. port driver to return power and resume command processing for the
  88. device. Since the queue is locked, no queued irps will be sent
  89. immediately.
  90. * A start unit command is issued to the device with appropriate flags
  91. to override the "power locked" queue.
  92. * The queue is "power unlocked" to start processing requests again.
  93. This routine uses the function in the srb which just completed to determine
  94. which state it is in.
  95. Arguments:
  96. DeviceObject - the device object being powered up
  97. Irp - the IO_REQUEST_PACKET containing the power request
  98. Srb - the SRB used to perform port/class operations.
  99. Return Value:
  100. STATUS_MORE_PROCESSING_REQUIRED or
  101. STATUS_SUCCESS
  102. --*/
  103. NTSTATUS
  104. ClasspPowerUpCompletion(
  105. IN PDEVICE_OBJECT DeviceObject,
  106. IN PIRP Irp,
  107. IN PCLASS_POWER_CONTEXT Context
  108. )
  109. {
  110. PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  111. PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  112. PIO_STACK_LOCATION currentStack = IoGetCurrentIrpStackLocation(Irp);
  113. PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation(Irp);
  114. NTSTATUS status = STATUS_MORE_PROCESSING_REQUIRED;
  115. DebugPrint((1, "ClasspPowerUpCompletion: Device Object %p, Irp %p, "
  116. "Context %p\n",
  117. DeviceObject, Irp, Context));
  118. ASSERT(!TEST_FLAG(Context->Srb.SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
  119. ASSERT(!TEST_FLAG(Context->Srb.SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
  120. ASSERT(Context->Options.PowerDown == FALSE);
  121. ASSERT(Context->Options.HandleSpinUp);
  122. if(Irp->PendingReturned) {
  123. IoMarkIrpPending(Irp);
  124. }
  125. Context->PowerChangeState.PowerUp++;
  126. switch(Context->PowerChangeState.PowerUp) {
  127. case PowerUpDeviceLocked: {
  128. DebugPrint((1, "(%p)\tPreviously sent power lock\n", Irp));
  129. //
  130. // Issue the actual power request to the lower driver.
  131. //
  132. IoCopyCurrentIrpStackLocationToNext(Irp);
  133. //
  134. // If the lock wasn't successful then just bail out on the power
  135. // request unless we can ignore failed locks
  136. //
  137. if((Context->Options.LockQueue == TRUE) &&
  138. (!NT_SUCCESS(Irp->IoStatus.Status))) {
  139. DebugPrint((1, "(%p)\tIrp status was %lx\n",
  140. Irp, Irp->IoStatus.Status));
  141. DebugPrint((1, "(%p)\tSrb status was %lx\n",
  142. Irp, Context->Srb.SrbStatus));
  143. //
  144. // Lock was not successful - throw down the power IRP
  145. // by itself and don't try to spin up the drive or unlock
  146. // the queue.
  147. //
  148. Context->InUse = FALSE;
  149. Context = NULL;
  150. //
  151. // Set the new power state
  152. //
  153. fdoExtension->DevicePowerState =
  154. currentStack->Parameters.Power.State.DeviceState;
  155. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  156. IoCopyCurrentIrpStackLocationToNext(Irp);
  157. IoSetCompletionRoutine(Irp,
  158. ClasspStartNextPowerIrpCompletion,
  159. NULL,
  160. TRUE,
  161. TRUE,
  162. TRUE);
  163. //
  164. // Indicate to Po that we've been successfully powered up so
  165. // it can do it's notification stuff.
  166. //
  167. PoSetPowerState(DeviceObject,
  168. currentStack->Parameters.Power.Type,
  169. currentStack->Parameters.Power.State);
  170. PoCallDriver(commonExtension->LowerDeviceObject, Irp);
  171. ClassReleaseRemoveLock(commonExtension->DeviceObject,
  172. Irp);
  173. return STATUS_MORE_PROCESSING_REQUIRED;
  174. } else {
  175. Context->QueueLocked = (UCHAR) Context->Options.LockQueue;
  176. }
  177. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  178. Context->PowerChangeState.PowerUp = PowerUpDeviceLocked;
  179. IoSetCompletionRoutine(Irp,
  180. ClasspPowerUpCompletion,
  181. Context,
  182. TRUE,
  183. TRUE,
  184. TRUE);
  185. status = PoCallDriver(commonExtension->LowerDeviceObject, Irp);
  186. DebugPrint((2, "(%p)\tPoCallDriver returned %lx\n", Irp, status));
  187. break;
  188. }
  189. case PowerUpDeviceOn: {
  190. PCDB cdb;
  191. if(NT_SUCCESS(Irp->IoStatus.Status)) {
  192. DebugPrint((1, "(%p)\tSending start unit to device\n", Irp));
  193. //
  194. // Issue the start unit command to the device.
  195. //
  196. Context->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
  197. Context->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
  198. Context->Srb.SrbStatus = Context->Srb.ScsiStatus = 0;
  199. Context->Srb.DataTransferLength = 0;
  200. Context->Srb.TimeOutValue = START_UNIT_TIMEOUT;
  201. Context->Srb.SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER |
  202. SRB_FLAGS_DISABLE_AUTOSENSE |
  203. SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
  204. SRB_FLAGS_NO_QUEUE_FREEZE;
  205. if(Context->Options.LockQueue) {
  206. SET_FLAG(Context->Srb.SrbFlags, SRB_FLAGS_BYPASS_LOCKED_QUEUE);
  207. }
  208. Context->Srb.CdbLength = 6;
  209. cdb = (PCDB) (Context->Srb.Cdb);
  210. RtlZeroMemory(cdb, sizeof(CDB));
  211. cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
  212. cdb->START_STOP.Start = 1;
  213. Context->PowerChangeState.PowerUp = PowerUpDeviceOn;
  214. IoSetCompletionRoutine(Irp,
  215. ClasspPowerUpCompletion,
  216. Context,
  217. TRUE,
  218. TRUE,
  219. TRUE);
  220. nextStack->Parameters.Scsi.Srb = &(Context->Srb);
  221. nextStack->MajorFunction = IRP_MJ_SCSI;
  222. status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
  223. DebugPrint((2, "(%p)\tIoCallDriver returned %lx\n", Irp, status));
  224. } else {
  225. //
  226. // we're done.
  227. //
  228. Context->FinalStatus = Irp->IoStatus.Status;
  229. goto ClasspPowerUpCompletionFailure;
  230. }
  231. break;
  232. }
  233. case PowerUpDeviceStarted: { // 3
  234. //
  235. // First deal with an error if one occurred.
  236. //
  237. if(SRB_STATUS(Context->Srb.SrbStatus) != SRB_STATUS_SUCCESS) {
  238. BOOLEAN retry;
  239. DebugPrint((1, "%p\tError occured when issuing START_UNIT "
  240. "command to device. Srb %p, Status %x\n",
  241. Irp,
  242. &Context->Srb,
  243. Context->Srb.SrbStatus));
  244. ASSERT(!(TEST_FLAG(Context->Srb.SrbStatus,
  245. SRB_STATUS_QUEUE_FROZEN)));
  246. ASSERT(Context->Srb.Function == SRB_FUNCTION_EXECUTE_SCSI);
  247. Context->RetryInterval = 0;
  248. retry = ClassInterpretSenseInfo(
  249. commonExtension->DeviceObject,
  250. &Context->Srb,
  251. IRP_MJ_SCSI,
  252. IRP_MJ_POWER,
  253. MAXIMUM_RETRIES - Context->RetryCount,
  254. &status,
  255. &Context->RetryInterval);
  256. if((retry == TRUE) && (Context->RetryCount-- != 0)) {
  257. DebugPrint((1, "(%p)\tRetrying failed request\n", Irp));
  258. //
  259. // Decrement the state so we come back through here the
  260. // next time.
  261. //
  262. Context->PowerChangeState.PowerUp--;
  263. RetryPowerRequest(commonExtension->DeviceObject,
  264. Irp,
  265. Context);
  266. break;
  267. }
  268. // reset retries
  269. Context->RetryCount = MAXIMUM_RETRIES;
  270. }
  271. ClasspPowerUpCompletionFailure:
  272. DebugPrint((1, "(%p)\tPreviously spun device up\n", Irp));
  273. if (Context->QueueLocked) {
  274. DebugPrint((1, "(%p)\tUnlocking queue\n", Irp));
  275. Context->Srb.Function = SRB_FUNCTION_UNLOCK_QUEUE;
  276. Context->Srb.SrbFlags = SRB_FLAGS_BYPASS_LOCKED_QUEUE;
  277. Context->Srb.SrbStatus = Context->Srb.ScsiStatus = 0;
  278. Context->Srb.DataTransferLength = 0;
  279. nextStack->Parameters.Scsi.Srb = &(Context->Srb);
  280. nextStack->MajorFunction = IRP_MJ_SCSI;
  281. Context->PowerChangeState.PowerUp = PowerUpDeviceStarted;
  282. IoSetCompletionRoutine(Irp,
  283. ClasspPowerUpCompletion,
  284. Context,
  285. TRUE,
  286. TRUE,
  287. TRUE);
  288. status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
  289. DebugPrint((1, "(%p)\tIoCallDriver returned %lx\n",
  290. Irp, status));
  291. break;
  292. }
  293. // Fall-through to next case...
  294. }
  295. case PowerUpDeviceUnlocked: {
  296. //
  297. // This is the end of the dance. Free the srb and complete the
  298. // request finally. We're ignoring possible intermediate
  299. // error conditions ....
  300. //
  301. if (Context->QueueLocked) {
  302. DebugPrint((1, "(%p)\tPreviously unlocked queue\n", Irp));
  303. ASSERT(NT_SUCCESS(Irp->IoStatus.Status));
  304. ASSERT(Context->Srb.SrbStatus == SRB_STATUS_SUCCESS);
  305. } else {
  306. DebugPrint((1, "(%p)\tFall-through (queue not locked)\n", Irp));
  307. }
  308. DebugPrint((1, "(%p)\tFreeing srb and completing\n", Irp));
  309. Context->InUse = FALSE;
  310. status = Context->FinalStatus;
  311. Irp->IoStatus.Status = status;
  312. Context = NULL;
  313. //
  314. // Set the new power state
  315. //
  316. if(NT_SUCCESS(status)) {
  317. fdoExtension->DevicePowerState =
  318. currentStack->Parameters.Power.State.DeviceState;
  319. }
  320. //
  321. // Indicate to Po that we've been successfully powered up so
  322. // it can do it's notification stuff.
  323. //
  324. PoSetPowerState(DeviceObject,
  325. currentStack->Parameters.Power.Type,
  326. currentStack->Parameters.Power.State);
  327. DebugPrint((1, "(%p)\tStarting next power irp\n", Irp));
  328. ClassReleaseRemoveLock(DeviceObject, Irp);
  329. PoStartNextPowerIrp(Irp);
  330. return status;
  331. }
  332. }
  333. return STATUS_MORE_PROCESSING_REQUIRED;
  334. } // end ClasspPowerUpCompletion()
  335. /*++////////////////////////////////////////////////////////////////////////////
  336. ClasspPowerDownCompletion()
  337. Routine Description:
  338. This routine is used for intermediate completion of a power up request.
  339. PowerUp requires four requests to be sent to the lower driver in sequence.
  340. * The queue is "power locked" to ensure that the class driver power-up
  341. work can be done before request processing resumes.
  342. * The power irp is sent down the stack for any filter drivers and the
  343. port driver to return power and resume command processing for the
  344. device. Since the queue is locked, no queued irps will be sent
  345. immediately.
  346. * A start unit command is issued to the device with appropriate flags
  347. to override the "power locked" queue.
  348. * The queue is "power unlocked" to start processing requests again.
  349. This routine uses the function in the srb which just completed to determine
  350. which state it is in.
  351. Arguments:
  352. DeviceObject - the device object being powered up
  353. Irp - the IO_REQUEST_PACKET containing the power request
  354. Srb - the SRB used to perform port/class operations.
  355. Return Value:
  356. STATUS_MORE_PROCESSING_REQUIRED or
  357. STATUS_SUCCESS
  358. --*/
  359. NTSTATUS
  360. ClasspPowerDownCompletion(
  361. IN PDEVICE_OBJECT DeviceObject,
  362. IN PIRP Irp,
  363. IN PCLASS_POWER_CONTEXT Context
  364. )
  365. {
  366. PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  367. PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  368. PIO_STACK_LOCATION currentStack = IoGetCurrentIrpStackLocation(Irp);
  369. PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation(Irp);
  370. NTSTATUS status = STATUS_MORE_PROCESSING_REQUIRED;
  371. DebugPrint((1, "ClasspPowerDownCompletion: Device Object %p, "
  372. "Irp %p, Context %p\n",
  373. DeviceObject, Irp, Context));
  374. ASSERT(!TEST_FLAG(Context->Srb.SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
  375. ASSERT(!TEST_FLAG(Context->Srb.SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
  376. ASSERT(Context->Options.PowerDown == TRUE);
  377. ASSERT(Context->Options.HandleSpinDown);
  378. if(Irp->PendingReturned) {
  379. IoMarkIrpPending(Irp);
  380. }
  381. Context->PowerChangeState.PowerDown2++;
  382. switch(Context->PowerChangeState.PowerDown2) {
  383. case PowerDownDeviceLocked2: {
  384. PCDB cdb;
  385. DebugPrint((1, "(%p)\tPreviously sent power lock\n", Irp));
  386. if((Context->Options.LockQueue == TRUE) &&
  387. (!NT_SUCCESS(Irp->IoStatus.Status))) {
  388. DebugPrint((1, "(%p)\tIrp status was %lx\n",
  389. Irp,
  390. Irp->IoStatus.Status));
  391. DebugPrint((1, "(%p)\tSrb status was %lx\n",
  392. Irp,
  393. Context->Srb.SrbStatus));
  394. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  395. //
  396. // Lock was not successful - throw down the power IRP
  397. // by itself and don't try to spin down the drive or unlock
  398. // the queue.
  399. //
  400. Context->InUse = FALSE;
  401. Context = NULL;
  402. //
  403. // Set the new power state
  404. //
  405. fdoExtension->DevicePowerState =
  406. currentStack->Parameters.Power.State.DeviceState;
  407. //
  408. // Indicate to Po that we've been successfully powered down
  409. // so it can do it's notification stuff.
  410. //
  411. IoCopyCurrentIrpStackLocationToNext(Irp);
  412. IoSetCompletionRoutine(Irp,
  413. ClasspStartNextPowerIrpCompletion,
  414. NULL,
  415. TRUE,
  416. TRUE,
  417. TRUE);
  418. PoSetPowerState(DeviceObject,
  419. currentStack->Parameters.Power.Type,
  420. currentStack->Parameters.Power.State);
  421. fdoExtension->PowerDownInProgress = FALSE;
  422. PoCallDriver(commonExtension->LowerDeviceObject, Irp);
  423. ClassReleaseRemoveLock(commonExtension->DeviceObject,
  424. Irp);
  425. return STATUS_MORE_PROCESSING_REQUIRED;
  426. } else {
  427. Context->QueueLocked = (UCHAR) Context->Options.LockQueue;
  428. }
  429. if (!TEST_FLAG(fdoExtension->PrivateFdoData->HackFlags,
  430. FDO_HACK_NO_SYNC_CACHE)) {
  431. //
  432. // send SCSIOP_SYNCHRONIZE_CACHE
  433. //
  434. Context->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
  435. Context->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
  436. Context->Srb.TimeOutValue = fdoExtension->TimeOutValue;
  437. Context->Srb.SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER |
  438. SRB_FLAGS_DISABLE_AUTOSENSE |
  439. SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
  440. SRB_FLAGS_NO_QUEUE_FREEZE |
  441. SRB_FLAGS_BYPASS_LOCKED_QUEUE;
  442. Context->Srb.SrbStatus = Context->Srb.ScsiStatus = 0;
  443. Context->Srb.DataTransferLength = 0;
  444. Context->Srb.CdbLength = 10;
  445. cdb = (PCDB) Context->Srb.Cdb;
  446. RtlZeroMemory(cdb, sizeof(CDB));
  447. cdb->SYNCHRONIZE_CACHE10.OperationCode = SCSIOP_SYNCHRONIZE_CACHE;
  448. IoSetCompletionRoutine(Irp,
  449. ClasspPowerDownCompletion,
  450. Context,
  451. TRUE,
  452. TRUE,
  453. TRUE);
  454. nextStack->Parameters.Scsi.Srb = &(Context->Srb);
  455. nextStack->MajorFunction = IRP_MJ_SCSI;
  456. status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
  457. DebugPrint((1, "(%p)\tIoCallDriver returned %lx\n", Irp, status));
  458. break;
  459. } else {
  460. DebugPrint((1, "(%p)\tPower Down: not sending SYNCH_CACHE\n",
  461. DeviceObject));
  462. Context->PowerChangeState.PowerDown2++;
  463. Context->Srb.SrbStatus = SRB_STATUS_SUCCESS;
  464. // and fall through....
  465. }
  466. // no break in case the device doesn't like synch_cache commands
  467. }
  468. case PowerDownDeviceFlushed2: {
  469. PCDB cdb;
  470. DebugPrint((1, "(%p)\tPreviously send SCSIOP_SYNCHRONIZE_CACHE\n",
  471. Irp));
  472. //
  473. // SCSIOP_SYNCHRONIZE_CACHE was sent
  474. //
  475. if(SRB_STATUS(Context->Srb.SrbStatus) != SRB_STATUS_SUCCESS) {
  476. BOOLEAN retry;
  477. DebugPrint((1, "(%p)\tError occured when issuing "
  478. "SYNCHRONIZE_CACHE command to device. "
  479. "Srb %p, Status %lx\n",
  480. Irp,
  481. &Context->Srb,
  482. Context->Srb.SrbStatus));
  483. ASSERT(!(TEST_FLAG(Context->Srb.SrbStatus,
  484. SRB_STATUS_QUEUE_FROZEN)));
  485. ASSERT(Context->Srb.Function == SRB_FUNCTION_EXECUTE_SCSI);
  486. Context->RetryInterval = 0;
  487. retry = ClassInterpretSenseInfo(
  488. commonExtension->DeviceObject,
  489. &Context->Srb,
  490. IRP_MJ_SCSI,
  491. IRP_MJ_POWER,
  492. MAXIMUM_RETRIES - Context->RetryCount,
  493. &status,
  494. &Context->RetryInterval);
  495. if((retry == TRUE) && (Context->RetryCount-- != 0)) {
  496. DebugPrint((1, "(%p)\tRetrying failed request\n", Irp));
  497. //
  498. // decrement the state so we come back through here
  499. // the next time.
  500. //
  501. Context->PowerChangeState.PowerDown2--;
  502. RetryPowerRequest(commonExtension->DeviceObject,
  503. Irp,
  504. Context);
  505. break;
  506. }
  507. DebugPrint((1, "(%p)\tSYNCHRONIZE_CACHE not retried\n", Irp));
  508. Context->RetryCount = MAXIMUM_RETRIES;
  509. } // end !SRB_STATUS_SUCCESS
  510. //
  511. // note: we are purposefully ignoring any errors. if the drive
  512. // doesn't support a synch_cache, then we're up a creek
  513. // anyways.
  514. //
  515. DebugPrint((1, "(%p)\tSending stop unit to device\n", Irp));
  516. //
  517. // Issue the start unit command to the device.
  518. //
  519. Context->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
  520. Context->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
  521. Context->Srb.TimeOutValue = START_UNIT_TIMEOUT;
  522. Context->Srb.SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER |
  523. SRB_FLAGS_DISABLE_AUTOSENSE |
  524. SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
  525. SRB_FLAGS_NO_QUEUE_FREEZE |
  526. SRB_FLAGS_BYPASS_LOCKED_QUEUE;
  527. Context->Srb.SrbStatus = Context->Srb.ScsiStatus = 0;
  528. Context->Srb.DataTransferLength = 0;
  529. Context->Srb.CdbLength = 6;
  530. cdb = (PCDB) Context->Srb.Cdb;
  531. RtlZeroMemory(cdb, sizeof(CDB));
  532. cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
  533. cdb->START_STOP.Start = 0;
  534. cdb->START_STOP.Immediate = 1;
  535. IoSetCompletionRoutine(Irp,
  536. ClasspPowerDownCompletion,
  537. Context,
  538. TRUE,
  539. TRUE,
  540. TRUE);
  541. nextStack->Parameters.Scsi.Srb = &(Context->Srb);
  542. nextStack->MajorFunction = IRP_MJ_SCSI;
  543. status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
  544. DebugPrint((1, "(%p)\tIoCallDriver returned %lx\n", Irp, status));
  545. break;
  546. }
  547. case PowerDownDeviceStopped2: {
  548. BOOLEAN ignoreError = TRUE;
  549. //
  550. // stop was sent
  551. //
  552. if(SRB_STATUS(Context->Srb.SrbStatus) != SRB_STATUS_SUCCESS) {
  553. BOOLEAN retry;
  554. DebugPrint((1, "(%p)\tError occured when issueing STOP_UNIT "
  555. "command to device. Srb %p, Status %lx\n",
  556. Irp,
  557. &Context->Srb,
  558. Context->Srb.SrbStatus));
  559. ASSERT(!(TEST_FLAG(Context->Srb.SrbStatus,
  560. SRB_STATUS_QUEUE_FROZEN)));
  561. ASSERT(Context->Srb.Function == SRB_FUNCTION_EXECUTE_SCSI);
  562. Context->RetryInterval = 0;
  563. retry = ClassInterpretSenseInfo(
  564. commonExtension->DeviceObject,
  565. &Context->Srb,
  566. IRP_MJ_SCSI,
  567. IRP_MJ_POWER,
  568. MAXIMUM_RETRIES - Context->RetryCount,
  569. &status,
  570. &Context->RetryInterval);
  571. if((retry == TRUE) && (Context->RetryCount-- != 0)) {
  572. DebugPrint((1, "(%p)\tRetrying failed request\n", Irp));
  573. //
  574. // decrement the state so we come back through here
  575. // the next time.
  576. //
  577. Context->PowerChangeState.PowerDown2--;
  578. RetryPowerRequest(commonExtension->DeviceObject,
  579. Irp,
  580. Context);
  581. break;
  582. }
  583. DebugPrint((1, "(%p)\tSTOP_UNIT not retried\n", Irp));
  584. Context->RetryCount = MAXIMUM_RETRIES;
  585. } // end !SRB_STATUS_SUCCESS
  586. DebugPrint((1, "(%p)\tPreviously sent stop unit\n", Irp));
  587. //
  588. // some operations, such as a physical format in progress,
  589. // should not be ignored and should fail the power operation.
  590. //
  591. if (!NT_SUCCESS(status)) {
  592. PSENSE_DATA senseBuffer = Context->Srb.SenseInfoBuffer;
  593. if (TEST_FLAG(Context->Srb.SrbStatus,
  594. SRB_STATUS_AUTOSENSE_VALID) &&
  595. ((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_NOT_READY) &&
  596. (senseBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) &&
  597. (senseBuffer->AdditionalSenseCodeQualifier == SCSI_SENSEQ_FORMAT_IN_PROGRESS)
  598. ) {
  599. ignoreError = FALSE;
  600. Context->FinalStatus = STATUS_DEVICE_BUSY;
  601. status = Context->FinalStatus;
  602. }
  603. }
  604. if (NT_SUCCESS(status) || ignoreError) {
  605. //
  606. // Issue the actual power request to the lower driver.
  607. //
  608. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  609. IoCopyCurrentIrpStackLocationToNext(Irp);
  610. IoSetCompletionRoutine(Irp,
  611. ClasspPowerDownCompletion,
  612. Context,
  613. TRUE,
  614. TRUE,
  615. TRUE);
  616. status = PoCallDriver(commonExtension->LowerDeviceObject, Irp);
  617. DebugPrint((1, "(%p)\tPoCallDriver returned %lx\n", Irp, status));
  618. break;
  619. }
  620. // else fall through w/o sending the power irp, since the device
  621. // is reporting an error that would be "really bad" to power down
  622. // during.
  623. }
  624. case PowerDownDeviceOff2: {
  625. //
  626. // SpinDown request completed ... whether it succeeded or not is
  627. // another matter entirely.
  628. //
  629. DebugPrint((1, "(%p)\tPreviously sent power irp\n", Irp));
  630. if (Context->QueueLocked) {
  631. DebugPrint((1, "(%p)\tUnlocking queue\n", Irp));
  632. Context->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
  633. Context->Srb.SrbStatus = Context->Srb.ScsiStatus = 0;
  634. Context->Srb.DataTransferLength = 0;
  635. Context->Srb.Function = SRB_FUNCTION_UNLOCK_QUEUE;
  636. Context->Srb.SrbFlags = SRB_FLAGS_BYPASS_LOCKED_QUEUE;
  637. nextStack->Parameters.Scsi.Srb = &(Context->Srb);
  638. nextStack->MajorFunction = IRP_MJ_SCSI;
  639. IoSetCompletionRoutine(Irp,
  640. ClasspPowerDownCompletion,
  641. Context,
  642. TRUE,
  643. TRUE,
  644. TRUE);
  645. status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
  646. DebugPrint((1, "(%p)\tIoCallDriver returned %lx\n",
  647. Irp,
  648. status));
  649. break;
  650. }
  651. }
  652. case PowerDownDeviceUnlocked2: {
  653. //
  654. // This is the end of the dance. Free the srb and complete the
  655. // request finally. We're ignoring possible intermediate
  656. // error conditions ....
  657. //
  658. if (Context->QueueLocked == FALSE) {
  659. DebugPrint((1, "(%p)\tFall through (queue not locked)\n", Irp));
  660. } else {
  661. DebugPrint((1, "(%p)\tPreviously unlocked queue\n", Irp));
  662. ASSERT(NT_SUCCESS(Irp->IoStatus.Status));
  663. ASSERT(Context->Srb.SrbStatus == SRB_STATUS_SUCCESS);
  664. }
  665. DebugPrint((1, "(%p)\tFreeing srb and completing\n", Irp));
  666. Context->InUse = FALSE;
  667. status = Context->FinalStatus; // allow failure to propogate
  668. Context = NULL;
  669. if(Irp->PendingReturned) {
  670. IoMarkIrpPending(Irp);
  671. }
  672. Irp->IoStatus.Status = status;
  673. Irp->IoStatus.Information = 0;
  674. if (NT_SUCCESS(status)) {
  675. //
  676. // Set the new power state
  677. //
  678. fdoExtension->DevicePowerState =
  679. currentStack->Parameters.Power.State.DeviceState;
  680. }
  681. DebugPrint((1, "(%p)\tStarting next power irp\n", Irp));
  682. ClassReleaseRemoveLock(DeviceObject, Irp);
  683. PoStartNextPowerIrp(Irp);
  684. fdoExtension->PowerDownInProgress = FALSE;
  685. return status;
  686. }
  687. }
  688. return STATUS_MORE_PROCESSING_REQUIRED;
  689. } // end ClasspPowerDownCompletion()
  690. /*++////////////////////////////////////////////////////////////////////////////
  691. ClasspPowerHandler()
  692. Routine Description:
  693. This routine reduces the number of useless spinups and spindown requests
  694. sent to a given device by ignoring transitions to power states we are
  695. currently in.
  696. ISSUE-2000/02/20-henrygab - by ignoring spin-up requests, we may be
  697. allowing the drive
  698. Arguments:
  699. DeviceObject - the device object which is transitioning power states
  700. Irp - the power irp
  701. Options - a set of flags indicating what the device handles
  702. Return Value:
  703. --*/
  704. NTSTATUS
  705. ClasspPowerHandler(
  706. IN PDEVICE_OBJECT DeviceObject,
  707. IN PIRP Irp,
  708. IN CLASS_POWER_OPTIONS Options // ISSUE-2000/02/20-henrygab - pass pointer, not whole struct
  709. )
  710. {
  711. PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  712. PDEVICE_OBJECT lowerDevice = commonExtension->LowerDeviceObject;
  713. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  714. PIO_STACK_LOCATION nextIrpStack;
  715. PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  716. PCLASS_POWER_CONTEXT context;
  717. if (!commonExtension->IsFdo) {
  718. //
  719. // certain assumptions are made here,
  720. // particularly: having the fdoExtension
  721. //
  722. DebugPrint((0, "ClasspPowerHandler: Called for PDO %p???\n",
  723. DeviceObject));
  724. ASSERT(!"PDO using ClasspPowerHandler");
  725. return STATUS_NOT_SUPPORTED;
  726. }
  727. DebugPrint((1, "ClasspPowerHandler: Power irp %p to %s %p\n",
  728. Irp, (commonExtension->IsFdo ? "fdo" : "pdo"), DeviceObject));
  729. switch(irpStack->MinorFunction) {
  730. case IRP_MN_SET_POWER: {
  731. PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
  732. DebugPrint((1, "(%p)\tIRP_MN_SET_POWER\n", Irp));
  733. DebugPrint((1, "(%p)\tSetting %s state to %d\n",
  734. Irp,
  735. (irpStack->Parameters.Power.Type == SystemPowerState ?
  736. "System" : "Device"),
  737. irpStack->Parameters.Power.State.SystemState));
  738. switch (irpStack->Parameters.Power.ShutdownType){
  739. case PowerActionSleep:
  740. case PowerActionHibernate:
  741. if (fdoData->HotplugInfo.MediaRemovable || fdoData->HotplugInfo.MediaHotplug){
  742. /*
  743. * We are suspending and this drive is either hot-pluggable
  744. * or contains removeable media.
  745. * Set the media dirty bit, since the media may change while
  746. * we are suspended.
  747. */
  748. SET_FLAG(DeviceObject->Flags, DO_VERIFY_VOLUME);
  749. }
  750. break;
  751. }
  752. break;
  753. }
  754. default: {
  755. DebugPrint((1, "(%p)\tIrp minor code = %#x\n",
  756. Irp, irpStack->MinorFunction));
  757. break;
  758. }
  759. }
  760. if (irpStack->Parameters.Power.Type != DevicePowerState ||
  761. irpStack->MinorFunction != IRP_MN_SET_POWER) {
  762. DebugPrint((1, "(%p)\tSending to lower device\n", Irp));
  763. goto ClasspPowerHandlerCleanup;
  764. }
  765. nextIrpStack = IoGetNextIrpStackLocation(Irp);
  766. //
  767. // already in exact same state, don't work to transition to it.
  768. //
  769. if(irpStack->Parameters.Power.State.DeviceState ==
  770. fdoExtension->DevicePowerState) {
  771. DebugPrint((1, "(%p)\tAlready in device state %x\n",
  772. Irp, fdoExtension->DevicePowerState));
  773. goto ClasspPowerHandlerCleanup;
  774. }
  775. //
  776. // or powering down from non-d0 state (device already stopped)
  777. // NOTE -- we're not sure whether this case can exist or not (the
  778. // power system may never send this sort of request) but it's trivial
  779. // to deal with.
  780. //
  781. if ((irpStack->Parameters.Power.State.DeviceState != PowerDeviceD0) &&
  782. (fdoExtension->DevicePowerState != PowerDeviceD0)) {
  783. DebugPrint((1, "(%p)\tAlready powered down to %x???\n",
  784. Irp, fdoExtension->DevicePowerState));
  785. fdoExtension->DevicePowerState =
  786. irpStack->Parameters.Power.State.DeviceState;
  787. goto ClasspPowerHandlerCleanup;
  788. }
  789. //
  790. // or going into a hibernation state when we're in the hibernation path.
  791. // If the device is spinning then we should leave it spinning - if it's not
  792. // then the dump driver will start it up for us.
  793. //
  794. if((irpStack->Parameters.Power.State.DeviceState == PowerDeviceD3) &&
  795. (irpStack->Parameters.Power.ShutdownType == PowerActionHibernate) &&
  796. (commonExtension->HibernationPathCount != 0)) {
  797. DebugPrint((1, "(%p)\tdoing nothing for hibernation request for "
  798. "state %x???\n",
  799. Irp, fdoExtension->DevicePowerState));
  800. fdoExtension->DevicePowerState =
  801. irpStack->Parameters.Power.State.DeviceState;
  802. goto ClasspPowerHandlerCleanup;
  803. }
  804. //
  805. // or when not handling powering up and are powering up
  806. //
  807. if ((!Options.HandleSpinUp) &&
  808. (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0)) {
  809. DebugPrint((2, "(%p)\tNot handling spinup to state %x\n",
  810. Irp, fdoExtension->DevicePowerState));
  811. fdoExtension->DevicePowerState =
  812. irpStack->Parameters.Power.State.DeviceState;
  813. goto ClasspPowerHandlerCleanup;
  814. }
  815. //
  816. // or when not handling powering down and are powering down
  817. //
  818. if ((!Options.HandleSpinDown) &&
  819. (irpStack->Parameters.Power.State.DeviceState != PowerDeviceD0)) {
  820. DebugPrint((2, "(%p)\tNot handling spindown to state %x\n",
  821. Irp, fdoExtension->DevicePowerState));
  822. fdoExtension->DevicePowerState =
  823. irpStack->Parameters.Power.State.DeviceState;
  824. goto ClasspPowerHandlerCleanup;
  825. }
  826. context = &(fdoExtension->PowerContext);
  827. #if DBG
  828. //
  829. // Mark the context as in use. We should be synchronizing this but
  830. // since it's just for debugging purposes we don't worry too much.
  831. //
  832. ASSERT(context->InUse == FALSE);
  833. #endif
  834. RtlZeroMemory(context, sizeof(CLASS_POWER_CONTEXT));
  835. context->InUse = TRUE;
  836. nextIrpStack->Parameters.Scsi.Srb = &(context->Srb);
  837. nextIrpStack->MajorFunction = IRP_MJ_SCSI;
  838. context->FinalStatus = STATUS_SUCCESS;
  839. context->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
  840. context->Srb.OriginalRequest = Irp;
  841. context->Srb.SrbFlags |= SRB_FLAGS_BYPASS_LOCKED_QUEUE
  842. | SRB_FLAGS_NO_QUEUE_FREEZE;
  843. context->Srb.Function = SRB_FUNCTION_LOCK_QUEUE;
  844. context->Srb.SenseInfoBuffer =
  845. commonExtension->PartitionZeroExtension->SenseData;
  846. context->Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE;
  847. context->RetryCount = MAXIMUM_RETRIES;
  848. context->Options = Options;
  849. context->DeviceObject = DeviceObject;
  850. context->Irp = Irp;
  851. if(irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0) {
  852. ASSERT(Options.HandleSpinUp);
  853. DebugPrint((2, "(%p)\tpower up - locking queue\n", Irp));
  854. //
  855. // We need to issue a queue lock request so that we
  856. // can spin the drive back up after the power is restored
  857. // but before any requests are processed.
  858. //
  859. context->Options.PowerDown = FALSE;
  860. context->PowerChangeState.PowerUp = PowerUpDeviceInitial;
  861. context->CompletionRoutine = ClasspPowerUpCompletion;
  862. } else {
  863. ASSERT(Options.HandleSpinDown);
  864. fdoExtension->PowerDownInProgress = TRUE;
  865. DebugPrint((2, "(%p)\tPowering down - locking queue\n", Irp));
  866. PoSetPowerState(DeviceObject,
  867. irpStack->Parameters.Power.Type,
  868. irpStack->Parameters.Power.State);
  869. context->Options.PowerDown = TRUE;
  870. context->PowerChangeState.PowerDown2 = PowerDownDeviceInitial2;
  871. context->CompletionRoutine = ClasspPowerDownCompletion;
  872. }
  873. //
  874. // we are not dealing with port-allocated sense in these routines.
  875. //
  876. ASSERT(!TEST_FLAG(context->Srb.SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
  877. ASSERT(!TEST_FLAG(context->Srb.SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
  878. //
  879. // we are always returning STATUS_PENDING, so we need to always
  880. // set the irp as pending.
  881. //
  882. IoMarkIrpPending(Irp);
  883. if(Options.LockQueue) {
  884. //
  885. // Send the lock irp down.
  886. //
  887. IoSetCompletionRoutine(Irp,
  888. context->CompletionRoutine,
  889. context,
  890. TRUE,
  891. TRUE,
  892. TRUE);
  893. IoCallDriver(lowerDevice, Irp);
  894. } else {
  895. //
  896. // Call the completion routine directly. It won't care what the
  897. // status of the "lock" was - it will just go and do the next
  898. // step of the operation.
  899. //
  900. context->CompletionRoutine(DeviceObject, Irp, context);
  901. }
  902. return STATUS_PENDING;
  903. ClasspPowerHandlerCleanup:
  904. ClassReleaseRemoveLock(DeviceObject, Irp);
  905. DebugPrint((1, "(%p)\tStarting next power irp\n", Irp));
  906. IoCopyCurrentIrpStackLocationToNext(Irp);
  907. IoSetCompletionRoutine(Irp,
  908. ClasspStartNextPowerIrpCompletion,
  909. NULL,
  910. TRUE,
  911. TRUE,
  912. TRUE);
  913. return PoCallDriver(lowerDevice, Irp);
  914. } // end ClasspPowerHandler()
  915. /*++////////////////////////////////////////////////////////////////////////////
  916. ClassMinimalPowerHandler()
  917. Routine Description:
  918. This routine is the minimum power handler for a storage driver. It does
  919. the least amount of work possible.
  920. --*/
  921. NTSTATUS
  922. ClassMinimalPowerHandler(
  923. IN PDEVICE_OBJECT DeviceObject,
  924. IN PIRP Irp
  925. )
  926. {
  927. PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  928. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  929. NTSTATUS status;
  930. ClassReleaseRemoveLock(DeviceObject, Irp);
  931. PoStartNextPowerIrp(Irp);
  932. if(commonExtension->IsFdo) {
  933. if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
  934. PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
  935. DeviceObject->DeviceExtension;
  936. //
  937. // Check if the system is going to hibernate or standby.
  938. //
  939. if (irpStack->MinorFunction == IRP_MN_SET_POWER){
  940. PVPB vpb;
  941. switch (irpStack->Parameters.Power.ShutdownType){
  942. case PowerActionSleep:
  943. case PowerActionHibernate:
  944. //
  945. // If the volume is mounted, set the verify bit so that
  946. // the filesystem will be forced re-read the media
  947. // after coming out of hibernation or standby.
  948. //
  949. vpb = ClassGetVpb(fdoExtension->DeviceObject);
  950. if (vpb && (vpb->Flags & VPB_MOUNTED)){
  951. SET_FLAG(fdoExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
  952. }
  953. break;
  954. }
  955. }
  956. }
  957. IoCopyCurrentIrpStackLocationToNext(Irp);
  958. return PoCallDriver(commonExtension->LowerDeviceObject, Irp);
  959. } else {
  960. if (irpStack->MinorFunction != IRP_MN_SET_POWER &&
  961. irpStack->MinorFunction != IRP_MN_QUERY_POWER) {
  962. NOTHING;
  963. } else {
  964. Irp->IoStatus.Status = STATUS_SUCCESS;
  965. Irp->IoStatus.Information = 0;
  966. }
  967. status = Irp->IoStatus.Status;
  968. ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
  969. return status;
  970. }
  971. } // end ClassMinimalPowerHandler()
  972. /*++////////////////////////////////////////////////////////////////////////////
  973. ClassSpinDownPowerHandler()
  974. Routine Description:
  975. This routine is a callback for disks and other things which require both
  976. a start and a stop to be sent to the device. (actually the starts are
  977. almost always optional, since most device power themselves on to process
  978. commands, but i digress).
  979. Determines proper use of spinup, spindown, and queue locking based upon
  980. ScanForSpecialFlags in the FdoExtension. This is the most common power
  981. handler passed into classpnp.sys
  982. Arguments:
  983. DeviceObject - Supplies the functional device object
  984. Irp - Supplies the request to be retried.
  985. Return Value:
  986. None
  987. --*/
  988. NTSTATUS
  989. ClassSpinDownPowerHandler(
  990. IN PDEVICE_OBJECT DeviceObject,
  991. IN PIRP Irp
  992. )
  993. {
  994. PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
  995. CLASS_POWER_OPTIONS options;
  996. fdoExtension = (PFUNCTIONAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  997. //
  998. // this will set all options to FALSE
  999. //
  1000. RtlZeroMemory(&options, sizeof(CLASS_POWER_OPTIONS));
  1001. //
  1002. // check the flags to see what options we need to worry about
  1003. //
  1004. if (!TEST_FLAG(fdoExtension->ScanForSpecialFlags,
  1005. CLASS_SPECIAL_DISABLE_SPIN_DOWN)) {
  1006. options.HandleSpinDown = TRUE;
  1007. }
  1008. if (!TEST_FLAG(fdoExtension->ScanForSpecialFlags,
  1009. CLASS_SPECIAL_DISABLE_SPIN_UP)) {
  1010. options.HandleSpinUp = TRUE;
  1011. }
  1012. if (!TEST_FLAG(fdoExtension->ScanForSpecialFlags,
  1013. CLASS_SPECIAL_NO_QUEUE_LOCK)) {
  1014. options.LockQueue = TRUE;
  1015. }
  1016. DebugPrint((3, "ClasspPowerHandler: Devobj %p\n"
  1017. "\t%shandling spin down\n"
  1018. "\t%shandling spin up\n"
  1019. "\t%slocking queue\n",
  1020. DeviceObject,
  1021. (options.HandleSpinDown ? "" : "not "),
  1022. (options.HandleSpinUp ? "" : "not "),
  1023. (options.LockQueue ? "" : "not ")
  1024. ));
  1025. //
  1026. // do all the dirty work
  1027. //
  1028. return ClasspPowerHandler(DeviceObject, Irp, options);
  1029. } // end ClassSpinDownPowerHandler()
  1030. /*++////////////////////////////////////////////////////////////////////////////
  1031. ClassStopUnitPowerHandler()
  1032. Routine Description:
  1033. This routine is an outdated call. To achieve equivalent functionality,
  1034. the driver should set the following flags in ScanForSpecialFlags in the
  1035. FdoExtension:
  1036. CLASS_SPECIAL_DISABLE_SPIN_UP
  1037. CLASS_SPECIAL_NO_QUEUE_LOCK
  1038. --*/
  1039. NTSTATUS
  1040. ClassStopUnitPowerHandler(
  1041. IN PDEVICE_OBJECT DeviceObject,
  1042. IN PIRP Irp
  1043. )
  1044. {
  1045. PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
  1046. DebugPrint((0, "ClassStopUnitPowerHandler - Devobj %p using outdated call\n"
  1047. "Drivers should set the following flags in ScanForSpecialFlags "
  1048. " in the FDO extension:\n"
  1049. "\tCLASS_SPECIAL_DISABLE_SPIN_UP\n"
  1050. "\tCLASS_SPECIAL_NO_QUEUE_LOCK\n"
  1051. "This will provide equivalent functionality if the power "
  1052. "routine is then set to ClassSpinDownPowerHandler\n\n",
  1053. DeviceObject));
  1054. fdoExtension = (PFUNCTIONAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  1055. SET_FLAG(fdoExtension->ScanForSpecialFlags,
  1056. CLASS_SPECIAL_DISABLE_SPIN_UP);
  1057. SET_FLAG(fdoExtension->ScanForSpecialFlags,
  1058. CLASS_SPECIAL_NO_QUEUE_LOCK);
  1059. return ClassSpinDownPowerHandler(DeviceObject, Irp);
  1060. } // end ClassStopUnitPowerHandler()
  1061. /*++////////////////////////////////////////////////////////////////////////////
  1062. RetryPowerRequest()
  1063. Routine Description:
  1064. This routine reinitalizes the necessary fields, and sends the request
  1065. to the lower driver.
  1066. Arguments:
  1067. DeviceObject - Supplies the device object associated with this request.
  1068. Irp - Supplies the request to be retried.
  1069. Context - Supplies a pointer to the power up context for this request.
  1070. Return Value:
  1071. None
  1072. --*/
  1073. VOID
  1074. RetryPowerRequest(
  1075. PDEVICE_OBJECT DeviceObject,
  1076. PIRP Irp,
  1077. PCLASS_POWER_CONTEXT Context
  1078. )
  1079. {
  1080. PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  1081. PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  1082. PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
  1083. PSCSI_REQUEST_BLOCK srb = &(Context->Srb);
  1084. LARGE_INTEGER dueTime;
  1085. DebugPrint((1, "(%p)\tDelaying retry by queueing DPC\n", Irp));
  1086. ASSERT(Context->Irp == Irp);
  1087. ASSERT(Context->DeviceObject == DeviceObject);
  1088. ASSERT(!TEST_FLAG(Context->Srb.SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
  1089. ASSERT(!TEST_FLAG(Context->Srb.SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
  1090. //
  1091. // reset the retry interval
  1092. //
  1093. Context->RetryInterval = 0;
  1094. //
  1095. // Reset byte count of transfer in SRB Extension.
  1096. //
  1097. srb->DataTransferLength = 0;
  1098. //
  1099. // Zero SRB statuses.
  1100. //
  1101. srb->SrbStatus = srb->ScsiStatus = 0;
  1102. //
  1103. // Set up major SCSI function.
  1104. //
  1105. nextIrpStack->MajorFunction = IRP_MJ_SCSI;
  1106. //
  1107. // Save SRB address in next stack for port driver.
  1108. //
  1109. nextIrpStack->Parameters.Scsi.Srb = srb;
  1110. //
  1111. // Set the completion routine up again.
  1112. //
  1113. IoSetCompletionRoutine(Irp, Context->CompletionRoutine, Context,
  1114. TRUE, TRUE, TRUE);
  1115. if (Context->RetryInterval == 0) {
  1116. DebugPrint((2, "(%p)\tDelaying minimum time (.2 sec)\n", Irp));
  1117. dueTime.QuadPart = (LONGLONG)1000000 * 2;
  1118. } else {
  1119. DebugPrint((2, "(%p)\tDelaying %x seconds\n",
  1120. Irp, Context->RetryInterval));
  1121. dueTime.Q

Large files files are truncated, but you can click here to view the full file