ReactOS 0.4.17-dev-1268-g5608ce5
srb.c File Reference
#include "precomp.h"
#include "inline.h"
#include <debug/driverdbg.h>
#include <debug.h>
Include dependency graph for srb.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static VOID StorpSrbInitRequestReference (_In_ PQUEUED_REQUEST_REFERENCE RequestReference, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ PIRP Irp, _In_ PPDO_DEVICE_EXTENSION PdoExtension)
 Initializes a request reference and sets the SRB => ReqRef link.
 
static PQUEUED_REQUEST_REFERENCE StorpSrbAllocateRequestReference (_In_ PSCSI_REQUEST_BLOCK Srb, _In_ PIRP Irp, _In_ PPDO_DEVICE_EXTENSION PdoExtension)
 Allocates QUEUED_REQUEST_REFERENCE for an SRB that is going to be processed.
 
static PQUEUED_REQUEST_REFERENCE StorpSrbAcquireReservedRequestReference (_In_ PSCSI_REQUEST_BLOCK Srb, _In_ PIRP Irp, _In_ PPDO_DEVICE_EXTENSION PdoExtension)
 Takes the adapter reserve, if it is there and nobody else holds it.
 
VOID StorpSrbFreeRequestReference (_In_ PSCSI_REQUEST_BLOCK Srb)
 Frees an SRB's Request Reference and restore Srb->OriginalRequest field to IRP. This function does not check if Srb->OriginalRequest is actually an request reference, and you must determine it by other means.
 
