114 return Transfer->Urb->TransferBufferMDL !=
NULL &&
115 Transfer->Urb->TransferBufferMDL->Next !=
NULL;
167 ULONG MaxPacket = Ring->m_Endpoint->MaxPacketSize();
173 (
Size % MaxPacket) == 0)
182 return MaxPacket - (
Size % MaxPacket);
190 _In_ const XhciBulkStage* Stage,
289 _In_ const XhciBulkStage* Stage,
313 _In_ const XhciBulkStage* Stage,
335 _In_ const XhciBulkStage* Stage)
371 XhciBulkStage* Stage = &
Bulk->m_Stages[
Index];
379 Bulk->m_ImmediateData = !
Controller->HasErrata(XhciErrata::XferNoInlineData) &&
383 if (
Controller->HasErrata(XhciErrata::XferOneAsyncTdAtATime) ||
384 Controller->HasErrata(XhciErrata::RingKeepTdInOneSegment))
386 Bulk->m_MaxPendingStages = 1;
394 if (
Controller->HasErrata(XhciErrata::RingKeepTdInOneSegment))
411 Burst = Ring->m_Endpoint->MaxPacketSize() * (Ring->m_Endpoint->MaxBurst() + 1);
412 if (Burst == 0 || (Ring->m_MaxStageSize % Burst) == 0)
415 Ring->m_MaxStageSize -= Ring->m_MaxStageSize % Burst;
417 DPRINT(
"Bulk DCI %lu stream %lu stage size cut to %lu\n",
418 Ring->m_Endpoint->Dci(), Ring->m_StreamId, Ring->m_MaxStageSize);
430 static_cast<LONG>(XhciMapState::Halted),
431 static_cast<LONG>(XhciMapState::PausedFill));
436 DPRINT1(
"Bulk DCI %lu stream %lu disabled while it still owns requests\n",
437 Ring->m_Endpoint->Dci(), Ring->m_StreamId);
452 DPRINT1(
"Bulk DCI %lu stream %lu disabled while waiting for segments\n",
453 Ring->m_Endpoint->Dci(), Ring->m_StreamId);
455 if (Ring->ChangeMapState(
FALSE, XhciMapState::Halting, XhciMapState::Halted) !=
456 XhciMapState::Halting)
459 static_cast<LONG>(XhciMapState::PausedFill),
460 static_cast<LONG>(XhciMapState::Filling));
472 ULONG PerSegment = Ring->m_SegmentSize /
sizeof(
XHCI_TRB) - 1;
473 ULONG Usable = PerSegment - (PerSegment % PerBurst);
479 DPRINT1(
"Bulk DCI %lu: a burst of %lu TRBs does not fit a segment\n",
480 Ring->m_Endpoint->Dci(), PerBurst);
488 Status = Ring->EnsureFreeSegments(Segments,
FALSE);
491 DPRINT1(
"Bulk DCI %lu: %lu forward progress segments not available, 0x%08lx\n",
492 Ring->m_Endpoint->Dci(), Segments,
Status);
496 Ring->m_DoubleBufferSize = 0;
497 Ring->m_Type.Bulk.m_ImmediateData =
FALSE;
514 DPRINT1(
"Bulk DCI %lu stream %lu cleaned up with requests still owned\n",
515 Ring->m_Endpoint->Dci(), Ring->m_StreamId);
530 if (Ring->
ChangeMapState(
FALSE, XhciMapState::PausedFill, XhciMapState::Filling) == XhciMapState::PausedFill)
574 if (
Bulk->m_DpcRunning)
594 Bulk->m_Flags &= ~XhciBulkReclaimAck;
615 Bulk->m_OutstandingEvents = 0;
616 Ring->m_DoorbellRung =
FALSE;
620 Previous = Ring->ChangeMapState(
TRUE, XhciMapState::Halted, XhciMapState::Filling);
621 if (
Previous == XhciMapState::Halted)
627 DPRINT1(
"Bulk DCI %lu stream %lu started mapping from map state %ld\n",
628 Ring->m_Endpoint->Dci(), Ring->m_StreamId,
static_cast<LONG>(
Previous));
637 Previous = Ring->ChangeMapState(
TRUE, XhciMapState::Halted, XhciMapState::Halting);
640 if (
Previous == XhciMapState::PausedFill)
641 Ring->ChangeMapState(
FALSE, XhciMapState::Halting, XhciMapState::Halted);
653 if (Ring->m_StreamId == 0)
713 if (
Bulk->m_OutstandingEvents == 0)
720 Ring->m_Endpoint->OnExpectedEventsProcessed();
743 return Ring->m_DoorbellRung;
807 DPRINT1(
"Bulk DCI %lu stream %lu segment growth failed, 0x%08lx\n",
808 Ring->m_Endpoint->Dci(), Ring->m_StreamId,
Status);
817 Bulk->m_SegmentWaits++;
833 Bulk->m_SegmentWaits++;
854 if (Ring->m_MapState !=
static_cast<LONG>(XhciMapState::PausedFill) ||
855 Bulk->m_FillWanted == 0)
860 if (Ring->ChangeMapState(
FALSE, XhciMapState::PausedFill, XhciMapState::Filling) != XhciMapState::PausedFill)
872 XhciBulkStage* Stage;
910 if (Ring->ChangeMapState(
FALSE, XhciMapState::Filling, XhciMapState::Filling) != XhciMapState::Filling)
915 Ring->ChangeMapState(
FALSE, XhciMapState::Filling, XhciMapState::PausedFill);
924 if (Ring->ChangeMapState(
FALSE, XhciMapState::PausedFill, XhciMapState::Filling) == XhciMapState::PausedFill)
934 XhciBulkStage* Stage;
942 if (
Bulk->m_PendingStages >=
Bulk->m_MaxPendingStages)
970 DPRINT1(
"Bulk DCI %lu stream %lu gave up waiting for segments\n",
971 Ring->m_Endpoint->Dci(), Ring->m_StreamId);
975 Bulk->m_SegmentWaits = 0;
983 Status = WdfIoQueueRetrieveNextRequest(Ring->m_Queue, &
Request);
994 Transfer = &XhciGetRequestData(
Request)->Bulk;
1002 DPRINT1(
"Bulk DCI %lu stream %lu request %p has no usable buffer, 0x%08lx\n",
1003 Ring->m_Endpoint->Dci(), Ring->m_StreamId,
Request,
Status);
1012 DPRINT1(
"Bulk DCI %lu stream %lu request %p canceled before mapping, 0x%08lx\n",
1013 Ring->m_Endpoint->Dci(), Ring->m_StreamId,
Request,
Status);
1023 Idle = (
Bulk->m_PendingStages == 0);
1045 XhciBulkStage* Stage;
1048 if (Transfer->Stage !=
NULL)
1057 Stage->InUse =
TRUE;
1058 Stage->OnHardware =
FALSE;
1059 Stage->FreeMdl =
FALSE;
1060 Stage->Generation++;
1061 Stage->Transfer = Transfer;
1066 Stage->SgList =
NULL;
1067 Stage->Buffer =
NULL;
1068 Stage->DoubleBuffer =
NULL;
1069 Stage->BurstTrbBudget = 0;
1070 Stage->TrbsReserved = 0;
1071 Stage->TrbsWritten = 0;
1072 Stage->FirstSegment = Ring->m_Segment;
1073 Stage->FirstIndex = Ring->m_EnqueueIndex;
1074 Stage->LastSegment = Ring->m_Segment;
1075 Stage->EndIndex = Ring->m_EnqueueIndex;
1077 Transfer->Stage = Stage;
1081 DPRINT1(
"Bulk DCI %lu stream %lu ran out of stage records\n",
1082 Ring->m_Endpoint->Dci(), Ring->m_StreamId);
1097 Stage->FreeMdl =
FALSE;
1101 Ring->ReturnSegments(&Stage->FreeSegments,
TRUE);
1102 Ring->ReturnSegments(&Stage->UsedSegments,
FALSE);
1106 if (Stage->Transfer !=
NULL)
1107 Stage->Transfer->Stage =
NULL;
1109 Stage->Transfer =
NULL;
1110 Stage->OnHardware =
FALSE;
1111 Stage->InUse =
FALSE;
1123 if (Stage->SgList ==
NULL)
1127 Adapter = Ring->m_Controller->m_Buffers.DmaAdapter();
1133 Stage->SgList =
NULL;
1150 NT_ASSERT(Transfer->CancelState == XhciBulkCancel::Idle);
1153 NT_ASSERT(Transfer->TdsQueued == Transfer->TdsRetired);
1165 Transfer->Urb =
Urb;
1166 Transfer->Ring = Ring;
1167 Transfer->CancelState = XhciBulkCancel::Idle;
1169 Transfer->Mechanism = XhciBulkMechanism::NoData;
1170 Transfer->BytesTotal =
Urb->TransferBufferLength;
1173 Urb->TransferBufferLength = 0;
1181 if (Transfer->BytesTotal == 0)
1183 Transfer->Mechanism = XhciBulkMechanism::NoData;
1189 Transfer->Mechanism = XhciBulkMechanism::Immediate;
1193 if (!
XhciBulkChainedMdl(Transfer) && Transfer->BytesTotal <= Ring->m_DoubleBufferSize)
1195 Transfer->DoubleBuffer = Ring->BorrowBounceBuffer();
1196 if (Transfer->DoubleBuffer !=
NULL)
1198 Transfer->Mechanism = XhciBulkMechanism::DoubleBuffer;
1203 Transfer->Mechanism = XhciBulkMechanism::Dma;
1214 switch (Transfer->Mechanism)
1216 case XhciBulkMechanism::Immediate:
1217 case XhciBulkMechanism::DoubleBuffer:
1218 if (
Urb->TransferBuffer !=
NULL)
1220 Transfer->Buffer =
static_cast<PUCHAR>(
Urb->TransferBuffer);
1222 else if (
Urb->TransferBufferMDL !=
NULL)
1224 Transfer->Buffer =
static_cast<PUCHAR>(
1228 if (Transfer->Buffer ==
NULL)
1230 DPRINT1(
"Bulk DCI %lu stream %lu: no system address for the buffer\n",
1231 Ring->m_Endpoint->Dci(), Ring->m_StreamId);
1236 case XhciBulkMechanism::Dma:
1237 if (
Urb->TransferBufferMDL !=
NULL)
1239 Transfer->Mdl =
Urb->TransferBufferMDL;
1244 if (Transfer->Mdl ==
NULL)
1247 Ring->m_ReservedMdl ==
NULL)
1249 DPRINT1(
"Bulk DCI %lu stream %lu: MDL allocation failed\n",
1250 Ring->m_Endpoint->Dci(), Ring->m_StreamId);
1257 DPRINT1(
"Bulk DCI %lu stream %lu: forward progress MDL already in use\n",
1258 Ring->m_Endpoint->Dci(), Ring->m_StreamId);
1262 Transfer->Mdl = Ring->m_ReservedMdl;
1263 Transfer->UsesReservedMdl =
TRUE;
1280 if (Transfer->Mdl ==
NULL)
1283 if (Transfer->UsesReservedMdl)
1285 Transfer->UsesReservedMdl =
FALSE;
1288 else if (Transfer->Mdl != Transfer->Urb->TransferBufferMDL)
1293 Transfer->Mdl =
NULL;
1303 if (Transfer->DoubleBuffer !=
NULL)
1305 Ring->ReturnBounceBuffer(Transfer->DoubleBuffer);
1306 Transfer->DoubleBuffer =
NULL;
1310 Transfer->Buffer =
NULL;
1311 Transfer->Initialized = 0;
1329 case XhciBulkMechanism::Immediate:
1333 case XhciBulkMechanism::DoubleBuffer:
1338 case XhciBulkMechanism::Dma:
1356 Status = Ring->TakeSegments(Segments, &Stage->FreeSegments);
1372 DPRINT1(
"Bulk DCI %lu stream %lu: %lu segments not available, 0x%08lx\n",
1373 Ring->m_Endpoint->Dci(), Ring->m_StreamId, Segments,
Status);
1377 Bulk->m_SegmentWaits = 0;
1416 DPRINT1(
"Bulk DCI %lu stream %lu: MDL chain shorter than the transfer\n",
1417 Ring->m_Endpoint->Dci(), Ring->m_StreamId);
1431 if (Partial ==
NULL)
1433 DPRINT1(
"Bulk DCI %lu stream %lu: partial MDL allocation failed\n",
1434 Ring->m_Endpoint->Dci(), Ring->m_StreamId);
1439 Partial->Next =
Mdl->Next;
1440 Stage->Mdl = Partial;
1441 Stage->FreeMdl =
TRUE;
1453 ULONG Registers = 0;
1459 if (Transfer->
Mechanism != XhciBulkMechanism::Dma)
1461 Stage->Size = Remaining;
1465 Adapter = Ring->m_Controller->m_Buffers.DmaAdapter();
1479 Registers =
Info.V1.MapRegisterCount;
1486 for (
Mdl = Stage->Mdl, Left = Remaining;
Mdl !=
NULL && Left != 0;
Mdl =
Mdl->Next)
1495 if (Registers > Ring->m_MapRegisterCount && Ring->m_MapRegisterCount > 1)
1498 Stage->Size =
min(Remaining,
Limit);
1509 ULONG CarryTrbs = 0;
1513 if (Transfer->
Mechanism != XhciBulkMechanism::Dma)
1516 Stage->TrbsReserved = 2;
1517 Stage->BurstTrbBudget = 2;
1521 Burst =
min(Ring->m_Endpoint->MaxEsitPayload(), Stage->Size);
1526 Stage->TrbsReserved = 0;
1536 for (
Mdl = Stage->Mdl, Left = Stage->Size;
Mdl !=
NULL && Left != 0;
Mdl =
Mdl->Next)
1548 if (Piece + Carry >= Burst)
1563 Stage->TrbsReserved += Span;
1565 if (Span >= Ring->m_LastIndex)
1567 DPRINT1(
"Bulk DCI %lu stream %lu: a %lu TRB fragment needs a whole segment\n",
1568 Ring->m_Endpoint->Dci(), Ring->m_StreamId, Span);
1571 if (Span > Stage->BurstTrbBudget)
1572 Stage->BurstTrbBudget = Span;
1577 Stage->TrbsReserved += 1;
1582 Stage->BurstTrbBudget += 1;
1583 Stage->TrbsReserved += 1;
1590 _In_ const XhciBulkStage* Stage,
1598 if (Ring->m_Controller->HasErrata(XhciErrata::RingKeepTdInOneSegment))
1605 Available = Ring->m_LastIndex - Ring->m_EnqueueIndex;
1606 Available -= Available % Stage->BurstTrbBudget;
1608 if (Stage->TrbsReserved > Available)
1610 Usable = Ring->m_LastIndex - (Ring->m_LastIndex % Stage->BurstTrbBudget);
1615 DPRINT1(
"Bulk DCI %lu stream %lu: a %lu TRB burst does not fit a segment\n",
1616 Ring->m_Endpoint->Dci(), Ring->m_StreamId, Stage->BurstTrbBudget);
1620 *Segments = (Stage->TrbsReserved - Available +
Usable - 1) /
Usable;
1670 if (Stage->Transfer->Mechanism != XhciBulkMechanism::Dma)
1677 Adapter = Ring->m_Controller->m_Buffers.DmaAdapter();
1681 WdfDeviceWdmGetDeviceObject(Ring->m_Controller->m_Device),
1692 DPRINT1(
"Bulk DCI %lu stream %lu: GetScatterGatherList failed, 0x%08lx\n",
1693 Ring->m_Endpoint->Dci(), Ring->m_StreamId,
Status);
1712 XhciBulkStage* Stage =
static_cast<XhciBulkStage*
>(
Context);
1724 if (Ring->
ChangeMapState(
FALSE, XhciMapState::Filling, XhciMapState::Filling) == XhciMapState::Filling)
1742 XhciDmaBuffer* PadBuffer = Ring->m_Controller->m_SplitPadBuffer;
1746 ULONG Packets = Ring->PacketCount(Stage->Size);
1751 ULONG ElementLeft = 0;
1754 volatile UCHAR* CycleByte;
1762 Stage->TrbsWritten = 0;
1764 if (Ring->m_Controller->HasErrata(XhciErrata::RingKeepTdInOneSegment) && !
InsertLink(Ring, Stage,
TRUE))
1770 while (Step != XhciBulkStep::Done)
1772 IsFirst = (&Ring->m_Trbs[Ring->m_EnqueueIndex] ==
First);
1775 if (
Pending + Ring->m_EnqueueIndex > Ring->m_LastIndex ||
1776 (NoOps && Step == XhciBulkStep::EventData &&
1790 if (Step == XhciBulkStep::Normal)
1796 case XhciBulkMechanism::Immediate:
1799 Chunk = Stage->Size;
1800 Step = XhciBulkStep::EventData;
1803 case XhciBulkMechanism::DoubleBuffer:
1805 RtlCopyMemory(Stage->DoubleBuffer->VirtualAddress, Stage->Buffer, Stage->Size);
1806 Trb.
Dword[0] = Stage->DoubleBuffer->LogicalAddress.LowPart;
1807 Trb.
Dword[1] = (
ULONG)Stage->DoubleBuffer->LogicalAddress.HighPart;
1808 Chunk = Stage->Size;
1809 Step = XhciBulkStep::EventData;
1812 case XhciBulkMechanism::Dma:
1813 if (ElementLeft == 0)
1815 ElementAddress = (
ULONG64)
SgList->Elements[Element].Address.QuadPart;
1816 ElementLeft =
SgList->Elements[Element].Length;
1823 Trb.
Dword[1] = (
ULONG)(ElementAddress >> 32);
1824 ElementAddress += Chunk;
1825 ElementLeft -= Chunk;
1827 if (ElementLeft == 0 && Element >=
SgList->NumberOfElements)
1828 Step = XhciBulkStep::EventData;
1833 Step = XhciBulkStep::EventData;
1838 Trb.
Dword[2] = Chunk |
1843 else if (Step == XhciBulkStep::Pad)
1847 Trb.
Dword[2] = PadBytes;
1851 Step = XhciBulkStep::EventData;
1859 Step = XhciBulkStep::Done;
1862 Stage->TrbsWritten++;
1864 if (Step == XhciBulkStep::EventData)
1866 if (PadBytes != 0 && PadBuffer !=
NULL)
1869 Step = XhciBulkStep::Pad;
1882 else if (Step == XhciBulkStep::Normal &&
Pending == 0)
1884 Pending = (Stage->TrbsReserved > Stage->TrbsWritten) ?
1885 min(Stage->BurstTrbBudget, Stage->TrbsReserved - Stage->TrbsWritten) :
1886 Stage->BurstTrbBudget;
1893 Ring->m_Trbs[Ring->m_EnqueueIndex] = Trb;
1894 Ring->m_EnqueueIndex++;
1896 if (Step == XhciBulkStep::Done && NoOps)
1902 Ring->m_Trbs[Ring->m_EnqueueIndex] = Trb;
1903 Ring->m_EnqueueIndex++;
1908 NT_ASSERT(Stage->TrbsWritten <= Stage->TrbsReserved);
1911 Stage->LastSegment = Ring->m_Segment;
1912 Stage->EndIndex = Ring->m_EnqueueIndex;
1919 Bulk->m_PendingStages++;
1920 Stage->OnHardware =
TRUE;
1921 Ring->m_DoorbellRung =
TRUE;
1926 CycleByte =
reinterpret_cast<volatile UCHAR*
>(&
First->Dword[3]);
1930 Ring->RingDoorbell();
1947 DPRINT1(
"Bulk DCI %lu stream %lu: no reserved segment left for a Link TRB\n",
1948 Ring->m_Endpoint->Dci(), Ring->m_StreamId);
1956 Ring->BuildLinkTrb(&Trb, FirstOfTd,
TRUE);
1957 Trb.
Dword[0] =
Next->LogicalAddress.LowPart;
1959 Ring->m_Trbs[Ring->m_EnqueueIndex] = Trb;
1964 Ring->m_Segment =
Next;
1965 Ring->m_Trbs =
static_cast<PXHCI_TRB>(
Next->VirtualAddress);
1966 Ring->m_EnqueueIndex = 0;
1967 Stage->LastSegment =
Next;
1983 if (Ring->m_Segment != Stage->FirstSegment)
1988 Ring->m_Segment = Stage->FirstSegment;
1989 Ring->m_Trbs =
static_cast<PXHCI_TRB>(Stage->FirstSegment->VirtualAddress);
1993 Ring->m_EnqueueIndex = Stage->FirstIndex;
1995 Stage->LastSegment = Stage->FirstSegment;
1996 Stage->EndIndex = Stage->FirstIndex;
2014 switch (Transfer->CancelState)
2026 Status = WdfRequestUnmarkCancelable(Transfer->Request);
2038 if (!FinishCanceled)
2068 WDFREQUEST
Request = Transfer->Request;
2079 Urb->TransferBufferLength = Transfer->BytesTransferred;
2082 Transfer->Status =
Status;
2086 DPRINT1(
"Bulk DCI %lu stream %lu request %p failed, 0x%08lx USBD 0x%08lx code %lu, %lu bytes\n",
2088 Transfer->CompletionCode, Transfer->BytesTransferred);
2091 FreeTransferResources(Ring, Transfer);
2102 XhciBulkStage* Stage;
2121 Stage = Transfer->
Stage;
2128 OnHardware = Stage->OnHardware;
2133 Bulk->m_PendingStages--;
2137 if (Transfer->
CancelState == XhciBulkCancel::Done)
2143 if (Transfer->
CancelState == XhciBulkCancel::Armed)
2148 Transfer->
CancelState = XhciBulkCancel::CancelRoutinePending;
2205 DPRINT1(
"Bulk DCI %lu stream %lu could not requeue request %p, 0x%08lx\n",
2206 Ring->m_Endpoint->Dci(), Ring->m_StreamId, Transfer->
Request,
Status);
2216 WdfDpcEnqueue(Ring->m_CompletionDpc);
2244 if (Transfer->
CancelState == XhciBulkCancel::Armed)
2264 if (Transfer->
CancelState == XhciBulkCancel::CancelRoutinePending)
2298 if (
Index == StageSlots || !Stage->InUse || !Stage->OnHardware || Stage->Transfer ==
NULL)
2325 XhciBulkStage* Match;
2342 if (Ring->m_StreamId == 0)
2344 DPRINT1(
"Bulk DCI %lu: stale or unknown Event Data 0x%I64x code %lu, dropped\n",
2349 return (Ring->m_StreamId == 0);
2352 Transfer = Stage->Transfer;
2354 if (EndpointId != Ring->m_Endpoint->Dci() ||
XhciTrbSlotId(
Event) != Ring->m_Device->SlotId())
2356 DPRINT1(
"Bulk event for slot %lu DCI %lu reached slot %lu DCI %lu\n",
2357 XhciTrbSlotId(
Event), EndpointId, Ring->m_Device->SlotId(), Ring->m_Endpoint->Dci());
2360 if (
Bytes > Stage->Size)
2362 DPRINT1(
"Bulk DCI %lu stream %lu: %lu bytes reported for a %lu byte stage\n",
2363 Ring->m_Endpoint->Dci(), Ring->m_StreamId,
Bytes, Stage->Size);
2369 DPRINT1(
"Bulk DCI %lu stream %lu: halted code %lu reported through Event Data\n",
2370 Ring->m_Endpoint->Dci(), Ring->m_StreamId,
Code);
2376 Address = (
ULONG64)Stage->FirstSegment->LogicalAddress.QuadPart +
2387 Ring->m_Endpoint->OnStoppedEvent();
2392 if (
Code ==
static_cast<ULONG>(XhciCompletionCode::ShortPacket) ||
2406 if (
Code ==
static_cast<ULONG>(XhciCompletionCode::ShortPacket) ||
2412 Bulk->m_PendingStages--;
2413 if (
Bulk->m_OutstandingEvents != 0)
2415 Bulk->m_OutstandingEvents--;
2422 Ring->m_Endpoint->OnExpectedEventsProcessed();
2437 XhciBulkStage* Stage;
2449 if (Ring->m_StreamId == 0)
2458 if (
Bytes > Stage->Size)
2460 DPRINT1(
"Bulk DCI %lu stream %lu: %lu bytes found in a %lu byte stage\n",
2461 Ring->m_Endpoint->Dci(), Ring->m_StreamId,
Bytes, Stage->Size);
2474 DPRINT(
"Bulk DCI %lu: halt reported at the enqueue pointer, dropped\n", Ring->m_Endpoint->Dci());
2485 Ring->m_Endpoint->OnStoppedEvent();
2490 DPRINT1(
"Bulk DCI %lu stream %lu: unexpected code %lu without Event Data\n",
2491 Ring->m_Endpoint->Dci(), Ring->m_StreamId,
Code);
2514 if (
Address == Ring->EnqueuePointer())
2516 *Skipped =
Bulk->m_PendingStages;
2524 if (Candidate ==
NULL || !Candidate->OnHardware)
2554 Bulk->m_OutstandingEvents = 1;
2558 Ring->m_Endpoint->OnHaltedCompletionCode(
Code,
TRUE);
2569 Bulk->m_PendingStages--;
2570 if (
Bulk->m_OutstandingEvents != 0)
2571 Bulk->m_OutstandingEvents--;
2577 Ring->m_Endpoint->OnExpectedEventsProcessed();
2593 Transfer = Stage->Transfer;
2604 Ring->m_Type.Bulk.m_OutstandingEvents = Skipped;
2620 *PointsToNoOp =
FALSE;
2632 Candidate = Ring->m_Segment;
2639 Candidate = Oldest->FirstSegment;
2667 if (!LikelyDuplicate(Ring, Pointer, &
NoOp))
2669 DPRINT1(
"Bulk DCI %lu: event TRB pointer 0x%I64x is not on the ring, resetting\n",
2670 Ring->m_Endpoint->Dci(), Pointer);
2677 DPRINT1(
"Bulk DCI %lu: likely duplicate event at 0x%I64x dropped\n",
2678 Ring->m_Endpoint->Dci(), Pointer);
2684 DPRINT1(
"Bulk DCI %lu: stopped event on a No Op TRB at 0x%I64x dropped\n",
2685 Ring->m_Endpoint->Dci(), Pointer);
2689 DPRINT1(
"Bulk DCI %lu: likely duplicate event at 0x%I64x code %lu, resetting\n",
2690 Ring->m_Endpoint->Dci(), Pointer,
Code);
2701 XhciBulkStage* Stage;
2708 Dequeue = Ring->m_Endpoint->StreamDequeuePointer(Ring->m_StreamId) & ~XHCI_DEQUEUE_FLAGS_MASK;
2710 if (!LookupStage(Ring, Dequeue, &Stage, &Skipped))
2712 DPRINT1(
"Bulk DCI %lu stream %lu: stream dequeue pointer 0x%I64x is not on the ring\n",
2713 Ring->m_Endpoint->Dci(), Ring->m_StreamId, Dequeue);
2719 Bulk->m_OutstandingEvents =
Bulk->m_PendingStages;
2723 Bytes = Ring->m_Endpoint->StreamTransferLength(Ring->m_StreamId);
2724 if (
Bytes > Stage->Size)
2726 DPRINT1(
"Bulk DCI %lu stream %lu: context reports %lu bytes for a %lu byte stage\n",
2727 Ring->m_Endpoint->Dci(), Ring->m_StreamId,
Bytes, Stage->Size);
2731 Stage->Transfer->BytesTransferred +=
Bytes;
2733 Bulk->m_OutstandingEvents = Skipped;
static _Out_opt_ PULONGLONG Start
#define InterlockedExchange
static const ULONG XhciBulkOkToReclaim
static const ULONG XhciBulkImmediateBytes
static const ULONG XhciBulkPendingStagesMax
static const USBD_STATUS XhciBulkStatusNotSet
static const ULONG XhciBulkReclaimAck
static BOOLEAN NTAPI XhciBulkNeedsNoOps(_In_ const XhciTransferRing *Ring)
static const LONG XhciBulkWaitArrived
static const LONG XhciBulkWaitParked
static const ULONG XhciBulkHalted
static BOOLEAN NTAPI XhciBulkIsHaltedCode(_In_ ULONG Code)
static const ULONG XhciBulkReasonEd0Invalid
static BOOLEAN NTAPI XhciBulkEndpointIn(_In_ const XhciTransferRing *Ring)
static XhciBulkStage *NTAPI XhciBulkStageFromEventData(_In_ ULONG64 Value)
static ULONG NTAPI XhciBulkWorstPages(_In_ ULONG Bytes)
static ULONG64 NTAPI XhciBulkEventData(_In_ const XhciTransferRing *Ring, _In_ const XhciBulkStage *Stage)
static const LONG XhciBulkWaitIdle
static ULONG NTAPI XhciBulkStageBytes(_In_ const XhciBulkStage *Stage, _In_ const XHCI_TRB *Event)
static BOOLEAN NTAPI XhciBulkScanSegment(_In_ const XhciDmaBuffer *Segment, _In_ ULONG Start, _In_ const XHCI_TRB *Event, _Inout_ PULONG Bytes)
static BOOLEAN NTAPI XhciBulkIsStoppedCode(_In_ ULONG Code)
static BOOLEAN NTAPI XhciBulkStageContains(_In_ const XhciBulkStage *Stage, _In_ ULONG64 Address)
static VOID NTAPI XhciBulkMoveList(_Inout_ PLIST_ENTRY Destination, _Inout_ PLIST_ENTRY Source)
static const ULONG XhciBulkAckExpected
static VOID NTAPI XhciBulkCopyIn(_In_ const XhciBulkTransfer *Transfer, _In_ const XhciBulkStage *Stage, _In_ ULONG Bytes)
static const ULONG XhciBulkReasonEd0Duplicate
static ULONG NTAPI XhciBulkPadSize(_In_ const XhciTransferRing *Ring, _In_ ULONG Size)
static const ULONG XhciBulkStageTag
static const ULONG XhciBulkCanceled
static BOOLEAN NTAPI XhciBulkSegmentHas(_In_ const XhciDmaBuffer *Segment, _In_ ULONG Start, _In_ ULONG OnePastEnd, _In_ ULONG64 Address)
static const ULONG XhciBulkNoOpCount
static const ULONG XhciBulkMinStageSize
static const LONG XhciBulkWaitAbandoned
static const ULONG XhciBulkStoppedSeen
static BOOLEAN NTAPI XhciBulkTransferIn(_In_ const XhciBulkTransfer *Transfer)
static BOOLEAN NTAPI XhciBulkChainedMdl(_In_ const XhciBulkTransfer *Transfer)
static const ULONG XhciBulkSegmentWaitLimit
static const ULONG XhciBulkTrbBytesMax
static const ULONG XhciBulkTransferTag
static BOOLEAN BuildTd(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkStage *Stage)
static VOID Cleanup(_In_ XhciTransferRing *Ring)
static VOID DropMdl(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkTransfer *Transfer)
static VOID FreeTransferResources(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkTransfer *Transfer)
static NTSTATUS EnableForwardProgress(_In_ XhciTransferRing *Ring, _In_ ULONG MaxTransferSize)
static VOID RecoverTransfers(_In_ XhciTransferRing *Ring)
static VOID EstimateTrbs(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkStage *Stage)
static VOID ResumeRingFill(_In_ XhciTransferRing *Ring)
static VOID StreamStopOrHaltOnce(_In_ XhciTransferRing *Ring, _In_ ULONG Flag)
static VOID InitTransfer(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkTransfer *Transfer, _In_ WDFREQUEST Request)
static NTSTATUS Initialize(_In_ XhciTransferRing *Ring)
static EVT_WDF_DPC EvtCompletionDpc
static BOOLEAN Ed0Event(_In_ XhciTransferRing *Ring, _In_ const XHCI_TRB *Event)
static VOID KickFill(_In_ XhciTransferRing *Ring)
static BOOLEAN DoorbellRungSinceFill(_In_ const XhciTransferRing *Ring)
static VOID Ed0Mismatch(_In_ XhciTransferRing *Ring, _In_ const XHCI_TRB *Event)
static XhciBulkStage * NextTdSlot(_In_ XhciTransferRing *Ring)
static BOOLEAN OnTransferEvent(_In_opt_ XhciTransferRing *Ring, _In_ XhciController *Controller, _In_ const XHCI_TRB *Event)
static VOID Complete(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkTransfer *Transfer, _In_ USBD_STATUS Default)
static BOOLEAN OwnsRequests(_In_ const XhciTransferRing *Ring)
static const ULONG StageSlots
static VOID StoppedEvent(_In_ XhciTransferRing *Ring, _Inout_opt_ XhciBulkStage *Stage, _In_ ULONG Code, _In_ ULONG Bytes, _In_ ULONG Skipped)
static EVT_WDF_IO_QUEUE_STATE ReadyNotification
static VOID CompleteAfterUncancel(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkTransfer *Transfer, _In_ USBD_STATUS Default, _In_ BOOLEAN FinishCanceled)
static BOOLEAN EstimateSegments(_In_ XhciTransferRing *Ring, _In_ const XhciBulkStage *Stage, _Out_ PULONG Segments)
static VOID SegmentsArrived(_In_ XhciTransferRing *Ring, _In_ NTSTATUS Status)
static VOID StreamStopOrHalt(_In_ XhciTransferRing *Ring)
static EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE EvtIoCanceledOnQueue
volatile LONG m_FillAgain
static BOOLEAN IsLikelyDuplicate(_In_ const XhciTransferRing *Ring, _In_ const XHCI_TRB *Event)
static VOID QueueCompletionDpc(_In_ XhciTransferRing *Ring)
static NTSTATUS ArrangeBuffer(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkTransfer *Transfer)
static VOID CompleteBatch(_In_ XhciTransferRing *Ring, _Inout_ PLIST_ENTRY Batch)
static VOID SizeStage(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkStage *Stage)
static VOID Enable(_In_ XhciTransferRing *Ring)
static BOOLEAN HasQueuedWork(_In_ const XhciTransferRing *Ring)
static Outcome EncodeStage(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkStage *Stage)
static VOID ConsumePendingEvents(_In_ XhciTransferRing *Ring)
static VOID HaltedEvent(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkStage *Stage, _In_ ULONG Code, _In_ ULONG Bytes)
static VOID FillLoop(_In_ XhciTransferRing *Ring)
static DRIVER_LIST_CONTROL DmaCallback
static BOOLEAN Ed1Event(_In_ XhciTransferRing *Ring, _In_ const XHCI_TRB *Event)
static VOID Disable(_In_ XhciTransferRing *Ring)
static VOID PutScatterGather(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkStage *Stage)
static VOID SuspendRingFill(_In_ XhciTransferRing *Ring)
static Outcome FailStage(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkStage *Stage)
static VOID OnPipeHalted(_In_ XhciTransferRing *Ring)
static VOID UndoTd(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkStage *Stage)
static Outcome PrimeStage(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkStage *Stage)
static BOOLEAN ParkOnSegments(_In_ XhciTransferRing *Ring)
static VOID ChooseMechanism(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkTransfer *Transfer)
static BOOLEAN LikelyDuplicate(_In_ const XhciTransferRing *Ring, _In_ ULONG64 Address, _Out_ PBOOLEAN PointsToNoOp)
static VOID AllowReclaimOnCancel(_In_ XhciTransferRing *Ring)
static BOOLEAN IsLiveStage(_In_ const XhciTransferRing *Ring, _In_ const XhciBulkStage *Stage, _In_ ULONG64 EventData)
static XhciBulkStage * AcquireStage(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkTransfer *Transfer)
static EVT_WDF_REQUEST_CANCEL EvtRequestCancel
static BOOLEAN LookupStage(_In_ const XhciTransferRing *Ring, _In_ ULONG64 Address, _Outptr_result_maybenull_ XhciBulkStage **Stage, _Out_ PULONG Skipped)
static VOID BuildTdsFromQueue(_In_ XhciTransferRing *Ring)
static NTSTATUS AcquireStageMdl(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkStage *Stage)
static VOID StoppedEventReceived(_In_ XhciTransferRing *Ring)
static BOOLEAN InsertLink(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkStage *Stage, _In_ BOOLEAN FirstOfTd)
static VOID ReleaseParkedMapping(_In_ XhciTransferRing *Ring)
static VOID ReleaseStage(_In_ XhciTransferRing *Ring, _Inout_ XhciBulkStage *Stage)
VOID OnTransferCanceled()
VOID OnTransfersReclaimed()
static XhciTransferRing * FromQueue(_In_ WDFQUEUE Queue)
XhciMapState ChangeMapState(_In_ BOOLEAN FromAny, _In_ XhciMapState From, _In_ XhciMapState To)
static ULONG UrbProcessorIndex(_In_ PURB Urb)
static NTSTATUS NtStatusFromUsbdStatus(_In_ USBD_STATUS UsbdStatus)
union XhciTransferRing::@1691 m_Type
static USBD_STATUS UsbdStatusFromCompletionCode(_In_ ULONG CompletionCode)
XhciEndpoint * m_Endpoint
#define _Requires_lock_held_(lock)
#define _Requires_lock_not_held_(lock)
_Inout_ HubConfiguration ** Slot
_In_ HANDLE _In_ CONST PDXGKMDT_OPM_GET_INFO_PARAMETERS Parameters
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
#define NT_SUCCESS(StatCode)
#define RemoveEntryList(Entry)
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
#define KeRaiseIrql(irql, oldIrql)
#define KeReleaseSpinLock(sl, irql)
#define KeLowerIrql(oldIrql)
#define KeAcquireSpinLock(sl, irql)
#define RemoveTailList(ListHead)
#define RemoveHeadList(ListHead)
#define InitializeListHead(ListHead)
pRequest Complete(RequestStatus)
static void Report(const char *msg)
#define USB3_URB_RESERVED_RESOURCES
#define InterlockedCompareExchange
VOID NTAPI IoBuildPartialMdl(IN PMDL SourceMdl, IN PMDL TargetMdl, IN PVOID VirtualAddress, IN ULONG Length)
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
#define _Outptr_result_maybenull_
#define UNREFERENCED_PARAMETER(P)
_In_ ULONG _In_ ULONG Offset
_In_ ULONG _In_ ULONG _In_ ULONG Length
_In_ ULONG MaxTransferSize
FORCEINLINE VOID KeMemoryBarrier(VOID)
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
PACPI_METHOD_ARGUMENT Next
XhciBulkMechanism Mechanism
XhciBulkCancel CancelState
struct _URB_BULK_OR_INTERRUPT_TRANSFER * Urb
XhciDmaBuffer * DoubleBuffer
PHYSICAL_ADDRESS LogicalAddress
struct _DMA_OPERATIONS * DmaOperations
struct _LIST_ENTRY * Flink
#define FIELD_OFFSET(t, f)
#define RtlCopyMemory(Destination, Source, Length)
#define RtlZeroMemory(Destination, Length)
#define CONTAINING_RECORD(address, type, field)
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ UCXCONTROLLER * Controller
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST Request
#define STATUS_INVALID_DEVICE_STATE
#define STATUS_INSUFFICIENT_RESOURCES
#define USB_ENDPOINT_DIRECTION_MASK
#define USB_ENDPOINT_TYPE_BULK
enum _USB_DEVICE_SPEED USB_DEVICE_SPEED
#define USBD_STATUS_CANCELED
#define USBD_TRANSFER_DIRECTION_IN
#define USBD_STATUS_INSUFFICIENT_RESOURCES
#define USBD_STATUS(Status)
_In_opt_ PUSB_CONFIGURATION_DESCRIPTOR _Inout_ PUSBD_INTERFACE_LIST_ENTRY _Outptr_ PURB * Urb
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ PDEVICE_OBJECT DeviceObject
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
_In_ UCHAR _In_ UCHAR _In_ ULONG Code
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
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
FORCEINLINE VOID WDF_REQUEST_PARAMETERS_INIT(_Out_ PWDF_REQUEST_PARAMETERS Parameters)
_In_ WDFREQUEST _In_ BOOLEAN Requeue
_In_ WDFREQUEST _In_ PFN_WDF_REQUEST_CANCEL EvtRequestCancel
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
_In_ NTSTATUS _In_ USBD_STATUS UsbdStatus
_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
NTKERNELAPI VOID NTAPI WRITE_REGISTER_UCHAR(IN PUCHAR Register, IN UCHAR Value)
#define DMA_TRANSFER_INFO_VERSION1
struct _SCATTER_GATHER_LIST * PSCATTER_GATHER_LIST
_In_ struct _IRP _In_ struct _SCATTER_GATHER_LIST * ScatterGather
#define DEVICE_DESCRIPTION_VERSION3
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
#define MmGetMdlByteCount(_Mdl)
#define MmGetMdlVirtualAddress(_Mdl)
#define MmInitializeMdl(_MemoryDescriptorList, _BaseVa, _Length)
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
#define XHCI_TRB_LENGTH_MASK
#define XHCI_TRB_ENDPOINT_MASK
#define XHCI_TRB_TYPE_SHIFT
FORCEINLINE ULONG64 NTAPI XhciTrbPointer(_In_ const XHCI_TRB *Trb)
#define XHCI_TRANSFER_EVENT_ED
#define XHCI_TRB_TD_SIZE_SHIFT
#define XHCI_TRB_ENDPOINT_SHIFT
#define XHCI_TRB_INTERRUPTER_SHIFT
#define XHCI_TRANSFER_EVENT_LENGTH_MASK
#define XHCI_EVENT_DATA_TYPE_MASK
struct _XHCI_TRB XHCI_TRB
FORCEINLINE ULONG NTAPI XhciTrbCompletionCode(_In_ const XHCI_TRB *Trb)
FORCEINLINE ULONG NTAPI XhciTrbSlotId(_In_ const XHCI_TRB *Trb)
FORCEINLINE BOOLEAN NTAPI XhciIsListEntryLinked(_In_ const LIST_ENTRY *Entry)
FORCEINLINE VOID NTAPI XhciClearListEntry(_Out_ PLIST_ENTRY Entry)