ReactOS  0.4.15-dev-1206-g731eddf
power.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (C) Microsoft Corporation, 1991 - 2010
4 
5 Module Name:
6 
7  power.c
8 
9 Abstract:
10 
11  SCSI class driver routines
12 
13 Environment:
14 
15  kernel mode only
16 
17 Notes:
18 
19 
20 Revision History:
21 
22 --*/
23 
24 #ifndef __REACTOS__
25 #include "stddef.h"
26 #include "ntddk.h"
27 #include "scsi.h"
28 #endif
29 #include "classp.h"
30 
31 // #include <stdarg.h> __REACTOS__
32 
33 #ifdef DEBUG_USE_WPP
34 #include "power.tmh"
35 #endif
36 
37 #define CLASS_TAG_POWER 'WLcS'
38 
39 // constants for power transition process. (UNIT: seconds)
40 #define DEFAULT_POWER_IRP_TIMEOUT_VALUE 10*60
41 #define TIME_LEFT_FOR_LOWER_DRIVERS 30
42 #define TIME_LEFT_FOR_UPPER_DRIVERS 5
43 #define DEFAULT_IO_TIMEOUT_VALUE 10
44 #define MINIMUM_STOP_UNIT_TIMEOUT_VALUE 2
45 
46 //
47 // MINIMAL value is one that has some slack and is the value to use
48 // if there is a shortened POWER IRP timeout value. If time remaining
49 // is less than MINIMAL, we will use the MINIMUM value. Both values
50 // are in the same unit as above (seconds).
51 //
52 #define MINIMAL_START_UNIT_TIMEOUT_VALUE 60
53 #define MINIMUM_START_UNIT_TIMEOUT_VALUE 30
54 
55 // PoQueryWatchdogTime was introduced in Windows 7.
56 // Returns TRUE if a watchdog-enabled power IRP is found, otherwise FALSE.
57 #if (NTDDI_VERSION < NTDDI_WIN7)
58 #define PoQueryWatchdogTime(A, B) FALSE
59 #endif
60 
61 IO_COMPLETION_ROUTINE ClasspPowerDownCompletion;
62 
63 IO_COMPLETION_ROUTINE ClasspPowerUpCompletion;
64 
65 IO_COMPLETION_ROUTINE ClasspStartNextPowerIrpCompletion;
67 
71  IN PIRP Irp,
73  );
74 
75 VOID
78  PIRP Irp,
80  );
81 
82 #ifdef ALLOC_PRAGMA
83  #pragma alloc_text(PAGE, ClasspPowerSettingCallback)
84 #endif
85 
86 /*++////////////////////////////////////////////////////////////////////////////
87 
88 ClassDispatchPower()
89 
90 Routine Description:
91 
92  This routine acquires the removelock for the irp and then calls the
93  appropriate power callback.
94 
95 Arguments:
96 
97  DeviceObject -
98  Irp -
99 
100 Return Value:
101 
102 --*/
103 NTSTATUS
104 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
107  IN PIRP Irp
108  )
109 {
110  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
111  ULONG isRemoved;
112 
113  //
114  // NOTE: This code may be called at PASSIVE or DISPATCH, depending
115  // upon the device object it is being called for.
116  // don't do anything that would break under either circumstance.
117  //
118 
119  //
120  // If device is added but not yet started, we need to send the Power
121  // request down the stack. If device is started and then stopped,
122  // we have enough state to process the power request.
123  //
124 
125  if (!commonExtension->IsInitialized) {
126 
129  return PoCallDriver(commonExtension->LowerDeviceObject, Irp);
130  }
131 
133 
134  if (isRemoved) {
136  Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
140  }
141 
142  return commonExtension->DevInfo->ClassPowerDevice(DeviceObject, Irp);
143 } // end ClassDispatchPower()
144 
145 /*++////////////////////////////////////////////////////////////////////////////
146 
147 ClasspPowerUpCompletion()
148 
149 Routine Description:
150 
151  This routine is used for intermediate completion of a power up request.
152  PowerUp requires four requests to be sent to the lower driver in sequence.
153 
154  * The queue is "power locked" to ensure that the class driver power-up
155  work can be done before request processing resumes.
156 
157  * The power irp is sent down the stack for any filter drivers and the
158  port driver to return power and resume command processing for the
159  device. Since the queue is locked, no queued irps will be sent
160  immediately.
161 
162  * A start unit command is issued to the device with appropriate flags
163  to override the "power locked" queue.
164 
165  * The queue is "power unlocked" to start processing requests again.
166 
167  This routine uses the function in the srb which just completed to determine
168  which state it is in.
169 
170 Arguments:
171 
172  DeviceObject - the device object being powered up
173 
174  Irp - Context->Irp: original power irp; fdoExtension->PrivateFdoData->PowerProcessIrp: power process irp
175 
176  Context - Class power context used to perform port/class operations.
177 
178 Return Value:
179 
180  STATUS_MORE_PROCESSING_REQUIRED or
181  STATUS_SUCCESS
182 
183 --*/
184 NTSTATUS
185 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
188  IN PIRP Irp,
190  )
191 {
193  PCOMMON_DEVICE_EXTENSION commonExtension;
194  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
196  PIO_STACK_LOCATION currentStack;
197  PIO_STACK_LOCATION nextStack;
198 
201  ULONG srbFlags;
202  BOOLEAN FailurePredictionEnabled = FALSE;
203 
205 
206  if (PowerContext == NULL) {
207  NT_ASSERT(PowerContext != NULL);
209  }
210 
211  commonExtension = PowerContext->DeviceObject->DeviceExtension;
212  fdoExtension = PowerContext->DeviceObject->DeviceExtension;
213  OriginalIrp = PowerContext->Irp;
214 
215  // currentStack - from original power irp
216  // nextStack - from power process irp
218  nextStack = IoGetNextIrpStackLocation(fdoExtension->PrivateFdoData->PowerProcessIrp);
219 
220  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "ClasspPowerUpCompletion: Device Object %p, Irp %p, "
221  "Context %p\n",
222  PowerContext->DeviceObject, Irp, Context));
223 
224  if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
225  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(fdoExtension->PrivateFdoData->PowerSrb.SrbEx);
226 
227  //
228  // Check if reverted to using legacy SRB.
229  //
230  if (PowerContext->Srb.Length == sizeof(SCSI_REQUEST_BLOCK)) {
231  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(PowerContext->Srb);
232  }
233  } else {
234  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(PowerContext->Srb);
235  }
236 
237  srbFlags = SrbGetSrbFlags(srbHeader);
240  NT_ASSERT(PowerContext->Options.PowerDown == FALSE);
241  NT_ASSERT(PowerContext->Options.HandleSpinUp);
242 
243  if ((Irp == OriginalIrp) && (Irp->PendingReturned)) {
244  // only for original power irp
246  }
247 
248  PowerContext->PowerChangeState.PowerUp++;
249 
250  switch (PowerContext->PowerChangeState.PowerUp) {
251 
252  case PowerUpDeviceLocked: {
253 
254  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tPreviously sent power lock\n", Irp));
255 
256  //
257  // Lock Queue operation has been sent.
258  // Now, send the original power irp down to get lower driver and device ready.
259  //
260 
262 
263  if ((PowerContext->Options.LockQueue == TRUE) &&
264  (!NT_SUCCESS(Irp->IoStatus.Status))) {
265 
266  //
267  // Lock was not successful:
268  // Issue the original power request to the lower driver and next power irp will be started in completion routine.
269  //
270 
271 
272  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tIrp status was %lx\n",
273  Irp, Irp->IoStatus.Status));
274  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tSrb status was %lx\n",
275  Irp, srbHeader->SrbStatus));
276 
279  PowerContext,
280  TRUE,
281  TRUE,
282  TRUE);
283 
284  PoCallDriver(commonExtension->LowerDeviceObject, OriginalIrp);
285 
287 
288  } else {
289  PowerContext->QueueLocked = (UCHAR)PowerContext->Options.LockQueue;
290  }
291 
292  Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
293 
295 
298  PowerContext,
299  TRUE,
300  TRUE,
301  TRUE);
302 
303  status = PoCallDriver(commonExtension->LowerDeviceObject, OriginalIrp);
304 
305  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tIoCallDriver returned %lx\n", OriginalIrp, status));
306  break;
307  }
308 
309  case PowerUpDeviceOn: {
310 
311  //
312  // Original power irp has been completed by lower driver.
313  //
314 
315  if (NT_SUCCESS(Irp->IoStatus.Status)) {
316  //
317  // If power irp succeeded, START UNIT command will be sent.
318  //
319  PCDB cdb;
320  ULONG secondsRemaining = 0;
321  ULONG timeoutValue = 0;
322  ULONG startUnitTimeout;
323 
324  if (PoQueryWatchdogTime(fdoExtension->LowerPdo, &secondsRemaining)) {
325 
326  // do not exceed DEFAULT_POWER_IRP_TIMEOUT_VALUE.
327  secondsRemaining = min(secondsRemaining, DEFAULT_POWER_IRP_TIMEOUT_VALUE);
328 
329  //
330  // It's possible for POWER IRP timeout value to be smaller than default of
331  // START_UNIT_TIMEOUT. If this is the case, use a smaller timeout value.
332  //
333  if (secondsRemaining >= START_UNIT_TIMEOUT) {
334  startUnitTimeout = START_UNIT_TIMEOUT;
335  } else {
336  startUnitTimeout = MINIMAL_START_UNIT_TIMEOUT_VALUE;
337  }
338 
339  // plan to leave (TIME_LEFT_FOR_UPPER_DRIVERS) seconds to upper level drivers
340  // for processing original power irp.
341  if (secondsRemaining >= (TIME_LEFT_FOR_UPPER_DRIVERS + startUnitTimeout)) {
342  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount =
343  (secondsRemaining - TIME_LEFT_FOR_UPPER_DRIVERS) / startUnitTimeout;
344 
345  // * No 'short' timeouts
346  //
347  //
348  // timeoutValue = (secondsRemaining - TIME_LEFT_FOR_UPPER_DRIVERS) %
349  // startUnitTimeout;
350  //
351 
352  if (--fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount)
353  {
354  timeoutValue = startUnitTimeout;
355  } else {
356  timeoutValue = secondsRemaining - TIME_LEFT_FOR_UPPER_DRIVERS;
357  }
358  } else {
359  // issue the command with minimum timeout value and do not retry on it.
360  // case of (secondsRemaining < DEFAULT_IO_TIMEOUT_VALUE) is ignored as it should not happen.
361  NT_ASSERT(secondsRemaining >= DEFAULT_IO_TIMEOUT_VALUE);
362 
363  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount = 0;
364  timeoutValue = MINIMUM_START_UNIT_TIMEOUT_VALUE; // use the minimum value for this corner case.
365  }
366 
367  } else {
368  // don't know how long left, do not exceed DEFAULT_POWER_IRP_TIMEOUT_VALUE.
369  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount =
371  timeoutValue = START_UNIT_TIMEOUT;
372  }
373 
374 
375  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tSending start unit to device\n", Irp));
376 
377  //
378  // Issue the start unit command to the device.
379  //
380 
381  PowerContext->RetryCount = fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount;
382 
383  if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
387  1,
389  if (NT_SUCCESS(status)) {
390  ((PSTORAGE_REQUEST_BLOCK)srbHeader)->SrbFunction = SRB_FUNCTION_EXECUTE_SCSI;
391 
392  //
393  // Set length field in Power Context SRB so we know legacy SRB is not being used.
394  //
395  PowerContext->Srb.Length = 0;
396 
397  } else {
398  //
399  // Should not happen. Revert to legacy SRB.
400  //
401  NT_ASSERT(FALSE);
402  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(PowerContext->Srb);
403  RtlZeroMemory(srbHeader, sizeof(SCSI_REQUEST_BLOCK));
404  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
405  srbHeader->Function = SRB_FUNCTION_EXECUTE_SCSI;
406  }
407 
408  } else {
409  RtlZeroMemory(srbHeader, sizeof(SCSI_REQUEST_BLOCK));
410  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
411  srbHeader->Function = SRB_FUNCTION_EXECUTE_SCSI;
412  }
413 
414  SrbSetOriginalRequest(srbHeader, fdoExtension->PrivateFdoData->PowerProcessIrp);
415  SrbSetSenseInfoBuffer(srbHeader, commonExtension->PartitionZeroExtension->SenseData);
417 
418  SrbSetTimeOutValue(srbHeader, timeoutValue);
419  SrbAssignSrbFlags(srbHeader,
424 
425  if (PowerContext->Options.LockQueue) {
427  }
428 
429  SrbSetCdbLength(srbHeader, 6);
430 
431  cdb = SrbGetCdb(srbHeader);
432  RtlZeroMemory(cdb, sizeof(CDB));
433 
434  cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
435  cdb->START_STOP.Start = 1;
436 
437  PowerContext->PowerChangeState.PowerUp = PowerUpDeviceOn;
438 
439  IoSetCompletionRoutine(fdoExtension->PrivateFdoData->PowerProcessIrp,
441  PowerContext,
442  TRUE,
443  TRUE,
444  TRUE);
445 
446  nextStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)srbHeader;
447  nextStack->MajorFunction = IRP_MJ_SCSI;
448 
449  status = IoCallDriver(commonExtension->LowerDeviceObject, fdoExtension->PrivateFdoData->PowerProcessIrp);
450 
451  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tIoCallDriver returned %lx\n", fdoExtension->PrivateFdoData->PowerProcessIrp, status));
452 
453  } else {
454 
455  //
456  // power irp is failed by lower driver. we're done.
457  //
458 
459  PowerContext->FinalStatus = Irp->IoStatus.Status;
460  goto ClasspPowerUpCompletionFailure;
461  }
462 
463  break;
464  }
465 
466  case PowerUpDeviceStarted: { // 3
467 
468  //
469  // First deal with an error if one occurred.
470  //
471 
472  if (SRB_STATUS(srbHeader->SrbStatus) != SRB_STATUS_SUCCESS) {
473 
474  BOOLEAN retry;
475  LONGLONG delta100nsUnits = 0;
476  ULONG secondsRemaining = 0;
477  ULONG startUnitTimeout = START_UNIT_TIMEOUT;
478 
479  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_POWER, "%p\tError occured when issuing START_UNIT "
480  "command to device. Srb %p, Status %x\n",
481  Irp,
482  srbHeader,
483  srbHeader->SrbStatus));
484 
485  NT_ASSERT(!(TEST_FLAG(srbHeader->SrbStatus, SRB_STATUS_QUEUE_FROZEN)));
486  NT_ASSERT((srbHeader->Function == SRB_FUNCTION_EXECUTE_SCSI) ||
487  (((PSTORAGE_REQUEST_BLOCK)srbHeader)->SrbFunction == SRB_FUNCTION_EXECUTE_SCSI));
488 
489  PowerContext->RetryInterval = 0;
491  fdoExtension->DeviceObject,
492  Irp,
493  (PSCSI_REQUEST_BLOCK)srbHeader,
494  IRP_MJ_SCSI,
495  IRP_MJ_POWER,
496  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount - PowerContext->RetryCount,
497  &status,
498  &delta100nsUnits);
499 
500  // NOTE: Power context is a public structure, and thus cannot be
501  // updated to use 100ns units. Therefore, must store the
502  // one-second equivalent. Round up to ensure minimum delay
503  // requirements have been met.
504  delta100nsUnits += (10*1000*1000) - 1;
505  delta100nsUnits /= (10*1000*1000);
506  // guaranteed not to have high bits set per SAL annotations
507  PowerContext->RetryInterval = (ULONG)(delta100nsUnits);
508 
509 
510  if ((retry == TRUE) && (PowerContext->RetryCount-- != 0)) {
511 
512  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tRetrying failed request\n", Irp));
513 
514  //
515  // Decrement the state so we come back through here the
516  // next time.
517  //
518 
519  PowerContext->PowerChangeState.PowerUp--;
520 
521  //
522  // Adjust start unit timeout based on remaining time if needed.
523  //
524  if (PoQueryWatchdogTime(fdoExtension->LowerPdo, &secondsRemaining)) {
525 
526  if (secondsRemaining >= TIME_LEFT_FOR_UPPER_DRIVERS) {
527  secondsRemaining -= TIME_LEFT_FOR_UPPER_DRIVERS;
528  }
529 
530  if (secondsRemaining < MINIMAL_START_UNIT_TIMEOUT_VALUE) {
531  startUnitTimeout = MINIMUM_START_UNIT_TIMEOUT_VALUE;
532  } else if (secondsRemaining < START_UNIT_TIMEOUT) {
533  startUnitTimeout = MINIMAL_START_UNIT_TIMEOUT_VALUE;
534  }
535  }
536 
537  SrbSetTimeOutValue(srbHeader, startUnitTimeout);
538 
539  RetryPowerRequest(commonExtension->DeviceObject,
540  Irp,
541  PowerContext);
542 
543  break;
544 
545  }
546 
547  // reset retry count for UNLOCK command.
548  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount = MAXIMUM_RETRIES;
549  PowerContext->RetryCount = MAXIMUM_RETRIES;
550  }
551 
552 ClasspPowerUpCompletionFailure:
553 
554  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tPreviously spun device up\n", Irp));
555 
556  if (PowerContext->QueueLocked) {
557  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tUnlocking queue\n", Irp));
558 
559  if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
560  //
561  // Will reuse SRB for a non-SCSI SRB.
562  //
566  0);
567  if (NT_SUCCESS(status)) {
568  ((PSTORAGE_REQUEST_BLOCK)srbHeader)->SrbFunction = SRB_FUNCTION_UNLOCK_QUEUE;
569 
570  //
571  // Set length field in Power Context SRB so we know legacy SRB is not being used.
572  //
573  PowerContext->Srb.Length = 0;
574 
575  } else {
576  //
577  // Should not occur. Revert to legacy SRB.
578  NT_ASSERT(FALSE);
579  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(PowerContext->Srb);
580  RtlZeroMemory(srbHeader, sizeof(SCSI_REQUEST_BLOCK));
581  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
582  srbHeader->Function = SRB_FUNCTION_UNLOCK_QUEUE;
583  }
584  } else {
585  RtlZeroMemory(srbHeader, sizeof(SCSI_REQUEST_BLOCK));
586  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
587  srbHeader->Function = SRB_FUNCTION_UNLOCK_QUEUE;
588  }
590  SrbSetOriginalRequest(srbHeader, fdoExtension->PrivateFdoData->PowerProcessIrp);
591 
592  nextStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)srbHeader;
593  nextStack->MajorFunction = IRP_MJ_SCSI;
594 
596 
597  IoSetCompletionRoutine(fdoExtension->PrivateFdoData->PowerProcessIrp,
599  PowerContext,
600  TRUE,
601  TRUE,
602  TRUE);
603 
604  status = IoCallDriver(commonExtension->LowerDeviceObject, fdoExtension->PrivateFdoData->PowerProcessIrp);
605  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tIoCallDriver returned %lx\n",
606  fdoExtension->PrivateFdoData->PowerProcessIrp, status));
607  break;
608  }
609 
610  // Fall-through to next case...
611 
612  }
613 
614  case PowerUpDeviceUnlocked: {
615 
616  //
617  // This is the end of the dance.
618  // We're ignoring possible intermediate error conditions ....
619  //
620 
621  if (PowerContext->QueueLocked) {
622  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tPreviously unlocked queue\n", OriginalIrp));
623 
624  //
625  // If the lower device is being removed, the IRP's status may be STATUS_DELETE_PENDING or
626  // STATUS_DEVICE_DOES_NOT_EXIST.
627  //
628  if((NT_SUCCESS(Irp->IoStatus.Status) == FALSE) &&
629  (Irp->IoStatus.Status != STATUS_DELETE_PENDING) &&
630  (Irp->IoStatus.Status != STATUS_DEVICE_DOES_NOT_EXIST)) {
631 
632 
633  NT_ASSERT(FALSE);
634  }
635 
636  } else {
637  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tFall-through (queue not locked)\n", OriginalIrp));
638  }
639 
640  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tFreeing srb and completing\n", OriginalIrp));
641 
642  status = PowerContext->FinalStatus;
643  OriginalIrp->IoStatus.Status = status;
644 
645  //
646  // Set the new power state
647  //
648 
649  if (NT_SUCCESS(status)) {
650  fdoExtension->DevicePowerState = currentStack->Parameters.Power.State.DeviceState;
651  }
652 
653  //
654  // Check whether failure detection is enabled
655  //
656 
657  if ((fdoExtension->FailurePredictionInfo != NULL) &&
658  (fdoExtension->FailurePredictionInfo->Method != FailurePredictionNone)) {
659  FailurePredictionEnabled = TRUE;
660  }
661 
662  //
663  // Enable tick timer at end of D0 processing if it was previously enabled.
664  //
665 
666  if ((commonExtension->DriverExtension->InitData.ClassTick != NULL) ||
667  ((fdoExtension->MediaChangeDetectionInfo != NULL) &&
668  (fdoExtension->FunctionSupportInfo != NULL) &&
669  (fdoExtension->FunctionSupportInfo->AsynchronousNotificationSupported == FALSE)) ||
670  (FailurePredictionEnabled)) {
671 
672 
673  //
674  // If failure prediction is turned on and we've been powered
675  // off longer than the failure prediction query period then
676  // force the query on the next timer tick.
677  //
678 
679  if ((FailurePredictionEnabled) && (ClasspFailurePredictionPeriodMissed(fdoExtension))) {
680  fdoExtension->FailurePredictionInfo->CountDown = 1;
681  }
682 
683  //
684  // Finally, enable the timer.
685  //
686 
687  ClasspEnableTimer(fdoExtension);
688  }
689 
690  //
691  // Indicate to Po that we've been successfully powered up so
692  // it can do it's notification stuff.
693  //
694 
695  PoSetPowerState(PowerContext->DeviceObject,
696  currentStack->Parameters.Power.Type,
697  currentStack->Parameters.Power.State);
698 
699  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tStarting next power irp\n", OriginalIrp));
700 
702 
703  PowerContext->InUse = FALSE;
704 
706 
707  // prevent from completing the irp allocated by ourselves
708  if ((fdoExtension->PrivateFdoData) && (Irp == fdoExtension->PrivateFdoData->PowerProcessIrp)) {
709  // complete original irp if we are processing powerprocess irp,
710  // otherwise, by returning status other than STATUS_MORE_PROCESSING_REQUIRED, IO manager will complete it.
713  }
714 
715  return status;
716  }
717  }
718 
720 } // end ClasspPowerUpCompletion()
721 
722 /*++////////////////////////////////////////////////////////////////////////////
723 
724 ClasspPowerDownCompletion()
725 
726 Routine Description:
727 
728  This routine is used for intermediate completion of a power down request.
729  PowerDown performs the following sequence to power down the device.
730 
731  1. The queue(s) in the lower stack is/are "power locked" to ensure new
732  requests are held until the power-down process is complete.
733 
734  2. A request to the lower layers to wait for all outstanding IO to
735  complete ("quiescence") is sent. This ensures we don't power down
736  the device while it's in the middle of handling IO.
737 
738  3. A request to flush the device's cache is sent. The device may lose
739  power when we forward the D-IRP so any data in volatile storage must
740  be committed to non-volatile storage first.
741 
742  4. A "stop unit" request is sent to the device to notify it that it
743  is about to be powered down.
744 
745  5. The D-IRP is forwarded down the stack. If D3Cold is supported and
746  enabled via ACPI, the ACPI filter driver may power off the device.
747 
748  6. Once the D-IRP is completed by the lower stack, we will "power
749  unlock" the queue(s). (It is the lower stack's responsibility to
750  continue to queue any IO that requires hardware access until the
751  device is powered up again.)
752 
753 Arguments:
754 
755  DeviceObject - the device object being powered down
756 
757  Irp - the IO_REQUEST_PACKET containing the power request
758 
759  Context - the class power context used to perform port/class operations.
760 
761 Return Value:
762 
763  STATUS_MORE_PROCESSING_REQUIRED or
764  STATUS_SUCCESS
765 
766 --*/
767 NTSTATUS
768 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
771  IN PIRP Irp,
773  )
774 {
776  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = PowerContext->DeviceObject->DeviceExtension;
777  PCOMMON_DEVICE_EXTENSION commonExtension = PowerContext->DeviceObject->DeviceExtension;
778  PIRP OriginalIrp = PowerContext->Irp;
779 
780  // currentStack is for original power irp
781  // nextStack is for power process irp
783  PIO_STACK_LOCATION nextStack = IoGetNextIrpStackLocation(fdoExtension->PrivateFdoData->PowerProcessIrp);
784 
787  ULONG srbFlags;
788 
790 
791  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "ClasspPowerDownCompletion: Device Object %p, "
792  "Irp %p, Context %p\n",
793  PowerContext->DeviceObject, Irp, Context));
794 
795  if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
796  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(fdoExtension->PrivateFdoData->PowerSrb.SrbEx);
797 
798  //
799  // Check if reverted to using legacy SRB.
800  //
801  if (PowerContext->Srb.Length == sizeof(SCSI_REQUEST_BLOCK)) {
802  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(PowerContext->Srb);
803  }
804  } else {
805  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(PowerContext->Srb);
806  }
807 
808  srbFlags = SrbGetSrbFlags(srbHeader);
811  NT_ASSERT(PowerContext->Options.PowerDown == TRUE);
812  NT_ASSERT(PowerContext->Options.HandleSpinDown);
813 
814  if ((Irp == OriginalIrp) && (Irp->PendingReturned)) {
815  // only for original power irp
817  }
818 
819  PowerContext->PowerChangeState.PowerDown3++;
820 
821  switch(PowerContext->PowerChangeState.PowerDown3) {
822 
823  case PowerDownDeviceLocked3: {
824 
825  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tPreviously sent power lock\n", Irp));
826 
827  if ((PowerContext->Options.LockQueue == TRUE) &&
828  (!NT_SUCCESS(Irp->IoStatus.Status))) {
829 
830  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tIrp status was %lx\n",
831  Irp,
832  Irp->IoStatus.Status));
833  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tSrb status was %lx\n",
834  Irp,
835  srbHeader->SrbStatus));
836 
837 
838 
839  //
840  // Lock was not successful - throw down the power IRP
841  // by itself and don't try to spin down the drive or unlock
842  // the queue.
843  //
844 
845  //
846  // Set the new power state
847  //
848 
849  fdoExtension->DevicePowerState =
850  currentStack->Parameters.Power.State.DeviceState;
851 
852  //
853  // Indicate to Po that we've been successfully powered down
854  // so it can do it's notification stuff.
855  //
856 
860  PowerContext,
861  TRUE,
862  TRUE,
863  TRUE);
864 
865  PoSetPowerState(PowerContext->DeviceObject,
866  currentStack->Parameters.Power.Type,
867  currentStack->Parameters.Power.State);
868 
869  fdoExtension->PowerDownInProgress = FALSE;
870 
871  ClassReleaseRemoveLock(commonExtension->DeviceObject,
872  OriginalIrp);
873 
874  PoCallDriver(commonExtension->LowerDeviceObject, OriginalIrp);
875 
877 
878  } else {
879  //
880  // Lock the device queue succeeded. Now wait for all outstanding IO to complete.
881  // To do this, Srb with SRB_FUNCTION_QUIESCE_DEVICE will be sent down with default timeout value.
882  // We need to tolerant failure of this request, no retry will be made.
883  //
884  PowerContext->QueueLocked = (UCHAR) PowerContext->Options.LockQueue;
885 
886  //
887  // No retry on device quiescence reqeust
888  //
889  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount = 0;
890  PowerContext->RetryCount = 0;
891 
892  if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
893  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(fdoExtension->PrivateFdoData->PowerSrb.SrbEx);
894 
895  //
896  // Initialize extended SRB for a SRB_FUNCTION_LOCK_QUEUE
897  //
901  0);
902  if (NT_SUCCESS(status)) {
903  ((PSTORAGE_REQUEST_BLOCK)srbHeader)->SrbFunction = SRB_FUNCTION_QUIESCE_DEVICE;
904  } else {
905  //
906  // Should not happen. Revert to legacy SRB.
907  //
908  NT_ASSERT(FALSE);
909  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(PowerContext->Srb);
910  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
911  srbHeader->Function = SRB_FUNCTION_QUIESCE_DEVICE;
912  }
913  } else {
914  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(PowerContext->Srb);
915  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
916  srbHeader->Function = SRB_FUNCTION_QUIESCE_DEVICE;
917  }
918 
919  SrbSetOriginalRequest(srbHeader, fdoExtension->PrivateFdoData->PowerProcessIrp);
920  SrbSetTimeOutValue(srbHeader, fdoExtension->TimeOutValue);
921 
922  SrbAssignSrbFlags(srbHeader,
929 
930  IoSetCompletionRoutine(fdoExtension->PrivateFdoData->PowerProcessIrp,
932  PowerContext,
933  TRUE,
934  TRUE,
935  TRUE);
936 
937  nextStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)srbHeader;
938  nextStack->MajorFunction = IRP_MJ_SCSI;
939 
940  status = IoCallDriver(commonExtension->LowerDeviceObject, fdoExtension->PrivateFdoData->PowerProcessIrp);
941 
942  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tIoCallDriver returned %lx\n", fdoExtension->PrivateFdoData->PowerProcessIrp, status));
943  break;
944  }
945 
946  }
947 
949 
950  PCDB cdb;
951 
952  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tPreviously sent device quiesce\n", Irp));
953 
954  //
955  // don't care the result of device quiesce, we've made the effort.
956  // continue on sending other SCSI commands anyway.
957  //
958 
959 
960  if (!TEST_FLAG(fdoExtension->PrivateFdoData->HackFlags,
962 
963  //
964  // send SCSIOP_SYNCHRONIZE_CACHE
965  //
966 
967  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount = MAXIMUM_RETRIES;
968  PowerContext->RetryCount = MAXIMUM_RETRIES;
969 
970  if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
974  1,
976  if (NT_SUCCESS(status)) {
977  ((PSTORAGE_REQUEST_BLOCK)srbHeader)->SrbFunction = SRB_FUNCTION_EXECUTE_SCSI;
978 
979  //
980  // Set length field in Power Context SRB so we know legacy SRB is not being used.
981  //
982  PowerContext->Srb.Length = 0;
983 
984  } else {
985  //
986  // Should not occur. Revert to legacy SRB.
987  NT_ASSERT(FALSE);
988  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(PowerContext->Srb);
989  RtlZeroMemory(srbHeader, sizeof(SCSI_REQUEST_BLOCK));
990  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
991  srbHeader->Function = SRB_FUNCTION_EXECUTE_SCSI;
992  }
993 
994  } else {
995  RtlZeroMemory(srbHeader, sizeof(SCSI_REQUEST_BLOCK));
996  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
997  srbHeader->Function = SRB_FUNCTION_EXECUTE_SCSI;
998  }
999 
1000 
1001  SrbSetOriginalRequest(srbHeader, fdoExtension->PrivateFdoData->PowerProcessIrp);
1002  SrbSetSenseInfoBuffer(srbHeader, commonExtension->PartitionZeroExtension->SenseData);
1004  SrbSetTimeOutValue(srbHeader, fdoExtension->TimeOutValue);
1005 
1006  SrbAssignSrbFlags(srbHeader,
1013 
1014  SrbSetCdbLength(srbHeader, 10);
1015 
1016  cdb = SrbGetCdb(srbHeader);
1017 
1018  RtlZeroMemory(cdb, sizeof(CDB));
1019  cdb->SYNCHRONIZE_CACHE10.OperationCode = SCSIOP_SYNCHRONIZE_CACHE;
1020 
1021  IoSetCompletionRoutine(fdoExtension->PrivateFdoData->PowerProcessIrp,
1023  PowerContext,
1024  TRUE,
1025  TRUE,
1026  TRUE);
1027 
1028  nextStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)srbHeader;
1029  nextStack->MajorFunction = IRP_MJ_SCSI;
1030 
1031  status = IoCallDriver(commonExtension->LowerDeviceObject, fdoExtension->PrivateFdoData->PowerProcessIrp);
1032 
1033  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tIoCallDriver returned %lx\n", fdoExtension->PrivateFdoData->PowerProcessIrp, status));
1034  break;
1035 
1036  } else {
1037 
1038  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_POWER, "(%p)\tPower Down: not sending SYNCH_CACHE\n",
1039  PowerContext->DeviceObject));
1040  PowerContext->PowerChangeState.PowerDown3++;
1041  srbHeader->SrbStatus = SRB_STATUS_SUCCESS;
1042  // and fall through....
1043  }
1044  // no break in case the device doesn't like synch_cache commands
1045 
1046  }
1047 
1048  case PowerDownDeviceFlushed3: {
1049 
1050  PCDB cdb;
1051 
1052  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tPreviously send SCSIOP_SYNCHRONIZE_CACHE\n",
1053  Irp));
1054 
1055  //
1056  // SCSIOP_SYNCHRONIZE_CACHE was sent
1057  //
1058 
1059  if (SRB_STATUS(srbHeader->SrbStatus) != SRB_STATUS_SUCCESS) {
1060 
1061  BOOLEAN retry;
1062  LONGLONG delta100nsUnits = 0;
1063 
1064  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_POWER, "(%p)\tError occured when issuing "
1065  "SYNCHRONIZE_CACHE command to device. "
1066  "Srb %p, Status %lx\n",
1067  Irp,
1068  srbHeader,
1069  srbHeader->SrbStatus));
1070 
1071  NT_ASSERT(!(TEST_FLAG(srbHeader->SrbStatus, SRB_STATUS_QUEUE_FROZEN)));
1072  NT_ASSERT((srbHeader->Function == SRB_FUNCTION_EXECUTE_SCSI) ||
1073  (((PSTORAGE_REQUEST_BLOCK)srbHeader)->SrbFunction == SRB_FUNCTION_EXECUTE_SCSI));
1074 
1075  PowerContext->RetryInterval = 0;
1077  fdoExtension->DeviceObject,
1078  Irp,
1079  (PSCSI_REQUEST_BLOCK)srbHeader,
1080  IRP_MJ_SCSI,
1081  IRP_MJ_POWER,
1082  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount - PowerContext->RetryCount,
1083  &status,
1084  &delta100nsUnits);
1085 
1086  // NOTE: Power context is a public structure, and thus cannot be
1087  // updated to use 100ns units. Therefore, must store the
1088  // one-second equivalent. Round up to ensure minimum delay
1089  // requirements have been met.
1090  delta100nsUnits += (10*1000*1000) - 1;
1091  delta100nsUnits /= (10*1000*1000);
1092  // guaranteed not to have high bits set per SAL annotations
1093  PowerContext->RetryInterval = (ULONG)(delta100nsUnits);
1094 
1095 
1096  if ((retry == TRUE) && (PowerContext->RetryCount-- != 0)) {
1097 
1098  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tRetrying failed request\n", Irp));
1099 
1100  //
1101  // decrement the state so we come back through here
1102  // the next time.
1103  //
1104 
1105  PowerContext->PowerChangeState.PowerDown3--;
1106  RetryPowerRequest(commonExtension->DeviceObject,
1107  Irp,
1108  PowerContext);
1109  break;
1110  }
1111 
1112  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tSYNCHRONIZE_CACHE not retried\n", Irp));
1113  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount = MAXIMUM_RETRIES;
1114  PowerContext->RetryCount = MAXIMUM_RETRIES;
1115  } // end !SRB_STATUS_SUCCESS
1116 
1117  //
1118  // note: we are purposefully ignoring any errors. if the drive
1119  // doesn't support a synch_cache, then we're up a creek
1120  // anyways.
1121  //
1122 
1123  if ((currentStack->Parameters.Power.State.DeviceState == PowerDeviceD3) &&
1124  (currentStack->Parameters.Power.ShutdownType == PowerActionHibernate) &&
1125  (commonExtension->HibernationPathCount != 0)) {
1126 
1127  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tPower Down: not sending SPIN DOWN due to hibernation path\n",
1128  PowerContext->DeviceObject));
1129 
1130  PowerContext->PowerChangeState.PowerDown3++;
1131  srbHeader->SrbStatus = SRB_STATUS_SUCCESS;
1133 
1134  // Fall through to next case...
1135 
1136  } else {
1137  // Send STOP UNIT command. As "Imme" bit is set to '1', this command should be completed in short time.
1138  // This command is at low importance, failure of this command has very small impact.
1139 
1140  ULONG secondsRemaining;
1141  ULONG timeoutValue;
1142 
1143  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tSending stop unit to device\n", Irp));
1144 
1145  if (PoQueryWatchdogTime(fdoExtension->LowerPdo, &secondsRemaining)) {
1146  // plan to leave some time (TIME_LEFT_FOR_LOWER_DRIVERS) to lower level drivers
1147  // for processing the original power irp.
1148  if (secondsRemaining >= (TIME_LEFT_FOR_LOWER_DRIVERS + DEFAULT_IO_TIMEOUT_VALUE)) {
1149  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount =
1151 
1152  // * No 'short' timeouts
1153  //
1154  // timeoutValue = (secondsRemaining - TIME_LEFT_FOR_LOWER_DRIVERS) %
1155  // DEFAULT_IO_TIMEOUT_VALUE;
1156  // if (timeoutValue < MINIMUM_STOP_UNIT_TIMEOUT_VALUE)
1157  // {
1158  if (--fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount)
1159  {
1160  timeoutValue = DEFAULT_IO_TIMEOUT_VALUE;
1161  } else {
1162  timeoutValue = secondsRemaining - TIME_LEFT_FOR_LOWER_DRIVERS;
1163  }
1164  // }
1165 
1166  // Limit to maximum retry count.
1167  if (fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount > MAXIMUM_RETRIES) {
1168  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount = MAXIMUM_RETRIES;
1169  }
1170  } else {
1171  // issue the command with minimum timeout value and do not retry on it.
1172  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount = 0;
1173 
1174  // minimum as MINIMUM_STOP_UNIT_TIMEOUT_VALUE.
1175  if (secondsRemaining > 2 * MINIMUM_STOP_UNIT_TIMEOUT_VALUE) {
1176  timeoutValue = secondsRemaining - MINIMUM_STOP_UNIT_TIMEOUT_VALUE;
1177  } else {
1178  timeoutValue = MINIMUM_STOP_UNIT_TIMEOUT_VALUE;
1179  }
1180 
1181  }
1182 
1183  } else {
1184  // do not know how long, use default values.
1185  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount = MAXIMUM_RETRIES;
1186  timeoutValue = DEFAULT_IO_TIMEOUT_VALUE;
1187  }
1188 
1189  //
1190  // Issue STOP UNIT command to the device.
1191  //
1192 
1193  PowerContext->RetryCount = fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount;
1194 
1195  if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1199  1,
1201  if (NT_SUCCESS(status)) {
1202  ((PSTORAGE_REQUEST_BLOCK)srbHeader)->SrbFunction = SRB_FUNCTION_EXECUTE_SCSI;
1203 
1204  //
1205  // Set length field in Power Context SRB so we know legacy SRB is not being used.
1206  //
1207  PowerContext->Srb.Length = 0;
1208 
1209  } else {
1210  //
1211  // Should not occur. Revert to legacy SRB.
1212  //
1213  NT_ASSERT(FALSE);
1214  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(PowerContext->Srb);
1215  RtlZeroMemory(srbHeader, sizeof(SCSI_REQUEST_BLOCK));
1216  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
1217  srbHeader->Function = SRB_FUNCTION_EXECUTE_SCSI;
1218  }
1219 
1220  } else {
1221  RtlZeroMemory(srbHeader, sizeof(SCSI_REQUEST_BLOCK));
1222  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
1223  srbHeader->Function = SRB_FUNCTION_EXECUTE_SCSI;
1224  }
1225 
1226  SrbSetOriginalRequest(srbHeader, fdoExtension->PrivateFdoData->PowerProcessIrp);
1227  SrbSetSenseInfoBuffer(srbHeader, commonExtension->PartitionZeroExtension->SenseData);
1229  SrbSetTimeOutValue(srbHeader, timeoutValue);
1230 
1231 
1232  SrbAssignSrbFlags(srbHeader,
1239 
1240  SrbSetCdbLength(srbHeader, 6);
1241 
1242  cdb = SrbGetCdb(srbHeader);
1243  RtlZeroMemory(cdb, sizeof(CDB));
1244 
1245  cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
1246  cdb->START_STOP.Start = 0;
1247  cdb->START_STOP.Immediate = 1;
1248 
1249  IoSetCompletionRoutine(fdoExtension->PrivateFdoData->PowerProcessIrp,
1251  PowerContext,
1252  TRUE,
1253  TRUE,
1254  TRUE);
1255 
1256  nextStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)srbHeader;
1257  nextStack->MajorFunction = IRP_MJ_SCSI;
1258 
1259  status = IoCallDriver(commonExtension->LowerDeviceObject, fdoExtension->PrivateFdoData->PowerProcessIrp);
1260 
1261  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tIoCallDriver returned %lx\n", fdoExtension->PrivateFdoData->PowerProcessIrp, status));
1262  break;
1263  }
1264  }
1265 
1266  case PowerDownDeviceStopped3: {
1267 
1268  BOOLEAN ignoreError = TRUE;
1269 
1270  //
1271  // stop was sent
1272  //
1273 
1274  if (SRB_STATUS(srbHeader->SrbStatus) != SRB_STATUS_SUCCESS) {
1275 
1276  BOOLEAN retry;
1277  LONGLONG delta100nsUnits = 0;
1278 
1279  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_POWER, "(%p)\tError occured when issueing STOP_UNIT "
1280  "command to device. Srb %p, Status %lx\n",
1281  Irp,
1282  srbHeader,
1283  srbHeader->SrbStatus));
1284 
1285  NT_ASSERT(!(TEST_FLAG(srbHeader->SrbStatus, SRB_STATUS_QUEUE_FROZEN)));
1286  NT_ASSERT((srbHeader->Function == SRB_FUNCTION_EXECUTE_SCSI) ||
1287  (((PSTORAGE_REQUEST_BLOCK)srbHeader)->SrbFunction == SRB_FUNCTION_EXECUTE_SCSI));
1288 
1289  PowerContext->RetryInterval = 0;
1291  fdoExtension->DeviceObject,
1292  Irp,
1293  (PSCSI_REQUEST_BLOCK)srbHeader,
1294  IRP_MJ_SCSI,
1295  IRP_MJ_POWER,
1296  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount - PowerContext->RetryCount,
1297  &status,
1298  &delta100nsUnits);
1299 
1300  // NOTE: Power context is a public structure, and thus cannot be
1301  // updated to use 100ns units. Therefore, must store the
1302  // one-second equivalent. Round up to ensure minimum delay
1303  // requirements have been met.
1304  delta100nsUnits += (10*1000*1000) - 1;
1305  delta100nsUnits /= (10*1000*1000);
1306  // guaranteed not to have high bits set per SAL annotations
1307  PowerContext->RetryInterval = (ULONG)(delta100nsUnits);
1308 
1309 
1310  if ((retry == TRUE) && (PowerContext->RetryCount-- != 0)) {
1311 
1312  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tRetrying failed request\n", Irp));
1313 
1314  //
1315  // decrement the state so we come back through here
1316  // the next time.
1317  //
1318 
1319  PowerContext->PowerChangeState.PowerDown3--;
1320 
1322 
1323  RetryPowerRequest(commonExtension->DeviceObject,
1324  Irp,
1325  PowerContext);
1326  break;
1327  }
1328 
1329  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tSTOP_UNIT not retried\n", Irp));
1330  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount = MAXIMUM_RETRIES;
1331  PowerContext->RetryCount = MAXIMUM_RETRIES;
1332 
1333  } // end !SRB_STATUS_SUCCESS
1334 
1335 
1336  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tPreviously sent stop unit\n", Irp));
1337 
1338  //
1339  // some operations, such as a physical format in progress,
1340  // should not be ignored and should fail the power operation.
1341  //
1342 
1343  if (!NT_SUCCESS(status)) {
1344 
1345  PVOID senseBuffer = SrbGetSenseInfoBuffer(srbHeader);
1346 
1347  if (TEST_FLAG(srbHeader->SrbStatus, SRB_STATUS_AUTOSENSE_VALID) &&
1348  (senseBuffer != NULL)) {
1349 
1351  UCHAR senseKey = 0;
1354 
1355  validSense = ScsiGetSenseKeyAndCodes(senseBuffer,
1356  SrbGetSenseInfoBufferLength(srbHeader),
1358  &senseKey,
1361 
1362  if (validSense) {
1363  if ((senseKey == SCSI_SENSE_NOT_READY) &&
1366 
1367  ignoreError = FALSE;
1368  PowerContext->FinalStatus = STATUS_DEVICE_BUSY;
1369  status = PowerContext->FinalStatus;
1370  }
1371  }
1372  }
1373  }
1374 
1375  if (NT_SUCCESS(status) || ignoreError) {
1376 
1377  //
1378  // Issue the original power request to the lower driver.
1379  //
1380 
1382 
1385  PowerContext,
1386  TRUE,
1387  TRUE,
1388  TRUE);
1389 
1390  status = PoCallDriver(commonExtension->LowerDeviceObject, OriginalIrp);
1391 
1392  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tPoCallDriver returned %lx\n", OriginalIrp, status));
1393  break;
1394  }
1395 
1396  // else fall through w/o sending the power irp, since the device
1397  // is reporting an error that would be "really bad" to power down
1398  // during.
1399 
1400  }
1401 
1402  case PowerDownDeviceOff3: {
1403 
1404  //
1405  // SpinDown request completed ... whether it succeeded or not is
1406  // another matter entirely.
1407  //
1408 
1409  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tPreviously sent power irp\n", OriginalIrp));
1410 
1411  if (PowerContext->QueueLocked) {
1412 
1413  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tUnlocking queue\n", OriginalIrp));
1414 
1415  if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1416  //
1417  // Will reuse SRB for a non-SCSI SRB.
1418  //
1422  0);
1423  if (NT_SUCCESS(status)) {
1424  ((PSTORAGE_REQUEST_BLOCK)srbHeader)->SrbFunction = SRB_FUNCTION_UNLOCK_QUEUE;
1425 
1426  //
1427  // Set length field in Power Context SRB so we know legacy SRB is not being used.
1428  //
1429  PowerContext->Srb.Length = 0;
1430 
1431  } else {
1432  //
1433  // Should not occur. Revert to legacy SRB.
1434  //
1435  NT_ASSERT(FALSE);
1436  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(PowerContext->Srb);
1437  RtlZeroMemory(srbHeader, sizeof(SCSI_REQUEST_BLOCK));
1438  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
1439  srbHeader->Function = SRB_FUNCTION_UNLOCK_QUEUE;
1440  }
1441  } else {
1442  RtlZeroMemory(srbHeader, sizeof(SCSI_REQUEST_BLOCK));
1443  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
1444  srbHeader->Function = SRB_FUNCTION_UNLOCK_QUEUE;
1445  }
1446 
1447  SrbSetOriginalRequest(srbHeader, fdoExtension->PrivateFdoData->PowerProcessIrp);
1450 
1451  nextStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)srbHeader;
1452  nextStack->MajorFunction = IRP_MJ_SCSI;
1453 
1454  IoSetCompletionRoutine(fdoExtension->PrivateFdoData->PowerProcessIrp,
1456  PowerContext,
1457  TRUE,
1458  TRUE,
1459  TRUE);
1460 
1461  status = IoCallDriver(commonExtension->LowerDeviceObject, fdoExtension->PrivateFdoData->PowerProcessIrp);
1462  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tIoCallDriver returned %lx\n",
1463  fdoExtension->PrivateFdoData->PowerProcessIrp,
1464  status));
1465  break;
1466  }
1467 
1468  }
1469 
1470  case PowerDownDeviceUnlocked3: {
1471 
1472  //
1473  // This is the end of the dance.
1474  // We're ignoring possible intermediate error conditions ....
1475  //
1476 
1477  if (PowerContext->QueueLocked == FALSE) {
1478  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tFall through (queue not locked)\n", OriginalIrp));
1479  } else {
1480  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tPreviously unlocked queue\n", OriginalIrp));
1481  NT_ASSERT(NT_SUCCESS(Irp->IoStatus.Status));
1482  NT_ASSERT(srbHeader->SrbStatus == SRB_STATUS_SUCCESS);
1483 
1484  if (NT_SUCCESS(Irp->IoStatus.Status)) {
1485  PowerContext->QueueLocked = FALSE;
1486  }
1487  }
1488 
1489  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tFreeing srb and completing\n", OriginalIrp));
1490  status = PowerContext->FinalStatus; // allow failure to propogate
1491 
1492  OriginalIrp->IoStatus.Status = status;
1493  OriginalIrp->IoStatus.Information = 0;
1494 
1495  if (NT_SUCCESS(status)) {
1496 
1497  //
1498  // Set the new power state
1499  //
1500 
1501  fdoExtension->DevicePowerState =
1502  currentStack->Parameters.Power.State.DeviceState;
1503 
1504  }
1505 
1506  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tStarting next power irp\n", OriginalIrp));
1507 
1509 
1510  PowerContext->InUse = FALSE;
1511 
1513 
1514  fdoExtension->PowerDownInProgress = FALSE;
1515 
1516  // prevent from completing the irp allocated by ourselves
1517  if (Irp == fdoExtension->PrivateFdoData->PowerProcessIrp) {
1518  // complete original irp if we are processing powerprocess irp,
1519  // otherwise, by returning status other than STATUS_MORE_PROCESSING_REQUIRED, IO manager will complete it.
1522  }
1523 
1524  return status;
1525  }
1526  }
1527 
1529 } // end ClasspPowerDownCompletion()
1530 
1531 /*++////////////////////////////////////////////////////////////////////////////
1532 
1533 ClasspPowerHandler()
1534 
1535 Routine Description:
1536 
1537  This routine reduces the number of useless spinups and spindown requests
1538  sent to a given device by ignoring transitions to power states we are
1539  currently in.
1540 
1541  ISSUE-2000/02/20-henrygab - by ignoring spin-up requests, we may be
1542  allowing the drive
1543 
1544 Arguments:
1545 
1546  DeviceObject - the device object which is transitioning power states
1547  Irp - the power irp
1548  Options - a set of flags indicating what the device handles
1549 
1550 Return Value:
1551 
1552 --*/
1553 NTSTATUS
1556  IN PIRP Irp,
1557  IN CLASS_POWER_OPTIONS Options // ISSUE-2000/02/20-henrygab - pass pointer, not whole struct
1558  )
1559 {
1560  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
1561  PDEVICE_OBJECT lowerDevice = commonExtension->LowerDeviceObject;
1563  PIO_STACK_LOCATION nextIrpStack;
1564  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
1567  ULONG srbFlags;
1568  NTSTATUS status;
1569 
1570  _Analysis_assume_(fdoExtension);
1571  _Analysis_assume_(fdoExtension->PrivateFdoData);
1572 
1573  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "ClasspPowerHandler: Power irp %p to %s %p\n",
1574  Irp, (commonExtension->IsFdo ? "fdo" : "pdo"), DeviceObject));
1575 
1576  if (!commonExtension->IsFdo) {
1577 
1578  //
1579  // certain assumptions are made here,
1580  // particularly: having the fdoExtension
1581  //
1582 
1583  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_POWER, "ClasspPowerHandler: Called for PDO %p???\n",
1584  DeviceObject));
1585  NT_ASSERT(!"PDO using ClasspPowerHandler");
1586 
1588  Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1591  return STATUS_NOT_SUPPORTED;
1592  }
1593 
1594  switch (irpStack->MinorFunction) {
1595 
1596  case IRP_MN_SET_POWER: {
1597  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
1598 
1599  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tIRP_MN_SET_POWER\n", Irp));
1600 
1601  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tSetting %s state to %d\n",
1602  Irp,
1603  (irpStack->Parameters.Power.Type == SystemPowerState ?
1604  "System" : "Device"),
1605  irpStack->Parameters.Power.State.SystemState));
1606 
1607  switch (irpStack->Parameters.Power.ShutdownType){
1608 
1609  case PowerActionNone:
1610 
1611  //
1612  // Skip if device doesn't need volume verification during idle power
1613  // transitions.
1614  //
1615  if ((fdoExtension->FunctionSupportInfo) &&
1616  (fdoExtension->FunctionSupportInfo->IdlePower.NoVerifyDuringIdlePower)) {
1617  break;
1618  }
1619 
1620  case PowerActionSleep:
1621  case PowerActionHibernate:
1622  if (fdoData->HotplugInfo.MediaRemovable || fdoData->HotplugInfo.MediaHotplug) {
1623  /*
1624  * We are suspending device and this drive is either hot-pluggable
1625  * or contains removeable media.
1626  * Set the media dirty bit, since the media may change while
1627  * we are suspended.
1628  */
1630 
1631  //
1632  // Bumping the media change count will force the
1633  // file system to verify the volume when we resume
1634  //
1635 
1636  InterlockedIncrement((volatile LONG *)&fdoExtension->MediaChangeCount);
1637  }
1638 
1639  break;
1640  }
1641 
1642  break;
1643  }
1644 
1645  default: {
1646 
1647  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tIrp minor code = %#x\n",
1648  Irp, irpStack->MinorFunction));
1649  break;
1650  }
1651  }
1652 
1653  if (irpStack->Parameters.Power.Type != DevicePowerState ||
1654  irpStack->MinorFunction != IRP_MN_SET_POWER) {
1655 
1656  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tSending to lower device\n", Irp));
1657 
1658  goto ClasspPowerHandlerCleanup;
1659 
1660  }
1661 
1662  //
1663  // already in exact same state, don't work to transition to it.
1664  //
1665 
1666  if (irpStack->Parameters.Power.State.DeviceState ==
1667  fdoExtension->DevicePowerState) {
1668 
1669  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tAlready in device state %x\n",
1670  Irp, fdoExtension->DevicePowerState));
1671  goto ClasspPowerHandlerCleanup;
1672 
1673  }
1674 
1675  //
1676  // or powering down from non-d0 state (device already stopped)
1677  // NOTE -- we're not sure whether this case can exist or not (the
1678  // power system may never send this sort of request) but it's trivial
1679  // to deal with.
1680  //
1681 
1682  if ((irpStack->Parameters.Power.State.DeviceState != PowerDeviceD0) &&
1683  (fdoExtension->DevicePowerState != PowerDeviceD0)) {
1684  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tAlready powered down to %x???\n",
1685  Irp, fdoExtension->DevicePowerState));
1686  fdoExtension->DevicePowerState =
1687  irpStack->Parameters.Power.State.DeviceState;
1688  goto ClasspPowerHandlerCleanup;
1689  }
1690 
1691  //
1692  // or when not handling powering up and are powering up
1693  //
1694 
1695  if ((!Options.HandleSpinUp) &&
1696  (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0)) {
1697 
1698  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tNot handling spinup to state %x\n",
1699  Irp, fdoExtension->DevicePowerState));
1700  fdoExtension->DevicePowerState =
1701  irpStack->Parameters.Power.State.DeviceState;
1702  goto ClasspPowerHandlerCleanup;
1703 
1704  }
1705 
1706  //
1707  // or when not handling powering down and are powering down
1708  //
1709 
1710  if ((!Options.HandleSpinDown) &&
1711  (irpStack->Parameters.Power.State.DeviceState != PowerDeviceD0)) {
1712 
1713  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tNot handling spindown to state %x\n",
1714  Irp, fdoExtension->DevicePowerState));
1715  fdoExtension->DevicePowerState =
1716  irpStack->Parameters.Power.State.DeviceState;
1717  goto ClasspPowerHandlerCleanup;
1718 
1719  }
1720 
1721  //
1722  // validation completed, start the real work.
1723  //
1724 
1725  IoReuseIrp(fdoExtension->PrivateFdoData->PowerProcessIrp, STATUS_SUCCESS);
1726  IoSetNextIrpStackLocation(fdoExtension->PrivateFdoData->PowerProcessIrp);
1727  nextIrpStack = IoGetNextIrpStackLocation(fdoExtension->PrivateFdoData->PowerProcessIrp);
1728 
1729  context = &(fdoExtension->PowerContext);
1730 
1731  NT_ASSERT(context->InUse == FALSE);
1732 
1734  context->InUse = TRUE;
1735 
1736  if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1737  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(fdoExtension->PrivateFdoData->PowerSrb.SrbEx);
1738 
1739  //
1740  // Initialize extended SRB for a SRB_FUNCTION_LOCK_QUEUE
1741  //
1745  0);
1746  if (NT_SUCCESS(status)) {
1747  ((PSTORAGE_REQUEST_BLOCK)srbHeader)->SrbFunction = SRB_FUNCTION_LOCK_QUEUE;
1748  } else {
1749  //
1750  // Should not happen. Revert to legacy SRB.
1751  //
1752  NT_ASSERT(FALSE);
1753  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(context->Srb);
1754  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
1755  srbHeader->Function = SRB_FUNCTION_LOCK_QUEUE;
1756  }
1757  } else {
1758  srbHeader = (PSTORAGE_REQUEST_BLOCK_HEADER)&(context->Srb);
1759  srbHeader->Length = sizeof(SCSI_REQUEST_BLOCK);
1760  srbHeader->Function = SRB_FUNCTION_LOCK_QUEUE;
1761  }
1762  nextIrpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)srbHeader;
1763  nextIrpStack->MajorFunction = IRP_MJ_SCSI;
1764 
1765  context->FinalStatus = STATUS_SUCCESS;
1766 
1767  SrbSetOriginalRequest(srbHeader, fdoExtension->PrivateFdoData->PowerProcessIrp);
1769 
1770  fdoExtension->PrivateFdoData->MaxPowerOperationRetryCount = MAXIMUM_RETRIES;
1771  context->RetryCount = MAXIMUM_RETRIES;
1772 
1773  context->Options = Options;
1774  context->DeviceObject = DeviceObject;
1775  context->Irp = Irp;
1776 
1777  if (irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0) {
1778 
1779  NT_ASSERT(Options.HandleSpinUp);
1780 
1781  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tpower up - locking queue\n", Irp));
1782 
1783  //
1784  // We need to issue a queue lock request so that we
1785  // can spin the drive back up after the power is restored
1786  // but before any requests are processed.
1787  //
1788 
1789  context->Options.PowerDown = FALSE;
1790  context->PowerChangeState.PowerUp = PowerUpDeviceInitial;
1791  context->CompletionRoutine = ClasspPowerUpCompletion;
1792 
1793  } else {
1794 
1795  NT_ASSERT(Options.HandleSpinDown);
1796 
1797  fdoExtension->PowerDownInProgress = TRUE;
1798 
1799  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tPowering down - locking queue\n", Irp));
1800 
1801  //
1802  // Disable tick timer at beginning of D3 processing if running.
1803  //
1804  if ((fdoExtension->PrivateFdoData->TickTimerEnabled)) {
1805  ClasspDisableTimer(fdoExtension);
1806  }
1807 
1809  irpStack->Parameters.Power.Type,
1810  irpStack->Parameters.Power.State);
1811 
1812  context->Options.PowerDown = TRUE;
1813  context->PowerChangeState.PowerDown3 = PowerDownDeviceInitial3;
1814  context->CompletionRoutine = ClasspPowerDownCompletion;
1815 
1816  }
1817 
1818  //
1819  // we are not dealing with port-allocated sense in these routines.
1820  //
1821 
1822  srbFlags = SrbGetSrbFlags(srbHeader);
1825 
1826  //
1827  // Mark the original power irp pending.
1828  //
1829 
1831 
1832  if (Options.LockQueue) {
1833 
1834  //
1835  // Send the lock irp down.
1836  //
1837 
1838  IoSetCompletionRoutine(fdoExtension->PrivateFdoData->PowerProcessIrp,
1839  context->CompletionRoutine,
1840  context,
1841  TRUE,
1842  TRUE,
1843  TRUE);
1844 
1845  IoCallDriver(lowerDevice, fdoExtension->PrivateFdoData->PowerProcessIrp);
1846 
1847  } else {
1848 
1849  //
1850  // Call the completion routine directly. It won't care what the
1851  // status of the "lock" was - it will just go and do the next
1852  // step of the operation.
1853  //
1854 
1855  context->CompletionRoutine(DeviceObject, fdoExtension->PrivateFdoData->PowerProcessIrp, context);
1856  }
1857 
1858  return STATUS_PENDING;
1859 
1860 ClasspPowerHandlerCleanup:
1861 
1862  //
1863  // Send the original power irp down, we will start the next power irp in completion routine.
1864  //
1866 
1867  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tStarting next power irp\n", Irp));
1871  NULL,
1872  TRUE,
1873  TRUE,
1874  TRUE);
1875  return PoCallDriver(lowerDevice, Irp);
1876 } // end ClasspPowerHandler()
1877 
1878 /*++////////////////////////////////////////////////////////////////////////////
1879 
1880 ClassMinimalPowerHandler()
1881 
1882 Routine Description:
1883 
1884  This routine is the minimum power handler for a storage driver. It does
1885  the least amount of work possible.
1886 
1887 --*/
1888 NTSTATUS
1889 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1892  IN PIRP Irp
1893  )
1894 {
1895  PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
1897  NTSTATUS status;
1898 
1901 
1902  switch (irpStack->MinorFunction)
1903  {
1904  case IRP_MN_SET_POWER:
1905  {
1906  switch (irpStack->Parameters.Power.ShutdownType)
1907  {
1908  case PowerActionNone:
1909  case PowerActionSleep:
1910  case PowerActionHibernate:
1911  {
1912  if (TEST_FLAG(DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA))
1913  {
1915  {
1916  //
1917  // This flag will cause the filesystem to verify the
1918  // volume when coming out of hibernation or standby or runtime power
1919  //
1921  }
1922  }
1923  }
1924  break;
1925  }
1926  }
1927 
1928  //
1929  // Fall through
1930  //
1931 
1932  case IRP_MN_QUERY_POWER:
1933  {
1934  if (!commonExtension->IsFdo)
1935  {
1936  Irp->IoStatus.Status = STATUS_SUCCESS;
1937  Irp->IoStatus.Information = 0;
1938  }
1939  }
1940  break;
1941  }
1942 
1943  if (commonExtension->IsFdo)
1944  {
1946  status = PoCallDriver(commonExtension->LowerDeviceObject, Irp);
1947  }
1948  else
1949  {
1950  status = Irp->IoStatus.Status;
1952  }
1953 
1954  return status;
1955 } // end ClassMinimalPowerHandler()
1956 
1957 /*++////////////////////////////////////////////////////////////////////////////
1958 
1959 ClassSpinDownPowerHandler()
1960 
1961 Routine Description:
1962 
1963  This routine is a callback for disks and other things which require both
1964  a start and a stop to be sent to the device. (actually the starts are
1965  almost always optional, since most device power themselves on to process
1966  commands, but i digress).
1967 
1968  Determines proper use of spinup, spindown, and queue locking based upon
1969  ScanForSpecialFlags in the FdoExtension. This is the most common power
1970  handler passed into classpnp.sys
1971 
1972 Arguments:
1973 
1974  DeviceObject - Supplies the functional device object
1975 
1976  Irp - Supplies the request to be retried.
1977 
1978 Return Value:
1979 
1980  None
1981 
1982 --*/
1984 NTSTATUS
1985 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1988  _In_ PIRP Irp
1989  )
1990 {
1991  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
1993 
1994  fdoExtension = (PFUNCTIONAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1995 
1996  //
1997  // check the flags to see what options we need to worry about
1998  //
1999 
2000  if (!TEST_FLAG(fdoExtension->ScanForSpecialFlags,
2002  options.HandleSpinDown = TRUE;
2003  }
2004 
2005  if (!TEST_FLAG(fdoExtension->ScanForSpecialFlags,
2007  options.HandleSpinUp = TRUE;
2008  }
2009 
2010  if (!TEST_FLAG(fdoExtension->ScanForSpecialFlags,
2012  options.LockQueue = TRUE;
2013  }
2014 
2015  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "ClasspPowerHandler: Devobj %p\n"
2016  "\t%shandling spin down\n"
2017  "\t%shandling spin up\n"
2018  "\t%slocking queue\n",
2019  DeviceObject,
2020  (options.HandleSpinDown ? "" : "not "),
2021  (options.HandleSpinUp ? "" : "not "),
2022  (options.LockQueue ? "" : "not ")
2023  ));
2024 
2025  //
2026  // do all the dirty work
2027  //
2028 
2030 } // end ClassSpinDownPowerHandler()
2031 
2032 /*++////////////////////////////////////////////////////////////////////////////
2033 
2034 ClassStopUnitPowerHandler()
2035 
2036 Routine Description:
2037 
2038  This routine is an outdated call. To achieve equivalent functionality,
2039  the driver should set the following flags in ScanForSpecialFlags in the
2040  FdoExtension:
2041 
2042  CLASS_SPECIAL_DISABLE_SPIN_UP
2043  CLASS_SPECIAL_NO_QUEUE_LOCK
2044 
2045 --*/
2046 NTSTATUS
2047 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2050  _In_ PIRP Irp
2051  )
2052 {
2053  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
2054 
2055  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_POWER, "ClassStopUnitPowerHandler - Devobj %p using outdated call\n"
2056  "Drivers should set the following flags in ScanForSpecialFlags "
2057  " in the FDO extension:\n"
2058  "\tCLASS_SPECIAL_DISABLE_SPIN_UP\n"
2059  "\tCLASS_SPECIAL_NO_QUEUE_LOCK\n"
2060  "This will provide equivalent functionality if the power "
2061  "routine is then set to ClassSpinDownPowerHandler\n\n",
2062  DeviceObject));
2063 
2064  fdoExtension = (PFUNCTIONAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
2065 
2066  SET_FLAG(fdoExtension->ScanForSpecialFlags,
2068  SET_FLAG(fdoExtension->ScanForSpecialFlags,
2070 
2072 } // end ClassStopUnitPowerHandler()
2073 
2074 /*++////////////////////////////////////////////////////////////////////////////
2075 
2076 RetryPowerRequest()
2077 
2078 Routine Description:
2079 
2080  This routine reinitalizes the necessary fields, and sends the request
2081  to the lower driver.
2082 
2083 Arguments:
2084 
2085  DeviceObject - Supplies the device object associated with this request.
2086 
2087  Irp - Supplies the request to be retried.
2088 
2089  Context - Supplies a pointer to the power up context for this request.
2090 
2091 Return Value:
2092 
2093  None
2094 
2095 --*/
2096 VOID
2099  PIRP Irp,
2101  )
2102 {
2104  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
2105  (PFUNCTIONAL_DEVICE_EXTENSION)Context->DeviceObject->DeviceExtension;
2107  LONGLONG dueTime;
2108  ULONG srbFlags;
2109  ULONG srbFunction;
2110 
2111  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tDelaying retry by queueing DPC\n", Irp));
2112 
2113  //NT_ASSERT(Context->Irp == Irp);
2114  if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
2115  srb = (PSTORAGE_REQUEST_BLOCK_HEADER)&(fdoExtension->PrivateFdoData->PowerSrb.SrbEx);
2116 
2117  //
2118  // Check if reverted to using legacy SRB.
2119  //
2120  if (Context->Srb.Length == sizeof(SCSI_REQUEST_BLOCK)) {
2121  srb = (PSTORAGE_REQUEST_BLOCK_HEADER)&(Context->Srb);
2122  srbFunction = srb->Function;
2123  } else {
2124  srbFunction = ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFunction;
2125  }
2126  } else {
2127  srb = (PSTORAGE_REQUEST_BLOCK_HEADER)&(Context->Srb);
2128  srbFunction = srb->Function;
2129  }
2130 
2131  NT_ASSERT(Context->DeviceObject == DeviceObject);
2132  srbFlags = SrbGetSrbFlags(srb);
2135 
2136  if (Context->RetryInterval == 0) {
2137 
2138  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tDelaying minimum time (.2 sec)\n", Irp));
2139  dueTime = (LONGLONG)1000000 * 2;
2140 
2141  } else {
2142 
2143  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER, "(%p)\tDelaying %x seconds\n",
2144  Irp, Context->RetryInterval));
2145  dueTime = (LONGLONG)1000000 * 10 * Context->RetryInterval;
2146 
2147  }
2148 
2149  //
2150  // reset the retry interval
2151  //
2152 
2153  Context->RetryInterval = 0;
2154 
2155  //
2156  // Reset byte count of transfer in SRB Extension.
2157  //
2158 
2159  SrbSetDataTransferLength(srb, 0);
2160 
2161  //
2162  // Zero SRB statuses.
2163  //
2164 
2165  srb->SrbStatus = 0;
2166  if (srbFunction == SRB_FUNCTION_EXECUTE_SCSI) {
2167  SrbSetScsiStatus(srb, 0);
2168  }
2169 
2170  //
2171  // Set up major SCSI function.
2172  //
2173 
2174  nextIrpStack->MajorFunction = IRP_MJ_SCSI;
2175 
2176  //
2177  // Save SRB address in next stack for port driver.
2178  //
2179 
2180  nextIrpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)srb;
2181 
2182  //
2183  // Set the completion routine up again.
2184  //
2185 
2186  IoSetCompletionRoutine(Irp, Context->CompletionRoutine, Context,
2187  TRUE, TRUE, TRUE);
2188 
2189  ClassRetryRequest(DeviceObject, Irp, dueTime);
2190 
2191  return;
2192 
2193 } // end RetryRequest()
2194 
2195 /*++////////////////////////////////////////////////////////////////////////////
2196 
2197 ClasspStartNextPowerIrpCompletion()
2198 
2199 Routine Description:
2200 
2201  This routine guarantees that the next power irp (power up or down) is not
2202  sent until the previous one has fully completed.
2203 
2204 --*/
2205 NTSTATUS
2206 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2209  IN PIRP Irp,
2210  IN PVOID Context
2211  )
2212 {
2214 
2216 
2217  if (Irp->PendingReturned) {
2219  }
2220 
2221  if (PowerContext != NULL)
2222  {
2223  PowerContext->InUse = FALSE;
2224  }
2225 
2226 
2228  return STATUS_SUCCESS;
2229 } // end ClasspStartNextPowerIrpCompletion()
2230 
2231 NTSTATUS
2232 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2235  IN PIRP Irp,
2236  IN PVOID Context
2237  )
2238 {
2240  PCOMMON_DEVICE_EXTENSION commonExtension;
2241  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
2242  PIO_STACK_LOCATION currentStack;
2243  BOOLEAN FailurePredictionEnabled = FALSE;
2244 
2246 
2247  commonExtension = PowerContext->DeviceObject->DeviceExtension;
2248  fdoExtension = PowerContext->DeviceObject->DeviceExtension;
2249 
2250  currentStack = IoGetCurrentIrpStackLocation(Irp);
2251 
2252  //
2253  // Set the new power state
2254  //
2255 
2256  fdoExtension->DevicePowerState = currentStack->Parameters.Power.State.DeviceState;
2257 
2258  //
2259  // We reach here becasue LockQueue operation was not successful.
2260  // However, media change detection would not happen in case of resume becasue we
2261  // had disabled the timer while going into lower power state.
2262  // So, if the device goes into D0 then enable the tick timer.
2263  //
2264 
2265  if (fdoExtension->DevicePowerState == PowerDeviceD0) {
2266  //
2267  // Check whether failure detection is enabled
2268  //
2269 
2270  if ((fdoExtension->FailurePredictionInfo != NULL) &&
2271  (fdoExtension->FailurePredictionInfo->Method != FailurePredictionNone)) {
2272  FailurePredictionEnabled = TRUE;
2273  }
2274 
2275  //
2276  // Enable tick timer at end of D0 processing if it was previously enabled.
2277  //
2278 
2279  if ((commonExtension->DriverExtension->InitData.ClassTick != NULL) ||
2280  ((fdoExtension->MediaChangeDetectionInfo != NULL) &&
2281  (fdoExtension->FunctionSupportInfo != NULL) &&
2282  (fdoExtension->FunctionSupportInfo->AsynchronousNotificationSupported == FALSE)) ||
2283  (FailurePredictionEnabled)) {
2284 
2285  //
2286  // If failure prediction is turned on and we've been powered
2287  // off longer than the failure prediction query period then
2288  // force the query on the next timer tick.
2289  //
2290 
2291  if ((FailurePredictionEnabled) && (ClasspFailurePredictionPeriodMissed(fdoExtension))) {
2292  fdoExtension->FailurePredictionInfo->CountDown = 1;
2293  }
2294 
2295  //
2296  // Finally, enable the timer.
2297  //
2298 
2299  ClasspEnableTimer(fdoExtension);
2300  }
2301  }
2302 
2303  //
2304  // Indicate to Po that we've been successfully powered up so
2305  // it can do it's notification stuff.
2306  //
2307 
2308  PoSetPowerState(PowerContext->DeviceObject,
2309  currentStack->Parameters.Power.Type,
2310  currentStack->Parameters.Power.State);
2311 
2312  PowerContext->InUse = FALSE;
2313 
2314 
2315  ClassReleaseRemoveLock(commonExtension->DeviceObject, Irp);
2316 
2317  //
2318  // Start the next power IRP
2319  //
2320 
2321  if (Irp->PendingReturned) {
2323  }
2324 
2326 
2327  return STATUS_SUCCESS;
2328 }
2329 
2330 
2332 NTSTATUS
2335  )
2336 /*++
2337 Description:
2338 
2339  This function is used to send IOCTL_STORAGE_ENABLE_IDLE_POWER to the port
2340  driver. It pulls the relevant idle power management properties from the
2341  FDO's device extension.
2342 
2343 Arguments:
2344 
2345  DeviceObject - The class FDO.
2346 
2347 Return Value:
2348 
2349  The NTSTATUS code returned from the port driver. STATUS_SUCCESS indicates
2350  this device is now enabled for idle (runtime) power management.
2351 
2352 --*/
2353 {
2354  NTSTATUS status;
2355  STORAGE_IDLE_POWER idlePower = {0};
2356  IO_STATUS_BLOCK ioStatus = {0};
2358  PCOMMON_DEVICE_EXTENSION commonExtension = &(fdoExtension->CommonExtension);
2359 
2360  idlePower.Version = 1;
2361  idlePower.Size = sizeof(STORAGE_IDLE_POWER);
2362  idlePower.WakeCapableHint = fdoExtension->FunctionSupportInfo->IdlePower.DeviceWakeable;
2363  idlePower.D3ColdSupported = fdoExtension->FunctionSupportInfo->IdlePower.D3ColdSupported;
2364  idlePower.D3IdleTimeout = fdoExtension->FunctionSupportInfo->IdlePower.D3IdleTimeout;
2365 
2368  commonExtension->LowerDeviceObject,
2369  &idlePower,
2370  sizeof(STORAGE_IDLE_POWER),
2371  0,
2372  FALSE,
2373  &ioStatus
2374  );
2375 
2376  status = ioStatus.Status;
2377 
2378  TracePrint((TRACE_LEVEL_INFORMATION,
2379  TRACE_FLAG_POWER,
2380  "ClasspSendEnableIdlePowerIoctl: Port driver returned status (%x) for FDO (%p)\n"
2381  "\tWakeCapableHint: %u\n"
2382  "\tD3ColdSupported: %u\n"
2383  "\tD3IdleTimeout: %u (ms)",
2384  status,
2385  DeviceObject,
2386  idlePower.WakeCapableHint,
2387  idlePower.D3ColdSupported,
2388  idlePower.D3IdleTimeout));
2389 
2390  return status;
2391 }
2392 
2393 _Function_class_(POWER_SETTING_CALLBACK)
2395 NTSTATUS
2396 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2402 )
2403 /*++
2404 Description:
2405 
2406  This function is the callback for power setting notifications (registered
2407  when ClasspGetD3IdleTimeout() is called for the first time).
2408 
2409  Currently, this function is used to get the disk idle timeout value from
2410  the system power settings.
2411 
2412  This function is guaranteed to be called at PASSIVE_LEVEL.
2413 
2414 Arguments:
2415 
2416  SettingGuid - The power setting GUID.
2417  Value - Pointer to the power setting value.
2418  ValueLength - Size of the Value buffer.
2419  Context - The FDO's device extension.
2420 
2421 Return Value:
2422 
2423  STATUS_SUCCESS
2424 
2425 --*/
2426 {
2427  PIDLE_POWER_FDO_LIST_ENTRY fdoEntry = NULL;
2428 
2429 #ifdef _MSC_VER
2430 #pragma warning(suppress:4054) // okay to type cast function pointer to PIRP for this use case
2431 #endif
2432  PIRP removeLockTag = (PIRP)&ClasspPowerSettingCallback;
2433 
2435 
2436  PAGED_CODE();
2437 
2438  if (IsEqualGUID(SettingGuid, &GUID_DISK_IDLE_TIMEOUT)) {
2439  if (ValueLength != sizeof(ULONG) || Value == NULL) {
2440  return STATUS_INVALID_PARAMETER;
2441  }
2442 
2443  //
2444  // The value supplied by this GUID is already in milliseconds.
2445  //
2447 
2448  //
2449  // For each FDO on the idle power list, grab the remove lock and send
2450  // IOCTL_STORAGE_ENABLE_IDLE_POWER to the port driver to update the
2451  // idle timeout value.
2452  //
2455  while ((PLIST_ENTRY)fdoEntry != &IdlePowerFDOList) {
2456 
2457  ULONG isRemoved = ClassAcquireRemoveLock(fdoEntry->Fdo, removeLockTag);
2458 
2459  if (!isRemoved) {
2461 
2462  //
2463  // Apply the new timeout if the user hasn't overridden it via the registry.
2464  //
2465  if (!fdoExtension->FunctionSupportInfo->IdlePower.D3IdleTimeoutOverridden) {
2466  fdoExtension->FunctionSupportInfo->IdlePower.D3IdleTimeout = DiskIdleTimeoutInMS;
2468  }
2469  }
2470 
2471  ClassReleaseRemoveLock(fdoEntry->Fdo, removeLockTag);
2472 
2473  fdoEntry = (PIDLE_POWER_FDO_LIST_ENTRY)fdoEntry->ListEntry.Flink;
2474  }
2476 
2477  } else if (IsEqualGUID(SettingGuid, &GUID_CONSOLE_DISPLAY_STATE)) {
2478 
2479  //
2480  // If monitor is off, change media change requests to not
2481  // keep device active. This allows removable media devices to
2482  // go to sleep if there are no other active requests. Otherwise,
2483  // let media change requests keep the device active.
2484  //
2485  if ((ValueLength == sizeof(ULONG)) && (Value != NULL)) {
2486  if (*((PULONG)Value) == PowerMonitorOff) {
2488  } else {
2490  }
2491 
2494  while ((PLIST_ENTRY)fdoEntry != &IdlePowerFDOList) {
2495 
2496  ULONG isRemoved = ClassAcquireRemoveLock(fdoEntry->Fdo, removeLockTag);
2497  if (!isRemoved) {
2499 
2500  if (ClasspScreenOff == FALSE) {
2501  //
2502  // Now that the screen is on, we may need to check for media
2503  // for devices that are not in D0 and may have removable media.
2504  // This is because the media change polling has been disabled
2505  // for devices in D3 and now that the screen is on the user may
2506  // have inserted some media that they want to interact with.
2507  //
2508  if ((fdoExtension->DevicePowerState != PowerDeviceD0) &&
2509  (fdoExtension->MediaChangeDetectionInfo != NULL) &&
2510  (fdoExtension->FunctionSupportInfo->AsynchronousNotificationSupported == FALSE)) {
2511  ClassCheckMediaState(fdoExtension);
2512  }
2513 
2514  //
2515  // We disabled failure prediction polling during screen-off
2516  // so now check to see if we missed a failure prediction
2517  // period and if so, force the IOCTL to be sent now.
2518  //
2519  if ((fdoExtension->FailurePredictionInfo != NULL) &&
2520  (fdoExtension->FailurePredictionInfo->Method != FailurePredictionNone)) {
2521  if (ClasspFailurePredictionPeriodMissed(fdoExtension)) {
2522  fdoExtension->FailurePredictionInfo->CountDown = 1;
2523  }
2524  }
2525  }
2526 
2527 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
2528  //
2529  // Screen state has changed so attempt to update the tick
2530  // timer's no-wake tolerance accordingly.
2531  //
2532  ClasspUpdateTimerNoWakeTolerance(fdoExtension);
2533 #endif
2534  }
2535  ClassReleaseRemoveLock(fdoEntry->Fdo, removeLockTag);
2536 
2537  fdoEntry = (PIDLE_POWER_FDO_LIST_ENTRY)fdoEntry->ListEntry.Flink;
2538  }
2540  }
2541 
2542  }
2543 
2544  return STATUS_SUCCESS;
2545 }
2546 
2547 
2549 NTSTATUS
2552  )
2553 /*++
2554 Description:
2555 
2556  This function is used to enable idle (runtime) power management for the
2557  device. It will do the work to determine D3Cold support, idle timeout,
2558  etc. and then notify the port driver that it wants to enable idle power
2559  management.
2560 
2561  This function may modify some of the idle power fields in the FDO's device
2562  extension.
2563 
2564 Arguments:
2565 
2566  DeviceObject - The class FDO.
2567 
2568 Return Value:
2569 
2570  An NTSTATUS code indicating the status of the operation.
2571 
2572 --*/
2573 {
2575  ULONG d3ColdDisabledByUser = FALSE;
2577  ULONG idleTimeoutOverrideInSeconds = 0;
2578 
2579  //
2580  // This function should only be called once.
2581  //
2582  NT_ASSERT(fdoExtension->FunctionSupportInfo->IdlePower.IdlePowerEnabled == FALSE);
2583 
2584  ClassGetDeviceParameter(fdoExtension,
2587  &d3ColdDisabledByUser);
2588 
2589  //
2590  // If the device is hot-pluggable or the user has explicitly
2591  // disabled D3Cold, do not enable D3Cold for this device.
2592  //
2593  if (d3ColdDisabledByUser || fdoExtension->PrivateFdoData->HotplugInfo.DeviceHotplug) {
2594  fdoExtension->FunctionSupportInfo->IdlePower.D3ColdSupported = 0;
2595  }
2596 
2597  ClassGetDeviceParameter(fdoExtension,
2600  &idleTimeoutOverrideInSeconds);
2601 
2602  //
2603  // Set the idle timeout. If the user has not specified an override value,
2604  // this will either be a default value or will have been updated by the
2605  // power setting notification callback.
2606  //
2607  if (idleTimeoutOverrideInSeconds != 0) {
2608  fdoExtension->FunctionSupportInfo->IdlePower.D3IdleTimeout = (idleTimeoutOverrideInSeconds * 1000);
2609  fdoExtension->FunctionSupportInfo->IdlePower.D3IdleTimeoutOverridden = TRUE;
2610  } else {
2611  fdoExtension->FunctionSupportInfo->IdlePower.D3IdleTimeout = DiskIdleTimeoutInMS;
2612  }
2613 
2614  //
2615  // We don't allow disks to be wakeable.
2616  //
2617  fdoExtension->FunctionSupportInfo->IdlePower.DeviceWakeable = FALSE;
2618 
2619  //
2620  // Send IOCTL_STORAGE_ENABLE_IDLE_POWER to the port driver to enable idle
2621  // power management by the port driver.
2622  //
2624 
2625  if (NT_SUCCESS(status)) {
2626  PIDLE_POWER_FDO_LIST_ENTRY fdoEntry = NULL;
2627 
2628  //
2629  // Put this FDO on the list of devices that are idle power managed.
2630  //
2631  fdoEntry = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(IDLE_POWER_FDO_LIST_ENTRY), CLASS_TAG_POWER);
2632  if (fdoEntry) {
2633 
2634  fdoExtension->FunctionSupportInfo->IdlePower.IdlePowerEnabled = TRUE;
2635 
2636  fdoEntry->Fdo = DeviceObject;
2637 
2639  InsertHeadList(&IdlePowerFDOList, &(fdoEntry->ListEntry));
2641 
2642  //
2643  // If not registered already, register for disk idle timeout power
2644  // setting notifications. The power manager will call our power
2645  // setting callback very soon to set the idle timeout to the actual
2646  // value.
2647  //
2650  &GUID_DISK_IDLE_TIMEOUT,
2652  NULL,
2654  }
2655  } else {
2656  fdoExtension->FunctionSupportInfo->IdlePower.IdlePowerEnabled = FALSE;
2658  }
2659  }
2660 
2661  return status;
2662 }
2663 
#define CLASSP_REG_IDLE_TIMEOUT_IN_SECONDS
Definition: classp.h:124
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:655
#define SRB_FUNCTION_UNLOCK_QUEUE
Definition: srb.h:325
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:428
#define SRB_FLAGS_DISABLE_AUTOSENSE
Definition: srb.h:391
NTSTATUS NTAPI ClassStopUnitPowerHandler(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
Definition: power.c:2048
#define SCSI_SENSEQ_FORMAT_IN_PROGRESS
Definition: cdrw_hw.h:1316
#define IN
Definition: typedefs.h:39
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
FORCEINLINE UCHAR SrbGetSenseInfoBufferLength(_In_ PVOID Srb)
Definition: srbhelper.h:638
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
VOID NTAPI ClassSendDeviceIoControlSynchronous(_In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT TargetDeviceObject, _Inout_updates_opt_(_Inexpressible_(max(InputBufferLength, OutputBufferLength))) PVOID Buffer, _In_ ULONG InputBufferLength, _In_ ULONG OutputBufferLength, _In_ BOOLEAN InternalDeviceIoControl, _Out_ PIO_STATUS_BLOCK IoStatus)
Definition: class.c:11065
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
#define SRB_FUNCTION_QUIESCE_DEVICE
Definition: srb.h:90
FORCEINLINE VOID SrbAssignSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:946
FORCEINLINE VOID SrbSetOriginalRequest(_In_ PVOID Srb, _In_opt_ PVOID OriginalRequest)
Definition: srbhelper.h:710
FORCEINLINE ULONG SrbGetSrbFlags(_In_ PVOID Srb)
Definition: srbhelper.h:927
UCHAR senseKey
Definition: scsi.h:4019
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:1971
FORCEINLINE VOID SrbSetDataTransferLength(_In_ PVOID Srb, _In_ ULONG DataTransferLength)
Definition: srbhelper.h:784
#define CLASS_SPECIAL_NO_QUEUE_LOCK
Definition: classpnp.h:167
#define IRP_MN_QUERY_POWER
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: classpnp.h:905
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
NTSTATUS FinalStatus
Definition: classpnp.h:684
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
_Function_class_(POWER_SETTING_CALLBACK)
Definition: power.c:2393
Definition: http.c:7094
BOOLEAN InterpretSenseInfoWithoutHistory(_In_ PDEVICE_OBJECT Fdo, _In_opt_ PIRP OriginalRequest, _In_ PSCSI_REQUEST_BLOCK Srb, UCHAR MajorFunctionCode, ULONG IoDeviceCode, ULONG PreviousRetryCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIn100nsUnits)
Definition: class.c:12844
#define SRB_FLAGS_FREE_SENSE_BUFFER
Definition: srb.h:398
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:379
_In_ PIRP Irp
Definition: csq.h:116
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
PVOID PowerSettingNotificationHandle
Definition: class.c:119
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
struct _STORAGE_IDLE_POWER STORAGE_IDLE_POWER
UCHAR additionalSenseCodeQualifier
Definition: scsi.h:4021
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:599
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
struct _CDB::_SYNCHRONIZE_CACHE10 SYNCHRONIZE_CACHE10
CLASS_POWER_OPTIONS Options
Definition: classpnp.h:681
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
CLASS_POWER_UP_STATE PowerUp
Definition: classpnp.h:679
#define SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED
Definition: scsi.h:3839
__control_entrypoint(DeviceDriver)
Definition: power.c:1983
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
FORCEINLINE PCDB SrbGetCdb(_In_ PVOID Srb)
Definition: srbhelper.h:583
struct _CLASS_POWER_CONTEXT * PCLASS_POWER_CONTEXT
#define CLASS_SPECIAL_DISABLE_SPIN_DOWN
Definition: classpnp.h:165
VOID NTAPI ClassCheckMediaState(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:1752
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
KGUARDED_MUTEX IdlePowerFDOListMutex
Definition: class.c:114
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
enum OPTION_FLAGS Options
Definition: stats.c:44
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
VOID ClassRetryRequest(IN PDEVICE_OBJECT SelfDeviceObject, IN PIRP Irp, _In_ _In_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) IN LONGLONG TimeDelta100ns)
Definition: class.c:12317
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:688
#define SRB_STATUS(Status)
Definition: srb.h:381
STORAGE_HOTPLUG_INFO HotplugInfo
Definition: classp.h:739
#define DEFAULT_IO_TIMEOUT_VALUE
Definition: power.c:43
IN UCHAR Value
Definition: halp.h:394
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
_IRQL_requires_same_ NTSTATUS ClasspSendEnableIdlePowerIoctl(_In_ PDEVICE_OBJECT DeviceObject)
Definition: power.c:2333
#define CLASS_TAG_POWER
Definition: power.c:37
PCLASS_TICK ClassTick
Definition: classpnp.h:545
BOOLEAN ClasspScreenOff
Definition: autorun.c:124
#define IRP_MJ_SCSI
struct SRB_ALIGN _STORAGE_REQUEST_BLOCK_HEADER * PSTORAGE_REQUEST_BLOCK_HEADER
FORCEINLINE VOID IoCopyCurrentIrpStackLocationToNext(_Inout_ PIRP Irp)
Definition: iofuncs.h:2864
#define MAXIMUM_RETRIES
Definition: cdrom.h:124
IO_COMPLETION_ROUTINE ClasspPowerUpCompletion
Definition: power.c:63
while(1)
Definition: macro.lex.yy.c:740
BOOLEAN MediaHotplug
Definition: imports.h:247
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
__inline UCHAR GET_FDO_EXTENSON_SENSE_DATA_LENGTH(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: classpnp.h:1437
union _CLASS_POWER_CONTEXT::@1885 PowerChangeState
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define CLASSP_REG_SUBKEY_NAME
Definition: cdromp.h:120
FORCEINLINE VOID SrbSetScsiStatus(_In_ PVOID Srb, _In_ UCHAR ScsiStatus)
Definition: srbhelper.h:1056
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
SCSI_REQUEST_BLOCK Srb
Definition: classpnp.h:690
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
struct _IDLE_POWER_FDO_LIST_ENTRY * PIDLE_POWER_FDO_LIST_ENTRY
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
BOOLEAN ClasspUpdateTimerNoWakeTolerance(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3653
#define SRB_FLAGS_BYPASS_LOCKED_QUEUE
Definition: srb.h:402
PVOID DeviceExtension
Definition: env_spec_w32.h:418
IO_COMPLETION_ROUTINE ClasspStartNextPowerIrpCompletion
Definition: power.c:65
unsigned char BOOLEAN
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
PDEVICE_OBJECT Fdo
Definition: classp.h:1035
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS ClasspPowerHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN CLASS_POWER_OPTIONS Options)
Definition: power.c:1554
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
#define _IRQL_requires_same_
Definition: driverspecs.h:215
#define MINIMUM_START_UNIT_TIMEOUT_VALUE
Definition: power.c:53
struct _CDB::_START_STOP START_STOP
_In_ LPCGUID SettingGuid
Definition: pofuncs.h:120
#define IOCTL_STORAGE_ENABLE_IDLE_POWER
Definition: ntddstor.h:214
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
UCHAR additionalSenseCode
Definition: scsi.h:4020
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
int64_t LONGLONG
Definition: typedefs.h:68
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PDEVICE_OBJECT DeviceObject
Definition: pci.h:43
_IRQL_requires_same_ NTSTATUS ClasspEnableIdlePower(_In_ PDEVICE_OBJECT DeviceObject)
Definition: power.c:2550
ULONG DiskIdleTimeoutInMS
Definition: class.c:132
IO_COMPLETION_ROUTINE ClasspDeviceLockFailurePowerIrpCompletion
Definition: power.c:66
#define FDO_HACK_NO_SYNC_CACHE
Definition: classp.h:137
if(!(yy_init))
Definition: macro.lex.yy.c:714
PCLASS_POWER_DEVICE ClassPowerDevice
Definition: classpnp.h:529
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
IO_COMPLETION_ROUTINE ClasspPowerDownCompletion
Definition: power.c:61
#define CLASS_SPECIAL_DISABLE_SPIN_UP
Definition: classpnp.h:166
FORCEINLINE VOID SrbSetTimeOutValue(_In_ PVOID Srb, _In_ ULONG TimeOutValue)
Definition: srbhelper.h:821
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
#define CLASSP_REG_DISABLE_D3COLD
Definition: classp.h:125
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
USHORT Length
Definition: srb.h:241
PVPB NTAPI ClassGetVpb(_In_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:11473
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:657
struct _IRP * PIRP
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
POWER_SETTING_CALLBACK ClasspPowerSettingCallback
Definition: classp.h:1619
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
CLASS_POWER_CONTEXT PowerContext
Definition: classpnp.h:928
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:394
NTSTATUS NTAPI ClassDispatchPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: power.c:105
#define IRP_MJ_POWER
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
PDEVICE_OBJECT LowerPdo
Definition: classpnp.h:875
_In_ GUID _In_ PVOID _In_ ULONG ValueLength
Definition: hubbusif.h:311
PCLASS_DRIVER_EXTENSION DriverExtension
Definition: classpnp.h:600
VOID ClasspEnableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3857
#define IRP_MN_SET_POWER
Definition: typedefs.h:119
_In_ PTRANSFER_PACKET _In_ ULONG _In_ PIRP OriginalIrp
Definition: classp.h:1757
BOOLEAN ClasspFailurePredictionPeriodMissed(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:4391
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2691
SCSIPORT_API NTSTATUS NTAPI ClassSpinDownPowerHandler(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define _In_
Definition: no_sal2.h:158
VOID ClasspDisableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3956
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
#define TIME_LEFT_FOR_UPPER_DRIVERS
Definition: power.c:42
#define SRB_FLAGS_PORT_DRIVER_ALLOCSENSE
Definition: srb.h:405
#define InterlockedIncrement
Definition: armddk.h:53
struct _FAILURE_PREDICTION_INFO * FailurePredictionInfo
Definition: classpnp.h:919
VOID NTAPI PoStartNextPowerIrp(IN PIRP Irp)
Definition: power.c:737
PCLASS_DEV_INFO DevInfo
Definition: classpnp.h:620
FORCEINLINE PVOID SrbGetSenseInfoBuffer(_In_ PVOID Srb)
Definition: srbhelper.h:619
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define CLASS_SRBEX_NO_SRBEX_DATA_BUFFER_SIZE
Definition: classpnp.h:696
#define _Analysis_assume_
Definition: no_sal2.h:388
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
Definition: classp.h:1033
#define START_UNIT_TIMEOUT
Definition: cdrom.h:132
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID RetryPowerRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp, PCLASS_POWER_CONTEXT Context)
Definition: power.c:2097
#define TIME_LEFT_FOR_LOWER_DRIVERS
Definition: power.c:41
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
CLASS_INIT_DATA InitData
Definition: classpnp.h:577
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:581
FORCEINLINE VOID SrbSetSenseInfoBuffer(_In_ PVOID Srb, _In_opt_ PVOID SenseInfoBuffer)
Definition: srbhelper.h:657
FORCEINLINE VOID SrbSetSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:964
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
POWER_STATE NTAPI PoSetPowerState(IN PDEVICE_OBJECT DeviceObject, IN POWER_STATE_TYPE Type, IN POWER_STATE State)
Definition: power.c:708
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
#define DEFAULT_POWER_IRP_TIMEOUT_VALUE
Definition: power.c:40
#define MINIMAL_START_UNIT_TIMEOUT_VALUE
Definition: power.c:52
LIST_ENTRY IdlePowerFDOList
Definition: class.c:113
NTSTATUS NTAPI ClassMinimalPowerHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: power.c:1890
_In_ SYSTEM_POWER_STATE SystemPowerState
Definition: iotypes.h:7498
#define SRB_FLAGS_D3_PROCESSING
Definition: srb.h:156
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
BOOLEAN MediaRemovable
Definition: imports.h:246
return STATUS_SUCCESS
Definition: btrfs.c:3014
IoMarkIrpPending(Irp)
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
#define VPB_MOUNTED
Definition: iotypes.h:1787
#define MINIMUM_STOP_UNIT_TIMEOUT_VALUE
Definition: power.c:44
static SERVICE_STATUS status
Definition: service.c:31
CLASS_POWER_DOWN_STATE3 PowerDown3
Definition: classpnp.h:678
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2676
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define SCSIOP_START_STOP_UNIT
Definition: cdrw_hw.h:897
LIST_ENTRY ListEntry
Definition: classp.h:1034
#define SRB_FUNCTION_LOCK_QUEUE
Definition: srb.h:324
BOOLEAN validSense
Definition: scsi.h:4018
DEVICE_POWER_STATE DevicePowerState
Definition: classpnp.h:878
#define _Inout_opt_
Definition: no_sal2.h:216
NTKRNLVISTAAPI NTSTATUS NTAPI PoRegisterPowerSettingCallback(_In_opt_ PDEVICE_OBJECT DeviceObject, _In_ LPCGUID SettingGuid, _In_ PPOWER_SETTING_CALLBACK Callback, _In_opt_ PVOID Context, _Outptr_opt_ PVOID *Handle)
Definition: po.c:14
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97