ReactOS 0.4.15-dev-8393-g61b7fb9
pnppower.c File Reference
#include "ntddk.h"
#include "wdfcore.h"
#include "cdrom.h"
#include "ioctl.h"
#include "scratch.h"
#include "mmc.h"
Include dependency graph for pnppower.c:

Go to the source code of this file.

Functions

NTSTATUS DeviceScratchSyncCache (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
 
NTSTATUS DeviceScratchPreventMediaRemoval (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ BOOLEAN Prevent)
 
NTSTATUS RequestIssueShutdownFlush (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PIRP Irp)
 
NTSTATUS NTAPI RequestProcessShutdownFlush (WDFDEVICE Device, PIRP Irp)
 
NTSTATUS NTAPI RequestProcessSetPower (WDFDEVICE Device, PIRP Irp)
 
VOID NTAPI RequestUnlockQueueCompletion (_In_ WDFREQUEST Request, _In_ WDFIOTARGET Target, _In_ PWDF_REQUEST_COMPLETION_PARAMS Params, _In_ WDFCONTEXT Context)
 
NTSTATUS NTAPI RequestProcessPowerIrpCompletion (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
 
 _IRQL_requires_max_ (DISPATCH_LEVEL)
 
 _Function_class_ (POWER_SETTING_CALLBACK)
 

Variables

IO_COMPLETION_ROUTINE RequestProcessPowerIrpCompletion
 
EVT_WDF_REQUEST_COMPLETION_ROUTINE RequestUnlockQueueCompletion
 

Function Documentation

◆ _Function_class_()

_Function_class_ ( POWER_SETTING_CALLBACK  )

Definition at line 609 of file pnppower.c.

642{
643 PCDROM_DEVICE_EXTENSION DeviceExtension = Context;
644 MONITOR_DISPLAY_STATE DisplayState;
645
646 PAGED_CODE();
647
648 if (IsEqualGUID(SettingGuid, &GUID_CONSOLE_DISPLAY_STATE)) {
649
650 if ((ValueLength == sizeof(ULONG)) && (Value != NULL)) {
651
652 DisplayState = *((PULONG)Value);
653
654 _Analysis_assume_(DeviceExtension != NULL);
655
656 //
657 // Power setting callbacks are asynchronous so make sure the device
658 // is completely initialized before taking any actions.
659 //
660 if (DeviceExtension->IsInitialized) {
661
662 //
663 // If monitor is off, change media change requests to not keep device active.
664 // This allows the devices to go to sleep if there are no other active requests.
665 //
666
667 if (DisplayState == PowerMonitorOff) {
668
669 //
670 // Mark the device inactive so that it can enter a low power state.
671 //
672
673 DeviceMarkActive(DeviceExtension, FALSE, TRUE);
675 }
676 else
677 {
679 DeviceMarkActive(DeviceExtension, TRUE, TRUE);
680 }
681 }
682 }
683 }
684
685 return STATUS_SUCCESS;
686}
#define PAGED_CODE()
#define CLEAR_FLAG(Flags, Bit)
Definition: cdrom.h:1494
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define SRB_FLAGS_NO_KEEP_AWAKE
Definition: srb.h:412
#define _Analysis_assume_(expr)
Definition: ms_sal.h:2901
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define STATUS_SUCCESS
Definition: shellext.h:65
BOOLEAN IsInitialized
Definition: cdrom.h:464
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: cdrom.h:563
uint32_t * PULONG
Definition: typedefs.h:59
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_In_ LPCGUID SettingGuid
Definition: pofuncs.h:120
@ PowerMonitorOff
Definition: potypes.h:151
enum _MONITOR_DISPLAY_STATE MONITOR_DISPLAY_STATE

◆ _IRQL_requires_max_()

_IRQL_requires_max_ ( DISPATCH_LEVEL  )

Definition at line 465 of file pnppower.c.

485{
487 WDF_REQUEST_REUSE_PARAMS reuseParams;
488 PIRP irp = NULL;
489
490 RtlZeroMemory(&(DeviceExtension->PowerContext.SenseData), sizeof(DeviceExtension->PowerContext.SenseData));
491 RtlZeroMemory(&(DeviceExtension->PowerContext.Srb), sizeof(DeviceExtension->PowerContext.Srb));
492
493 irp = WdfRequestWdmGetIrp(DeviceExtension->PowerContext.PowerRequest);
494
495 // Re-use the previously created PowerRequest object and format it
497 status = WdfRequestReuse(DeviceExtension->PowerContext.PowerRequest, &reuseParams);
498 if (NT_SUCCESS(status))
499 {
500 // This request was preformated during initialization so this call should never fail.
501 status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget,
502 DeviceExtension->PowerContext.PowerRequest,
504 NULL, NULL,
505 NULL, NULL,
506 NULL, NULL);
507
508 if (!NT_SUCCESS(status))
509 {
510 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,
511 "PowerContextReuseRequest: WdfIoTargetFormatRequestForInternalIoctlOthers failed, %!STATUS!\n",
512 status));
513 }
514 }
515
516 // Do some basic initialization of the PowerRequest, the rest will be done by the caller
517 // of this function
518 if (NT_SUCCESS(status))
519 {
520 PIO_STACK_LOCATION nextStack = NULL;
521
522 nextStack = IoGetNextIrpStackLocation(irp);
523
524 nextStack->MajorFunction = IRP_MJ_SCSI;
525 nextStack->Parameters.Scsi.Srb = &(DeviceExtension->PowerContext.Srb);
526
527 DeviceExtension->PowerContext.Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
528 DeviceExtension->PowerContext.Srb.OriginalRequest = irp;
529
530 DeviceExtension->PowerContext.Srb.SenseInfoBuffer = &(DeviceExtension->PowerContext.SenseData);
531 DeviceExtension->PowerContext.Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE;
532 }
533
534 return status;
535}
LONG NTSTATUS
Definition: precomp.h:26
#define IOCTL_SCSI_EXECUTE_IN
Definition: cdrw_hw.h:1451
#define SENSE_BUFFER_SIZE
Definition: cdrw_hw.h:1183
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
FxIrp * irp
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
union _IO_STACK_LOCATION::@1565 Parameters
struct _IO_STACK_LOCATION::@3974::@3996 Scsi
Definition: ps.c:97
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
@ WDF_REQUEST_REUSE_NO_FLAGS
Definition: wdfrequest.h:92
FORCEINLINE VOID WDF_REQUEST_REUSE_PARAMS_INIT(_Out_ PWDF_REQUEST_REUSE_PARAMS Params, _In_ ULONG Flags, _In_ NTSTATUS Status)
Definition: wdfrequest.h:364
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IRP_MJ_SCSI

