ReactOS 0.4.16-dev-2633-g8dc9e50
scsi.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS ATA Port Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: SCSI I/O queue and requests handling
5 * COPYRIGHT: Copyright 2026 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include "atapi.h"
11
12/* GLOBALS ********************************************************************/
13
16
17static DRIVER_CANCEL AtaReqDeviceQueueCancelIo;
18static DRIVER_LIST_CONTROL AtaReqPreparePrdTable;
19static DRIVER_CONTROL AtaReqCallSendRequestSerialized;
20
21static
26
27static
28VOID
32 _In_ BOOLEAN DoReleaseDeviceQueueLock);
33
34static
38
39/* FUNCTIONS ******************************************************************/
40
41static
44 _In_ UCHAR SrbStatus)
45{
47
48 /* We translate only the values that are actually used by the driver */
49 switch (SRB_STATUS(SrbStatus))
50 {
52 return STATUS_SUCCESS;
53
55 return STATUS_IO_TIMEOUT;
56
59
62
65
66 default:
67 break;
68 }
69
71}
72
73static
74VOID
77{
81
82 /*
83 * The device might have been powered down as a part of an idle detection logic,
84 * so we have to power up the device again.
85 */
86 if (!(Device->QueueFlags & QUEUE_FLAG_FROZEN_POWER))
87 return;
88
91 return;
92
94 return;
95
96 INFO("Powering up idle device\n");
97
98 PowerState.DeviceState = PowerDeviceD0;
102 NULL,
103 NULL,
104 NULL);
105 if (!NT_SUCCESS(Status))
106 {
107 ERR("Failed to power up device '%s' %lx\n", DevExt->FriendlyName, Status);
108 }
109}
110
111static
112VOID
115{
117
118 KeSetEvent(&Device->QueueStoppedEvent, 0, FALSE);
119
120 Srb = Device->QuiescenceSrb;
121 if (Srb)
122 {
124
125 Device->QuiescenceSrb = NULL;
126
128
130
132 Irp->IoStatus.Status = STATUS_SUCCESS;
134
136 }
137}
138
139static
144 _Out_ PUCHAR ResultSrbStatus)
145{
146 UCHAR SrbStatus;
147
148 SrbStatus = SRB_STATUS(*ResultSrbStatus);
149
150 /* Only requeue busy requests */
151 if ((SrbStatus != SRB_STATUS_BUSY) && (SrbStatus != SRB_STATUS_INSUFFICIENT_RESOURCES))
152 return COMPLETE_IRP;
153
154 /* Retry at least once if the request was rejected due to lack of resources */
155 if (SrbStatus == SRB_STATUS_INSUFFICIENT_RESOURCES)
156 {
158 {
159 /* We have no chance to dispatch it */
160 return COMPLETE_IRP;
161 }
162
163 WARN("Retrying operation\n");
164
166 }
167
171
172 /* Place the Srb back into the queue */
174 {
175 /* We failed because of the IRP was cancelled, just update the status */
176 *ResultSrbStatus = Request->Srb->SrbStatus;
177
178 return COMPLETE_IRP;
179 }
180
181 return COMPLETE_NO_IRP;
182}
183
184_Requires_lock_held_(PortData->QueueLock)
185static
187AtaReqPortQueueListDispatchNextRequest(
188 _In_ PATAPORT_PORT_DATA PortData)
189{
193
195
196 if (IsListEmpty(&PortData->PortQueueList))
197 return FALSE;
198
199 Entry = RemoveHeadList(&PortData->PortQueueList);
200
203
205
206 /* Try to unfreeze the device queue */
207 Device->QueueFlags &= ~QUEUE_FLAG_FROZEN_SLOT;
209
210 return TRUE;
211}
212
213static
214VOID
218{
220
222 {
223 PDMA_ADAPTER DmaAdapter = Device->PortData->DmaAdapter;
224 PDMA_OPERATIONS DmaOperations = DmaAdapter->DmaOperations;
225
226 ASSERT(Request->SgList);
228
229 DmaOperations->PutScatterGatherList(DmaAdapter,
230 Request->SgList,
231 !!(Request->Flags & REQUEST_FLAG_DATA_IN));
232 }
234 {
235 MmUnmapReservedMapping(Device->PortData->ReservedVaSpace, ATAPORT_TAG, Request->Mdl);
236 _InterlockedExchange(&Device->PortData->ReservedMappingLock, 0);
237 }
238
239 if (Request->Flags & REQUEST_FLAG_HAS_MDL)
240 {
241 ASSERT(Request->Mdl);
242
243 IoFreeMdl(Request->Mdl);
244 }
245
246#if DBG
247 Request->Mdl = NULL;
248 Request->SgList = NULL;
249#endif
250
254}
255
256static
257VOID
260{
263 PIRP Irp;
264 UCHAR SrbStatus;
265 ATA_COMPLETION_ACTION CompletionAction = COMPLETE_IRP;
266
268
269 if (Request->InternalState != REQUEST_STATE_NOT_STARTED)
270 {
271 if (Request->Complete)
272 {
273 if (Request->Flags & REQUEST_FLAG_INTERNAL)
274 {
275 Request->Complete(Request);
276 return;
277 }
278 else
279 {
281 CompletionAction = Request->Complete(Request);
283 }
284 }
285
286 if (Device->PortData->PortFlags & PORT_FLAG_IS_SIMPLEX)
287 {
288 IoFreeController(Device->PortData->HwSyncObject);
289 }
290 }
291
293
294 Srb = Request->Srb;
295
296 Irp = Request->Irp;
297 Irp->IoStatus.Information = Request->DataTransferLength;
298
300
301 /* Release the request back to the device queue */
302 ASSERT(!(Device->FreeRequestsBitmap & Request->Tag));
303 Device->FreeRequestsBitmap |= Request->Tag;
304
305 /* Release the slot back to the port queue */
306 if (Request->InternalState != REQUEST_STATE_NOT_STARTED)
307 {
308 PATAPORT_PORT_DATA PortData = Device->PortData;
309
311
312 /* Stop the timer tied to the completed slot */
313 PortData->ActiveTimersBitmap &= ~(1 << Request->Slot);
314
315 /* Release exclusive access to the port queue */
317 PortData->QueueFlags &= ~PORT_QUEUE_FLAG_EXCLUSIVE_MODE;
318
319 /* Release the slot */
320 ASSERT(!(PortData->FreeSlotsBitmap & (1 << Request->Slot)));
321 PortData->FreeSlotsBitmap |= (1 << Request->Slot);
322#if DBG
323 PortData->Slots[Request->Slot] = NULL;
324#endif
325 if (Request->Flags & REQUEST_FLAG_NCQ)
326 --PortData->AllocatedSlots;
327 else
328 ++PortData->AllocatedSlots;
329
330 PortData->AllocateSlot(PortData->ChannelContext, Request, FALSE);
331
332 if ((PortData->QueueFlags & PORT_QUEUE_FLAG_SIGNAL_STOP) && AtaPortQueueEmpty(PortData))
333 {
334 PortData->QueueFlags &= ~PORT_QUEUE_FLAG_SIGNAL_STOP;
335 KeSetEvent(&PortData->QueueStoppedEvent, 0, FALSE);
336 }
337
338 /* Start the next request on the port queue */
339 if (!AtaReqPortQueueListDispatchNextRequest(PortData))
341 }
342
343 /* Check if we need to retry later */
344 if (Request->InternalState == REQUEST_STATE_NOT_STARTED ||
345 Request->InternalState == REQUEST_STATE_REQUEUE)
346 {
347 CompletionAction = AtaReqRequeueRequest(Device, Request, &Request->SrbStatus);
348 }
349
350#if DBG
351 if (CompletionAction == COMPLETE_IRP)
352 ++Device->Statistics.RequestsCompleted;
353#endif
354
355 /* Freeze the Srb queue in case of device error */
356 if ((Request->InternalState == REQUEST_STATE_FREEZE_QUEUE) &&
358 {
360
362 Request->SrbStatus |= SRB_STATUS_QUEUE_FROZEN;
363 INFO("Freeze queue\n");
364 }
365
366 /* Signal the event when the list of active IRPs is empty */
367 if ((Device->QueueFlags & QUEUE_FLAG_SIGNAL_STOP) &&
368 (Device->FreeRequestsBitmap == Device->MaxRequestsBitmap))
369 {
370 Device->QueueFlags &= ~QUEUE_FLAG_SIGNAL_STOP;
372 }
373
377
378 SrbStatus = Request->SrbStatus;
379
380 /*
381 * Start the next request on the device queue.
382 * It's important to do this before actually completing an IRP.
383 */
386
387 /*
388 * Complete the IRP outside of the spinlock to avoid deadlocks.
389 * A new SCSI device I/O request might sent immediately after the IRP completed.
390 */
391 if (CompletionAction == COMPLETE_IRP)
392 {
394 {
395 /* Special status for the upper class driver */
398 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
399 }
400 else
401 {
402 Srb->SrbStatus = SrbStatus;
403 Irp->IoStatus.Status = AtaSrbStatusToNtStatus(SrbStatus);
404 }
405
407 }
408}
409
410UCHAR
413 _In_ SCSI_SENSE_CODE SenseCode)
414{
415 SENSE_DATA SenseData;
416
417 if ((Srb->SenseInfoBuffer == NULL) || (Srb->SenseInfoBufferLength == 0))
418 return SenseCode.SrbStatus;
419
420 ASSERT(!(SenseCode.SrbStatus & SRB_STATUS_AUTOSENSE_VALID));
421
423
424 // TODO: D_SENSE (fixed or descriptor format) is not supported yet
425 RtlZeroMemory(&SenseData, sizeof(SenseData));
426 SenseData.Valid = 1;
428 SenseData.SenseKey = SenseCode.SenseKey;
429 SenseData.AdditionalSenseCode = SenseCode.AdditionalSenseCode;
430 SenseData.AdditionalSenseCodeQualifier = SenseCode.AdditionalSenseCodeQualifier;
431 SenseData.AdditionalSenseLength =
432 sizeof(SenseData) - RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength);
433
435 &SenseData,
436 min(Srb->SenseInfoBufferLength, sizeof(SenseData)));
437
438 return SenseCode.SrbStatus | SRB_STATUS_AUTOSENSE_VALID;
439}
440
441VOID
444 _In_ ULONG64 Lba)
445{
446 PSENSE_DATA SenseData;
447
448 if ((Srb->SenseInfoBuffer == NULL) || (Srb->SenseInfoBufferLength == 0))
449 return;
450
451 SenseData = Srb->SenseInfoBuffer;
452
454 {
455 ASSERT(SenseData->Valid);
456
457 SenseData->Information[0] = (UCHAR)(Lba >> 24);
458 SenseData->Information[1] = (UCHAR)(Lba >> 16);
459 SenseData->Information[2] = (UCHAR)(Lba >> 8);
460 SenseData->Information[3] = (UCHAR)(Lba >> 0);
461 }
462
463 // TODO: D_SENSE (fixed or descriptor format) is not supported yet
464}
465
469{
470 PMDL Mdl;
471
472 Mdl = IoAllocateMdl(Request->DataBuffer,
473 Request->DataTransferLength,
474 FALSE,
475 FALSE,
476 NULL);
477 if (!Mdl)
478 return FALSE;
479
481
482 Request->Mdl = Mdl;
484
485 return TRUE;
486}
487
488static
489VOID
492{
494 PATAPORT_PORT_DATA PortData = Device->PortData;
496
498 ASSERT(PortData->Slots[Request->Slot] == Request);
499
500 PortData->PrepareIo(PortData->ChannelContext, Request);
501
502 OldIrql = KeAcquireInterruptSpinLock(PortData->InterruptObject);
503
504 ASSERT(!(PortData->ActiveSlotsBitmap & (1 << Request->Slot)));
505
506 if ((PortData->InterruptFlags & PORT_INT_FLAG_IS_IO_ACTIVE) ||
508 {
509 PortData->ActiveSlotsBitmap |= 1 << Request->Slot;
510
511 if (!PortData->StartIo(PortData->ChannelContext, Request))
512 {
513 PortData->TimerCount[Request->Slot] = Request->TimeOut;
514 }
515
516 KeReleaseInterruptSpinLock(PortData->InterruptObject, OldIrql);
517 }
518 else
519 {
521
522 /*
523 * Needed to prevent an infinite loop that happens
524 * when the queue manager keeps retrying the SRB at dispatch level.
525 */
527
528 KeReleaseInterruptSpinLock(PortData->InterruptObject, OldIrql);
529
530 /* If the queue is frozen, then force queue manager to requeue the SRB */
531 Request->SrbStatus = SRB_STATUS_BUSY;
532 Request->InternalState = REQUEST_STATE_REQUEUE;
533
534 /* Defer the completion to a DPC to avoid the recursive call in some cases */
536 }
537}
538
539static
540VOID
541NTAPI
544 _In_ PIRP Irp,
547{
550 PATAPORT_PORT_DATA PortData = Device->PortData;
551
554
556
557 Request->SgList = SgList;
559
560 PortData->PreparePrdTable(PortData->ChannelContext, Request, SgList);
562}
563
564static
565PVOID
569{
570 PATAPORT_PORT_DATA PortData;
572 ULONG PagesNeeded;
573
575 if (BaseAddress)
576 return BaseAddress;
577
578 PortData = Device->PortData;
579 if (!PortData->ReservedVaSpace)
580 return NULL;
581
582 /* The system is low resources, handle it in a non-fatal way */
585 if (PagesNeeded > ATA_RESERVED_PAGES)
586 return NULL;
587
588 /* Utilize the reserved mapping to overcome memory issues */
590 {
593 Request->Mdl,
594 MmCached);
595 if (BaseAddress)
597 else
599 }
600
601 return BaseAddress;
602}
603
604static
607 _In_ PATAPORT_PORT_DATA PortData,
609{
610 PDMA_ADAPTER DmaAdapter = PortData->DmaAdapter;
611 PDMA_OPERATIONS DmaOperations = DmaAdapter->DmaOperations;
613
614 ASSERT(Request->Mdl);
615
616 Status = DmaOperations->GetScatterGatherList(DmaAdapter,
617 PortData->ChannelObject,
618 Request->Mdl,
619 Request->DataBuffer,
620 Request->DataTransferLength,
622 Request,
623 !!(Request->Flags & REQUEST_FLAG_DATA_IN));
624 if (NT_SUCCESS(Status))
625 return TRUE;
626
627 WARN("Failed to get the S/G list with status %lx\n", Status);
628 return FALSE;
629}
630
631VOID
634{
636
639
641
642 /* The channel can only perform DMA I/O and PIO is not supported */
643 if (Device->DeviceFlags & DEVICE_PIO_VIA_DMA)
645
646 if (Request->Flags & REQUEST_FLAG_DMA)
648
649 if (!(Request->Flags & REQUEST_FLAG_NO_KEEP_AWAKE))
650 {
651 PULONG PowerIdleCounter = Device->PowerIdleCounter;
652
653 if (PowerIdleCounter)
654 PoSetDeviceBusy(PowerIdleCounter);
655 }
656
657 /* Local buffer transfer */
659 {
661
663 {
664 /* DMA transfer */
665 Device->PortData->LocalSgList.Elements[0].Length = Request->DataTransferLength;
666 AtaReqPreparePrdTable(NULL, NULL, &Device->PortData->LocalSgList, Request);
667 }
668 else
669 {
670 /* PIO data transfer */
671 Request->DataBuffer = Device->LocalBuffer;
673 }
674 return;
675 }
676
677 /* No data transfer */
679 {
681 return;
682 }
683
684 /* DMA transfer, get the S/G list for the MDL */
686 {
688 return;
689
690 /* This channel can only perform DMA I/O and PIO is not supported */
691 if (Device->DeviceFlags & DEVICE_PIO_VIA_DMA)
692 goto CompleteNoMemory;
693
694 /* S/G list construction failed, attempt to fall back to PIO mode */
696 goto CompleteNoMemory;
697 }
698
699 /* PIO data transfer path */
700 ASSERT(!(Device->DeviceFlags & DEVICE_PIO_VIA_DMA));
701
703 if (!BaseAddress)
704 goto CompleteNoMemory;
705
706 /* Calculate the offset within DataBuffer */
708 (ULONG_PTR)Request->DataBuffer -
710 Request->DataBuffer = (PVOID)Offset;
711
713 return;
714
715CompleteNoMemory:
717 Request->InternalState = REQUEST_STATE_REQUEUE;
718
719 /*
720 * Defer the completion to a DPC.
721 * We cannot complete request with the queue spinlock held.
722 */
724}
725
726static
728NTAPI
734{
736
740
742 return KeepObject;
743}
744
745VOID
746NTAPI
748 _In_ PKDPC Dpc,
752{
753 PSLIST_ENTRY CurrentEntry, NextEntry;
754
759
761 while (CurrentEntry)
762 {
764
765 NextEntry = CurrentEntry->Next;
766
767 Request = CONTAINING_RECORD(CurrentEntry, ATA_DEVICE_REQUEST, CompletionEntry);
769
771
772 CurrentEntry = NextEntry;
773 }
774}
775
776VOID
779{
781
784}
785
786/*
787 * The control flow is designed such that
788 * we can just return FALSE without having to undo the failed slot allocation later.
789 */
790static
794 _In_ PATAPORT_PORT_DATA PortData,
796{
797 ULONG SlotMask, SlotNumber, SlotsBitmap;
798
799 if (PortData->QueueFlags & PORT_QUEUE_FLAG_EXCLUSIVE_MODE)
800 return FALSE;
801
802 /* Gain exclusive access to the slot queue */
804 {
805 /* Check if we have any outstanding commands */
806 if (PortData->AllocatedSlots != 0)
807 return FALSE;
808 }
809
810 /* Queued command */
811 if (Request->Flags & REQUEST_FLAG_NCQ)
812 {
813 ULONG QueueDepth;
814
815 /* Check if we have any outstanding non-queued commands */
816 if (PortData->AllocatedSlots < 0)
817 return FALSE;
818
819 QueueDepth = Device->TransportFlags & DEVICE_QUEUE_DEPTH_MASK;
820 QueueDepth >>= DEVICE_QUEUE_DEPTH_SHIFT;
821
822 /* The device capacity may be less than the total HBA capacity */
823 if (PortData->AllocatedSlots >= QueueDepth)
824 return FALSE;
825 }
826 else
827 {
828 /* Check if we have any outstanding native queued commands */
829 if (PortData->AllocatedSlots > 0)
830 return FALSE;
831 }
832
833 SlotsBitmap = PortData->FreeSlotsBitmap;
834
835 /* Mask off previously issued commands */
836 SlotMask = ~(0xFFFFFFFF >> (MAX_SLOTS - (PortData->LastUsedSlot + 1)));
837 if (!(SlotsBitmap & SlotMask))
838 SlotMask = 0xFFFFFFFF;
839
840 /* Allocate slot in a circular fashion. This is required to maintain CCS update */
841 if (!_BitScanForward(&SlotNumber, SlotsBitmap & SlotMask))
842 return FALSE;
843
844 if (!PortData->AllocateSlot(PortData->ChannelContext, Request, TRUE))
845 return FALSE;
846
847 /* The slot can safely be consumed at this point */
848 if (Request->Flags & REQUEST_FLAG_NCQ)
849 ++PortData->AllocatedSlots;
850 else
851 --PortData->AllocatedSlots;
852
854 PortData->QueueFlags |= PORT_QUEUE_FLAG_EXCLUSIVE_MODE;
855
856 ASSERT(PortData->LastUsedSlot < MAX_SLOTS);
857 ASSERT(IsPowerOfTwo(SlotsBitmap) || (SlotNumber != PortData->LastUsedSlot));
858 ASSERT(PortData->FreeSlotsBitmap & (1 << SlotNumber));
859 ASSERT(PortData->Slots[SlotNumber] == NULL);
860
861 Request->Slot = SlotNumber;
862
863 PortData->LastUsedSlot = SlotNumber;
864 PortData->FreeSlotsBitmap &= ~(1 << SlotNumber);
865 PortData->Slots[SlotNumber] = Request;
866 return TRUE;
867}
868
869static
870VOID
874 _In_ BOOLEAN DoReleaseDeviceQueueLock)
875{
876 PATAPORT_PORT_DATA PortData = Device->PortData;
878
880 if (Success)
881 {
882 PortData->ActiveTimersBitmap |= 1 << Request->Slot;
883 }
884 else
885 {
886 /*
887 * If all slots are busy, overloading the port can starve other incoming I/O requests:
888 * - An IDE channel can only deal with one active request at a time.
889 * - A SATA Port Multiplier shares the bandwidth with up to 15 devices.
890 * In order to avoid starvation of the device,
891 * put the request on the high-priority port queue.
892 */
893 InsertTailList(&PortData->PortQueueList, &Request->PortEntry);
894
895 TRACE("Freeze slot queue\n");
896
897 /*
898 * Freeze the device queue to ensure
899 * that only one request per device is queued to the port queue.
900 */
901 ASSERT(!(Device->QueueFlags & QUEUE_FLAG_FROZEN_SLOT));
902 Device->QueueFlags |= QUEUE_FLAG_FROZEN_SLOT;
903 }
904
906
907 if (DoReleaseDeviceQueueLock)
909
910 if (Success)
911 {
912 if (PortData->PortFlags & PORT_FLAG_IS_SIMPLEX)
913 {
915 PortData->ChannelObject,
917 Request);
918 }
919 else
920 {
922 }
923 }
924}
925
926static
927ULONG
932{
933 UCHAR SrbStatus;
934
935 Request->Srb = Srb;
937 Request->DataTransferLength = Srb->DataTransferLength;
939 Request->Mdl = ((PIRP)(Srb->OriginalRequest))->MdlAddress;
940 Request->TimeOut = Srb->TimeOutValue;
941 Request->Complete = NULL;
942 Request->Flags = 0;
943 Request->State = 0;
944
945 switch (Srb->Function)
946 {
948 {
949 SrbStatus = AtaReqExecuteScsi(DevExt, Request, Srb);
950 break;
951 }
952
954 {
955 SrbStatus = AtaReqSmartIoControl(DevExt, Request, Srb);
956 break;
957 }
958
961 {
962 SrbStatus = SRB_STATUS_SUCCESS;
963 break;
964 }
965
966 default:
967 {
968 ASSERT(FALSE);
970 }
971 }
972
973 return SrbStatus;
974}
975
976static
977VOID
982{
984 UCHAR SrbStatus;
985
987
988 SrbStatus = AtaReqTranslateRequest(DevExt, Request, Srb);
989
990 if (SrbStatus != SRB_STATUS_PENDING)
991 {
993
994 Request->SrbStatus = SrbStatus;
995 Request->InternalState = REQUEST_STATE_NOT_STARTED;
996
997 /* Defer the completion to a DPC to avoid the recursive call in some cases */
999 }
1000 else
1001 {
1003
1004 KeAcquireSpinLockAtDpcLevel(&Device->PortData->QueueLock);
1005
1007 }
1008}
1009
1010static
1014{
1015 PATAPORT_PORT_DATA PortData = Device->PortData;
1018
1019 if (!(Device->QueueFlags & QUEUE_FLAG_FROZEN_SLOT))
1020 return NULL;
1021
1022 Device->QueueFlags &= ~QUEUE_FLAG_FROZEN_SLOT;
1023
1025
1026 for (Entry = PortData->PortQueueList.Flink;
1027 Entry != &PortData->PortQueueList;
1028 Entry = Entry->Flink)
1029 {
1032
1033 if (Request->Device != (PATA_IO_CONTEXT_COMMON)Device)
1034 continue;
1035
1036 RemoveEntryList(&Request->PortEntry);
1037
1038 Result = Request;
1039 break;
1040 }
1041
1043
1044 ASSERT(Result != NULL);
1045 return Result;
1046}
1047
1049static
1050VOID
1051AtaReqDeviceQueueRemoveEntry(
1054{
1056}
1057
1058static
1059VOID
1060NTAPI
1064{
1066 KIRQL OldLevel;
1069
1071
1072 IoReleaseCancelSpinLock(Irp->CancelIrql);
1073
1076
1077 KeAcquireSpinLock(&Device->QueueLock, &OldLevel);
1078 AtaReqDeviceQueueRemoveEntry(Device, QueueEntry);
1079 KeReleaseSpinLock(&Device->QueueLock, OldLevel);
1080
1082 ASSERT(Srb);
1084
1087
1088 Irp->IoStatus.Status = STATUS_CANCELLED;
1090}
1091
1092static
1093VOID
1097 _In_ PIRP Irp)
1098{
1101 ULONG SortKey;
1102
1104
1105 /* Use the C-LOOK hard disk scheduling algorithm to service the PDO requests */
1106 for (Entry = Device->DeviceQueueList.Flink;
1107 Entry != &Device->DeviceQueueList;
1108 Entry = Entry->Flink)
1109 {
1112
1113 if (QueueEntry->SortKey > SortKey)
1114 break;
1115 }
1116
1120
1122}
1123
1124static
1129{
1131
1132 if (Device->QueueFlags & QUEUE_FLAG_FROZEN_REMOVED)
1133 {
1135 return STATUS_NO_SUCH_DEVICE;
1136 }
1137
1139
1141
1142 /*
1143 * If the device queue is full or frozen,
1144 * the requests may take a long period of time to process,
1145 * and therefore we have to do the cancellation ourselves.
1146 */
1148
1149 /* This IRP has already been cancelled */
1150 if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
1151 {
1152 /* Remove the IRP from the queue */
1153 AtaReqDeviceQueueRemoveEntry(Device, QUEUE_ENTRY_FROM_IRP(Irp));
1154
1157 return STATUS_CANCELLED;
1158 }
1159
1160 return STATUS_PENDING;
1161}
1162
1163static
1164inline
1165UCHAR
1170{
1171 /* Check if the queue is actually frozen and the request is not a bypass */
1172 if (Device->QueueFlags & (QUEUE_FLAGS_FROZEN &
1174 {
1175 return FALSE;
1176 }
1177 if ((Device->QueueFlags & QUEUE_FLAG_FROZEN_QUEUE_FREEZE) &&
1179 {
1180 return FALSE;
1181 }
1182 if ((Device->QueueFlags & QUEUE_FLAG_FROZEN_QUEUE_LOCK) &&
1184 {
1185 return FALSE;
1186 }
1187
1188 /*
1189 * Stack-based request allocation.
1190 * It will return us the last request structure in the CPU cache.
1191 */
1192 return _BitScanForward(Tag, Device->FreeRequestsBitmap);
1193}
1194
1195static
1196inline
1200 _In_ ULONG Tag)
1201{
1203
1204 ASSERT(Device->FreeRequestsBitmap & (1 << Tag));
1205
1206 Device->FreeRequestsBitmap &= ~(1 << Tag);
1207
1208 Request = &Device->Requests[Tag];
1210
1211 Request->Tag = 1 << Tag;
1212
1213 return Request;
1214}
1215
1216static
1217BOOLEAN
1220{
1222 PIRP Irp;
1225 ULONG Tag;
1226
1227 if (Device->FreeRequestsBitmap == 0)
1228 return FALSE;
1229
1230 /* Find a bypass request to dispatch */
1232 !(Device->QueueFlags & QUEUE_FLAGS_FROZEN_NOT_BYPASS))
1233 {
1235
1236 for (Entry = Device->DeviceQueueList.Flink;
1237 Entry != &Device->DeviceQueueList;
1238 Entry = Entry->Flink)
1239 {
1242
1245
1246 ASSERT(Srb);
1248
1250 continue;
1251
1252 AtaReqDeviceQueueRemoveEntry(Device, QueueEntry);
1253
1254 /* Clear our cancel routine */
1256 {
1257 /* We're already canceled, reset the list entry to point to itself */
1259 continue;
1260 }
1261
1263
1265 return TRUE;
1266 }
1267 }
1268 else
1269 {
1271
1272 if (Device->QueueFlags & QUEUE_FLAGS_FROZEN)
1273 return FALSE;
1274
1275 NT_VERIFY(_BitScanForward(&Tag, Device->FreeRequestsBitmap));
1276
1277 for (Entry = Device->DeviceQueueList.Flink;
1278 Entry != &Device->DeviceQueueList;
1279 Entry = Entry->Flink)
1280 {
1283 ListEntry);
1285
1288
1289 ASSERT(Srb);
1291
1292 AtaReqDeviceQueueRemoveEntry(Device, QueueEntry);
1293
1294 /* Clear our cancel routine */
1296 {
1297 /* We're already canceled, reset the list entry to point to itself */
1299 continue;
1300 }
1301
1303
1305 return TRUE;
1306 }
1307 }
1308
1309 return FALSE;
1310}
1311
1312static
1317{
1318 KIRQL OldIrql;
1321 ULONG Tag;
1322
1325
1326#if DBG
1327 ++Device->Statistics.RequestsStarted;
1328#endif
1329
1331 {
1333
1335 }
1336 else
1337 {
1340
1342 }
1343
1345
1346 return Status;
1347}
1348
1350VOID
1353 _In_ ULONG ReasonFlags)
1354{
1355 PATAPORT_IO_CONTEXT Device = &DevExt->Device;
1356 KIRQL OldLevel;
1357
1358 KeAcquireSpinLock(&Device->QueueLock, &OldLevel);
1359 _InterlockedOr(&Device->QueueFlags, ReasonFlags);
1360 KeReleaseSpinLock(&Device->QueueLock, OldLevel);
1361}
1362
1364VOID
1367 _In_ ULONG ReasonFlags)
1368{
1369 PATAPORT_IO_CONTEXT Device = &DevExt->Device;
1370 PATAPORT_PORT_DATA PortData;
1371 KIRQL OldIrql;
1372
1375
1376 if (Device->FreeRequestsBitmap != Device->MaxRequestsBitmap)
1378
1379 PortData = Device->PortData;
1381 if (!AtaReqPortQueueListDispatchNextRequest(PortData))
1383
1384 _InterlockedAnd(&Device->QueueFlags, ~ReasonFlags);
1385
1388
1390}
1391
1392/* Must not be paged */
1394VOID
1398{
1399 KIRQL OldIrql;
1400 BOOLEAN DoWait;
1402
1405
1406 ASSERT(Device->QueueFlags & QUEUE_FLAGS_FROZEN);
1407
1408 KeClearEvent(&Device->QueueStoppedEvent);
1409
1410 if (Srb)
1411 Device->QuiescenceSrb = Srb;
1412
1413 /* Wait for all the active IRPs to finish executing */
1414 if (Device->FreeRequestsBitmap != Device->MaxRequestsBitmap)
1415 {
1416 Device->QueueFlags |= QUEUE_FLAG_SIGNAL_STOP;
1417 DoWait = !Srb;
1418 }
1419 else
1420 {
1422
1423 KeSetEvent(&Device->QueueStoppedEvent, 0, FALSE);
1424 DoWait = FALSE;
1425 }
1426
1428
1431
1432 /* Requeue the pending request */
1433 if (Request)
1434 {
1435 Request->SrbStatus = SRB_STATUS_BUSY;
1436 Request->InternalState = REQUEST_STATE_NOT_STARTED;
1437
1441 }
1442
1443 if (!DoWait)
1444 return;
1445
1446 KeWaitForSingleObject(&Device->QueueStoppedEvent, Executive, KernelMode, FALSE, NULL);
1447}
1448
1450VOID
1453{
1455 KIRQL OldLevel;
1457
1458 KeAcquireSpinLock(&Device->QueueLock, &OldLevel);
1459
1460 for (Entry = Device->DeviceQueueList.Flink;
1461 Entry != &Device->DeviceQueueList;
1462 Entry = Entry->Flink)
1463 {
1465 PIRP Irp;
1467
1470
1471 AtaReqDeviceQueueRemoveEntry(Device, QueueEntry);
1472
1473 /* Clear our cancel routine */
1476 {
1477 /* We're already canceled, reset the list entry to point to itself */
1479 continue;
1480 }
1481
1482 KeReleaseSpinLock(&Device->QueueLock, OldLevel);
1483
1485 ASSERT(Srb);
1487
1489 Irp->IoStatus.Status = STATUS_CANCELLED;
1490 Irp->IoStatus.Information = Srb->DataTransferLength;
1492
1493 KeAcquireSpinLock(&Device->QueueLock, &OldLevel);
1494 }
1495
1497
1498 KeReleaseSpinLock(&Device->QueueLock, OldLevel);
1499
1500 if (Request)
1501 {
1502 KIRQL OldIrql;
1503
1504 Request->SrbStatus = SRB_STATUS_ABORTED;
1505 Request->InternalState = REQUEST_STATE_NOT_STARTED;
1506
1510 }
1511}
1512
1513static
1515CODE_SEG("PAGE")
1520{
1521 ULONG Status, SrbStatus;
1522
1523 PAGED_CODE();
1524
1526 {
1527 DevExt->DeviceClaimed = FALSE;
1528
1529 SrbStatus = SRB_STATUS_SUCCESS;
1531 goto Exit;
1532 }
1533
1534 if (DevExt->DeviceClaimed)
1535 {
1536 SrbStatus = SRB_STATUS_BUSY;
1538 goto Exit;
1539 }
1540
1541 DevExt->DeviceClaimed = TRUE;
1542 Srb->DataBuffer = DevExt->Common.Self;
1543
1544 SrbStatus = SRB_STATUS_SUCCESS;
1546
1547Exit:
1548 Srb->SrbStatus = SrbStatus;
1549 return Status;
1550}
1551
1552static
1556 _In_ PIRP Irp,
1558{
1561
1563
1564 /* Wait for outstanding I/O requests to finish */
1566
1568 return STATUS_PENDING;
1569}
1570
1571static
1573CODE_SEG("PAGE")
1574BOOLEAN
1579{
1581
1582 PAGED_CODE();
1583
1584 switch (SrbControl->ControlCode)
1585 {
1588 break;
1589
1592 break;
1593
1605 {
1606 /* Queue the request */
1607 return FALSE;
1608 }
1609
1610 default:
1613 break;
1614 }
1615
1616 return TRUE;
1617}
1618
1619static
1624{
1627
1629 ASSERT(Srb);
1631
1632 Status = IoAcquireRemoveLock(&DevExt->Common.RemoveLock, Irp);
1633 if (!NT_SUCCESS(Status))
1634 {
1637
1638 Irp->IoStatus.Status = Status;
1640
1641 return Status;
1642 }
1643
1644 switch (Srb->Function)
1645 {
1648 {
1650 break;
1651 }
1652
1654 {
1656
1659 break;
1660 }
1661
1663 {
1664 ASSERT(DevExt->Device.QueueFlags & QUEUE_FLAGS_FROZEN);
1665 AtaReqFlushDeviceQueue(&DevExt->Device);
1667 }
1670 {
1671 ULONG Reason;
1672
1675 else
1677 AtaReqThawQueue(DevExt, Reason);
1678
1681 break;
1682 }
1683
1685 {
1686 Status = AtaPdoHandleQuiesceDevice(&DevExt->Device, Irp, Srb);
1687 break;
1688 }
1689
1691 {
1692 if (AtaPdoHandleIoControl(DevExt, Srb, &Status))
1693 break;
1694
1696 }
1698 case SRB_FUNCTION_FLUSH:
1700 {
1701 ATA_SCSI_ADDRESS AtaScsiAddress;
1702
1704
1705 /* Set the SCSI address to the correct value */
1706 AtaScsiAddress = DevExt->Device.AtaScsiAddress;
1707 Srb->PathId = AtaScsiAddress.PathId;
1708 Srb->TargetId = AtaScsiAddress.TargetId;
1709 Srb->Lun = AtaScsiAddress.Lun;
1710
1711 /* This field is used by the driver to mark internal requests */
1713
1714 /*
1715 * NOTE: Disk I/O requests need a lot of the kernel stack space.
1716 * We should avoid nesting several levels deep in the call chain.
1717 */
1718 Status = AtaReqStartSrb(&DevExt->Device, Srb);
1719 break;
1720 }
1721
1722 default:
1725 break;
1726 }
1727
1728 if (Status != STATUS_PENDING)
1729 {
1730 Irp->IoStatus.Status = Status;
1732 }
1733
1734 IoReleaseRemoveLock(&DevExt->Common.RemoveLock, Irp);
1735
1736 return Status;
1737}
1738
1739static
1741CODE_SEG("PAGE")
1746{
1749
1750 UNREFERENCED_PARAMETER(ChanExt);
1751
1752 PAGED_CODE();
1753
1754 /* Drivers should not call the FDO */
1755 ASSERT(FALSE);
1756
1758 ASSERT(Srb);
1760
1763
1764 Irp->IoStatus.Status = Status;
1766 return Status;
1767}
1768
1770NTAPI
1774{
1775 if (IS_FDO(DeviceObject->DeviceExtension))
1776 return AtaFdoDispatchScsi(DeviceObject->DeviceExtension, Irp);
1777 else
1778 return AtaPdoDispatchScsi(DeviceObject->DeviceExtension, Irp);
1779}
1780
1781VOID
1782NTAPI
1786{
1787 PATAPORT_PORT_DATA PortData = Context;
1788 ULONG Slot, ActiveTimersBitmap;
1789
1791
1792 /* Check timeouts */
1793 ActiveTimersBitmap = PortData->ActiveTimersBitmap;
1794 while (_BitScanForward(&Slot, ActiveTimersBitmap) != 0)
1795 {
1796 ActiveTimersBitmap &= ~(1 << Slot);
1797
1798 /* Decrease the timeout counter */
1799 if ((PortData->TimerCount[Slot] > 0) && (--PortData->TimerCount[Slot] == 0))
1800 {
1802
1803 /* Handle timeout of an active command */
1804 if (PortData->ActiveSlotsBitmap & (1 << Slot))
1805 AtaPortTimeout(PortData, Slot);
1806
1808 }
1809 }
1810
1812}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
struct _IRP * PIRP
#define PAGED_CODE()
#define CODE_SEG(...)
#define VOID
Definition: acefi.h:82
unsigned char BOOLEAN
Definition: actypes.h:127
ATA_COMPLETION_ACTION
Definition: ata_shared.h:148
@ COMPLETE_NO_IRP
Definition: ata_shared.h:150
@ COMPLETE_IRP
Definition: ata_shared.h:149
#define REQUEST_FLAG_NCQ
Definition: ata_shared.h:284
#define REQUEST_FLAG_HAS_LOCAL_BUFFER
Definition: ata_shared.h:327
#define REQUEST_FLAG_HAS_MDL
Definition: ata_shared.h:333
#define REQUEST_FLAG_DATA_IN
Definition: ata_shared.h:287
#define REQUEST_STATE_NOT_STARTED
Definition: ata_shared.h:267
#define DEVICE_QUEUE_DEPTH_SHIFT
Definition: ata_shared.h:171
#define REQUEST_FLAG_NO_KEEP_AWAKE
Definition: ata_shared.h:339
#define REQUEST_EXCLUSIVE_ACCESS_FLAGS
Definition: ata_shared.h:365
#define REQUEST_FLAG_HAS_RESERVED_MAPPING
Definition: ata_shared.h:336
#define REQUEST_STATE_REQUEUE
Definition: ata_shared.h:270
#define REQUEST_FLAG_DATA_OUT
Definition: ata_shared.h:290
#define REQUEST_FLAG_PROGRAM_DMA
Definition: ata_shared.h:342
#define REQUEST_FLAG_HAS_SG_LIST
Definition: ata_shared.h:330
#define REQUEST_FLAG_DMA
Definition: ata_shared.h:278
#define REQUEST_FLAG_INTERNAL
Definition: ata_shared.h:345
#define REQUEST_STATE_FREEZE_QUEUE
Definition: ata_shared.h:273
#define DEVICE_QUEUE_DEPTH_MASK
Definition: ata_shared.h:169
#define QUEUE_FLAGS_FROZEN
Definition: atapi.h:114
IO_TIMER_ROUTINE AtaPortIoTimer
Definition: atapi.h:938
#define ASSERT_REQUEST(Request)
Definition: atapi.h:326
#define QUEUE_FLAG_SIGNAL_STOP
Definition: atapi.h:108
#define PORT_INT_FLAG_IS_IO_ACTIVE
Definition: atapi.h:360
#define SRB_GET_FLAGS(Srb)
Definition: atapi.h:238
#define QUEUE_FLAG_FROZEN_SLOT
Definition: atapi.h:106
UCHAR AtaReqExecuteScsi(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PATA_DEVICE_REQUEST Request, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: satl.c:2054
#define MAX_SLOTS
Definition: atapi.h:207
#define QUEUE_ENTRY_FROM_IRP(Irp)
Definition: atapi.h:310
#define QUEUE_FLAG_FROZEN_POWER
Definition: atapi.h:110
#define PORT_QUEUE_FLAG_SIGNAL_STOP
Definition: atapi.h:370
#define IS_FDO(p)
Definition: atapi.h:173
#define ATA_RESERVED_PAGES
Definition: atapi.h:200
struct _ATAPORT_IO_CONTEXT * PATAPORT_IO_CONTEXT
Definition: atapi.h:36
#define QUEUE_FLAGS_FROZEN_NOT_BYPASS
Definition: atapi.h:123
KDEFERRED_ROUTINE AtaReqCompletionDpc
Definition: atapi.h:939
#define PORT_FLAG_IS_SIMPLEX
Definition: atapi.h:336
NTSTATUS AtaPdoHandleMiniportSmartVersion(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: smart.c:246
FORCEINLINE BOOLEAN IsPowerOfTwo(_In_ ULONG x)
Definition: atapi.h:604
VOID AtaPortTimeout(_In_ PATAPORT_PORT_DATA PortData, _In_ ULONG Slot)
Definition: portstate.c:905
UCHAR AtaReqSmartIoControl(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PATA_DEVICE_REQUEST Request, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: smart.c:92
#define QUEUE_FLAG_FROZEN_QUEUE_LOCK
Definition: atapi.h:112
#define QUEUE_FLAG_FROZEN_PORT_BUSY
Definition: atapi.h:105
#define SRB_FLAG_LOW_MEM_RETRY
Definition: atapi.h:229
BOOLEAN AtaReqDmaTransferToPioTransfer(_In_ PATA_DEVICE_REQUEST Request)
Definition: satl.c:78
#define IRP_FROM_QUEUE_ENTRY(QueueEntry)
Definition: atapi.h:313
#define PORT_QUEUE_FLAG_EXCLUSIVE_MODE
Definition: atapi.h:369
FORCEINLINE BOOLEAN AtaPortQueueEmpty(_In_ PATAPORT_PORT_DATA PortData)
Definition: atapi.h:573
#define ATAPORT_TAG
Definition: atapi.h:171
#define SRB_SET_FLAGS(Srb, Flags)
Definition: atapi.h:232
NTSTATUS AtaPdoHandleMiniportIdentify(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: smart.c:207
#define DEVICE_PIO_VIA_DMA
Definition: atapi.h:94
#define QUEUE_FLAG_FROZEN_REMOVED
Definition: atapi.h:111
#define QUEUE_FLAG_FROZEN_QUEUE_FREEZE
Definition: atapi.h:109
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
#define SCSISTAT_CHECK_CONDITION
Definition: cdrw_hw.h:1079
#define IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
Definition: cdrw_hw.h:1465
#define IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
Definition: cdrw_hw.h:1459
#define IOCTL_SCSI_MINIPORT_DISABLE_SMART
Definition: cdrw_hw.h:1462
#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
Definition: cdrw_hw.h:1464
#define IOCTL_SCSI_MINIPORT_IDENTIFY
Definition: cdrw_hw.h:1458
#define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
Definition: cdrw_hw.h:1466
#define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
Definition: cdrw_hw.h:1460
#define IOCTL_SCSI_MINIPORT_ENABLE_SMART
Definition: cdrw_hw.h:1461
#define IOCTL_SCSI_MINIPORT_RETURN_STATUS
Definition: cdrw_hw.h:1463
#define IOCTL_SCSI_MINIPORT_SMART_VERSION
Definition: cdrw_hw.h:1457
#define _Requires_lock_held_(lock)
VOID NTAPI IoFreeController(IN PCONTROLLER_OBJECT ControllerObject)
Definition: controller.c:125
VOID NTAPI IoAllocateController(IN PCONTROLLER_OBJECT ControllerObject, IN PDEVICE_OBJECT DeviceObject, IN PDRIVER_CONTROL ExecutionRoutine, IN PVOID Context)
Definition: controller.c:25
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:725
#define INFO
Definition: debug.h:89
#define ULONG_PTR
Definition: config.h:101
#define IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
Definition: scsi.h:1421
#define IOCTL_SCSI_MINIPORT_READ_SMART_LOG
Definition: scsi.h:1420
#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE
Definition: scsi.h:1419
#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_RELEASE_QUEUE
Definition: srb.h:319
#define SRB_FLAGS_BYPASS_FROZEN_QUEUE
Definition: srb.h:398
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
#define SRB_STATUS_ABORTED
Definition: srb.h:342
#define SRB_STATUS_PENDING
Definition: srb.h:340
#define SRB_FUNCTION_LOCK_QUEUE
Definition: srb.h:332
#define SRB_FUNCTION_FLUSH
Definition: srb.h:323
#define SRB_FUNCTION_FLUSH_QUEUE
Definition: srb.h:329
#define SRB_STATUS_TIMEOUT
Definition: srb.h:349
#define SRB_FUNCTION_SHUTDOWN
Definition: srb.h:322
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:387
#define SRB_FUNCTION_UNLOCK_QUEUE
Definition: srb.h:333
#define SRB_FLAGS_BYPASS_LOCKED_QUEUE
Definition: srb.h:410
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
#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_QUEUE_FROZEN
Definition: srb.h:386
#define SRB_STATUS_NO_DEVICE
Definition: srb.h:348
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:404
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:346
#define _IRQL_uses_cancel_
Definition: driverspecs.h:237
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
@ Success
Definition: eventcreate.c:712
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
Status
Definition: gdiplustypes.h:25
volatile char *const const char modify _InterlockedAnd
Definition: intrin_ppc.h:267
IoMarkIrpPending(Irp)
IoSetCancelRoutine(Irp, CancelRoutine)
PVOID NTAPI MmMapLockedPagesWithReservedMapping(_In_ PVOID MappingAddress, _In_ ULONG PoolTag, _In_ PMDL Mdl, _In_ MEMORY_CACHING_TYPE CacheType)
Definition: mdlsup.c:1629
VOID NTAPI MmUnmapReservedMapping(_In_ PVOID BaseAddress, _In_ ULONG PoolTag, _In_ PMDL Mdl)
Definition: mdlsup.c:1749
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:424
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
@ HighPagePriority
Definition: imports.h:55
PVOID PVOID PWCHAR PVOID USHORT PULONG Reason
Definition: env.c:47
#define min(a, b)
Definition: monoChain.cc:55
#define KernelMode
Definition: asm.h:38
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define UNREACHABLE
#define RTL_CONTAINS_FIELD(Struct, Size, Field)
Definition: ntbasedef.h:687
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:684
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define IoCompleteRequest
Definition: irp.c:1240
VOID NTAPI IoReleaseCancelSpinLock(IN KIRQL Irql)
Definition: util.c:150
KIRQL NTAPI KeAcquireInterruptSpinLock(IN PKINTERRUPT Interrupt)
Definition: spinlock.c:154
VOID NTAPI KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt, IN KIRQL OldIrql)
Definition: spinlock.c:171
NTSTATUS NTAPI PoRequestPowerIrp(_In_ PDEVICE_OBJECT DeviceObject, _In_ UCHAR MinorFunction, _In_ POWER_STATE PowerState, _In_opt_ PREQUEST_POWER_COMPLETE CompletionFunction, _In_opt_ __drv_aliasesMem PVOID Context, _Outptr_opt_ PIRP *pIrp)
Definition: power.c:659
@ PowerSystemWorking
Definition: ntpoapi.h:36
@ PowerDeviceD0
Definition: ntpoapi.h:49
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:522
#define __fallthrough
Definition: sal_old.h:314
struct _SRB_IO_CONTROL * PSRB_IO_CONTROL
#define SCSI_SENSE_ERRORCODE_FIXED_CURRENT
Definition: scsi.h:623
#define SRB_STATUS_INSUFFICIENT_RESOURCES
Definition: srb.h:142
#define SRB_FUNCTION_QUIESCE_DEVICE
Definition: srb.h:99
long _InterlockedOr(_Interlocked_operand_ long volatile *_Value, long _Mask)
long __cdecl _InterlockedExchange(_Interlocked_operand_ long volatile *_Target, long _Value)
long __cdecl _InterlockedCompareExchange(_Interlocked_operand_ long volatile *_Destination, long _Exchange, long _Comparand)
unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask)
Definition: intrin_arm.h:57
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
Definition: ke.h:125
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
Definition: ke.h:135
Entry
Definition: section.c:5210
#define DECLSPEC_NOINLINE_FROM_NOT_PAGED
#define DECLSPEC_NOINLINE_FROM_PAGED
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
static void Exit(void)
Definition: sock.c:1330
#define TRACE(s)
Definition: solgame.cpp:4
static VOID AtaReqStartRequest(_In_ PATAPORT_IO_CONTEXT Device, _In_ PATA_DEVICE_REQUEST Request, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: scsi.c:978
static ULONG AtaReqTranslateRequest(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PATA_DEVICE_REQUEST Request, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: scsi.c:928
NTSTATUS NTAPI AtaDispatchScsi(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
Definition: scsi.c:1771
VOID AtaReqSendRequest(_In_ PATA_DEVICE_REQUEST Request)
Definition: scsi.c:632
static DRIVER_LIST_CONTROL AtaReqPreparePrdTable
Definition: scsi.c:18
static VOID AtaReqCompleteRequest(_In_ PATA_DEVICE_REQUEST Request)
Definition: scsi.c:258
static DRIVER_CANCEL AtaReqDeviceQueueCancelIo
Definition: scsi.c:17
static BOOLEAN AtaReqAllocateSlot(_In_ PATAPORT_IO_CONTEXT Device, _In_ PATAPORT_PORT_DATA PortData, _In_ PATA_DEVICE_REQUEST Request)
Definition: scsi.c:792
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaFdoDispatchScsi(_In_ PATAPORT_CHANNEL_EXTENSION ChanExt, _Inout_ PIRP Irp)
Definition: scsi.c:1743
static NTSTATUS AtaSrbStatusToNtStatus(_In_ UCHAR SrbStatus)
Definition: scsi.c:43
static DECLSPEC_NOINLINE_FROM_NOT_PAGED BOOLEAN AtaPdoHandleIoControl(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PSCSI_REQUEST_BLOCK Srb, _Out_ NTSTATUS *Status)
Definition: scsi.c:1575
static NTSTATUS AtaReqRequeueRequest(_In_ PATAPORT_IO_CONTEXT Device, _In_ PATA_DEVICE_REQUEST Request, _Out_ PUCHAR ResultSrbStatus)
Definition: scsi.c:141
static PATA_DEVICE_REQUEST AtaReqAllocateRequestFromTag(_In_ PATAPORT_IO_CONTEXT Device, _In_ ULONG Tag)
Definition: scsi.c:1198
SLIST_HEADER AtapCompletionQueueList
Definition: scsi.c:14
UCHAR AtaReqSetFixedSenseData(_In_ PSCSI_REQUEST_BLOCK Srb, _In_ SCSI_SENSE_CODE SenseCode)
Definition: scsi.c:411
VOID AtaReqSetLbaInformation(_In_ PSCSI_REQUEST_BLOCK Srb, _In_ ULONG64 Lba)
Definition: scsi.c:442
static VOID AtaReqStartIo(_In_ PATA_DEVICE_REQUEST Request)
Definition: scsi.c:490
static VOID AtaDeviceQueueEmptyEvent(_In_ PATAPORT_IO_CONTEXT Device)
Definition: scsi.c:113
static NTSTATUS AtaReqDeviceQueueAddSrb(_In_ PATAPORT_IO_CONTEXT Device, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: scsi.c:1126
DECLSPEC_NOINLINE_FROM_PAGED VOID AtaReqFlushDeviceQueue(_In_ PATAPORT_IO_CONTEXT Device)
Definition: scsi.c:1451
static NTSTATUS AtaReqStartSrb(_In_ PATAPORT_IO_CONTEXT Device, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: scsi.c:1314
static BOOLEAN AtaReqDeviceQueueDispatchNextRequest(_In_ PATAPORT_IO_CONTEXT Device)
Definition: scsi.c:1218
_In_ PREQUEST_QUEUE_ENTRY QueueEntry
Definition: scsi.c:1054
static VOID AtaDeviceCheckPowerState(_In_ PATAPORT_IO_CONTEXT Device)
Definition: scsi.c:75
static VOID AtaReqReleaseResources(_In_ PATAPORT_IO_CONTEXT Device, _In_ PATA_DEVICE_REQUEST Request)
Definition: scsi.c:215
DECLSPEC_NOINLINE_FROM_PAGED VOID AtaReqThawQueue(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ ULONG ReasonFlags)
Definition: scsi.c:1365
static UCHAR AtaReqGetTagForRequest(_In_ PATAPORT_IO_CONTEXT Device, _In_ PSCSI_REQUEST_BLOCK Srb, _Out_ PULONG Tag)
Definition: scsi.c:1166
VOID AtaReqStartCompletionDpc(_In_ PATA_DEVICE_REQUEST Request)
Definition: scsi.c:777
static PATA_DEVICE_REQUEST AtaReqRemovePortRequest(_In_ PATAPORT_IO_CONTEXT Device)
Definition: scsi.c:1012
static DRIVER_CONTROL AtaReqCallSendRequestSerialized
Definition: scsi.c:19
static VOID AtaReqDeviceQueueInsertSrb(_In_ PATAPORT_IO_CONTEXT Device, _In_ PSCSI_REQUEST_BLOCK Srb, _In_ PIRP Irp)
Definition: scsi.c:1094
static NTSTATUS AtaPdoDispatchScsi(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _Inout_ PIRP Irp)
Definition: scsi.c:1621
static DECLSPEC_NOINLINE_FROM_NOT_PAGED NTSTATUS AtaPdoHandleAttachReleaseDevice(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: scsi.c:1517
DECLSPEC_NOINLINE_FROM_PAGED VOID AtaReqWaitForOutstandingIoToComplete(_In_ PATAPORT_IO_CONTEXT Device, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: scsi.c:1395
static VOID AtaReqDispatchRequest(_In_ PATAPORT_IO_CONTEXT Device, _In_ PATA_DEVICE_REQUEST Request, _In_ BOOLEAN DoReleaseDeviceQueueLock)
Definition: scsi.c:871
static PVOID AtaReqMapBuffer(_In_ PATAPORT_IO_CONTEXT Device, _In_ PATA_DEVICE_REQUEST Request)
Definition: scsi.c:566
KDPC AtapCompletionDpc
Definition: scsi.c:15
BOOLEAN AtaReqAllocateMdl(_In_ PATA_DEVICE_REQUEST Request)
Definition: scsi.c:467
DECLSPEC_NOINLINE_FROM_PAGED VOID AtaReqFreezeQueue(_In_ PATAPORT_DEVICE_EXTENSION DevExt, _In_ ULONG ReasonFlags)
Definition: scsi.c:1351
static BOOLEAN AtaReqGetScatterGatherList(_In_ PATAPORT_PORT_DATA PortData, _In_ PATA_DEVICE_REQUEST Request)
Definition: scsi.c:606
static NTSTATUS AtaPdoHandleQuiesceDevice(_In_ PATAPORT_IO_CONTEXT Device, _In_ PIRP Irp, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: scsi.c:1554
_In_ PVOID Context
Definition: storport.h:2269
PDEVICE_OBJECT Self
Definition: atapi.h:432
DEVICE_POWER_STATE DevicePowerState
Definition: atapi.h:415
SYSTEM_POWER_STATE SystemPowerState
Definition: atapi.h:418
ATAPORT_COMMON_EXTENSION Common
Definition: atapi.h:455
PVOID ChannelContext
Definition: atapi.h:348
PDEVICE_OBJECT ChannelObject
Definition: atapi.h:354
ULONG FreeSlotsBitmap
Definition: atapi.h:366
volatile LONG ReservedMappingLock
Definition: atapi.h:379
PATA_DEVICE_REQUEST Slots[MAX_SLOTS]
Definition: atapi.h:355
KEVENT QueueStoppedEvent
Definition: atapi.h:391
KSPIN_LOCK QueueLock
Definition: atapi.h:363
PKINTERRUPT InterruptObject
Definition: atapi.h:357
ULONG PortFlags
Definition: atapi.h:335
LONG TimerCount[MAX_SLOTS]
Definition: atapi.h:356
PCHANNEL_ALLOCATE_SLOT AllocateSlot
Definition: atapi.h:349
ULONG ActiveSlotsBitmap
Definition: atapi.h:358
LIST_ENTRY PortQueueList
Definition: atapi.h:364
PCONTROLLER_OBJECT HwSyncObject
Definition: atapi.h:381
PVOID ReservedVaSpace
Definition: atapi.h:380
ULONG QueueFlags
Definition: atapi.h:368
LONG AllocatedSlots
Definition: atapi.h:377
ULONG ActiveTimersBitmap
Definition: atapi.h:365
struct _DMA_OPERATIONS * DmaOperations
Definition: iotypes.h:2297
PPUT_SCATTER_GATHER_LIST PutScatterGatherList
Definition: iotypes.h:2647
PGET_SCATTER_GATHER_LIST GetScatterGatherList
Definition: iotypes.h:2646
union _IO_STACK_LOCATION::@1696 Parameters
struct _IO_STACK_LOCATION::@4366::@4388 Scsi
Definition: ketypes.h:751
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: atapi.h:317
PVOID Context
Definition: atapi.h:319
ULONG SortKey
Definition: atapi.h:320
LIST_ENTRY ListEntry
Definition: atapi.h:318
ULONG TimeOutValue
Definition: srb.h:262
UCHAR TargetId
Definition: srb.h:254
PVOID OriginalRequest
Definition: srb.h:266
UCHAR SenseInfoBufferLength
Definition: srb.h:259
PVOID DataBuffer
Definition: srb.h:263
UCHAR PathId
Definition: srb.h:253
PVOID SenseInfoBuffer
Definition: srb.h:264
ULONG QueueSortKey
Definition: srb.h:270
UCHAR Function
Definition: srb.h:250
UCHAR ScsiStatus
Definition: srb.h:252
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
UCHAR AdditionalSenseLength
Definition: cdrw_hw.h:1173
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
UCHAR Information[4]
Definition: cdrw_hw.h:1172
UCHAR ErrorCode
Definition: cdrw_hw.h:1164
UCHAR AdditionalSenseCodeQualifier
Definition: cdrw_hw.h:1176
UCHAR SenseKey
Definition: cdrw_hw.h:1167
UCHAR Valid
Definition: cdrw_hw.h:1165
ULONG ControlCode
Definition: scsi_port.h:128
#define STATUS_PENDING
Definition: telnetd.h:14
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
UCHAR PathId
Definition: atapi.h:65
UCHAR TargetId
Definition: atapi.h:60
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4071
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ WDF_DEVICE_POWER_STATE PowerState
Definition: wdfdevice.h:3040
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
WDF_EXTERN_C_START typedef _In_ WDFDEVICE _In_ WDFCONTEXT _In_ WDF_DMA_DIRECTION _In_ PSCATTER_GATHER_LIST SgList
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
_In_ WDFIORESREQLIST _In_ ULONG SlotNumber
Definition: wdfresource.h:68
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
#define ExInterlockedFlushSList(SListHead)
Definition: exfuncs.h:169
#define IoAcquireRemoveLock(RemoveLock, Tag)
#define IoReleaseRemoveLock(_RemoveLock, _Tag)
Definition: iofuncs.h:2764
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
Definition: iotypes.h:2206
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_Inout_ struct _IRP _In_ PVOID MapRegisterBase
Definition: iotypes.h:213
enum _IO_ALLOCATION_ACTION IO_ALLOCATION_ACTION
@ KeepObject
Definition: iotypes.h:202
#define IRP_MN_SET_POWER
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
_Inout_ PKDEVICE_QUEUE_ENTRY _In_ ULONG SortKey
Definition: kefuncs.h:328
@ Executive
Definition: ketypes.h:467
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:740
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:739
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:741
#define MmGetMdlByteCount(_Mdl)
#define MmGetMdlVirtualAddress(_Mdl)
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
@ MmCached
Definition: mmtypes.h:130
#define PoSetDeviceBusy(IdlePointer)
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3304
#define InterlockedPushEntrySList(SListHead, SListEntry)
Definition: rtlfuncs.h:3406
#define PSLIST_ENTRY
Definition: rtltypes.h:134