ReactOS 0.4.17-dev-1133-gc25e4fd
srb.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Storport Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Storport SRB I/O code
5 * COPYRIGHT: Copyright 2017 Eric Kohl (eric.kohl@reactos.org)
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "precomp.h"
11#include "inline.h"
12
13#define NDEBUG
14#include <debug/driverdbg.h>
15#include <debug.h>
16
17
18/* FUNCTIONS ******************************************************************/
19
23static
24VOID
26 _In_ PQUEUED_REQUEST_REFERENCE RequestReference,
30{
31 /* Both the lookaside entries and the reserve are recycled, so they need zeroing */
32 RtlZeroMemory(RequestReference, sizeof(*RequestReference));
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
49static
55{
56 PQUEUED_REQUEST_REFERENCE RequestReference;
57
58 RequestReference =
59 ExAllocateFromNPagedLookasideList(&PdoExtension->FdoExtension->RequestReferenceLookaside);
60 if (RequestReference == NULL)
61 {
62 return NULL;
63 }
64
66
67 return RequestReference;
68}
69
75static
81{
83 PQUEUED_REQUEST_REFERENCE RequestReference;
84
85 if (FdoExtension->ReservedRequestReference == NULL ||
86 InterlockedCompareExchange(&FdoExtension->ReserveInUse, 1, 0) != 0)
87 {
88 return NULL;
89 }
90
91 RequestReference = FdoExtension->ReservedRequestReference;
93 RequestReference->FromReserve = TRUE;
94
95 return RequestReference;
96}
97
105VOID
108{
109 PQUEUED_REQUEST_REFERENCE RequestReference;
111
112 RequestReference = (PQUEUED_REQUEST_REFERENCE)Srb->OriginalRequest;
113 Srb->OriginalRequest = RequestReference->Irp;
114 FdoExtension = RequestReference->PdoExtension->FdoExtension;
115
116 if (RequestReference->FromReserve)
117 {
118 InterlockedExchange(&FdoExtension->ReserveInUse, 0);
119 }
120 else
121 {
122 ExFreeToNPagedLookasideList(&FdoExtension->RequestReferenceLookaside, RequestReference);
123 }
124}
125
126
139)
140{
141 ULONG NewTag;
142
143 /* Bail out if the request is untagged */
145 {
146 return FALSE;
147 }
148
149 /* FIXME: What if the counter overflows? */
150 NewTag = InterlockedIncrement(&PdoExtension->TagCounter);
151
152 /*
153 * We use ULONG for tag counter, and here seems to do a stupid truncation by casting to UCHAR;
154 * But since Storport has a default maximum 254 requests/LUN limitation, this is actually OK for
155 * our use case. If a miniport needs to support more than 254 tags it must use
156 * STORAGE_REQUEST_BLOCK which we don't support yet :D
157 */
158 Srb->QueueTag = (UCHAR)(NewTag % PdoExtension->OutstandingRequestMax);
159
160 DPRINT("StorpAssignTagToSrb: Assigned Tag %x, TagCounter was %x\n", Srb->QueueTag, NewTag);
161
162 return TRUE;
163}
164
165
166VOID
167NTAPI
170 _In_ PIRP Irp,
171 _In_ PSCATTER_GATHER_LIST ScatterGatherList,
173{
175 PVOID MiniportExtension;
176 PHW_INITIALIZATION_DATA HwInitData;
177 PQUEUED_REQUEST_REFERENCE RequestReference;
178 BOOLEAN CanStartIo = TRUE;
180
181 RequestReference = (PQUEUED_REQUEST_REFERENCE)Context;
183 MiniportExtension = &FdoExtension->Miniport.MiniportExtension->HwDeviceExtension;
184 HwInitData = FdoExtension->HwInitData;
185
186 /* Save our SG List */
187 RequestReference->ScatterGatherList = (PSTOR_SCATTER_GATHER_LIST)ScatterGatherList;
188
189 /* BuildIo and StartIo are called on DISPATCH_LEVEL */
191
192 do {
193 /* Call BuildIo, if one is provided */
194 if (HwInitData->HwBuildIo)
195 {
196 CanStartIo = HwInitData->HwBuildIo(MiniportExtension, RequestReference->Srb);
197 }
198
199 /* If BuildIo says the request processing shall stop here, no more processing is needed */
200 if (!CanStartIo)
201 {
202 break;
203 }
204
205 HwInitData->HwStartIo(MiniportExtension, RequestReference->Srb);
206 }
207 while (0);
208
209 /* Restore IRQL */
211}
212
213
218static
223 _In_ PIRP Irp)
224{
225 /* Without a reserve nothing guarantees a completion that would retry the request */
226 if (FdoExtension->ReservedRequestReference == NULL)
227 {
230 }
231 else
232 {
234 }
235
236 return STATUS_PENDING;
237}
238
244{
245 PQUEUED_REQUEST_REFERENCE RequestReference;
246 ULONG SrbExtensionSize = FdoExtension->HwInitData->SrbExtensionSize;
247 PIRP Irp;
248
250
251 /* Allocate our private data area, falling back on the reserve when pool is exhausted */
253 if (RequestReference == NULL)
254 {
256 if (RequestReference == NULL)
257 {
259 }
260 }
261
262 /* Allocate SRB extension */
263 if (SrbExtensionSize == 0)
264 {
266 return STATUS_SUCCESS;
267 }
268
269 if (RequestReference->FromReserve)
270 {
271 Srb->SrbExtension = FdoExtension->ReservedSrbExtension;
272 RtlZeroMemory(Srb->SrbExtension, SrbExtensionSize);
273 return STATUS_SUCCESS;
274 }
275
277 SrbExtensionSize,
279 if (Srb->SrbExtension == NULL)
280 {
283 }
284
285 return STATUS_SUCCESS;
286}
287
288
292 _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
293{
294 PIRP Irp;
297 PHW_INITIALIZATION_DATA HwInitData;
299
300 Irp = RequestReference->Irp;
301 FdoExtension = PdoExtension->FdoExtension;
302 HwInitData = FdoExtension->Miniport.InitData;
303
304 NT_ASSERT(HwInitData);
305
306 /* Fill in SCSI address data */
307 /* FIXME: Not sure if this is the best place for it. */
308 RequestReference->Srb->PathId = PdoExtension->Bus;
309 RequestReference->Srb->TargetId = PdoExtension->Target;
310 RequestReference->Srb->Lun = PdoExtension->Lun;
311
312 /* FIXME: Delete after debug */
313 // PSCSI_REQUEST_BLOCK Srb = RequestReference->Srb;
314 // if (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI &&
315 // (Srb->Cdb[0] == SCSIOP_GET_EVENT_STATUS || Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY))
316 // {
317 // RequestReference->DumpSpecialRequest = TRUE;
318 // StorpDumpRequest(RequestReference);
319 // }
320
321 /* Start an DMA if IO subsystem allocated an MDL for us */
322 /* FIXME: Does this strategy work? */
323 if (RequestReference->Irp->MdlAddress)
324 {
325 /*
326 * Lock the buffer so that it stays in physical memory.
327 * In the two cases avoided here the memory has already been locked
328 */
329 if (!TEST_FLAG(Irp->MdlAddress->MdlFlags, MDL_SOURCE_IS_NONPAGED_POOL) &&
330 !TEST_FLAG(Irp->MdlAddress->MdlFlags, MDL_MAPPED_TO_SYSTEM_VA) &&
331 !TEST_FLAG(Irp->MdlAddress->MdlFlags, MDL_PAGES_LOCKED) &&
332 !TEST_FLAG(Irp->MdlAddress->MdlFlags, MDL_PARTIAL))
333 {
334 RequestReference->MappedSystemVa = (PVOID)1; /* FIXME: CHANGE ITS NAME */
336 }
337
338 /* Following call requires DISPATCH_LEVEL. */
340
341 /* Make up the scatter gather list */
342 /* FIXME: I don't know if we actually hit it */
343 NT_ASSERT((RequestReference->Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) !=
345 RequestReference->WriteToDevice =
346 TEST_FLAG(RequestReference->Srb->SrbFlags, SRB_FLAGS_DATA_OUT);
347
348 FdoExtension->DmaAdapter->DmaOperations->
349 GetScatterGatherList(FdoExtension->DmaAdapter,
350 FdoExtension->Device,
351 RequestReference->Irp->MdlAddress,
352 MmGetMdlVirtualAddress(RequestReference->Irp->MdlAddress),
353 RequestReference->Srb->DataTransferLength,
355 (PVOID)RequestReference,
356 RequestReference->WriteToDevice);
357
358 /* Restore IRQL */
360 } else {
361 /* Otherwise just start the IO with a NULL scatter gather list */
363 RequestReference->Irp,
364 NULL,
365 RequestReference);
366 }
367
368 /* FIXME: Is this correct? */
370
371 return Status;
372}
373
374
375VOID
378 _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
379{
380 /* Ensure outstanding flag is unset */
381 RequestReference->IsOutstanding = FALSE;
382}
383
384
400 _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
401{
402 PPDO_IO_FLOW_CONTROL FlowControl = &PdoExtension->FlowControl;
404 PSCSI_REQUEST_BLOCK Srb = RequestReference->Srb;
405 BOOLEAN StrongOrderedRequest = FALSE;
406 BOOLEAN IssueRequest = TRUE;
407
408 /* Set outstanding flag */
409 RequestReference->IsOutstanding = TRUE;
410
411 /* Check if we can issue this request. */
412 /* Acquire the HBA global flow control lock first */
415
416 do
417 {
418 /* Check PDO flow control conditions */
419
420 /* Sanity check */
421 NT_ASSERT(FlowControl->OutstandingRequestCount <= PdoExtension->OutstandingRequestMax);
422
423 /* If PDO is not suitable to receive a request, make it wait */
424 if (FlowControl->IsBusy || FlowControl->IsPaused ||
427 FlowControl->StrongOrderedCount ||
428 FlowControl->OutstandingRequestCount == PdoExtension->OutstandingRequestMax ||
429 (!IsListEmpty(&FlowControl->AwaitingRequestsListHead)))
430 {
432 &RequestReference->PdoEntry);
433 IssueRequest = FALSE;
434 break;
435 }
436
437 /* Check if this request is strong-ordered */
440 {
441 RequestReference->StrongOrdered = TRUE;
442 StrongOrderedRequest = TRUE;
443 ++FlowControl->StrongOrderedCount;
444 }
445
446 /*
447 * If this request is strong ordered and the LUN's active/approved list is not
448 * drained, the request must wait.
449 */
450 if (StrongOrderedRequest && !IsListEmpty(&FlowControl->ActiveRequestsListHead))
451 {
453 &RequestReference->PdoEntry);
454 IssueRequest = FALSE;
455 break;
456 }
457
458 /*
459 * If any break's triggered before this point, the request is in PDO waiting queue.
460 * Going past this point meant PDO approves this request. Put it into active list.
461 */
463 {
465 &RequestReference->PdoEntry);
466 } else {
468 &RequestReference->PdoEntry);
469 }
470
471 /* A new outstanding request is added to this LUN */
472 ++FlowControl->OutstandingRequestCount;
473
474 /* Check FDO flow control status. */
475
476 /* If the FDO can't handle more requests, then the request should be queued. */
477 if (FlowControl->IsBusy || FlowControl->IsPaused ||
478 FlowControl->OutstandingRequestCount == FdoExtension->OutstandingRequestMax)
479 {
480 /* Put into FDO queue */
481 InsertHeadList(&FdoExtension->FlowControl.FdoBlockedRequestsListHead,
482 &RequestReference->FdoEntry);
483
484 /*
485 * Now the request is in PDO active list, in FDO awaiting queue, not issued.
486 * Let it wait until another completion event schedules it.
487 */
488 break;
489 }
490
491 /* Seems good, increment FDO request count */
492 ++FdoExtension->FlowControl.OutstandingRequestCount;
493
494 /*
495 * Now the request is counted in FDO & PDO, and is put into PDO active list,
496 * next step we're going to issue it.
497 */
498 } while (0);
499
500 // FIXME: The port driver indicates that an LU-specific queue has been frozen by
501 // returning a request with SRB_STATUS_QUEUE_FROZEN in the SrbStatus member. New
502 // requests from the class driver can be inserted into the queue, but only autosense
503 // requests are sent to the logical unit as long as its queue is frozen.
504 // https://learn.microsoft.com/en-us/windows-hardware/drivers/storage/storage-class-driver-s-releasequeue-routine
505
506 /* We've determined where the request goes. Release the flow control lock */
509
510 return IssueRequest;
511}
512
513
515NTAPI
518 _In_ PIRP Irp)
519{
525 PMINIPORT Miniport;
526 PHW_INITIALIZATION_DATA HwInitData;
527
528 DPRINT("PortPdoScsi(%p %p)\n", DeviceObject, Irp);
529
531 Srb = Stack->Parameters.Scsi.Srb;
532
533 if (Srb == NULL) {
534 DPRINT1("Srb is NULL!");
537
538 Irp->IoStatus.Information = 0;
539 Irp->IoStatus.Status = Status;
540
542 return Status;
543 }
544
547 FdoExtension = PdoExtension->FdoExtension;
549 Miniport = &FdoExtension->Miniport;
550 HwInitData = Miniport->InitData;
551
552 switch (Srb->Function) {
553 /* Both of these should be sent to device and let themselves process this */
556 {
557 PQUEUED_REQUEST_REFERENCE RequestReference;
558 BOOLEAN IssueRequest;
559
560 /* Mark IRP as pending */
562
563 /* Allocate private contexts */
565 if (Status != STATUS_SUCCESS)
566 {
567 break;
568 }
569 RequestReference = (PQUEUED_REQUEST_REFERENCE)Srb->OriginalRequest;
570
571 /* Assign a tag to the SRB if it supports tagging */
573
574 DPRINT("New request (%d:%d:%d) ReqRef %p Srb %p Irp %p Tag %x SrbExt %p(%d)\n",
576 RequestReference, Srb, Irp, Srb->QueueTag,
577 Srb->SrbExtension, HwInitData->SrbExtensionSize);
578
579 /*
580 * Do the scheduling. If returns TRUE, we should issue this request to the hardware.
581 * Otherwise it will keep waiting until next completion schedules it, or be cancelled on
582 * an error, etc.
583 */
586 RequestReference);
587
588 /* This request is viable to be issued. */
589 if (IssueRequest)
590 {
591 Status = PortPdoIssueRequest(PdoExtension, RequestReference);
592 } else {
594 }
595
596 break;
597 }
598
599 /*
600 * These requests are actually sent to adapters and are not outstanding requests for devices
601 * so we simply pass them down to miniport
602 */
605 {
606 PQUEUED_REQUEST_REFERENCE RequestReference;
607
608 /* Mark IRP as pending */
610
611 /* Allocate private contexts */
613 if (Status != STATUS_SUCCESS)
614 {
615 break;
616 }
617 RequestReference = (PQUEUED_REQUEST_REFERENCE)Srb->OriginalRequest;
618
619 /*
620 * Call the non-flow-controlled scheduling function (it does nothing but the model is
621 * preserved for consistency)
622 */
624
625 /* Fire up the request immediately */
626 PortPdoIssueRequest(PdoExtension, RequestReference);
627
628 break;
629 }
630
632 {
633 if (InterlockedCompareExchange(&PdoExtension->IsClaimed, 1, 0))
634 {
637 break;
638 }
639
640 /* The claimed device object is handed back to the class driver here */
641 Srb->DataBuffer = PdoExtension->Device;
644 break;
645 }
646
648 {
649 InterlockedExchange(&PdoExtension->IsClaimed, 0);
650
653 break;
654 }
655
656 default:
657 DPRINT1("Unsupported Srb Function %02X!", Srb->Function);
658 // DbgBreakPoint();
661 break;
662 }
663
664 return Status;
665}
666
667
668static
669VOID
673{
675 PQUEUED_REQUEST_REFERENCE RequestReference;
676
677 /* Sanity check again whether FDO has resource to handle the request */
678 NT_ASSERT(FdoExtension->FlowControl.OutstandingRequestCount <
679 FdoExtension->OutstandingRequestMax);
680
681 /* If FDO has waiting requests, issue one. */
682 if (!IsListEmpty(&FdoExtension->FlowControl.FdoBlockedRequestsListHead))
683 {
684 /* Sanity check */
685 NT_ASSERT(FdoExtension->FlowControl.OutstandingRequestCount <
686 FdoExtension->OutstandingRequestMax);
687
688 /* Take it out of FDO list */
689 Entry = RemoveTailList(&FdoExtension->FlowControl.FdoBlockedRequestsListHead);
690 RequestReference = CONTAINING_RECORD(Entry, QUEUED_REQUEST_REFERENCE, FdoEntry);
691
692 /* Increment FDO request counter */
693 ++FdoExtension->FlowControl.OutstandingRequestCount;
694 NT_ASSERT(FdoExtension->FlowControl.OutstandingRequestCount <=
695 FdoExtension->OutstandingRequestMax);
696
697 /* Call the start routine */
698 PortPdoIssueRequest(PdoExtension, RequestReference);
699
700 /* Our task is done */
701 return;
702 }
703
704 /* FDO's got no request, check the PDO of the just-finished request for awaiting requests */
705 if (!IsListEmpty(&PdoExtension->FlowControl.AwaitingRequestsListHead))
706 {
707 /* Sanity check */
708 NT_ASSERT(PdoExtension->FlowControl.OutstandingRequestCount <
709 PdoExtension->OutstandingRequestMax);
710
711 /* Take one request */
712 Entry = RemoveTailList(&PdoExtension->FlowControl.AwaitingRequestsListHead);
713 RequestReference = CONTAINING_RECORD(Entry, QUEUED_REQUEST_REFERENCE, PdoEntry);
714
715 /* This one goes to active list */
716 InsertHeadList(&PdoExtension->FlowControl.ActiveRequestsListHead, Entry);
717
718 /* Increment PDO request counter */
719 ++PdoExtension->FlowControl.OutstandingRequestCount;
720 NT_ASSERT(PdoExtension->FlowControl.OutstandingRequestCount <=
721 PdoExtension->OutstandingRequestMax);
722
723 /* FIXME: should be false. Allocate resource if it is determined required */
724 if (RequestReference->Srb->SrbExtension == NULL)
725 {
726 __debugbreak();
727 }
728
729 /* Call the start routine */
730 PortPdoIssueRequest(PdoExtension, RequestReference);
731
732 /* Our task is done */
733 return;
734 }
735}
736
737
738static
739VOID
741 _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
742{
744 PIRP Irp;
749 BOOLEAN FromReserve;
750
751 /* Take out our information */
752 Srb = RequestReference->Srb;
753 Irp = RequestReference->Irp;
754 PdoExtension = RequestReference->PdoExtension;
755 FdoExtension = PdoExtension->FdoExtension;
756
757 /* The reference is released further down, so remember this while it is still valid */
758 FromReserve = RequestReference->FromReserve;
759
760 /* FIXME: DELETE AFTER DEBUG */
761 // if (RequestReference->DumpSpecialRequest)
762 // {
763 // StorpDumpRequestResponse(RequestReference);
764 // }
765
766 DPRINT("Completing request: (%d:%d:%d) ReqRef %p Srb %p Irp %p Tag %x\n",
767 Srb->PathId, Srb->TargetId, Srb->Lun, RequestReference, Srb, RequestReference->Irp, Srb->QueueTag);
768
769 /* Return SG list resources back to system */
770 if (RequestReference->ScatterGatherList)
771 {
772 FdoExtension->DmaAdapter->DmaOperations->
773 PutScatterGatherList(FdoExtension->DmaAdapter,
774 (PSCATTER_GATHER_LIST)RequestReference->ScatterGatherList,
775 RequestReference->WriteToDevice);
776 RequestReference->ScatterGatherList = NULL;
777
778 // /* Release pages we locked for DMA, if we actually have locked it */
779 // if (RequestReference->MappedSystemVa != NULL)
780 // {
781 // MmUnmapLockedPages(RequestReference->MappedSystemVa, RequestReference->Irp->MdlAddress);
782 // }
783 /* Unlock the pages locked for DMA */
784 if (RequestReference->MappedSystemVa)
785 {
786 MmUnlockPages(RequestReference->Irp->MdlAddress);
787 }
788 }
789
790 /* Check if we need to interact with flow control. */
791 if (RequestReference->IsOutstanding)
792 {
793 /* Take the request out of FDO and PDO structures, and update flow control data */
796
797 FdoExtension->FlowControl.OutstandingRequestCount--;
798 if (FdoExtension->FlowControl.RemainingBusyRequests)
799 {
800 --FdoExtension->FlowControl.RemainingBusyRequests;
801
802 /* Clear busy state as needed */
803 if (FdoExtension->FlowControl.OutstandingRequestCount == 0 ||
804 FdoExtension->FlowControl.RemainingBusyRequests == 0)
805 {
806 FdoExtension->FlowControl.IsBusy = FALSE;
807 }
808 }
809
810 RemoveEntryList(&RequestReference->PdoEntry);
811 --PdoExtension->FlowControl.OutstandingRequestCount;
812 if (PdoExtension->FlowControl.RemainingBusyRequests)
813 {
814 --PdoExtension->FlowControl.RemainingBusyRequests;
815
816 /* Clear busy state as needed */
817 if (PdoExtension->FlowControl.OutstandingRequestCount == 0 ||
818 PdoExtension->FlowControl.RemainingBusyRequests == 0)
819 {
820 PdoExtension->FlowControl.IsBusy = FALSE;
821 }
822 }
823
824 /* Decrement strong ordered request count if needed */
825 if (RequestReference->StrongOrdered)
826 {
827 --PdoExtension->FlowControl.StrongOrderedCount;
828 }
829
830 /* Free the private data structure. No one should use it anymore */
832 RequestReference = NULL;
833
834 /* Schedule next IO before we release flow control lock */
836
837 /* We're done, release flow control lock */
840
841 }
842
843 /*
844 * Free SRB extension as this request will never go back to miniport again. Must free it before
845 * IoCompleteRequest because class driver's completion routine may issue another request. If we
846 * free it after IoCompleteRequest we may zero out the newly-issued SRB's extension, since one
847 * single SRB can be reused between requests, and the SRB issued in completion routine could be
848 * the same one we operating here.
849 */
850 if (Srb->SrbExtension)
851 {
852 /* The reserved one is handed back along with its packet, not freed */
853 if (!FromReserve)
854 {
856 }
858 }
859
860 /*
861 * After done with internal accountings, we can finally complete this IO.
862 *
863 * We must not complete the IO before scheduling next IO, because at that point the flow control
864 * lock is still held, and class driver's completion routine may issue another request. This
865 * will cause a recursive lock acquisition in PDO SCSI handler and lead to bugcheck.
866 */
867 switch (SRB_STATUS(Srb->SrbStatus))
868 {
871 break;
872
873 case SRB_STATUS_BUSY:
875 break;
876
877 default:
878 IoStatus = STATUS_UNSUCCESSFUL; // FIXME:
879 break;
880 }
881 Irp->IoStatus.Status = IoStatus;
882 Irp->IoStatus.Information = Srb->DataTransferLength; /* FIXME: hopefully this is correct */
883
884 /* We just gave memory back, so let one request that ran out of it through */
886
887 DPRINT("Calling IoCompleteRequest\n");
889}
890
891
892VOID
893NTAPI
895 _In_ PKDPC Dpc,
899{
900 PQUEUED_REQUEST_REFERENCE RequestReference;
904 ULONG Count = 0;
905
906 DPRINT("PortCompletionDpc(%p %p %p %p)\n", Dpc, Context, SystemArgument1, SystemArgument2);
907
908 /* Take context pointer as FDO extension */
910
911 /* Flush all entries in the list and complete all requests */
912 Entry = InterlockedFlushSList(&FdoExtension->CompletionList);
913 while (Entry)
914 {
915 /* Prepare Next pointer first (Completion routine will free the memory that contains it) */
916 Next = Entry->Next;
917
918 /* Get original request */
919 RequestReference = CONTAINING_RECORD(Entry, QUEUED_REQUEST_REFERENCE, CompletionEntry);
920
921 /* Call real completion routine */
922 PortCompleteRequest(RequestReference);
923
924 /* Move on to next one */
925 Entry = Next;
926 ++Count;
927 }
928
929 DPRINT("Completed %d requests\n", Count);
930}
931
932
933/* EOF */
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
struct _IRP * PIRP
unsigned char BOOLEAN
Definition: actypes.h:127
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedExchange
Definition: armddk.h:54
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
struct _FDO_DEVICE_EXTENSION * PFDO_DEVICE_EXTENSION
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_FLAGS_BYPASS_FROZEN_QUEUE
Definition: srb.h:398
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:401
#define SRB_ORDERED_QUEUE_TAG_REQUEST
Definition: srb.h:425
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:395
#define SRB_FUNCTION_FLUSH
Definition: srb.h:323
#define SRB_FUNCTION_SHUTDOWN
Definition: srb.h:322
#define SRB_HEAD_OF_QUEUE_TAG_REQUEST
Definition: srb.h:424
#define SRB_FLAGS_BYPASS_LOCKED_QUEUE
Definition: srb.h:410
#define SRB_FLAGS_UNSPECIFIED_DIRECTION
Definition: srb.h:403
#define SRB_STATUS(Status)
Definition: srb.h:389
#define SRB_STATUS_INTERNAL_ERROR
Definition: srb.h:373
#define SRB_STATUS_BUSY
Definition: srb.h:345
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:346
#define TAG_SRB_EXTENSION
Definition: precomp.h:41
struct _QUEUED_REQUEST_REFERENCE * PQUEUED_REQUEST_REFERENCE
@ PdoExtension
Definition: precomp.h:61
@ FdoExtension
Definition: precomp.h:60
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define RemoveTailList(ListHead)
Definition: env_spec_w32.h:975
#define NonPagedPool
Definition: env_spec_w32.h:307
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
Status
Definition: gdiplustypes.h:24
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
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
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)
if(dx< 0)
Definition: linetemp.h:194
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:931
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
#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 KernelMode
Definition: asm.h:38
#define _In_
Definition: no_sal2.h:158
int Count
Definition: noreturn.cpp:7
#define IoCompleteRequest
Definition: irp.c:1272
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
Entry
Definition: section.c:5216
#define STATUS_SUCCESS
Definition: shellext.h:65
STDMETHOD() Next(THIS_ ULONG celt, IAssociationElement *pElement, ULONG *pceltFetched) PURE
#define DPRINT
Definition: sndvol32.h:73
NTSTATUS NTAPI PortPdoScsi(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
Definition: srb.c:516
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:136
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:220
static VOID PortCompleteRequest(_In_ PQUEUED_REQUEST_REFERENCE RequestReference)
Definition: srb.c:740
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:397
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:77
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
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:106
static VOID PortScheduleComingRequestsOnCompletion(_In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PFDO_DEVICE_EXTENSION FdoExtension)
Definition: srb.c:670
VOID PortPdoScheduleRequestNoFlowControl(_In_ PFDO_DEVICE_EXTENSION FdoExtension, _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
Definition: srb.c:376
VOID NTAPI PortPdoAfterBuildingScatterGatherList(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PSCATTER_GATHER_LIST ScatterGatherList, _In_ PVOID Context)
Definition: srb.c:168
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:51
NTSTATUS PortPdoSrbAllocatePrivateContexts(_In_ PSCSI_REQUEST_BLOCK Srb, _In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PFDO_DEVICE_EXTENSION FdoExtension)
Definition: srb.c:240
VOID NTAPI PortCompletionDpc(_In_ PKDPC Dpc, _In_ PVOID Context, _In_ PVOID SystemArgument1, _In_ PVOID SystemArgument2)
Definition: srb.c:894
NTSTATUS PortPdoIssueRequest(_In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
Definition: srb.c:290
VOID PortQueueStarvedRequest(_In_ PFDO_DEVICE_EXTENSION FdoExtension, _In_ PIRP Irp)
Queues a request that could not allocate its private contexts.
Definition: fdo.c:124
VOID PortRetryStarvedRequest(_In_ PFDO_DEVICE_EXTENSION FdoExtension)
Retries one queued request, so each completion lets exactly one through.
Definition: fdo.c:135
_In_ PVOID Context
Definition: storport.h:2325
PHW_STARTIO HwStartIo
Definition: srb.h:568
ULONG SrbExtensionSize
Definition: srb.h:576
PHW_BUILDIO HwBuildIo
Definition: storport.h:2423
Definition: ketypes.h:767
Definition: typedefs.h:120
PHW_INITIALIZATION_DATA InitData
Definition: precomp.h:91
PFDO_DEVICE_EXTENSION FdoExtension
Definition: precomp.h:303
LIST_ENTRY ActiveRequestsListHead
Definition: precomp.h:180
ULONG OutstandingRequestCount
Definition: precomp.h:171
ULONG StrongOrderedCount
Definition: precomp.h:168
LIST_ENTRY AwaitingRequestsListHead
Definition: precomp.h:186
PSCSI_REQUEST_BLOCK Srb
Definition: precomp.h:343
PSTOR_SCATTER_GATHER_LIST ScatterGatherList
Definition: precomp.h:345
PPDO_DEVICE_EXTENSION PdoExtension
Definition: precomp.h:342
UCHAR QueueTag
Definition: srb.h:256
ULONG TimeOutValue
Definition: srb.h:262
UCHAR TargetId
Definition: srb.h:254
PVOID OriginalRequest
Definition: srb.h:266
PVOID DataBuffer
Definition: srb.h:263
UCHAR PathId
Definition: srb.h:253
UCHAR QueueAction
Definition: srb.h:257
UCHAR Function
Definition: srb.h:250
ULONG DataTransferLength
Definition: srb.h:261
PVOID SrbExtension
Definition: srb.h:267
ULONG InternalStatus
Definition: srb.h:269
ULONG SrbFlags
Definition: srb.h:260
UCHAR SrbStatus
Definition: srb.h:251
#define STATUS_PENDING
Definition: telnetd.h:14
unsigned char UCHAR
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
#define FORCEINLINE
Definition: wdftypes.h:67
NTSYSAPI void WINAPI DbgBreakPoint(void)
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2206
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
*LockHandle LockHandle _Out_ PKLOCK_QUEUE_HANDLE LockHandle
Definition: kefuncs.h:717
@ IoModifyAccess
Definition: ketypes.h:933
_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 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
#define InterlockedFlushSList(SListHead)
Definition: rtlfuncs.h:3419
#define PSLIST_ENTRY
Definition: rtltypes.h:134