◆ DeviceScratchPreventMediaRemoval()

NTSTATUS DeviceScratchPreventMediaRemoval ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ BOOLEAN  Prevent 
)

Definition at line 259 of file pnppower.c.

279{
281 ULONG transferSize = 0;
282 CDB cdb;
283
284 ScratchBuffer_BeginUse(DeviceExtension);
285
286 RtlZeroMemory(&cdb, sizeof(CDB));
287 // Set up the CDB
288 cdb.MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
289 cdb.MEDIA_REMOVAL.Prevent = Prevent;
290 //srb->QueueTag = SP_UNTAGGED;
291 //srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
292
293 status = ScratchBuffer_ExecuteCdb(DeviceExtension, NULL, transferSize, FALSE, &cdb, 6);
294
295 ScratchBuffer_EndUse(DeviceExtension);
296
297 return status;
298}
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
FORCEINLINE VOID ScratchBuffer_EndUse(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: scratch.h:104
#define ScratchBuffer_BeginUse(context)
Definition: scratch.h:87
Definition: cdrw_hw.h:28
struct _CDB::_MEDIA_REMOVAL MEDIA_REMOVAL

Referenced by RequestProcessShutdownFlush().

◆ DeviceScratchSyncCache()

NTSTATUS DeviceScratchSyncCache ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension)