FORCEINLINE BOOLEAN StorpAssignTagToSrb (_In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
 Assigns a queue tag to a request if it stated it supports one.
 
VOID NTAPI PortPdoAfterBuildingScatterGatherList (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PSCATTER_GATHER_LIST ScatterGatherList, _In_ PVOID Context)
 
static NTSTATUS PortPdoStarveRequest (_In_ PFDO_DEVICE_EXTENSION FdoExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ PIRP Irp)
 Parks a request that is out of memory, or fails it if there is no reserve to wait for. Either way the IRP is no longer ours, hence STATUS_PENDING.
 
NTSTATUS PortPdoSrbAllocatePrivateContexts (_In_ PSCSI_REQUEST_BLOCK Srb, _In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PFDO_DEVICE_EXTENSION FdoExtension)
 
NTSTATUS PortPdoIssueRequest (_In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
 
VOID PortPdoScheduleRequestNoFlowControl (_In_ PFDO_DEVICE_EXTENSION FdoExtension, _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
 
BOOLEAN PortPdoScheduleRequestFlowControlled (_In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PFDO_DEVICE_EXTENSION FdoExtension, _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
 Schedules an outstanding request and return a boolean value to indicate if the request can be immediately issued.
 
NTSTATUS NTAPI PortPdoScsi (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
 
static VOID PortScheduleComingRequestsOnCompletion (_In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PFDO_DEVICE_EXTENSION FdoExtension)
 
static VOID PortCompleteRequest (_In_ PQUEUED_REQUEST_REFERENCE RequestReference)
 
VOID NTAPI PortCompletionDpc (_In_ PKDPC Dpc, _In_ PVOID Context, _In_ PVOID SystemArgument1, _In_ PVOID SystemArgument2)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file srb.c.

Function Documentation

◆ PortCompleteRequest()

static VOID PortCompleteRequest ( _In_ PQUEUED_REQUEST_REFERENCE  RequestReference)
static

Definition at line 770 of file srb.c.

772{
774 PIRP Irp;
779 BOOLEAN FromReserve;
780
781 /* Take out our information */
782 Srb = RequestReference->Srb;
783 Irp = RequestReference->Irp;
784 PdoExtension = RequestReference->PdoExtension;
785 FdoExtension = PdoExtension->FdoExtension;
786
787 /* The reference is released further down, so remember this while it is still valid */
788 FromReserve = RequestReference->FromReserve;
789
790 /* FIXME: DELETE AFTER DEBUG */
791 // if (RequestReference->DumpSpecialRequest)
792 // {
793 // StorpDumpRequestResponse(RequestReference);
794 // }
795
796 DPRINT("Completing request: (%d:%d:%d) ReqRef %p Srb %p Irp %p Tag %x\n",
797 Srb->PathId, Srb->TargetId, Srb->Lun, RequestReference, Srb, RequestReference->Irp, Srb->QueueTag);
798
799 /* Return SG list resources back to system */
800 if (RequestReference->ScatterGatherList)
801 {
802 FdoExtension->DmaAdapter->DmaOperations->
803 PutScatterGatherList(FdoExtension->DmaAdapter,
804 (PSCATTER_GATHER_LIST)RequestReference->ScatterGatherList,
805 RequestReference->WriteToDevice);
806 RequestReference->ScatterGatherList = NULL;
807 }
808
809 /* A virtual miniport never built a list, so this cannot hang off one */
810 if (RequestReference->MappedSystemVa)
811 {
812 MmUnlockPages(RequestReference->Irp->MdlAddress);
813 RequestReference->MappedSystemVa = NULL;
814 }
815
816 /* Check if we need to interact with flow control. */
817 if (RequestReference->IsOutstanding)
818 {
819 /* Take the request out of FDO and PDO structures, and update flow control data */
822
823 FdoExtension->FlowControl.OutstandingRequestCount--;
824 if (FdoExtension->FlowControl.RemainingBusyRequests)
825 {
826 --FdoExtension->FlowControl.RemainingBusyRequests;
827
828 /* Clear busy state as needed */
829 if (FdoExtension->FlowControl.OutstandingRequestCount == 0 ||
830 FdoExtension->FlowControl.RemainingBusyRequests == 0)
831 {
832 FdoExtension->FlowControl.IsBusy = FALSE;
833 }
834 }
835
836 RemoveEntryList(&RequestReference->PdoEntry);
837 --PdoExtension->FlowControl.OutstandingRequestCount;
838 if (PdoExtension->FlowControl.RemainingBusyRequests)
839 {
840 --PdoExtension->FlowControl.RemainingBusyRequests;
841
842 /* Clear busy state as needed */
843 if (PdoExtension->FlowControl.OutstandingRequestCount == 0 ||
844 PdoExtension->FlowControl.RemainingBusyRequests == 0)
845 {
846 PdoExtension->FlowControl.IsBusy = FALSE;
847 }
848 }
849
850 /* Decrement strong ordered request count if needed */
851 if (RequestReference->StrongOrdered)
852 {
853 --PdoExtension->FlowControl.StrongOrderedCount;
854 }
855
856 /* Free the private data structure. No one should use it anymore */
858 RequestReference = NULL;
859
860 /* Schedule next IO before we release flow control lock */
862
863 /* We're done, release flow control lock */
866
867 }
868
869 /*
870 * Free SRB extension as this request will never go back to miniport again. Must free it before
871 * IoCompleteRequest because class driver's completion routine may issue another request. If we
872 * free it after IoCompleteRequest we may zero out the newly-issued SRB's extension, since one
873 * single SRB can be reused between requests, and the SRB issued in completion routine could be
874 * the same one we operating here.
875 */
876 if (Srb->SrbExtension)
877 {
878 /* The reserved one is handed back along with its packet, not freed */
879 if (!FromReserve)
880 {
882 }
884 }
885
886 /*
887 * After done with internal accountings, we can finally complete this IO.
888 *
889 * We must not complete the IO before scheduling next IO, because at that point the flow control
890 * lock is still held, and class driver's completion routine may issue another request. This
891 * will cause a recursive lock acquisition in PDO SCSI handler and lead to bugcheck.
892 */
893 switch (SRB_STATUS(Srb->SrbStatus))
894 {
897 break;
898
899 case SRB_STATUS_BUSY:
901 break;
902
903 default:
904 IoStatus = STATUS_UNSUCCESSFUL; // FIXME:
905 break;
906 }
907 Irp->IoStatus.Status = IoStatus;
908 Irp->IoStatus.Information = Srb->DataTransferLength; /* FIXME: hopefully this is correct */
909
910 /* We just gave memory back, so let one request that ran out of it through */
912
913 DPRINT("Calling IoCompleteRequest\n");
915}
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define SRB_STATUS(Status)
Definition: srb.h:389
#define SRB_STATUS_BUSY
Definition: srb.h:345
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define TAG_SRB_EXTENSION
Definition: precomp.h:42
@ PdoExtension
Definition: precomp.h:62
@ FdoExtension
Definition: precomp.h:61
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
VOID FASTCALL KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:130
VOID FASTCALL KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
Definition: spinlock.c:166
#define StorpCheckFlowControl(...)
Definition: inline.h:252
_In_ PIRP Irp
Definition: kse.h:79
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1432
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define IoCompleteRequest
Definition: irp.c:1272
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
VOID StorpSrbFreeRequestReference(_In_ PSCSI_REQUEST_BLOCK Srb)
Frees an SRB's Request Reference and restore Srb->OriginalRequest field to IRP. This function does no...
Definition: srb.c:112
static VOID PortScheduleComingRequestsOnCompletion(_In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PFDO_DEVICE_EXTENSION FdoExtension)
Definition: srb.c:700
VOID PortRetryStarvedRequest(_In_ PFDO_DEVICE_EXTENSION FdoExtension)
Retries one queued request, so each completion lets exactly one through.
Definition: fdo.c:135
UCHAR QueueTag
Definition: srb.h:256
UCHAR TargetId
Definition: srb.h:254
UCHAR PathId
Definition: srb.h:253
ULONG DataTransferLength
Definition: srb.h:261
PVOID SrbExtension
Definition: srb.h:267
UCHAR SrbStatus
Definition: srb.h:251
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2219
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
*LockHandle LockHandle _Out_ PKLOCK_QUEUE_HANDLE LockHandle
Definition: kefuncs.h:717

Referenced by PortCompletionDpc().

◆ PortCompletionDpc()

VOID NTAPI PortCompletionDpc ( _In_ PKDPC  Dpc,
_In_ PVOID  Context,
_In_ PVOID  SystemArgument1,
_In_ PVOID  SystemArgument2 
)

Definition at line 920 of file srb.c.

925{
926 PQUEUED_REQUEST_REFERENCE RequestReference;
930 ULONG Count = 0;
931
932 DPRINT("PortCompletionDpc(%p %p %p %p)\n", Dpc, Context, SystemArgument1, SystemArgument2);
933
934 /* Take context pointer as FDO extension */
936
937 /* Flush all entries in the list and complete all requests */
938 Entry = InterlockedFlushSList(&FdoExtension->CompletionList);
939 while (Entry)
940 {
941 /* Prepare Next pointer first (Completion routine will free the memory that contains it) */
942 Next = Entry->Next;
943
944 /* Get original request */
945 RequestReference = CONTAINING_RECORD(Entry, QUEUED_REQUEST_REFERENCE, CompletionEntry);
946
947 /* Call real completion routine */
948 PortCompleteRequest(RequestReference);
949
950 /* Move on to next one */
951 Entry = Next;
952 ++Count;
953 }
954
955 DPRINT("Completed %d requests\n", Count);
956}
struct _FDO_DEVICE_EXTENSION * PFDO_DEVICE_EXTENSION
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
int Count
Definition: noreturn.cpp:7
Entry
Definition: section.c:5216
STDMETHOD() Next(THIS_ ULONG celt, IAssociationElement *pElement, ULONG *pceltFetched) PURE
static VOID PortCompleteRequest(_In_ PQUEUED_REQUEST_REFERENCE RequestReference)
Definition: srb.c:770
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:756
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:757
#define InterlockedFlushSList(SListHead)
Definition: rtlfuncs.h:3419
#define PSLIST_ENTRY
Definition: rtltypes.h:134

Referenced by PortAddDevice().

◆ PortPdoAfterBuildingScatterGatherList()

VOID NTAPI PortPdoAfterBuildingScatterGatherList ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_In_ PSCATTER_GATHER_LIST  ScatterGatherList,
_In_ PVOID  Context 
)

Definition at line 174 of file srb.c.

179{
181 PVOID MiniportExtension;
182 PHW_INITIALIZATION_DATA HwInitData;
183 PQUEUED_REQUEST_REFERENCE RequestReference;
184 PSCSI_REQUEST_BLOCK MiniportSrb;
185 BOOLEAN CanStartIo = TRUE;
187
188 RequestReference = (PQUEUED_REQUEST_REFERENCE)Context;
190 MiniportExtension = &FdoExtension->Miniport.MiniportExtension->HwDeviceExtension;
191 HwInitData = FdoExtension->HwInitData;
192
193 /* Save our SG List */
194 RequestReference->ScatterGatherList = (PSTOR_SCATTER_GATHER_LIST)ScatterGatherList;
195
196 /* Translate last, once the tag and SRB extension are final */
197 if (RequestReference->ExtendedRequest != NULL)
198 {
199 StorpBuildExtendedSrb(RequestReference->Srb, RequestReference->ExtendedRequest);
200 MiniportSrb = (PSCSI_REQUEST_BLOCK)RequestReference->ExtendedRequest;
201 }
202 else
203 {
204 MiniportSrb = RequestReference->Srb;
205 }
206
207 /* BuildIo and StartIo are called on DISPATCH_LEVEL */
209
210 do {
211 /* Call BuildIo, if one is provided */
212 if (HwInitData->HwBuildIo)
213 {
214 CanStartIo = HwInitData->HwBuildIo(MiniportExtension, MiniportSrb);
215 }
216
217 /* If BuildIo says the request processing shall stop here, no more processing is needed */
218 if (!CanStartIo)
219 {
220 break;
221 }
222
223 HwInitData->HwStartIo(MiniportExtension, MiniportSrb);
224 }
225 while (0);
226
227 /* Restore IRQL */
229}
#define TRUE
Definition: types.h:120
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
struct _QUEUED_REQUEST_REFERENCE * PQUEUED_REQUEST_REFERENCE
VOID NTAPI StorpBuildExtendedSrb(_In_ PSCSI_REQUEST_BLOCK Srb, _Out_ PEXTENDED_REQUEST Request)
Fills in the extended request a miniport will be given.
Definition: srbex.c:102
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
PHW_STARTIO HwStartIo
Definition: srb.h:568
PHW_BUILDIO HwBuildIo
Definition: storport.h:7278
PSCSI_REQUEST_BLOCK Srb
Definition: precomp.h:376
PEXTENDED_REQUEST ExtendedRequest
Definition: precomp.h:378
PSTOR_SCATTER_GATHER_LIST ScatterGatherList
Definition: precomp.h:380
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

Referenced by PortPdoIssueRequest().

◆ PortPdoIssueRequest()

NTSTATUS PortPdoIssueRequest ( _In_ PPDO_DEVICE_EXTENSION  PdoExtension,
_In_ PQUEUED_REQUEST_REFERENCE  RequestReference 
)

Definition at line 311 of file srb.c.

314{
315 PIRP Irp;
318 PHW_INITIALIZATION_DATA HwInitData;
320
321 Irp = RequestReference->Irp;
322 FdoExtension = PdoExtension->FdoExtension;
323 HwInitData = FdoExtension->Miniport.InitData;
324
325 NT_ASSERT(HwInitData);
326
327 /* Fill in SCSI address data */
328 /* FIXME: Not sure if this is the best place for it. */
329 RequestReference->Srb->PathId = PdoExtension->Bus;
330 RequestReference->Srb->TargetId = PdoExtension->Target;
331 RequestReference->Srb->Lun = PdoExtension->Lun;
332
333 /* FIXME: Delete after debug */
334 // PSCSI_REQUEST_BLOCK Srb = RequestReference->Srb;
335 // if (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI &&
336 // (Srb->Cdb[0] == SCSIOP_GET_EVENT_STATUS || Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY))
337 // {
338 // RequestReference->DumpSpecialRequest = TRUE;
339 // StorpDumpRequest(RequestReference);
340 // }
341
342 /* Start an DMA if IO subsystem allocated an MDL for us */
343 /* FIXME: Does this strategy work? */
344 if (RequestReference->Irp->MdlAddress)
345 {
346 /*
347 * Lock the buffer so that it stays in physical memory.
348 * In the two cases avoided here the memory has already been locked
349 */
350 if (!TEST_FLAG(Irp->MdlAddress->MdlFlags, MDL_SOURCE_IS_NONPAGED_POOL) &&
351 !TEST_FLAG(Irp->MdlAddress->MdlFlags, MDL_MAPPED_TO_SYSTEM_VA) &&
352 !TEST_FLAG(Irp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED) &&
353 !TEST_FLAG(Irp->MdlAddress->MdlFlags, MDL_PARTIAL))
354 {
355 RequestReference->MappedSystemVa = (PVOID)1; /* FIXME: CHANGE ITS NAME */
357 }
358
359 RequestReference->WriteToDevice =
360 TEST_FLAG(RequestReference->Srb->SrbFlags, SRB_FLAGS_DATA_OUT);
361
362 /* A virtual miniport has no DMA adapter and moves the buffer itself through the MDL */
363 if (FdoExtension->Miniport.IsVirtual)
364 {
366 RequestReference->Irp,
367 NULL,
368 RequestReference);
369 return STATUS_PENDING;
370 }
371
372 /* Following call requires DISPATCH_LEVEL. */
374
375 /* Make up the scatter gather list */
376 /* FIXME: I don't know if we actually hit it */
377 NT_ASSERT((RequestReference->Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) !=
379
380 FdoExtension->DmaAdapter->DmaOperations->
381 GetScatterGatherList(FdoExtension->DmaAdapter,
382 FdoExtension->Device,
383 RequestReference->Irp->MdlAddress,
384 MmGetMdlVirtualAddress(RequestReference->Irp->MdlAddress),
385 RequestReference->Srb->DataTransferLength,
387 (PVOID)RequestReference,
388 RequestReference->WriteToDevice);
389
390 /* Restore IRQL */
392 } else {
393 /* Otherwise just start the IO with a NULL scatter gather list */
395 RequestReference->Irp,
396 NULL,
397 RequestReference);
398 }
399
400 /* FIXME: Is this correct? */
402
403 return Status;
404}
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:401
#define SRB_FLAGS_UNSPECIFIED_DIRECTION
Definition: srb.h:403
Status
Definition: gdiplustypes.h:24
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:928
#define KernelMode
Definition: asm.h:38
VOID NTAPI PortPdoAfterBuildingScatterGatherList(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PSCATTER_GATHER_LIST ScatterGatherList, _In_ PVOID Context)
Definition: srb.c:174
#define STATUS_PENDING
Definition: telnetd.h:14
void * PVOID
Definition: typedefs.h:50
@ IoModifyAccess
Definition: ketypes.h:933
#define MmGetMdlVirtualAddress(_Mdl)
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define MDL_PARTIAL
Definition: mmtypes.h:22
#define MDL_SOURCE_IS_NONPAGED_POOL
Definition: mmtypes.h:20
#define MDL_MAPPED_TO_SYSTEM_VA
Definition: mmtypes.h:18
#define NT_ASSERT
Definition: rtlfuncs.h:3334

Referenced by PortPdoScsi(), and PortScheduleComingRequestsOnCompletion().

◆ PortPdoScheduleRequestFlowControlled()

BOOLEAN PortPdoScheduleRequestFlowControlled ( _In_ PPDO_DEVICE_EXTENSION  PdoExtension,
_In_ PFDO_DEVICE_EXTENSION  FdoExtension,
_In_ PQUEUED_REQUEST_REFERENCE  RequestReference 
)

Schedules an outstanding request and return a boolean value to indicate if the request can be immediately issued.

Parameters
PdoExtensionPDO device extension.
FdoExtensionFDO device extension.
RequestReferenceRequestReference must be allocated beforehand.
Returns
BOOLEAN When TRUE, you can call PortPdoIssueRequest to issue request right away; When FALSE, the request is already queued in flow control structures and you can safely go on without further processing, it will be issued upon completions.

Definition at line 429 of file srb.c.

433{
434 PPDO_IO_FLOW_CONTROL FlowControl = &PdoExtension->FlowControl;
436 PSCSI_REQUEST_BLOCK Srb = RequestReference->Srb;
437 BOOLEAN StrongOrderedRequest = FALSE;
438 BOOLEAN IssueRequest = TRUE;
439
440 /* Set outstanding flag */
441 RequestReference->IsOutstanding = TRUE;
442
443 /* Check if we can issue this request. */
444 /* Acquire the HBA global flow control lock first */
447
448 do
449 {
450 /* Check PDO flow control conditions */
451
452 /* Sanity check */
453 NT_ASSERT(FlowControl->OutstandingRequestCount <= PdoExtension->OutstandingRequestMax);
454
455 /* If PDO is not suitable to receive a request, make it wait */
456 if (FlowControl->IsBusy || FlowControl->IsPaused ||
459 FlowControl->StrongOrderedCount ||
460 FlowControl->OutstandingRequestCount == PdoExtension->OutstandingRequestMax ||
461 (!IsListEmpty(&FlowControl->AwaitingRequestsListHead)))
462 {
464 &RequestReference->PdoEntry);
465 IssueRequest = FALSE;
466 break;
467 }
468
469 /* Check if this request is strong-ordered */
472 {
473 RequestReference->StrongOrdered = TRUE;
474 StrongOrderedRequest = TRUE;
475 ++FlowControl->StrongOrderedCount;
476 }
477
478 /*
479 * If this request is strong ordered and the LUN's active/approved list is not
480 * drained, the request must wait.
481 */
482 if (StrongOrderedRequest && !IsListEmpty(&FlowControl->ActiveRequestsListHead))
483 {
485 &RequestReference->PdoEntry);
486 IssueRequest = FALSE;
487 break;
488 }
489
490 /*
491 * If any break's triggered before this point, the request is in PDO waiting queue.
492 * Going past this point meant PDO approves this request. Put it into active list.
493 */
495 {
497 &RequestReference->PdoEntry);
498 } else {
500 &RequestReference->PdoEntry);
501 }
502
503 /* A new outstanding request is added to this LUN */
504 ++FlowControl->OutstandingRequestCount;
505
506 /* Check FDO flow control status. */
507
508 /* If the FDO can't handle more requests, then the request should be queued. */
509 if (FlowControl->IsBusy || FlowControl->IsPaused ||
510 FlowControl->OutstandingRequestCount == FdoExtension->OutstandingRequestMax)
511 {
512 /* Put into FDO queue */
513 InsertHeadList(&FdoExtension->FlowControl.FdoBlockedRequestsListHead,
514 &RequestReference->FdoEntry);
515
516 /*
517 * Now the request is in PDO active list, in FDO awaiting queue, not issued.
518 * Let it wait until another completion event schedules it.
519 */
520 break;
521 }
522
523 /* Seems good, increment FDO request count */
524 ++FdoExtension->FlowControl.OutstandingRequestCount;
525
526 /*
527 * Now the request is counted in FDO & PDO, and is put into PDO active list,
528 * next step we're going to issue it.
529 */
530 } while (0);
531
532 // FIXME: The port driver indicates that an LU-specific queue has been frozen by
533 // returning a request with SRB_STATUS_QUEUE_FROZEN in the SrbStatus member. New
534 // requests from the class driver can be inserted into the queue, but only autosense
535 // requests are sent to the logical unit as long as its queue is frozen.
536 // https://learn.microsoft.com/en-us/windows-hardware/drivers/storage/storage-class-driver-s-releasequeue-routine
537
538 /* We've determined where the request goes. Release the flow control lock */
541
542 return IssueRequest;
543}
#define SRB_FLAGS_BYPASS_FROZEN_QUEUE
Definition: srb.h:398
#define SRB_ORDERED_QUEUE_TAG_REQUEST
Definition: srb.h:425
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:395
#define SRB_HEAD_OF_QUEUE_TAG_REQUEST
Definition: srb.h:424
#define SRB_FLAGS_BYPASS_LOCKED_QUEUE
Definition: srb.h:410
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
LIST_ENTRY ActiveRequestsListHead
Definition: precomp.h:194
ULONG OutstandingRequestCount
Definition: precomp.h:185
ULONG StrongOrderedCount
Definition: precomp.h:182
LIST_ENTRY AwaitingRequestsListHead
Definition: precomp.h:200
UCHAR QueueAction
Definition: srb.h:257
ULONG SrbFlags
Definition: srb.h:260

