ReactOS 0.4.16-dev-197-g92996da
power.c
Go to the documentation of this file.
1/*++
2
3Copyright (C) Microsoft Corporation, 1991 - 2010
4
5Module Name:
6
7 power.c
8
9Abstract:
10
11 SCSI class driver routines
12
13Environment:
14
15 kernel mode only
16
17Notes:
18
19
20Revision 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
61IO_COMPLETION_ROUTINE ClasspPowerDownCompletion;
62
63IO_COMPLETION_ROUTINE ClasspPowerUpCompletion;
64
67
71 IN PIRP Irp,
73 );
74
75VOID
78 PIRP Irp,
80 );
81
82#ifdef ALLOC_PRAGMA
83 #pragma alloc_text(PAGE, ClasspPowerSettingCallback)
84#endif
85
86/*++////////////////////////////////////////////////////////////////////////////
87
88ClassDispatchPower()
89
90Routine Description:
91
92 This routine acquires the removelock for the irp and then calls the
93 appropriate power callback.
94
95Arguments:
96
97 DeviceObject -
98 Irp -
99
100Return Value:
101
102--*/
104NTAPI /* 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
147ClasspPowerUpCompletion()
148
149Routine 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
170Arguments:
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
178Return Value:
179
180 STATUS_MORE_PROCESSING_REQUIRED or
181 STATUS_SUCCESS
182
183--*/
185NTAPI /* 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 //
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
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,
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
552ClasspPowerUpCompletionFailure:
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.
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
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
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
724ClasspPowerDownCompletion()
725
726Routine 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
753Arguments:
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
761Return Value:
762
763 STATUS_MORE_PROCESSING_REQUIRED or
764 STATUS_SUCCESS
765
766--*/
768NTAPI /* 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
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,
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 //
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.
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
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,
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 //
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
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,
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 //
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
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
1533ClasspPowerHandler()
1534
1535Routine 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
1544Arguments:
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
1550Return Value:
1551
1552--*/
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;
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:
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 //
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
1860ClasspPowerHandlerCleanup:
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
1880ClassMinimalPowerHandler()
1881
1882Routine 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--*/
1889NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1892 IN PIRP Irp
1893 )
1894{
1895 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
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:
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
1959ClassSpinDownPowerHandler()
1960
1961Routine 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
1972Arguments:
1973
1974 DeviceObject - Supplies the functional device object
1975
1976 Irp - Supplies the request to be retried.
1977
1978Return Value:
1979
1980 None
1981
1982--*/
1985NTAPI /* 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",
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
2034ClassStopUnitPowerHandler()
2035
2036Routine 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--*/
2047NTAPI /* 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
2076RetryPowerRequest()
2077
2078Routine Description:
2079
2080 This routine reinitalizes the necessary fields, and sends the request
2081 to the lower driver.
2082
2083Arguments:
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
2091Return Value:
2092
2093 None
2094
2095--*/
2096VOID
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)) {
2122 srbFunction = srb->Function;
2123 } else {
2124 srbFunction = ((PSTORAGE_REQUEST_BLOCK)srb)->SrbFunction;
2125 }
2126 } else {
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
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
2190
2191 return;
2192
2193} // end RetryRequest()
2194
2195/*++////////////////////////////////////////////////////////////////////////////
2196
2197ClasspStartNextPowerIrpCompletion()
2198
2199Routine 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--*/
2206NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2209 IN PIRP Irp,
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
2232NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2235 IN PIRP Irp,
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
2335 )
2336/*++
2337Description:
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
2343Arguments:
2344
2345 DeviceObject - The class FDO.
2346
2347Return 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{
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,
2386 idlePower.WakeCapableHint,
2387 idlePower.D3ColdSupported,
2388 idlePower.D3IdleTimeout));
2389
2390 return status;
2391}
2392
2393_Function_class_(POWER_SETTING_CALLBACK)
2396NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2402)
2403/*++
2404Description:
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
2414Arguments:
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
2421Return Value:
2422
2423 STATUS_SUCCESS
2424
2425--*/
2426{
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) {
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 //
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
2552 )
2553/*++
2554Description:
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
2564Arguments:
2565
2566 DeviceObject - The class FDO.
2567
2568Return 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)) {
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
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
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
struct _IRP * PIRP
#define PAGED_CODE()
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
LONG NTSTATUS
Definition: precomp.h:26
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
@ PowerUpDeviceOn
Definition: cdrom.h:422
@ PowerUpDeviceUnlocked
Definition: cdrom.h:424
@ PowerUpDeviceStarted
Definition: cdrom.h:423
@ PowerUpDeviceInitial
Definition: cdrom.h:420
@ PowerUpDeviceLocked
Definition: cdrom.h:421
#define START_UNIT_TIMEOUT
Definition: cdrom.h:132
#define MAXIMUM_RETRIES
Definition: cdrom.h:124
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define CLASSP_REG_SUBKEY_NAME
Definition: cdromp.h:120
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define SCSIOP_START_STOP_UNIT
Definition: cdrw_hw.h:897
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
#define SCSI_SENSEQ_FORMAT_IN_PROGRESS
Definition: cdrw_hw.h:1316
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
_In_ PTRANSFER_PACKET _In_ ULONG _In_ PIRP OriginalIrp
Definition: classp.h:1757
#define FDO_HACK_NO_SYNC_CACHE
Definition: classp.h:137
#define CLASSP_REG_IDLE_TIMEOUT_IN_SECONDS
Definition: classp.h:124
#define CLASSP_REG_DISABLE_D3COLD
Definition: classp.h:125
struct _IDLE_POWER_FDO_LIST_ENTRY * PIDLE_POWER_FDO_LIST_ENTRY
POWER_SETTING_CALLBACK ClasspPowerSettingCallback
Definition: classp.h:1619
BOOLEAN ClasspUpdateTimerNoWakeTolerance(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3653
VOID ClasspEnableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3857
VOID ClasspDisableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3956
BOOLEAN ClasspScreenOff
Definition: autorun.c:124
BOOLEAN ClasspFailurePredictionPeriodMissed(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:4391
VOID NTAPI ClassCheckMediaState(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:1752
FORCEINLINE UCHAR GET_FDO_EXTENSON_SENSE_DATA_LENGTH(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: classpnp.h:1437
#define CLASS_SRBEX_NO_SRBEX_DATA_BUFFER_SIZE
Definition: classpnp.h:696
struct _CLASS_POWER_CONTEXT * PCLASS_POWER_CONTEXT
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
SCSIPORT_API NTSTATUS NTAPI ClassSpinDownPowerHandler(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
#define CLASS_SPECIAL_DISABLE_SPIN_DOWN
Definition: classpnp.h:165
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
@ PowerDownDeviceUnlocked3
Definition: classpnp.h:264
@ PowerDownDeviceOff3
Definition: classpnp.h:263
@ PowerDownDeviceFlushed3
Definition: classpnp.h:261
@ PowerDownDeviceLocked3
Definition: classpnp.h:259
@ PowerDownDeviceInitial3
Definition: classpnp.h:258
@ PowerDownDeviceStopped3
Definition: classpnp.h:262
@ PowerDownDeviceQuiesced3
Definition: classpnp.h:260
#define CLASS_SPECIAL_NO_QUEUE_LOCK
Definition: classpnp.h:167
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
#define CLASS_SPECIAL_DISABLE_SPIN_UP
Definition: classpnp.h:166
@ FailurePredictionNone
Definition: classpnp.h:234
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_PENDING
Definition: d3dkmdt.h:43
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
@ DeviceDriver
Definition: devaction.c:68
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
PVPB NTAPI ClassGetVpb(_In_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:11473
KGUARDED_MUTEX IdlePowerFDOListMutex
Definition: class.c:114
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
ULONG DiskIdleTimeoutInMS
Definition: class.c:132
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
PVOID PowerSettingNotificationHandle
Definition: class.c:119
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
LIST_ENTRY IdlePowerFDOList
Definition: class.c:113
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
VOID RetryPowerRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp, PCLASS_POWER_CONTEXT Context)
Definition: power.c:2097
#define MINIMUM_START_UNIT_TIMEOUT_VALUE
Definition: power.c:53
#define DEFAULT_POWER_IRP_TIMEOUT_VALUE
Definition: power.c:40
#define CLASS_TAG_POWER
Definition: power.c:37
NTSTATUS NTAPI ClassMinimalPowerHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: power.c:1890
IO_COMPLETION_ROUTINE ClasspPowerUpCompletion
Definition: power.c:63
IO_COMPLETION_ROUTINE ClasspDeviceLockFailurePowerIrpCompletion
Definition: power.c:66
#define TIME_LEFT_FOR_UPPER_DRIVERS
Definition: power.c:42
IO_COMPLETION_ROUTINE ClasspPowerDownCompletion
Definition: power.c:61
#define DEFAULT_IO_TIMEOUT_VALUE
Definition: power.c:43
IO_COMPLETION_ROUTINE ClasspStartNextPowerIrpCompletion
Definition: power.c:65
_IRQL_requires_same_ NTSTATUS ClasspSendEnableIdlePowerIoctl(_In_ PDEVICE_OBJECT DeviceObject)
Definition: power.c:2333
#define TIME_LEFT_FOR_LOWER_DRIVERS
Definition: power.c:41
NTSTATUS ClasspPowerHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN CLASS_POWER_OPTIONS Options)
Definition: power.c:1554
_IRQL_requires_same_ NTSTATUS ClasspEnableIdlePower(_In_ PDEVICE_OBJECT DeviceObject)
Definition: power.c:2550
NTSTATUS NTAPI ClassDispatchPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: power.c:105
#define MINIMUM_STOP_UNIT_TIMEOUT_VALUE
Definition: power.c:44
NTSTATUS NTAPI ClassStopUnitPowerHandler(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
Definition: power.c:2048
#define MINIMAL_START_UNIT_TIMEOUT_VALUE
Definition: power.c:52
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define SRB_FLAGS_FREE_SENSE_BUFFER
Definition: srb.h:406
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:402
#define SRB_FUNCTION_LOCK_QUEUE
Definition: srb.h:332
#define SRB_FLAGS_PORT_DRIVER_ALLOCSENSE
Definition: srb.h:413
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:387
#define SRB_FLAGS_DISABLE_AUTOSENSE
Definition: srb.h:399
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define SRB_FUNCTION_UNLOCK_QUEUE
Definition: srb.h:333
#define SRB_FLAGS_BYPASS_LOCKED_QUEUE
Definition: srb.h:410
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:397
#define SRB_STATUS(Status)
Definition: srb.h:389
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:386
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:404
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define _IRQL_requires_same_
Definition: driverspecs.h:232
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
IoMarkIrpPending(Irp)
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
if(dx< 0)
Definition: linetemp.h:194
#define min(a, b)
Definition: monoChain.cc:55
#define _Function_class_(x)
Definition: ms_sal.h:2946
#define _In_reads_bytes_(size)
Definition: ms_sal.h:321
#define __control_entrypoint(category)
Definition: ms_sal.h:2879
#define _Inout_opt_
Definition: ms_sal.h:379
#define _In_
Definition: ms_sal.h:308
#define _Analysis_assume_(expr)
Definition: ms_sal.h:2901
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define IOCTL_STORAGE_ENABLE_IDLE_POWER
Definition: ntddstor.h:214
struct _STORAGE_IDLE_POWER STORAGE_IDLE_POWER
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IoCopyCurrentIrpStackLocationToNext(Irp)
Definition: ntifs_ex.h:413
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:1971
#define IoCallDriver
Definition: irp.c:1225
POWER_STATE NTAPI PoSetPowerState(IN PDEVICE_OBJECT DeviceObject, IN POWER_STATE_TYPE Type, IN POWER_STATE State)
Definition: power.c:729
VOID NTAPI PoStartNextPowerIrp(IN PIRP Irp)
Definition: power.c:758
@ DevicePowerState
Definition: ntpoapi.h:63
@ PowerActionNone
Definition: ntpoapi.h:123
@ PowerActionHibernate
Definition: ntpoapi.h:126
@ PowerActionSleep
Definition: ntpoapi.h:125
@ PowerDeviceD0
Definition: ntpoapi.h:49
@ PowerDeviceD3
Definition: ntpoapi.h:52
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:428
long LONG
Definition: pedump.c:60
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 IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
UCHAR additionalSenseCode
Definition: scsi.h:4020
UCHAR additionalSenseCodeQualifier
Definition: scsi.h:4021
#define SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED
Definition: scsi.h:3839
UCHAR senseKey
Definition: scsi.h:4019
BOOLEAN validSense
Definition: scsi.h:4018
#define SRB_FLAGS_D3_PROCESSING
Definition: srb.h:165
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:664
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:666
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:661
@ SrbExDataTypeScsiCdb16
Definition: srb.h:459
struct SRB_ALIGN _STORAGE_REQUEST_BLOCK_HEADER * PSTORAGE_REQUEST_BLOCK_HEADER
#define SRB_FUNCTION_QUIESCE_DEVICE
Definition: srb.h:99
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
FORCEINLINE VOID SrbSetSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:964
FORCEINLINE VOID SrbAssignSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:946
FORCEINLINE VOID SrbSetDataTransferLength(_In_ PVOID Srb, _In_ ULONG DataTransferLength)
Definition: srbhelper.h:784
FORCEINLINE VOID SrbSetOriginalRequest(_In_ PVOID Srb, _In_opt_ PVOID OriginalRequest)
Definition: srbhelper.h:710
FORCEINLINE VOID SrbSetScsiStatus(_In_ PVOID Srb, _In_ UCHAR ScsiStatus)
Definition: srbhelper.h:1056
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
FORCEINLINE ULONG SrbGetSrbFlags(_In_ PVOID Srb)
Definition: srbhelper.h:927
FORCEINLINE VOID SrbSetSenseInfoBuffer(_In_ PVOID Srb, _In_opt_ PVOID SenseInfoBuffer)
Definition: srbhelper.h:657
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
FORCEINLINE VOID SrbSetTimeOutValue(_In_ PVOID Srb, _In_ ULONG TimeOutValue)
Definition: srbhelper.h:821
FORCEINLINE PVOID SrbGetSenseInfoBuffer(_In_ PVOID Srb)
Definition: srbhelper.h:619
FORCEINLINE UCHAR SrbGetSenseInfoBufferLength(_In_ PVOID Srb)
Definition: srbhelper.h:638
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
PCLASS_POWER_DEVICE ClassPowerDevice
Definition: classpnp.h:529
CLASS_INIT_DATA InitData
Definition: classpnp.h:577
PCLASS_TICK ClassTick
Definition: classpnp.h:545
union _CLASS_POWER_CONTEXT::@1916 PowerChangeState
NTSTATUS FinalStatus
Definition: classpnp.h:684
CLASS_POWER_DOWN_STATE3 PowerDown3
Definition: classpnp.h:678
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:688
CLASS_POWER_UP_STATE PowerUp
Definition: classpnp.h:679
SCSI_REQUEST_BLOCK Srb
Definition: classpnp.h:690
CLASS_POWER_OPTIONS Options
Definition: classpnp.h:681
STORAGE_HOTPLUG_INFO HotplugInfo
Definition: classp.h:739
PDEVICE_OBJECT DeviceObject
Definition: pci.h:46
PCLASS_DRIVER_EXTENSION DriverExtension
Definition: classpnp.h:600
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:599
PCLASS_DEV_INFO DevInfo
Definition: classpnp.h:620
PVOID DeviceExtension
Definition: env_spec_w32.h:418
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
PDEVICE_OBJECT LowerPdo
Definition: classpnp.h:875
struct _FAILURE_PREDICTION_INFO * FailurePredictionInfo
Definition: classpnp.h:919
CLASS_POWER_CONTEXT PowerContext
Definition: classpnp.h:928
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
DEVICE_POWER_STATE DevicePowerState
Definition: classpnp.h:878
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: classpnp.h:905
Definition: classp.h:1033
LIST_ENTRY ListEntry
Definition: classp.h:1034
PDEVICE_OBJECT Fdo
Definition: classp.h:1035
struct _IO_STACK_LOCATION::@3974::@3996 Scsi
struct _IO_STACK_LOCATION::@3974::@4010 Power
union _IO_STACK_LOCATION::@1575 Parameters
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT Length
Definition: srb.h:249
BOOLEAN MediaRemovable
Definition: imports.h:246
BOOLEAN MediaHotplug
Definition: imports.h:247
Definition: http.c:7252
Definition: ps.c:97
uint32_t * PULONG
Definition: typedefs.h:59
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
Definition: cdrw_hw.h:28
struct _CDB::_START_STOP START_STOP
struct _CDB::_SYNCHRONIZE_CACHE10 SYNCHRONIZE_CACHE10
#define SrbGetCdb(srb)
Definition: usbstor.h:18
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3534
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2680
#define IRP_MJ_SCSI
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_MN_SET_POWER
#define IRP_MJ_POWER
_In_ SYSTEM_POWER_STATE SystemPowerState
Definition: iotypes.h:7519
#define IRP_MN_QUERY_POWER
_In_ LPCGUID SettingGuid
Definition: pofuncs.h:120
@ PowerMonitorOff
Definition: potypes.h:151
#define NT_ASSERT
Definition: rtlfuncs.h:3324
unsigned char UCHAR
Definition: xmlstorage.h:181