Definition at line 220 of file pnppower.c.

238{
240 ULONG transferSize = 0;
241 CDB cdb;
242
243 ScratchBuffer_BeginUse(DeviceExtension);
244
245 RtlZeroMemory(&cdb, sizeof(CDB));
246 // Set up the CDB
248 //srb->QueueTag = SP_UNTAGGED;
249 //srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
250
251 status = ScratchBuffer_ExecuteCdbEx(DeviceExtension, NULL, transferSize, FALSE, &cdb, 10, TimeOutValueGetCapValue(DeviceExtension->TimeOutValue, 4));
252
253 ScratchBuffer_EndUse(DeviceExtension);
254
255 return status;
256}
FORCEINLINE ULONG TimeOutValueGetCapValue(_In_ ULONG TimeOutValue, _In_ ULONG Times)
Definition: cdrom.h:1569
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
struct _CDB::_SYNCHRONIZE_CACHE10 SYNCHRONIZE_CACHE10

Referenced by RequestProcessShutdownFlush().

◆ RequestIssueShutdownFlush()

NTSTATUS RequestIssueShutdownFlush ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ PIRP  Irp 
)

Definition at line 301 of file pnppower.c.

321{
323 PSCSI_REQUEST_BLOCK srb = DeviceExtension->ScratchContext.ScratchSrb;
324 PIO_STACK_LOCATION currentStack = NULL;
325
326 ULONG transferSize = 0;
327 BOOLEAN shouldRetry = TRUE;
328 ULONG timesAlreadyRetried = 0;
329 LONGLONG retryIn100nsUnits = 0;
330
331
332 currentStack = IoGetCurrentIrpStackLocation(Irp);
333
334
335 ScratchBuffer_BeginUse(DeviceExtension);
336
337 // no retry needed.
338 {
339 ScratchBuffer_SetupSrb(DeviceExtension, NULL, transferSize, FALSE);
340
341 // Set up the SRB/CDB
342 srb->QueueTag = SP_UNTAGGED;
344 srb->TimeOutValue = TimeOutValueGetCapValue(DeviceExtension->TimeOutValue, 4);
345 srb->CdbLength = 0;
346
347 if (currentStack->MajorFunction == IRP_MJ_SHUTDOWN)
348 {
350 }
351 else
352 {
354 }
355
356 ScratchBuffer_SendSrb(DeviceExtension, TRUE, NULL);
357
358 shouldRetry = RequestSenseInfoInterpretForScratchBuffer(DeviceExtension,
359 timesAlreadyRetried,
360 &status,
361 &retryIn100nsUnits);
362 UNREFERENCED_PARAMETER(shouldRetry); //defensive coding, avoid PREFAST warning.
363 UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning.
364
365 // retrieve the real status from the request.
366 status = WdfRequestGetStatus(DeviceExtension->ScratchContext.ScratchRequest);
367 }
368
369 ScratchBuffer_EndUse(DeviceExtension);
370
371
372 return status;
373}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
BOOLEAN RequestSenseInfoInterpretForScratchBuffer(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG RetriedCount, _Out_ NTSTATUS *Status, _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIntervalIn100ns)
Definition: sense.c:2564
_In_ PIRP Irp
Definition: csq.h:116
#define SP_UNTAGGED
Definition: srb.h:233
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:423
#define SRB_FUNCTION_FLUSH
Definition: srb.h:323
#define SRB_FUNCTION_SHUTDOWN
Definition: srb.h:322
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
NTSTATUS ScratchBuffer_SendSrb(_Inout_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ BOOLEAN SynchronousSrb, _When_(SynchronousSrb, _Pre_null_) _When_(!SynchronousSrb, _In_opt_) PSRB_HISTORY_ITEM *SrbHistoryItem)
Definition: scratch.c:906
UCHAR QueueTag
Definition: srb.h:256
ULONG TimeOutValue
Definition: srb.h:262
UCHAR QueueAction
Definition: srb.h:257
UCHAR CdbLength
Definition: srb.h:258
UCHAR Function
Definition: srb.h:250
int64_t LONGLONG
Definition: typedefs.h:68
#define IRP_MJ_SHUTDOWN

