ReactOS  0.4.15-dev-1203-g0e5a4d5
power.c File Reference
#include "stddef.h"
#include "ntddk.h"
#include "scsi.h"
#include "classp.h"
Include dependency graph for power.c:

Go to the source code of this file.

Macros

#define CLASS_TAG_POWER   'WLcS'
 
#define DEFAULT_POWER_IRP_TIMEOUT_VALUE   10*60
 
#define TIME_LEFT_FOR_LOWER_DRIVERS   30
 
#define TIME_LEFT_FOR_UPPER_DRIVERS   5
 
#define DEFAULT_IO_TIMEOUT_VALUE   10
 
#define MINIMUM_STOP_UNIT_TIMEOUT_VALUE   2
 
#define MINIMAL_START_UNIT_TIMEOUT_VALUE   60
 
#define MINIMUM_START_UNIT_TIMEOUT_VALUE   30
 

Functions

NTSTATUS ClasspPowerHandler (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN CLASS_POWER_OPTIONS Options)
 
VOID RetryPowerRequest (PDEVICE_OBJECT DeviceObject, PIRP Irp, PCLASS_POWER_CONTEXT Context)
 
NTSTATUS NTAPI ClassDispatchPower (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
NTSTATUS NTAPI ClasspPowerUpCompletion (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
 
NTSTATUS NTAPI ClasspPowerDownCompletion (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
 
NTSTATUS NTAPI ClassMinimalPowerHandler (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
 __control_entrypoint (DeviceDriver)
 
NTSTATUS NTAPI ClassStopUnitPowerHandler (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
 
NTSTATUS NTAPI ClasspStartNextPowerIrpCompletion (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
 
NTSTATUS NTAPI ClasspDeviceLockFailurePowerIrpCompletion (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
 
_IRQL_requires_same_ NTSTATUS ClasspSendEnableIdlePowerIoctl (_In_ PDEVICE_OBJECT DeviceObject)
 
 _Function_class_ (POWER_SETTING_CALLBACK)
 
_IRQL_requires_same_ NTSTATUS ClasspEnableIdlePower (_In_ PDEVICE_OBJECT DeviceObject)
 

Variables

IO_COMPLETION_ROUTINE ClasspPowerDownCompletion
 
IO_COMPLETION_ROUTINE ClasspPowerUpCompletion
 
IO_COMPLETION_ROUTINE ClasspStartNextPowerIrpCompletion
 
IO_COMPLETION_ROUTINE ClasspDeviceLockFailurePowerIrpCompletion
 

Macro Definition Documentation

◆ CLASS_TAG_POWER

#define CLASS_TAG_POWER   'WLcS'

Definition at line 37 of file power.c.

◆ DEFAULT_IO_TIMEOUT_VALUE

#define DEFAULT_IO_TIMEOUT_VALUE   10

Definition at line 43 of file power.c.

◆ DEFAULT_POWER_IRP_TIMEOUT_VALUE

#define DEFAULT_POWER_IRP_TIMEOUT_VALUE   10*60

Definition at line 40 of file power.c.

◆ MINIMAL_START_UNIT_TIMEOUT_VALUE

#define MINIMAL_START_UNIT_TIMEOUT_VALUE   60

Definition at line 52 of file power.c.

◆ MINIMUM_START_UNIT_TIMEOUT_VALUE

#define MINIMUM_START_UNIT_TIMEOUT_VALUE   30

Definition at line 53 of file power.c.

◆ MINIMUM_STOP_UNIT_TIMEOUT_VALUE

#define MINIMUM_STOP_UNIT_TIMEOUT_VALUE   2

Definition at line 44 of file power.c.

◆ TIME_LEFT_FOR_LOWER_DRIVERS

#define TIME_LEFT_FOR_LOWER_DRIVERS   30

Definition at line 41 of file power.c.

◆ TIME_LEFT_FOR_UPPER_DRIVERS

#define TIME_LEFT_FOR_UPPER_DRIVERS   5

Definition at line 42 of file power.c.

Function Documentation

◆ __control_entrypoint()

__control_entrypoint ( DeviceDriver  )

Definition at line 1983 of file power.c.

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()
#define CLASS_SPECIAL_NO_QUEUE_LOCK
Definition: classpnp.h:167
_In_ PIRP Irp
Definition: csq.h:116
#define TRUE
Definition: types.h:120
#define CLASS_SPECIAL_DISABLE_SPIN_DOWN
Definition: classpnp.h:165
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
NTSTATUS ClasspPowerHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN CLASS_POWER_OPTIONS Options)
Definition: power.c:1554
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define CLASS_SPECIAL_DISABLE_SPIN_UP
Definition: classpnp.h:166
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464

◆ _Function_class_()

_Function_class_ ( POWER_SETTING_CALLBACK  )

Definition at line 2393 of file power.c.

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 }
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: classpnp.h:905
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
VOID NTAPI ClassCheckMediaState(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:1752
KGUARDED_MUTEX IdlePowerFDOListMutex
Definition: class.c:114
IN UCHAR Value
Definition: halp.h:394
_IRQL_requires_same_ NTSTATUS ClasspSendEnableIdlePowerIoctl(_In_ PDEVICE_OBJECT DeviceObject)
Definition: power.c:2333
BOOLEAN ClasspScreenOff
Definition: autorun.c:124
while(1)
Definition: macro.lex.yy.c:740
#define FALSE
Definition: types.h:117
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
struct _IDLE_POWER_FDO_LIST_ENTRY * PIDLE_POWER_FDO_LIST_ENTRY
BOOLEAN ClasspUpdateTimerNoWakeTolerance(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3653
PVOID DeviceExtension
Definition: env_spec_w32.h:418
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
_In_ LPCGUID SettingGuid
Definition: pofuncs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
ULONG DiskIdleTimeoutInMS
Definition: class.c:132
if(!(yy_init))
Definition: macro.lex.yy.c:714
struct _IRP * PIRP
POWER_SETTING_CALLBACK ClasspPowerSettingCallback
Definition: classp.h:1619
_In_ GUID _In_ PVOID _In_ ULONG ValueLength
Definition: hubbusif.h:311
Definition: typedefs.h:119
BOOLEAN ClasspFailurePredictionPeriodMissed(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:4391
struct _FAILURE_PREDICTION_INFO * FailurePredictionInfo
Definition: classpnp.h:919
unsigned int * PULONG
Definition: retypes.h:1
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
Definition: classp.h:1033
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
unsigned int ULONG
Definition: retypes.h:1
LIST_ENTRY IdlePowerFDOList
Definition: class.c:113
return STATUS_SUCCESS
Definition: btrfs.c:3014
LIST_ENTRY ListEntry
Definition: classp.h:1034
DEVICE_POWER_STATE DevicePowerState
Definition: classpnp.h:878
#define PAGED_CODE()

◆ ClassDispatchPower()

NTSTATUS NTAPI ClassDispatchPower ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 105 of file power.c.

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()
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:428
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
_In_ PIRP Irp
Definition: csq.h:116
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
PCLASS_POWER_DEVICE ClassPowerDevice
Definition: classpnp.h:529
VOID NTAPI PoStartNextPowerIrp(IN PIRP Irp)
Definition: power.c:737
PCLASS_DEV_INFO DevInfo
Definition: classpnp.h:620
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:581
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401

Referenced by ClassInitializeDispatchTables().

◆ ClassMinimalPowerHandler()

NTSTATUS NTAPI ClassMinimalPowerHandler ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 1890 of file power.c.

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()
#define IRP_MN_QUERY_POWER
_In_ PIRP Irp
Definition: csq.h:116
LONG NTSTATUS
Definition: precomp.h:26
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
FORCEINLINE VOID IoCopyCurrentIrpStackLocationToNext(_Inout_ PIRP Irp)
Definition: iofuncs.h:2864
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
PVPB NTAPI ClassGetVpb(_In_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:11473
#define IRP_MN_SET_POWER
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
VOID NTAPI PoStartNextPowerIrp(IN PIRP Irp)
Definition: power.c:737
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
#define IO_NO_INCREMENT
Definition: iotypes.h:581
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
return STATUS_SUCCESS
Definition: btrfs.c:3014
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
#define VPB_MOUNTED
Definition: iotypes.h:1787
static SERVICE_STATUS status
Definition: service.c:31
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
Definition: ps.c:97

Referenced by _IRQL_requires_max_().

◆ ClasspDeviceLockFailurePowerIrpCompletion()

NTSTATUS NTAPI ClasspDeviceLockFailurePowerIrpCompletion ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context 
)

Definition at line 2233 of file power.c.

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 }
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: classpnp.h:905
_In_ PIRP Irp
Definition: csq.h:116
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
struct _CLASS_POWER_CONTEXT * PCLASS_POWER_CONTEXT
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:688
PCLASS_TICK ClassTick
Definition: classpnp.h:545
#define FALSE
Definition: types.h:117
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
PDEVICE_OBJECT DeviceObject
Definition: pci.h:43
PCLASS_DRIVER_EXTENSION DriverExtension
Definition: classpnp.h:600
VOID ClasspEnableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3857
BOOLEAN ClasspFailurePredictionPeriodMissed(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:4391
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
struct _FAILURE_PREDICTION_INFO * FailurePredictionInfo
Definition: classpnp.h:919
VOID NTAPI PoStartNextPowerIrp(IN PIRP Irp)
Definition: power.c:737
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
CLASS_INIT_DATA InitData
Definition: classpnp.h:577
POWER_STATE NTAPI PoSetPowerState(IN PDEVICE_OBJECT DeviceObject, IN POWER_STATE_TYPE Type, IN POWER_STATE State)
Definition: power.c:708
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
return STATUS_SUCCESS
Definition: btrfs.c:3014
IoMarkIrpPending(Irp)
DEVICE_POWER_STATE DevicePowerState
Definition: classpnp.h:878

◆ ClasspEnableIdlePower()

_IRQL_requires_same_ NTSTATUS ClasspEnableIdlePower ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 2550 of file power.c.

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 }
#define CLASSP_REG_IDLE_TIMEOUT_IN_SECONDS
Definition: classp.h:124
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define TRUE
Definition: types.h:120
PVOID PowerSettingNotificationHandle
Definition: class.c:119
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
LONG NTSTATUS
Definition: precomp.h:26
KGUARDED_MUTEX IdlePowerFDOListMutex
Definition: class.c:114
_IRQL_requires_same_ NTSTATUS ClasspSendEnableIdlePowerIoctl(_In_ PDEVICE_OBJECT DeviceObject)
Definition: power.c:2333
#define CLASS_TAG_POWER
Definition: power.c:37
#define CLASSP_REG_SUBKEY_NAME
Definition: cdromp.h:120
#define FALSE
Definition: types.h:117
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
PDEVICE_OBJECT Fdo
Definition: classp.h:1035
smooth NULL
Definition: ftsmooth.c:416
ULONG DiskIdleTimeoutInMS
Definition: class.c:132
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define CLASSP_REG_DISABLE_D3COLD
Definition: classp.h:125
POWER_SETTING_CALLBACK ClasspPowerSettingCallback
Definition: classp.h:1619
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
Definition: classp.h:1033
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
unsigned int ULONG
Definition: retypes.h:1
LIST_ENTRY IdlePowerFDOList
Definition: class.c:113
return STATUS_SUCCESS
Definition: btrfs.c:3014
static SERVICE_STATUS status
Definition: service.c:31
LIST_ENTRY ListEntry
Definition: classp.h:1034
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 NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

Referenced by ClassPnpStartDevice().

◆ ClasspPowerDownCompletion()

NTSTATUS NTAPI ClasspPowerDownCompletion ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context 
)

Definition at line 769 of file power.c.

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()
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:655
#define SRB_FUNCTION_UNLOCK_QUEUE
Definition: srb.h:325
#define SRB_FLAGS_DISABLE_AUTOSENSE
Definition: srb.h:391
#define SCSI_SENSEQ_FORMAT_IN_PROGRESS
Definition: cdrw_hw.h:1316
FORCEINLINE UCHAR SrbGetSenseInfoBufferLength(_In_ PVOID Srb)
Definition: srbhelper.h:638
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
#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
NTSTATUS FinalStatus
Definition: classpnp.h:684
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
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
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
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
struct _CDB::_SYNCHRONIZE_CACHE10 SYNCHRONIZE_CACHE10
CLASS_POWER_OPTIONS Options
Definition: classpnp.h:681
#define SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED
Definition: scsi.h:3839
#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
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:688
#define SRB_STATUS(Status)
Definition: srb.h:381
#define DEFAULT_IO_TIMEOUT_VALUE
Definition: power.c:43
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#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
__inline UCHAR GET_FDO_EXTENSON_SENSE_DATA_LENGTH(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: classpnp.h:1437
union _CLASS_POWER_CONTEXT::@1885 PowerChangeState
#define FALSE
Definition: types.h:117
SCSI_REQUEST_BLOCK Srb
Definition: classpnp.h:690
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
#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
smooth NULL
Definition: ftsmooth.c:416
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
struct _CDB::_START_STOP START_STOP
#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
PDEVICE_OBJECT DeviceObject
Definition: pci.h:43
#define FDO_HACK_NO_SYNC_CACHE
Definition: classp.h:137
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
IO_COMPLETION_ROUTINE ClasspPowerDownCompletion
Definition: power.c:61
FORCEINLINE VOID SrbSetTimeOutValue(_In_ PVOID Srb, _In_ ULONG TimeOutValue)
Definition: srbhelper.h:821
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
USHORT Length
Definition: srb.h:241
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:657
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:394
#define IRP_MJ_POWER
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
PDEVICE_OBJECT LowerPdo
Definition: classpnp.h:875
_In_ PTRANSFER_PACKET _In_ ULONG _In_ PIRP OriginalIrp
Definition: classp.h:1757
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2691
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
#define SRB_FLAGS_PORT_DRIVER_ALLOCSENSE
Definition: srb.h:405
VOID NTAPI PoStartNextPowerIrp(IN PIRP Irp)
Definition: power.c:737
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
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
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
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
#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 SRB_FLAGS_D3_PROCESSING
Definition: srb.h:156
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
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 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
#define SCSIOP_START_STOP_UNIT
Definition: cdrw_hw.h:897
BOOLEAN validSense
Definition: scsi.h:4018
DEVICE_POWER_STATE DevicePowerState
Definition: classpnp.h:878
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

◆ ClasspPowerHandler()

NTSTATUS ClasspPowerHandler ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN CLASS_POWER_OPTIONS  Options 
)

Definition at line 1554 of file power.c.

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()
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:655
FORCEINLINE VOID SrbSetOriginalRequest(_In_ PVOID Srb, _In_opt_ PVOID OriginalRequest)
Definition: srbhelper.h:710
FORCEINLINE ULONG SrbGetSrbFlags(_In_ PVOID Srb)
Definition: srbhelper.h:927
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:1971
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
Definition: http.c:7094
#define SRB_FLAGS_FREE_SENSE_BUFFER
Definition: srb.h:398
_In_ PIRP Irp
Definition: csq.h:116
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define TRUE
Definition: types.h:120
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
LONG NTSTATUS
Definition: precomp.h:26
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
enum OPTION_FLAGS Options
Definition: stats.c:44
STORAGE_HOTPLUG_INFO HotplugInfo
Definition: classp.h:739
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#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
BOOLEAN MediaHotplug
Definition: imports.h:247
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
#define SRB_FLAGS_BYPASS_LOCKED_QUEUE
Definition: srb.h:402
IO_COMPLETION_ROUTINE ClasspStartNextPowerIrpCompletion
Definition: power.c:65
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
IO_COMPLETION_ROUTINE ClasspPowerDownCompletion
Definition: power.c:61
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:657
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
CLASS_POWER_CONTEXT PowerContext
Definition: classpnp.h:928
#define IRP_MN_SET_POWER
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2691
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
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 SRB_FLAGS_PORT_DRIVER_ALLOCSENSE
Definition: srb.h:405
#define InterlockedIncrement
Definition: armddk.h:53
VOID NTAPI PoStartNextPowerIrp(IN PIRP Irp)
Definition: power.c:737
#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
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#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 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
_In_ SYSTEM_POWER_STATE SystemPowerState
Definition: iotypes.h:7498
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
static SERVICE_STATUS status
Definition: service.c:31
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2676
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define SRB_FUNCTION_LOCK_QUEUE
Definition: srb.h:324
DEVICE_POWER_STATE DevicePowerState
Definition: classpnp.h:878
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

Referenced by __control_entrypoint().

◆ ClasspPowerUpCompletion()

NTSTATUS NTAPI ClasspPowerUpCompletion ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context 
)

Definition at line 186 of file power.c.

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()
#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
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
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
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: classpnp.h:905
NTSTATUS FinalStatus
Definition: classpnp.h:684
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
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
_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
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:599
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
CLASS_POWER_OPTIONS Options
Definition: classpnp.h:681
CLASS_POWER_UP_STATE PowerUp
Definition: classpnp.h:679
FORCEINLINE PCDB SrbGetCdb(_In_ PVOID Srb)
Definition: srbhelper.h:583
struct _CLASS_POWER_CONTEXT * PCLASS_POWER_CONTEXT
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:688
#define SRB_STATUS(Status)
Definition: srb.h:381
#define DEFAULT_IO_TIMEOUT_VALUE
Definition: power.c:43
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
PCLASS_TICK ClassTick
Definition: classpnp.h:545
#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
__inline UCHAR GET_FDO_EXTENSON_SENSE_DATA_LENGTH(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: classpnp.h:1437
union _CLASS_POWER_CONTEXT::@1885 PowerChangeState
#define FALSE
Definition: types.h:117
SCSI_REQUEST_BLOCK Srb
Definition: classpnp.h:690
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
#define SRB_FLAGS_BYPASS_LOCKED_QUEUE
Definition: srb.h:402
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
#define MINIMUM_START_UNIT_TIMEOUT_VALUE
Definition: power.c:53
struct _CDB::_START_STOP START_STOP
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
int64_t LONGLONG
Definition: typedefs.h:68
PDEVICE_OBJECT DeviceObject
Definition: pci.h:43
IO_COMPLETION_ROUTINE ClasspDeviceLockFailurePowerIrpCompletion
Definition: power.c:66
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
FORCEINLINE VOID SrbSetTimeOutValue(_In_ PVOID Srb, _In_ ULONG TimeOutValue)
Definition: srbhelper.h:821
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
USHORT Length
Definition: srb.h:241
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:657
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:394
#define IRP_MJ_POWER
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
PDEVICE_OBJECT LowerPdo
Definition: classpnp.h:875
PCLASS_DRIVER_EXTENSION DriverExtension
Definition: classpnp.h:600
VOID ClasspEnableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3857
_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
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
__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
struct _FAILURE_PREDICTION_INFO * FailurePredictionInfo
Definition: classpnp.h:919
VOID NTAPI PoStartNextPowerIrp(IN PIRP Irp)
Definition: power.c:737
#define CLASS_SRBEX_NO_SRBEX_DATA_BUFFER_SIZE
Definition: classpnp.h:696
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
#define min(a, b)
Definition: monoChain.cc:55
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define START_UNIT_TIMEOUT
Definition: cdrom.h:132
VOID RetryPowerRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp, PCLASS_POWER_CONTEXT Context)
Definition: power.c:2097
#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
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
IoMarkIrpPending(Irp)
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
static SERVICE_STATUS status
Definition: service.c:31
#define SCSIOP_START_STOP_UNIT
Definition: cdrw_hw.h:897
DEVICE_POWER_STATE DevicePowerState
Definition: classpnp.h:878
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

◆ ClasspSendEnableIdlePowerIoctl()

_IRQL_requires_same_ NTSTATUS ClasspSendEnableIdlePowerIoctl ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 2333 of file power.c.

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 }
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
struct _STORAGE_IDLE_POWER STORAGE_IDLE_POWER
LONG NTSTATUS
Definition: precomp.h:26
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define FALSE
Definition: types.h:117
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
#define IOCTL_STORAGE_ENABLE_IDLE_POWER
Definition: ntddstor.h:214
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

Referenced by _Function_class_(), and ClasspEnableIdlePower().

◆ ClasspStartNextPowerIrpCompletion()

NTSTATUS NTAPI ClasspStartNextPowerIrpCompletion ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Context 
)

Definition at line 2207 of file power.c.

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()
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
struct _CLASS_POWER_CONTEXT * PCLASS_POWER_CONTEXT
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
VOID NTAPI PoStartNextPowerIrp(IN PIRP Irp)
Definition: power.c:737
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
return STATUS_SUCCESS
Definition: btrfs.c:3014
IoMarkIrpPending(Irp)

◆ ClassStopUnitPowerHandler()

NTSTATUS NTAPI ClassStopUnitPowerHandler ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp 
)

Definition at line 2048 of file power.c.

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()
#define CLASS_SPECIAL_NO_QUEUE_LOCK
Definition: classpnp.h:167
_In_ PIRP Irp
Definition: csq.h:116
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
#define CLASS_SPECIAL_DISABLE_SPIN_UP
Definition: classpnp.h:166
SCSIPORT_API NTSTATUS NTAPI ClassSpinDownPowerHandler(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493

◆ RetryPowerRequest()

VOID RetryPowerRequest ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp,
PCLASS_POWER_CONTEXT  Context 
)

Definition at line 2097 of file power.c.

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()
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:655
FORCEINLINE ULONG SrbGetSrbFlags(_In_ PVOID Srb)
Definition: srbhelper.h:927
FORCEINLINE VOID SrbSetDataTransferLength(_In_ PVOID Srb, _In_ ULONG DataTransferLength)
Definition: srbhelper.h:784
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define SRB_FLAGS_FREE_SENSE_BUFFER
Definition: srb.h:398
_In_ PIRP Irp
Definition: csq.h:116
#define TRUE
Definition: types.h:120
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
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
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#define IRP_MJ_SCSI
struct SRB_ALIGN _STORAGE_REQUEST_BLOCK_HEADER * PSTORAGE_REQUEST_BLOCK_HEADER
FORCEINLINE VOID SrbSetScsiStatus(_In_ PVOID Srb, _In_ UCHAR ScsiStatus)
Definition: srbhelper.h:1056
struct _FUNCTIONAL_DEVICE_EXTENSION * PFUNCTIONAL_DEVICE_EXTENSION
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
int64_t LONGLONG
Definition: typedefs.h:68
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2691
#define SRB_FLAGS_PORT_DRIVER_ALLOCSENSE
Definition: srb.h:405
_In_ PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2464
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
unsigned int ULONG
Definition: retypes.h:1
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
#define NT_ASSERT
Definition: rtlfuncs.h:3312

Referenced by ClasspPowerDownCompletion(), and ClasspPowerUpCompletion().

Variable Documentation

◆ ClasspDeviceLockFailurePowerIrpCompletion

IO_COMPLETION_ROUTINE ClasspDeviceLockFailurePowerIrpCompletion

Definition at line 66 of file power.c.

Referenced by ClasspPowerUpCompletion().

◆ ClasspPowerDownCompletion

IO_COMPLETION_ROUTINE ClasspPowerDownCompletion

Definition at line 61 of file power.c.

Referenced by ClasspPowerDownCompletion(), and ClasspPowerHandler().

◆ ClasspPowerUpCompletion

IO_COMPLETION_ROUTINE ClasspPowerUpCompletion

Definition at line 63 of file power.c.

Referenced by ClasspPowerHandler(), and ClasspPowerUpCompletion().

◆ ClasspStartNextPowerIrpCompletion

IO_COMPLETION_ROUTINE ClasspStartNextPowerIrpCompletion

Definition at line 65 of file power.c.

Referenced by ClasspPowerDownCompletion(), and ClasspPowerHandler().