ReactOS  0.4.15-dev-1374-g8d3e80e
zpodd.c File Reference
#include "ntddk.h"
#include "ntddstor.h"
#include "wdmguid.h"
#include "cdrom.h"
#include "mmc.h"
#include "ioctl.h"
#include "scratch.h"
Include dependency graph for zpodd.c:

Go to the source code of this file.

Functions

 _IRQL_requires_max_ (PASSIVE_LEVEL)
 
 _IRQL_requires_max_ (APC_LEVEL)
 
NTSTATUS DeviceZPODDGetPowerupReason (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _Out_ PSTORAGE_IDLE_POWERUP_REASON PowerupReason)
 

Function Documentation

◆ _IRQL_requires_max_() [1/2]

_IRQL_requires_max_ ( PASSIVE_LEVEL  )

Definition at line 36 of file zpodd.c.

69  :4152) // nonstandard extension, function/data pointer conversion in expression
70 #pragma warning(disable:26000) // read overflow reported because of pointer type conversion
71 
74 DeviceInitializeZPODD(
75  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
76  )
77 /*++
78 
79 Routine Description:
80 
81  This routine initialize the contents of ZPODD structure.
82 
83 Arguments:
84 
85  DeviceExtension - the device extension
86 
87 Return Value:
88  NTSTATUS
89 
90 --*/
91 {
93  NTSTATUS tempStatus = STATUS_SUCCESS;
94  PZERO_POWER_ODD_INFO zpoddInfo = NULL;
95  PFEATURE_DATA_REMOVABLE_MEDIUM removableMediumHeader = NULL;
96  ULONG ZPODDEnabledInRegistry = 0;
97  PD3COLD_SUPPORT_INTERFACE d3ColdInterface = NULL;
98  DEVICE_WAKE_DEPTH deepestWakeableDstate = DeviceWakeDepthNotWakeable;
99  BOOLEAN inHomePosition = FALSE;
100 
101  PAGED_CODE();
102 
103  if (DeviceExtension->ZeroPowerODDInfo != NULL)
104  {
105  //
106  // Already initialized.
107  //
108 
109  goto Cleanup;
110  }
111 
112  ZPODDEnabledInRegistry = DeviceGetZPODDEnabledFromRegistry();
113 
114  if (ZPODDEnabledInRegistry == 0)
115  {
116  //
117  // User has explicitly disabled Zero Power ODD.
118  //
119 
121 
122  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
123  "DeviceInitializeZPODD: ZPODD not enabled due to registry settings.\n"
124  ));
125 
126  goto Cleanup;
127  }
128 
129  zpoddInfo = ExAllocatePoolWithTag(NonPagedPoolNx,
130  sizeof(ZERO_POWER_ODD_INFO),
132 
133  if (zpoddInfo == NULL)
134  {
136 
137  goto Cleanup;
138  }
139 
140  RtlZeroMemory(zpoddInfo, sizeof (ZERO_POWER_ODD_INFO));
141 
142  //
143  // Check the system for the following prerequisites:
144  //
145  // 1. SATA: Device Attention line
146  // 2. SATA: Asynchronous Notification
147  // 3. ODD: LoChange / MediaRemoval
148  // 4. ACPI: Wake capable
149  //
150  // Only drawer and slot loading types have well defined behaviors in the spec, so only these two
151  // types are supported.
152  //
153 
154  //
155  // Check for DA & AN
156  //
157 
158  if ((DeviceExtension->PowerDescriptor == NULL) ||
159  (DeviceExtension->PowerDescriptor->DeviceAttentionSupported == FALSE) ||
160  (DeviceExtension->PowerDescriptor->AsynchronousNotificationSupported == FALSE))
161  {
163 
164  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
165  "DeviceInitializeZPODD: ZPODD not enabled due to SATA features not present.\n"
166  ));
167 
168  goto Cleanup;
169  }
170 
171  //
172  // Check for LoChange / MediaRemoval
173  //
174 
175  removableMediumHeader = (PFEATURE_DATA_REMOVABLE_MEDIUM)
176  DeviceFindFeaturePage(DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBuffer,
177  DeviceExtension->DeviceAdditionalData.Mmc.CapabilitiesBufferSize,
179 
180  if ((removableMediumHeader == NULL) ||
181  (!((removableMediumHeader->LoadingMechanism == LOADING_MECHANISM_TRAY) && (removableMediumHeader->Load == 0) && // Drawer ...
182  (removableMediumHeader->DBML != FALSE)) && // requires LoChange/NotBusy
183  !((removableMediumHeader->LoadingMechanism == LOADING_MECHANISM_CADDY) && (removableMediumHeader->Load == 0) && // Slot ...
184  (DeviceExtension->MediaChangeDetectionInfo->Gesn.Supported != FALSE)))) // requires MediaRemoval
185  {
187 
188  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
189  "DeviceInitializeZPODD: ZPODD not enabled due to ODD features not present.\n"
190  ));
191 
192  goto Cleanup;
193  }
194 
195  zpoddInfo->LoadingMechanism = removableMediumHeader->LoadingMechanism;
196  zpoddInfo->Load = removableMediumHeader->Load;
197 
198  //
199  // Check for ACPI
200  //
201 
202  status = DeviceQueryD3ColdInterface(DeviceExtension, &zpoddInfo->D3ColdInterface);
203 
204  if (!NT_SUCCESS(status))
205  {
206  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
207  "DeviceInitializeZPODD: Query D3Cold support interface failed.\n"
208  ));
209 
210  goto Cleanup;
211  }
212 
213  //
214  // If the platform supports Zero Power ODD, the following conditions must be met:
215  //
216  // 1. The deepest wakeable D-state for the device is D3Cold;
217  // 2. The platform supports D3Cold for the device.
218  //
219 
220  d3ColdInterface = &zpoddInfo->D3ColdInterface;
221 
222  status = d3ColdInterface->GetIdleWakeInfo(d3ColdInterface->Context,
224  &deepestWakeableDstate);
225 
226  if (!NT_SUCCESS(status))
227  {
228  goto Cleanup;
229  }
230 
231  //
232  // DeviceExtension->PowerDescriptor->D3ColdSupported is retrieved from lower layer.
233  // It has more accurate supportive information than just uses d3ColdInterface->GetD3ColdCapability
234  //
235  if ((deepestWakeableDstate != DeviceWakeDepthD3cold) ||
236  (DeviceExtension->PowerDescriptor->D3ColdSupported == FALSE))
237  {
239 
240  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
241  "DeviceInitializeZPODD: ZPODD not enabled due to ACPI support not present.\n"
242  ));
243 
244  goto Cleanup;
245  }
246 
247  //
248  // The system meets all requirements. Go ahead and enable ZPODD.
249  //
250 
251  //
252  // Register with the runtime power framework.
253  // Note that no un-registration is needed during tear-down.
254  // D3Cold will be enabled (success case of following call) or disabled by port driver during processing Enable Idle Power IOCTL.
255  //
256 
257  status = DeviceSendEnableIdlePowerIoctl(DeviceExtension, TRUE, TRUE, DELAY_TIME_TO_ENTER_ZERO_POWER_IN_MS);
258 
259  if (!NT_SUCCESS(status))
260  {
261  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
262  "DeviceInitializeZPODD: ZPODD not enabled due to runtime power framework.\n"
263  ));
264 
265  goto Cleanup;
266  }
267 
268  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
269  "DeviceInitializeZPODD: ZPODD is enabled.\n"
270  ));
271 
272  DeviceExtension->ZeroPowerODDInfo = zpoddInfo;
273 
274  //
275  // If device is not in home position, then we should take an active reference here
276  // to prevent it from being powered off.
277  //
278 
279  inHomePosition = DeviceZPODDIsInHomePosition(DeviceExtension);
280 
281  if (inHomePosition == FALSE)
282  {
283  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
284  "DeviceInitializeZPODD: not ready to power off, device marked as active\n"));
285 
286  DeviceMarkActive(DeviceExtension, TRUE, FALSE);
287  }
288  else
289  {
290  //
291  // cache get configuration response.
292  // failing is not critical, so we don't want to check for status here.
293  //
294 
295  if (zpoddInfo->GetConfigurationBuffer == NULL)
296  {
297  tempStatus = DeviceGetConfigurationWithAlloc(DeviceExtension->Device,
298  &zpoddInfo->GetConfigurationBuffer,
299  &zpoddInfo->GetConfigurationBufferSize,
302 
303  UNREFERENCED_PARAMETER(tempStatus); // Avoid PREFAST warning.
304  }
305  }
306 
307 Cleanup:
308 
309  if (!NT_SUCCESS(status))
310  {
311  //
312  // We register always even in non-ZPODD case, per request from storport.
313  //
314 
315  tempStatus = DeviceSendEnableIdlePowerIoctl(DeviceExtension, FALSE, FALSE, DELAY_TIME_TO_ENTER_ZERO_POWER_IN_MS);
316 
317  if (NT_SUCCESS(tempStatus))
318  {
319  //
320  // Mark the device active; this reference will never be released unless the system enters a
321  // low power state.
322  //
323 
324  DeviceMarkActive(DeviceExtension, TRUE, FALSE);
325  }
326 
327  FREE_POOL(zpoddInfo);
328  }
329 
330  //
331  // If Zero Power ODD is not supported, we should not block the device init sequence.
332  //
333 
334  return STATUS_SUCCESS;
335 }
return STATUS_NOT_SUPPORTED
#define LOADING_MECHANISM_CADDY
Definition: scsi.h:971
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define CDROM_TAG_ZERO_POWER_ODD
Definition: cdrom.h:745
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_IRQL_requires_max_(PASSIVE_LEVEL)
Definition: zpodd.c:36
LONG NTSTATUS
Definition: precomp.h:26
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
ULONG GetConfigurationBufferSize
Definition: cdromp.h:284
D3COLD_SUPPORT_INTERFACE D3ColdInterface
Definition: cdromp.h:269
enum _DEVICE_WAKE_DEPTH DEVICE_WAKE_DEPTH
#define LOADING_MECHANISM_TRAY
Definition: scsi.h:972
#define FALSE
Definition: types.h:117
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
unsigned char BOOLEAN
PGET_CONFIGURATION_HEADER GetConfigurationBuffer
Definition: cdromp.h:283
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define DELAY_TIME_TO_ENTER_ZERO_POWER_IN_MS
Definition: cdromp.h:259
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
struct _FEATURE_DATA_REMOVABLE_MEDIUM * PFEATURE_DATA_REMOVABLE_MEDIUM
PGET_IDLE_WAKE_INFO GetIdleWakeInfo
Definition: iotypes.h:7538
#define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL
Definition: ntddmmc.h:15
static const WCHAR Cleanup[]
Definition: register.c:80
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define _In_
Definition: no_sal2.h:158
#define NULL
Definition: types.h:112
int disable
Definition: msacm.c:1365
UCHAR LoadingMechanism
Definition: cdromp.h:266
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_SUCCESS
Definition: shellext.h:65
#define warning(s)
Definition: debug.h:83
#define PAGED_CODE()
Definition: ps.c:97