Referenced by RequestProcessShutdownFlush().

◆ RequestProcessPowerIrpCompletion()

NTSTATUS NTAPI RequestProcessPowerIrpCompletion ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_In_reads_opt_(_Inexpressible_("varies")) PVOID  Context 
)

Definition at line 401 of file pnppower.c.

424{
425 PCDROM_DEVICE_EXTENSION deviceExtension = Context;
426 PIO_STACK_LOCATION currentStack;
427
429
430 if (Irp->PendingReturned)
431 {
433 }
434
435 currentStack = IoGetCurrentIrpStackLocation(Irp);
436
437 NT_ASSERT(currentStack->Parameters.Power.Type == DevicePowerState);
438 NT_ASSERT(currentStack->Parameters.Power.State.DeviceState != PowerDeviceD0);
439
440 _Analysis_assume_(deviceExtension != NULL);
441
442 deviceExtension->PowerContext.PowerChangeState.PowerDown++;
443
444 // Step 5. UNLOCK QUEUE
445 if (deviceExtension->PowerContext.Options.LockQueue)
446 {
447 (VOID)DeviceSendPowerDownProcessRequest(deviceExtension,
449 Irp);
450
451 // Let the completion routine complete the Irp
453 }
454
455 // Release the power context if it wasn't already done as part of D0Exit handling
456 if (deviceExtension->PowerContext.InUse)
457 {
458 PowerContextEndUse(deviceExtension);
459 }
460
462}
#define VOID
Definition: acefi.h:82
IoMarkIrpPending(Irp)
@ DevicePowerState
Definition: ntpoapi.h:63
@ PowerDeviceD0
Definition: ntpoapi.h:49
EVT_WDF_REQUEST_COMPLETION_ROUTINE RequestUnlockQueueCompletion
Definition: pnppower.c:59
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
CDROM_POWER_CONTEXT PowerContext
Definition: cdrom.h:586
union _CDROM_POWER_CONTEXT::@1044 PowerChangeState
CDROM_POWER_OPTIONS Options
Definition: cdrom.h:442
CDROM_POWER_DOWN_STATE PowerDown
Definition: cdrom.h:438
struct _IO_STACK_LOCATION::@3974::@4010 Power
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define STATUS_CONTINUE_COMPLETION
#define NT_ASSERT
Definition: rtlfuncs.h:3310

◆ RequestProcessSetPower()

NTSTATUS NTAPI RequestProcessSetPower ( WDFDEVICE  Device,
PIRP  Irp 
)

Definition at line 149 of file pnppower.c.

169{
170 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
171 PIO_STACK_LOCATION currentStack;
173 BOOLEAN IrpMarkedPending = FALSE;
174
175 currentStack = IoGetCurrentIrpStackLocation(Irp);
176
177 if ((currentStack->Parameters.Power.Type == DevicePowerState) &&
178 (currentStack->Parameters.Power.State.DeviceState != PowerDeviceD0))
179 {
180 // We need to unlock the device queue in D3 postprocessing.
184 deviceExtension,
185 TRUE,
186 TRUE,
187 TRUE);
188
189 // Mark the Irp pending as we'll defer the I/O completion.
191 IrpMarkedPending = TRUE;
192 }
193 else {
194
196 }
197
198#pragma warning(push)
199#pragma warning(disable: 28193) // OACR will complain that the status variable is not examined.
200
201 //
202 // Deliver the IRP back to the framework.
203 //
204
205 status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
206
207 if (IrpMarkedPending)
208 {
210 return STATUS_PENDING;
211 }
212
213#pragma warning(pop)
214
215 return status;
216}
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IoCopyCurrentIrpStackLocationToNext(Irp)
Definition: ntifs_ex.h:413
#define STATUS_PENDING
Definition: ntstatus.h:82
IO_COMPLETION_ROUTINE RequestProcessPowerIrpCompletion
Definition: pnppower.c:57
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474