Referenced by PortPdoScsi().

◆ PortPdoScheduleRequestNoFlowControl()

VOID PortPdoScheduleRequestNoFlowControl ( _In_ PFDO_DEVICE_EXTENSION  FdoExtension,
_In_ PQUEUED_REQUEST_REFERENCE  RequestReference 
)

Definition at line 408 of file srb.c.

411{
412 /* Ensure outstanding flag is unset */
413 RequestReference->IsOutstanding = FALSE;
414}

Referenced by PortPdoScsi().

◆ PortPdoScsi()

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

Definition at line 548 of file srb.c.

551{
557 PMINIPORT Miniport;
558
559 DPRINT("PortPdoScsi(%p %p)\n", DeviceObject, Irp);
560
562 Srb = Stack->Parameters.Scsi.Srb;
563
564 if (Srb == NULL) {
565 DPRINT1("Srb is NULL!");
568
569 Irp->IoStatus.Information = 0;
570 Irp->IoStatus.Status = Status;
571
573 return Status;
574 }
575
578 FdoExtension = PdoExtension->FdoExtension;
580 Miniport = &FdoExtension->Miniport;
581
582 switch (Srb->Function) {
583 /* Both of these should be sent to device and let themselves process this */
586 {
587 PQUEUED_REQUEST_REFERENCE RequestReference;
588 BOOLEAN IssueRequest;
589
590 /* Mark IRP as pending */
592
593 /* Allocate private contexts */
595 if (Status != STATUS_SUCCESS)
596 {
597 break;
598 }
599 RequestReference = (PQUEUED_REQUEST_REFERENCE)Srb->OriginalRequest;
600
601 /* Assign a tag to the SRB if it supports tagging */
603
604 DPRINT("New request (%d:%d:%d) ReqRef %p Srb %p Irp %p Tag %x SrbExt %p(%d)\n",
606 RequestReference, Srb, Irp, Srb->QueueTag,
608
609 /*
610 * Do the scheduling. If returns TRUE, we should issue this request to the hardware.
611 * Otherwise it will keep waiting until next completion schedules it, or be cancelled on
612 * an error, etc.
613 */
616 RequestReference);
617
618 /* This request is viable to be issued. */
619 if (IssueRequest)
620 {
621 Status = PortPdoIssueRequest(PdoExtension, RequestReference);
622 } else {
624 }
625
626 break;
627 }
628
629 /*
630 * These requests are actually sent to adapters and are not outstanding requests for devices
631 * so we simply pass them down to miniport
632 */
635 {
636 PQUEUED_REQUEST_REFERENCE RequestReference;
637
638 /* Mark IRP as pending */
640
641 /* Allocate private contexts */
643 if (Status != STATUS_SUCCESS)
644 {
645 break;
646 }
647 RequestReference = (PQUEUED_REQUEST_REFERENCE)Srb->OriginalRequest;
648
649 /*
650 * Call the non-flow-controlled scheduling function (it does nothing but the model is
651 * preserved for consistency)
652 */
654
655 /* Fire up the request immediately */
656 Status = PortPdoIssueRequest(PdoExtension, RequestReference);
657
658 break;
659 }
660
662 {
663 if (InterlockedCompareExchange(&PdoExtension->IsClaimed, 1, 0))
664 {
667 break;
668 }
669
670 /* The claimed device object is handed back to the class driver here */
671 Srb->DataBuffer = PdoExtension->Device;
674 break;
675 }
676
678 {
679 InterlockedExchange(&PdoExtension->IsClaimed, 0);
680
683 break;
684 }
685
686 default:
687 DPRINT1("Unsupported Srb Function %02X!", Srb->Function);
688 // DbgBreakPoint();
691 break;
692 }
693
694 return Status;
695}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define InterlockedExchange
Definition: armddk.h:54
#define DPRINT1
Definition: precomp.h:8
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
struct _PDO_DEVICE_EXTENSION * PPDO_DEVICE_EXTENSION
#define SRB_FUNCTION_RELEASE_DEVICE
Definition: srb.h:321
#define SRB_FUNCTION_CLAIM_DEVICE
Definition: srb.h:316
#define SRB_FUNCTION_IO_CONTROL
Definition: srb.h:317
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_FUNCTION_FLUSH
Definition: srb.h:323
#define SRB_FUNCTION_SHUTDOWN
Definition: srb.h:322
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:346
FORCEINLINE VOID StorpCompleteRequest(_In_ PIRP Irp, _In_ UCHAR SrbStatus, _In_ NTSTATUS IrpStatus)
Completes a request with specified SRB status and IRP status.
Definition: inline.h:19
#define InterlockedCompareExchange
Definition: interlocked.h:119
IoMarkIrpPending(Irp)
FORCEINLINE BOOLEAN StorpAssignTagToSrb(_In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Assigns a queue tag to a request if it stated it supports one.
Definition: srb.c:142
BOOLEAN PortPdoScheduleRequestFlowControlled(_In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PFDO_DEVICE_EXTENSION FdoExtension, _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
Schedules an outstanding request and return a boolean value to indicate if the request can be immedia...
Definition: srb.c:429
VOID PortPdoScheduleRequestNoFlowControl(_In_ PFDO_DEVICE_EXTENSION FdoExtension, _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
Definition: srb.c:408
NTSTATUS PortPdoSrbAllocatePrivateContexts(_In_ PSCSI_REQUEST_BLOCK Srb, _In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PFDO_DEVICE_EXTENSION FdoExtension)
Definition: srb.c:258
NTSTATUS PortPdoIssueRequest(_In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
Definition: srb.c:311
PORT_CONFIGURATION_INFORMATION PortConfig
Definition: precomp.h:99
PVOID OriginalRequest
Definition: srb.h:266
PVOID DataBuffer
Definition: srb.h:263
UCHAR Function
Definition: srb.h:250
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
NTSYSAPI void WINAPI DbgBreakPoint(void)
#define IO_NO_INCREMENT
Definition: iotypes.h:598

Referenced by PortDispatchScsi(), and PortRetryStarvedRequest().

◆ PortPdoSrbAllocatePrivateContexts()

NTSTATUS PortPdoSrbAllocatePrivateContexts ( _In_ PSCSI_REQUEST_BLOCK  Srb,
_In_ PPDO_DEVICE_EXTENSION  PdoExtension,
_In_ PFDO_DEVICE_EXTENSION  FdoExtension 
)

Definition at line 258 of file srb.c.

262{
263 PQUEUED_REQUEST_REFERENCE RequestReference;
264 ULONG SrbExtensionSize = FdoExtension->Miniport.PortConfig.SrbExtensionSize;
265 PIRP Irp;
266
268
269 /* Allocate our private data area, falling back on the reserve when pool is exhausted */
271 if (RequestReference == NULL)
272 {
274 if (RequestReference == NULL)
275 {
277 }
278 }
279
280 /* Allocate SRB extension */
281 if (SrbExtensionSize == 0)
282 {
284 return STATUS_SUCCESS;
285 }
286
287 if (RequestReference->FromReserve)
288 {
289 NT_ASSERT(FdoExtension->ReservedSrbExtension != NULL);
290 Srb->SrbExtension = FdoExtension->ReservedSrbExtension;
291 RtlZeroMemory(Srb->SrbExtension, SrbExtensionSize);
292 return STATUS_SUCCESS;
293 }
294
296 SrbExtensionSize,
298 if (Srb->SrbExtension == NULL)
299 {
302 }
303
304 RtlZeroMemory(Srb->SrbExtension, SrbExtensionSize);
305
306 return STATUS_SUCCESS;
307}
struct _IRP * PIRP
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
static NTSTATUS PortPdoStarveRequest(_In_ PFDO_DEVICE_EXTENSION FdoExtension, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ PIRP Irp)
Parks a request that is out of memory, or fails it if there is no reserve to wait for....
Definition: srb.c:238
static PQUEUED_REQUEST_REFERENCE StorpSrbAcquireReservedRequestReference(_In_ PSCSI_REQUEST_BLOCK Srb, _In_ PIRP Irp, _In_ PPDO_DEVICE_EXTENSION PdoExtension)
Takes the adapter reserve, if it is there and nobody else holds it.
Definition: srb.c:83
static PQUEUED_REQUEST_REFERENCE StorpSrbAllocateRequestReference(_In_ PSCSI_REQUEST_BLOCK Srb, _In_ PIRP Irp, _In_ PPDO_DEVICE_EXTENSION PdoExtension)
Allocates QUEUED_REQUEST_REFERENCE for an SRB that is going to be processed.
Definition: srb.c:57
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by PortPdoScsi().

◆ PortPdoStarveRequest()

static NTSTATUS PortPdoStarveRequest ( _In_ PFDO_DEVICE_EXTENSION  FdoExtension,
_In_ PSCSI_REQUEST_BLOCK  Srb,
_In_ PIRP  Irp 
)
static

Parks a request that is out of memory, or fails it if there is no reserve to wait for. Either way the IRP is no longer ours, hence STATUS_PENDING.

Definition at line 238 of file srb.c.

242{
243 /* Without a reserve nothing guarantees a completion that would retry the request */
244 if (FdoExtension->ReservedRequestReference == NULL)
245 {
248 }
249 else
250 {
252 }
253
254 return STATUS_PENDING;
255}
#define SRB_STATUS_INTERNAL_ERROR
Definition: srb.h:373
VOID PortQueueStarvedRequest(_In_ PFDO_DEVICE_EXTENSION FdoExtension, _In_ PIRP Irp)
Queues a request that could not allocate its private contexts.
Definition: fdo.c:124
ULONG InternalStatus
Definition: srb.h:269
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158

Referenced by PortPdoSrbAllocatePrivateContexts().

◆ PortScheduleComingRequestsOnCompletion()

static VOID PortScheduleComingRequestsOnCompletion ( _In_ PPDO_DEVICE_EXTENSION  PdoExtension,
_In_ PFDO_DEVICE_EXTENSION  FdoExtension 
)
static

Definition at line 700 of file srb.c.

703{
705 PQUEUED_REQUEST_REFERENCE RequestReference;
706
707 /* Sanity check again whether FDO has resource to handle the request */
708 NT_ASSERT(FdoExtension->FlowControl.OutstandingRequestCount <
709 FdoExtension->OutstandingRequestMax);
710
711 /* If FDO has waiting requests, issue one. */
712 if (!IsListEmpty(&FdoExtension->FlowControl.FdoBlockedRequestsListHead))
713 {
714 /* Sanity check */
715 NT_ASSERT(FdoExtension->FlowControl.OutstandingRequestCount <
716 FdoExtension->OutstandingRequestMax);
717
718 /* Take it out of FDO list */
719 Entry = RemoveTailList(&FdoExtension->FlowControl.FdoBlockedRequestsListHead);
720 RequestReference = CONTAINING_RECORD(Entry, QUEUED_REQUEST_REFERENCE, FdoEntry);
721
722 /* Increment FDO request counter */
723 ++FdoExtension->FlowControl.OutstandingRequestCount;
724 NT_ASSERT(FdoExtension->FlowControl.OutstandingRequestCount <=
725 FdoExtension->OutstandingRequestMax);
726
727 /* Call the start routine */
728 PortPdoIssueRequest(PdoExtension, RequestReference);
729
730 /* Our task is done */
731 return;
732 }
733
734 /* FDO's got no request, check the PDO of the just-finished request for awaiting requests */
735 if (!IsListEmpty(&PdoExtension->FlowControl.AwaitingRequestsListHead))
736 {
737 /* Sanity check */
738 NT_ASSERT(PdoExtension->FlowControl.OutstandingRequestCount <
739 PdoExtension->OutstandingRequestMax);
740
741 /* Take one request */
742 Entry = RemoveTailList(&PdoExtension->FlowControl.AwaitingRequestsListHead);
743 RequestReference = CONTAINING_RECORD(Entry, QUEUED_REQUEST_REFERENCE, PdoEntry);
744
745 /* This one goes to active list */
746 InsertHeadList(&PdoExtension->FlowControl.ActiveRequestsListHead, Entry);
747
748 /* Increment PDO request counter */
749 ++PdoExtension->FlowControl.OutstandingRequestCount;
750 NT_ASSERT(PdoExtension->FlowControl.OutstandingRequestCount <=
751 PdoExtension->OutstandingRequestMax);
752
753 /* FIXME: should be false. Allocate resource if it is determined required */
754 if (RequestReference->Srb->SrbExtension == NULL)
755 {
756 __debugbreak();
757 }
758
759 /* Call the start routine */
760 PortPdoIssueRequest(PdoExtension, RequestReference);
761
762 /* Our task is done */
763 return;
764 }
765}
#define RemoveTailList(ListHead)
Definition: env_spec_w32.h:975
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
Definition: typedefs.h:120

Referenced by PortCompleteRequest().

◆ StorpAssignTagToSrb()

FORCEINLINE BOOLEAN StorpAssignTagToSrb ( _In_ PPDO_DEVICE_EXTENSION  PdoExtension,
_In_ PSCSI_REQUEST_BLOCK  Srb 
)

Assigns a queue tag to a request if it stated it supports one.

Parameters
PdoExtensionPDO Device extension
SrbSRB that represents this request
Returns
BOOLEAN Whether the request was assigned a tag at last.

Definition at line 142 of file srb.c.

146{
147 ULONG NewTag;
148
149 /* Bail out if the request is untagged */
151 {
152 return FALSE;
153 }
154
155 /* FIXME: What if the counter overflows? */
156 NewTag = InterlockedIncrement(&PdoExtension->TagCounter);
157
158 /*
159 * We use ULONG for tag counter, and here seems to do a stupid truncation by casting to UCHAR;
160 * But since Storport has a default maximum 254 requests/LUN limitation, this is actually OK for
161 * our use case. If a miniport needs to support more than 254 tags it must use
162 * STORAGE_REQUEST_BLOCK which we don't support yet :D
163 */
164 Srb->QueueTag = (UCHAR)(NewTag % PdoExtension->OutstandingRequestMax);
165
166 DPRINT("StorpAssignTagToSrb: Assigned Tag %x, TagCounter was %x\n", Srb->QueueTag, NewTag);
167
168 return TRUE;
169}
#define InterlockedIncrement
Definition: armddk.h:53
unsigned char UCHAR
Definition: typedefs.h:53

Referenced by PortPdoScsi().

◆ StorpSrbAcquireReservedRequestReference()

static PQUEUED_REQUEST_REFERENCE StorpSrbAcquireReservedRequestReference ( _In_ PSCSI_REQUEST_BLOCK  Srb,
_In_ PIRP  Irp,
_In_ PPDO_DEVICE_EXTENSION  PdoExtension 
)
static

Takes the adapter reserve, if it is there and nobody else holds it.

Returns
PQUEUED_REQUEST_REFERENCE The reserved reference, or NULL if unavailable.

Definition at line 83 of file srb.c.

87{
89 PQUEUED_REQUEST_REFERENCE RequestReference;
90
91 if (FdoExtension->ReservedRequestReference == NULL ||
92 InterlockedCompareExchange(&FdoExtension->ReserveInUse, 1, 0) != 0)
93 {
94 return NULL;
95 }
96
97 RequestReference = FdoExtension->ReservedRequestReference;
99 RequestReference->FromReserve = TRUE;
100
101 return RequestReference;
102}
static VOID StorpSrbInitRequestReference(_In_ PQUEUED_REQUEST_REFERENCE RequestReference, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ PIRP Irp, _In_ PPDO_DEVICE_EXTENSION PdoExtension)
Initializes a request reference and sets the SRB => ReqRef link.
Definition: srb.c:25

Referenced by PortPdoSrbAllocatePrivateContexts().

◆ StorpSrbAllocateRequestReference()

static PQUEUED_REQUEST_REFERENCE StorpSrbAllocateRequestReference ( _In_ PSCSI_REQUEST_BLOCK  Srb,
_In_ PIRP  Irp,
_In_ PPDO_DEVICE_EXTENSION  PdoExtension 
)
static

Allocates QUEUED_REQUEST_REFERENCE for an SRB that is going to be processed.

Parameters
Srb
Irp
Returns
PQUEUED_REQUEST_REFERENCE RequestReference structure allocated, or NULL on failure.

Definition at line 57 of file srb.c.

61{
62 PQUEUED_REQUEST_REFERENCE RequestReference;
63
64 RequestReference =
65 ExAllocateFromNPagedLookasideList(&PdoExtension->FdoExtension->RequestReferenceLookaside);
66 if (RequestReference == NULL)
67 {
68 return NULL;
69 }
70
72
73 return RequestReference;
74}

Referenced by PortPdoSrbAllocatePrivateContexts().

◆ StorpSrbFreeRequestReference()

VOID StorpSrbFreeRequestReference ( _In_ PSCSI_REQUEST_BLOCK  Srb)

Frees an SRB's Request Reference and restore Srb->OriginalRequest field to IRP. This function does not check if Srb->OriginalRequest is actually an request reference, and you must determine it by other means.

Parameters
Srb

Definition at line 112 of file srb.c.

114{
115 PQUEUED_REQUEST_REFERENCE RequestReference;
117
118 RequestReference = (PQUEUED_REQUEST_REFERENCE)Srb->OriginalRequest;
119 Srb->OriginalRequest = RequestReference->Irp;
120 FdoExtension = RequestReference->PdoExtension->FdoExtension;
121
122 if (RequestReference->FromReserve)
123 {
124 InterlockedExchange(&FdoExtension->ReserveInUse, 0);
125 }
126 else
127 {
128 ExFreeToNPagedLookasideList(&FdoExtension->RequestReferenceLookaside, RequestReference);
129 }
130}
if(dx< 0)
Definition: linetemp.h:194
PFDO_DEVICE_EXTENSION FdoExtension
Definition: precomp.h:325
PPDO_DEVICE_EXTENSION PdoExtension
Definition: precomp.h:375

Referenced by PortCompleteRequest(), and PortPdoSrbAllocatePrivateContexts().

◆ StorpSrbInitRequestReference()

static VOID StorpSrbInitRequestReference ( _In_ PQUEUED_REQUEST_REFERENCE  RequestReference,
_In_ PSCSI_REQUEST_BLOCK  Srb,
_In_ PIRP  Irp,
_In_ PPDO_DEVICE_EXTENSION  PdoExtension 
)
static

Initializes a request reference and sets the SRB => ReqRef link.

Definition at line 25 of file srb.c.

30{
31 /* Both the lookaside entries and the reserve are recycled, so they need zeroing */
33
34 Srb->OriginalRequest = (PVOID)RequestReference;
35 RequestReference->Irp = Irp;
36 RequestReference->Srb = Srb;
37 RequestReference->TimeoutCounter = Srb->TimeOutValue;
38
39 RequestReference->PdoExtension = PdoExtension;
40
41 if (PdoExtension->FdoExtension->Miniport.PortConfig.SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK)
42 {
43 RequestReference->ExtendedRequest = &RequestReference->Ex;
44 RtlZeroMemory(RequestReference->ExtendedRequest, sizeof(*RequestReference->ExtendedRequest));
45 }
46}
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:664
ULONG TimeOutValue
Definition: srb.h:262
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255

Referenced by StorpSrbAcquireReservedRequestReference(), and StorpSrbAllocateRequestReference().