◆ _IRQL_requires_max_() [2/2]

_IRQL_requires_max_ ( APC_LEVEL  )

Definition at line 574 of file zpodd.c.

593 {
594  PZERO_POWER_ODD_INFO zpoddInfo = DeviceExtension->ZeroPowerODDInfo;
595 
596  PAGED_CODE()
597 
598  if (zpoddInfo != NULL)
599  {
600  FREE_POOL(zpoddInfo->GetConfigurationBuffer);
601  FREE_POOL(zpoddInfo);
602  }
603 
604  return;
605 }
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
PGET_CONFIGURATION_HEADER GetConfigurationBuffer
Definition: cdromp.h:283
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define NULL
Definition: types.h:112
#define PAGED_CODE()

◆ DeviceZPODDGetPowerupReason()

NTSTATUS DeviceZPODDGetPowerupReason ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_Out_ PSTORAGE_IDLE_POWERUP_REASON  PowerupReason 
)

Definition at line 608 of file zpodd.c.

627 {
629  PIRP irp = NULL;
630  IO_STATUS_BLOCK ioStatus = {0};
631  KEVENT event;
632 
633  RtlZeroMemory(PowerupReason, sizeof (STORAGE_IDLE_POWERUP_REASON));
634 
635  PowerupReason->Size = sizeof (STORAGE_IDLE_POWERUP_REASON);
636  PowerupReason->Version = STORAGE_IDLE_POWERUP_REASON_VERSION_V1;
637 
638  //
639  // Setup a synchronous irp.
640  //
641 
643 
645  DeviceExtension->LowerPdo,
646  PowerupReason,
648  PowerupReason,
650  FALSE,
651  &event,
652  &ioStatus);
653 
654  if (irp == NULL)
655  {
657  }
658  else
659  {
660  //
661  // Send the synchronous request to port driver.
662  //
663 
664  status = IoCallDriver(DeviceExtension->LowerPdo, irp);
665 
666  if (status == STATUS_PENDING)
667  {
669 
670  status = ioStatus.Status;
671  }
672  }
673 
674  return status;
675 }
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define FALSE
Definition: types.h:117
struct _STORAGE_IDLE_POWERUP_REASON STORAGE_IDLE_POWERUP_REASON
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STORAGE_IDLE_POWERUP_REASON_VERSION_V1
Definition: ntddstor.h:1105
struct _cl_event * event
Definition: glext.h:7739
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define NULL
Definition: types.h:112
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define IOCTL_STORAGE_GET_IDLE_POWERUP_REASON
Definition: ntddstor.h:217
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_SUCCESS
Definition: shellext.h:65
static SERVICE_STATUS status
Definition: service.c:31
FxIrp * irp
Definition: ps.c:97

Referenced by DeviceEvtD0Entry().