◆ RequestProcessShutdownFlush()

NTSTATUS NTAPI RequestProcessShutdownFlush ( WDFDEVICE  Device,
PIRP  Irp 
)

Definition at line 76 of file pnppower.c.

96{
98 PIO_STACK_LOCATION currentStack = NULL;
99 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
100
101 //add trace info
102
103 // acquire the shutdown/flush lock
105
106 currentStack = IoGetCurrentIrpStackLocation(Irp);
107
108 // finish all current requests
109 WdfIoQueueStopSynchronously(deviceExtension->SerialIOQueue);
110
111 // sync cache
112 if (NT_SUCCESS(status))
113 {
114 // safe to use scratch srb to send the request.
115 status = DeviceScratchSyncCache(deviceExtension);
116 }
117
118 // For SHUTDOWN, allow media removal.
119 if (NT_SUCCESS(status))
120 {
121 if (currentStack->MajorFunction == IRP_MJ_SHUTDOWN)
122 {
123 // safe to use scratch srb to send the request.
125 }
126 }
127
128 // Use original IRP, send SRB_FUNCTION_SHUTDOWN or SRB_FUNCTION_FLUSH (no retry)
129 if (NT_SUCCESS(status))
130 {
131 status = RequestIssueShutdownFlush(deviceExtension, Irp);
132 }
133
134 // restart queue to allow processing further requests.
135 WdfIoQueueStart(deviceExtension->SerialIOQueue);
136
137 // release the shutdown/flush lock
138 WdfWaitLockRelease(deviceExtension->ShutdownFlushWaitLock);
139
140 // 6. complete the irp
141 Irp->IoStatus.Status = status;
143
144 return status;
145}
#define IoCompleteRequest
Definition: irp.c:1240
NTSTATUS RequestIssueShutdownFlush(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ PIRP Irp)
Definition: pnppower.c:301
NTSTATUS DeviceScratchPreventMediaRemoval(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ BOOLEAN Prevent)
Definition: pnppower.c:259
NTSTATUS DeviceScratchSyncCache(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: pnppower.c:220
WDFQUEUE SerialIOQueue
Definition: cdrom.h:479
WDFWAITLOCK ShutdownFlushWaitLock
Definition: cdrom.h:595
_Must_inspect_result_ FORCEINLINE NTSTATUS WdfWaitLockAcquire(_In_ _Requires_lock_not_held_(_Curr_) WDFWAITLOCK Lock, _In_opt_ PLONGLONG Timeout)
Definition: wdfsync.h:173

◆ RequestUnlockQueueCompletion()

VOID NTAPI RequestUnlockQueueCompletion ( _In_ WDFREQUEST  Request,
_In_ WDFIOTARGET  Target,
_In_ PWDF_REQUEST_COMPLETION_PARAMS  Params,
_In_ WDFCONTEXT  Context 
)

Definition at line 377 of file pnppower.c.

383{
384 PIRP Irp = Context;
385 WDFDEVICE device = WdfIoTargetGetDevice(Target);
386 PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
387
390
391 deviceExtension->PowerContext.Options.LockQueue = FALSE;
392
393 PowerContextEndUse(deviceExtension);
394
395 // Complete the original power irp
397}
Definition: devices.h:37
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:308
#define IO_NO_INCREMENT
Definition: iotypes.h:598

Variable Documentation

◆ RequestProcessPowerIrpCompletion

IO_COMPLETION_ROUTINE RequestProcessPowerIrpCompletion

Definition at line 57 of file pnppower.c.

Referenced by RequestProcessSetPower().

◆ RequestUnlockQueueCompletion

EVT_WDF_REQUEST_COMPLETION_ROUTINE RequestUnlockQueueCompletion

Definition at line 59 of file pnppower.c.

Referenced by RequestProcessPowerIrpCompletion().