ReactOS 0.4.15-dev-7953-g1f49173
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_ ( 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 {
601 FREE_POOL(zpoddInfo);
602 }
603
604 return;
605}
#define PAGED_CODE()
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
#define NULL
Definition: types.h:112
if(dx< 0)
Definition: linetemp.h:194
PGET_CONFIGURATION_HEADER GetConfigurationBuffer
Definition: cdromp.h:283

◆ _IRQL_requires_max_() [2/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
74DeviceInitializeZPODD(
75 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
76 )
77/*++
78
79Routine Description:
80
81 This routine initialize the contents of ZPODD structure.
82
83Arguments:
84
85 DeviceExtension - the device extension
86
87Return 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
307Cleanup:
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}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define CDROM_TAG_ZERO_POWER_ODD
Definition: cdrom.h:745
#define DELAY_TIME_TO_ENTER_ZERO_POWER_IN_MS
Definition: cdromp.h:259
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static const WCHAR Cleanup[]
Definition: register.c:80
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define _In_
Definition: ms_sal.h:308
int disable
Definition: msacm.c:1365
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL
Definition: ntddmmc.h:15
@ FeatureRemovableMedium
Definition: ntddmmc.h:78
@ FeatureProfileList
Definition: ntddmmc.h:75
struct _FEATURE_DATA_REMOVABLE_MEDIUM * PFEATURE_DATA_REMOVABLE_MEDIUM
@ PowerSystemWorking
Definition: ntpoapi.h:36
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define LOADING_MECHANISM_CADDY
Definition: scsi.h:971
#define LOADING_MECHANISM_TRAY
Definition: scsi.h:972
#define warning(s)
Definition: debug.h:83
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
PGET_IDLE_WAKE_INFO GetIdleWakeInfo
Definition: iotypes.h:7559
ULONG GetConfigurationBufferSize
Definition: cdromp.h:284
D3COLD_SUPPORT_INTERFACE D3ColdInterface
Definition: cdromp.h:269
UCHAR LoadingMechanism
Definition: cdromp.h:266
Definition: ps.c:97
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
enum _DEVICE_WAKE_DEPTH DEVICE_WAKE_DEPTH
@ DeviceWakeDepthD3cold
Definition: iotypes.h:7484
@ DeviceWakeDepthNotWakeable
Definition: iotypes.h:7479

◆ 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};
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 KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
FxIrp * irp
struct _cl_event * event
Definition: glext.h:7739
#define KernelMode
Definition: asm.h:34
struct _STORAGE_IDLE_POWERUP_REASON STORAGE_IDLE_POWERUP_REASON
#define IOCTL_STORAGE_GET_IDLE_POWERUP_REASON
Definition: ntddstor.h:217
#define STORAGE_IDLE_POWERUP_REASON_VERSION_V1
Definition: ntddstor.h:1105
@ NotificationEvent
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 IoCallDriver
Definition: irp.c:1225
#define STATUS_PENDING
Definition: ntstatus.h:82
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
@ Executive
Definition: ketypes.h:415

Referenced by DeviceEvtD0Entry().