ReactOS 0.4.17-dev-1268-g5608ce5
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 */
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}
47
55static
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}
75
81static
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}
103
111VOID
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}
131
132
145)
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}
170
171
172VOID
173NTAPI
176 _In_ PIRP Irp,
177 _In_ PSCATTER_GATHER_LIST ScatterGatherList,
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}
230
231
236static
241 _In_ PIRP Irp)
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}
256
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}
308
309
313 _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
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}
405
406
407VOID
410 _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
411{
412 /* Ensure outstanding flag is unset */
413 RequestReference->IsOutstanding = FALSE;
414}
415
416
432 _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
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}
544
545
547NTAPI
550 _In_ PIRP Irp)
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}
696
697
698static
699VOID
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}
766
767
768static
769VOID
771 _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
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}
916
917
918VOID
919NTAPI
921 _In_ PKDPC Dpc,
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}
957
958
959/* 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
#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
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#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:42
struct _QUEUED_REQUEST_REFERENCE * PQUEUED_REQUEST_REFERENCE
@ PdoExtension
Definition: precomp.h:62
@ FdoExtension
Definition: precomp.h:61
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
#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)
_In_ PIRP Irp
Definition: kse.h:79
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
if(dx< 0)
Definition: linetemp.h:194
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:928
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 KernelMode
Definition: asm.h:38
#define _In_
Definition: no_sal2.h:158
int Count
Definition: noreturn.cpp:7
#define IoCompleteRequest
Definition: irp.c:1272
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:664
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:548
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
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 VOID PortCompleteRequest(_In_ PQUEUED_REQUEST_REFERENCE RequestReference)
Definition: srb.c:770
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
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 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:112
static VOID PortScheduleComingRequestsOnCompletion(_In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PFDO_DEVICE_EXTENSION FdoExtension)
Definition: srb.c:700
VOID PortPdoScheduleRequestNoFlowControl(_In_ PFDO_DEVICE_EXTENSION FdoExtension, _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
Definition: srb.c:408
VOID NTAPI PortPdoAfterBuildingScatterGatherList(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PSCATTER_GATHER_LIST ScatterGatherList, _In_ PVOID Context)
Definition: srb.c:174
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
NTSTATUS PortPdoSrbAllocatePrivateContexts(_In_ PSCSI_REQUEST_BLOCK Srb, _In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PFDO_DEVICE_EXTENSION FdoExtension)
Definition: srb.c:258
VOID NTAPI PortCompletionDpc(_In_ PKDPC Dpc, _In_ PVOID Context, _In_ PVOID SystemArgument1, _In_ PVOID SystemArgument2)
Definition: srb.c:920
NTSTATUS PortPdoIssueRequest(_In_ PPDO_DEVICE_EXTENSION PdoExtension, _In_ PQUEUED_REQUEST_REFERENCE RequestReference)
Definition: srb.c:311
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
PHW_STARTIO HwStartIo
Definition: srb.h:568
PHW_BUILDIO HwBuildIo
Definition: storport.h:7278
Definition: ketypes.h:767
Definition: typedefs.h:120
PORT_CONFIGURATION_INFORMATION PortConfig
Definition: precomp.h:99
PFDO_DEVICE_EXTENSION FdoExtension
Definition: precomp.h:325
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
PSCSI_REQUEST_BLOCK Srb
Definition: precomp.h:376
PEXTENDED_REQUEST ExtendedRequest
Definition: precomp.h:378
PSTOR_SCATTER_GATHER_LIST ScatterGatherList
Definition: precomp.h:380
PPDO_DEVICE_EXTENSION PdoExtension
Definition: precomp.h:375
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 FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#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:2219
#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