78 return (Packets + PerFrame - 1) / PerFrame;
91 End = (
Packet + 1 < Transfer->PacketsInUrb) ?
Urb->IsoPacket[
Packet + 1].Offset : Transfer->BytesTotal;
112 ULONG Payload = Ring->m_Endpoint->MaxEsitPayload();
115 Payload = Ring->m_Endpoint->MaxPacketSize();
192 return Transfer->Sequence == Sequence;
208 while (*Element < SgList->NumberOfElements && *
Offset >=
SgList->Elements[*Element].Length)
236 if (*Element >=
SgList->NumberOfElements)
275 return (Pieces == 0) ? 1 : Pieces;
292 if (*Element >=
SgList->NumberOfElements)
351 if (
Segment == Stage->LastSegment)
354 if (
Segment->Link.Flink == &Stage->UsedSegments)
355 return Stage->LastSegment;
384 if (!Ring->m_Controller->m_Registers.MseLengthUsable())
405 DPRINT1(
"Isoch DCI %lu: code %lu on a data TRB\n", Ring->m_Endpoint->Dci(),
Code);
412 DPRINT1(
"Isoch DCI %lu: residual %lu above TRB length %lu, code %lu\n",
413 Ring->m_Endpoint->Dci(), Residual,
Length,
Code);
416 return Sum +
Length - Residual;
458 DPRINT1(
"Isoch DCI %lu: ring empty watchdog not created, 0x%08lx\n",
459 Ring->m_Endpoint->Dci(),
Status);
474 Ring->m_Type.Isoch.m_FreshStream =
TRUE;
490 DPRINT1(
"Isoch DCI %lu disabled while it still owns requests\n", Ring->m_Endpoint->Dci());
507 DPRINT1(
"Isoch DCI %lu disabled while waiting for segments\n", Ring->m_Endpoint->Dci());
509 if (Ring->ChangeMapState(
FALSE, XhciMapState::Halting, XhciMapState::Halted) != XhciMapState::Halting)
512 static_cast<LONG>(XhciMapState::PausedFill),
513 static_cast<LONG>(XhciMapState::Filling));
530 DPRINT1(
"Isoch DCI %lu cleaned up with requests still owned\n", Ring->m_Endpoint->Dci());
545 if (Ring->
ChangeMapState(
FALSE, XhciMapState::PausedFill, XhciMapState::Filling) == XhciMapState::PausedFill)
553 if (Ring->
ChangeMapState(
FALSE, XhciMapState::PausedFill, XhciMapState::Filling) == XhciMapState::PausedFill)
572 Urb->TransferBufferLength = 0;
581 Transfer->
Ring = Ring;
649 Previous = Ring->ChangeMapState(
TRUE, XhciMapState::Halted, XhciMapState::Filling);
650 if (
Previous == XhciMapState::Halted)
656 DPRINT1(
"Isoch DCI %lu started mapping from map state %ld\n",
666 Previous = Ring->ChangeMapState(
TRUE, XhciMapState::Halted, XhciMapState::Halting);
670 case XhciMapState::AwaitingStarve:
671 WdfTimerStop(Ring->m_Type.Isoch.m_Watchdog,
FALSE);
672 Ring->ChangeMapState(
FALSE, XhciMapState::Halting, XhciMapState::Halted);
675 case XhciMapState::PausedFill:
676 Ring->ChangeMapState(
FALSE, XhciMapState::Halting, XhciMapState::Halted);
679 case XhciMapState::Filling:
684 DPRINT1(
"Isoch DCI %lu stopped mapping from map state %ld\n",
697 Ring->m_Type.Isoch.m_FreshStream =
TRUE;
722 WdfDpcEnqueue(Ring->m_CompletionDpc);
730 Ring->m_Endpoint->OnExpectedEventsProcessed();
746 WdfDpcEnqueue(Ring->m_CompletionDpc);
792 DPRINT1(
"Isoch DCI %lu segment growth failed, 0x%08lx\n", Ring->m_Endpoint->Dci(),
Status);
841 if (Ring->ChangeMapState(
FALSE, XhciMapState::PausedFill, XhciMapState::Filling) == XhciMapState::PausedFill)
872 Ring->ChangeMapState(
FALSE, XhciMapState::Filling, XhciMapState::PausedFill);
888 Ring->ChangeMapState(
FALSE, XhciMapState::Filling, XhciMapState::PausedFill);
902 if (Ring->ChangeMapState(
FALSE, XhciMapState::Filling, XhciMapState::Filling) != XhciMapState::Filling)
911 if (Ring->ChangeMapState(
FALSE, XhciMapState::Filling, XhciMapState::AwaitingStarve) == XhciMapState::Filling)
919 if (Ring->ChangeMapState(
FALSE, XhciMapState::AwaitingStarve, XhciMapState::Filling) !=
920 XhciMapState::AwaitingStarve)
925 WdfTimerStop(Ring->m_Type.Isoch.m_Watchdog,
FALSE);
937 if (Ring->ChangeMapState(
FALSE, XhciMapState::PausedFill, XhciMapState::Filling) == XhciMapState::PausedFill)
993 DPRINT1(
"Isoch DCI %lu gave up waiting for segments\n", Ring->m_Endpoint->Dci());
1032 Status = WdfIoQueueRetrieveNextRequest(Ring->m_Queue, &
Request);
1036 DPRINT(
"Isoch DCI %lu has nothing queued, the stream may starve\n", Ring->m_Endpoint->Dci());
1084 Transfer = &
Data->Isoch;
1093 Transfer->
Ring = Ring;
1101 Transfer->
Mdl =
Urb->TransferBufferMDL;
1105 if (
Urb->TransferBuffer !=
NULL)
1110 DPRINT1(
"Isoch DCI %lu request %p: no MDL for a %lu byte buffer\n",
1125 DPRINT1(
"Isoch DCI %lu request %p: %lu packets with bad offsets for %lu bytes\n",
1127 Urb->ErrorCount = 0;
1142 DPRINT(
"Isoch DCI %lu request %p is late in full\n", Ring->m_Endpoint->Dci(),
Request);
1149 DPRINT(
"Isoch DCI %lu request %p has no data\n", Ring->m_Endpoint->Dci(),
Request);
1158 DPRINT1(
"Isoch DCI %lu request %p canceled before mapping, 0x%08lx\n",
1176 if (Transfer->PacketsInUrb == 0)
1185 return Urb->IsoPacket[Transfer->PacketsInUrb - 1].Offset <= Transfer->BytesTotal;
1220 Urb->StartFrame = StartFrame;
1224 StartFrame =
Urb->StartFrame;
1230 Transfer->StartFrame = StartFrame;
1231 Urb->TransferBufferLength = 0;
1232 Urb->ErrorCount = 0;
1239 DPRINT1(
"Isoch DCI %lu: start frame 0x%lx is %ld frames away\n",
1240 Ring->m_Endpoint->Dci(), StartFrame, Distance);
1257 ULONG PerFrame = Ring->m_Type.Isoch.m_PacketsPerFrame;
1258 ULONG First = Transfer->PacketsQueued + Transfer->PacketsDropped;
1266 while (Frame <
End && Frame <=
Now)
1268 Packet = (Frame - Transfer->StartFrame) * PerFrame;
1274 Transfer->PacketsDropped++;
1285 Transfer->PacketsDropped = Transfer->PacketsInUrb - Transfer->PacketsQueued;
1286 Transfer->BytesDropped = (Transfer->BytesTotal > Transfer->BytesQueued) ?
1287 Transfer->BytesTotal - Transfer->BytesQueued : 0;
1302 Transfer->StageCount++;
1316 Stage->
EndIndex = Ring->m_EnqueueIndex;
1317 Stage->
ScanIndex = Ring->m_EnqueueIndex;
1336 Stage->FreeMdl =
FALSE;
1338 Ring->ReturnSegments(&Stage->FreeSegments,
TRUE);
1339 Ring->ReturnSegments(&Stage->UsedSegments,
FALSE);
1343 if (Ring->m_Type.Isoch.m_CurrentStage == Stage)
1344 Ring->m_Type.Isoch.m_CurrentStage =
NULL;
1357 Stage->InUse =
FALSE;
1358 Stage->OnHardware =
FALSE;
1374 Adapter = Ring->m_Controller->m_Buffers.DmaAdapter();
1385 return Transfer->StageCount == 0 &&
1386 Transfer->TdsRetired == Transfer->TdsQueued &&
1387 Transfer->PacketsQueued + Transfer->PacketsDropped >= Transfer->PacketsInUrb;
1409 if (!Ring->m_Controller->m_Registers.ContiguousFrameId())
1423 DPRINT(
"Isoch DCI %lu: frame 0x%lx does not follow 0x%lx, waiting for the ring to drain\n",
1439 Status = Ring->TakeSegments(Segments, &Stage->FreeSegments);
1455 DPRINT1(
"Isoch DCI %lu: %lu segments not available, 0x%08lx\n",
1456 Ring->m_Endpoint->Dci(), Segments,
Status);
1484 DPRINT1(
"Isoch DCI %lu: MDL chain shorter than the transfer\n", Ring->m_Endpoint->Dci());
1498 if (Partial ==
NULL)
1500 DPRINT1(
"Isoch DCI %lu: partial MDL allocation failed\n", Ring->m_Endpoint->Dci());
1505 Partial->Next =
Mdl->Next;
1506 Stage->Mdl = Partial;
1507 Stage->FreeMdl =
TRUE;
1518 ULONG PerFrame = Ring->m_Type.Isoch.m_PacketsPerFrame;
1522 ULONG Registers = 0;
1530 Adapter = Ring->m_Controller->m_Buffers.DmaAdapter();
1533 Adapter->DmaOperations->GetDmaTransferInfo !=
NULL)
1537 if (
NT_SUCCESS(Adapter->DmaOperations->GetDmaTransferInfo(Adapter,
1544 Registers =
Info.V1.MapRegisterCount;
1551 for (
Mdl = Stage->Mdl, Left = Remaining;
Mdl !=
NULL && Left != 0;
Mdl =
Mdl->Next)
1560 if (Registers > Ring->m_MapRegisterCount && Ring->m_MapRegisterCount > 1)
1563 if (Remaining <=
Limit)
1566 Stage->Size = Remaining;
1571 Packet = Stage->FirstPacket;
1572 while (Packet < Transfer->PacketsInUrb)
1574 ULONG FrameBytes = 0;
1583 Total += FrameBytes;
1588 if (
Packet == Stage->FirstPacket)
1590 DPRINT1(
"Isoch DCI %lu: one frame needs more than %lu bytes of mapping\n",
1591 Ring->m_Endpoint->Dci(),
Limit);
1595 Stage->LastPacket =
Packet - 1;
1596 Stage->Size =
Total;
1620 if (PerTd > Ring->m_LastIndex)
1621 PerTd = Ring->m_LastIndex;
1625 Needed = PerTd * (Stage->LastPacket - Stage->FirstPacket + 1);
1626 Available = Ring->m_LastIndex - Ring->m_EnqueueIndex;
1627 Available -= Available % PerTd;
1629 if (Needed > Available)
1631 Usable = Ring->m_LastIndex - (Ring->m_LastIndex % PerTd);
1652 Stage->SgList =
NULL;
1680 PDMA_ADAPTER Adapter = Ring->m_Controller->m_Buffers.DmaAdapter();
1688 WdfDeviceWdmGetDeviceObject(Ring->m_Controller->m_Device),
1699 DPRINT1(
"Isoch DCI %lu: GetScatterGatherList for %lu bytes failed, 0x%08lx\n",
1700 Ring->m_Endpoint->Dci(), Stage->Size,
Status);
1739 if (Ring->
ChangeMapState(
FALSE, XhciMapState::Filling, XhciMapState::Filling) == XhciMapState::Filling)
1761 if (Ring->m_Controller->HasErrata(XhciErrata::IsochSkipPastFrames))
1768 DPRINT1(
"Isoch DCI %lu: stage for frame 0x%lx is late at 0x%lx\n",
1769 Ring->m_Endpoint->Dci(), Frame,
Now);
1772 Stage->SgList =
NULL;
1781 Ring->RingDoorbell();
1790 DPRINT1(
"Isoch DCI %lu: packet %lu does not fit the reserved segments\n",
1791 Ring->m_Endpoint->Dci(), Stage->FirstPacket);
1797 if (Stage->FirstPacket + Fit - 1 != Stage->LastPacket)
1799 DPRINT1(
"Isoch DCI %lu: stage cut after %lu of %lu packets\n",
1800 Ring->m_Endpoint->Dci(), Fit, Stage->LastPacket - Stage->FirstPacket + 1);
1802 for (
Packet = Stage->FirstPacket; Packet < Stage->FirstPacket + Fit;
Packet++)
1806 Stage->LastPacket = Stage->FirstPacket + Fit - 1;
1808 Stage->Truncated =
TRUE;
1815 Ring->RingDoorbell();
1831 ULONG LastSlot = Ring->m_LastIndex;
1835 BOOLEAN AllowBei = !Ring->m_Controller->HasErrata(XhciErrata::IsochInterruptEveryTd);
1836 ULONG Hcc2 = Ring->m_Controller->m_Registers.Hccparams2();
1839 ULONG MaxPacket = Ring->m_Endpoint->MaxPacketSize();
1840 ULONG BurstSize = Ring->m_Endpoint->MaxBurst() + 1;
1854 Stage->FirstSegment = Ring->m_Segment;
1855 Stage->LastSegment = Ring->m_Segment;
1856 Stage->ScanSegment = Ring->m_Segment;
1857 Stage->FirstIndex = Ring->m_EnqueueIndex;
1858 Stage->EndIndex = Ring->m_EnqueueIndex;
1859 Stage->ScanIndex = Ring->m_EnqueueIndex;
1871 volatile UCHAR* CycleByte;
1883 Index = Ring->m_EnqueueIndex;
1886 if (
Index + Pieces + 1 > LastSlot)
1890 if (Spares == 0 || Pieces + 1 > LastSlot)
1896 First = &Ring->m_Trbs[Ring->m_EnqueueIndex];
1907 if (!Guard || Spares != 0)
1919 Index += Pieces + 1;
1928 Tdpc = (MaxPacket != 0) ? (Carried + MaxPacket - 1) / MaxPacket : 1;
1931 Tbc = (Tdpc + BurstSize - 1) / BurstSize - 1;
1932 Tlbpc = (Tdpc % BurstSize) ? (Tdpc % BurstSize) - 1 : BurstSize - 1;
1935 First = &Ring->m_Trbs[Ring->m_EnqueueIndex];
1937 for (Piece = 0; Piece < Pieces; Piece++)
1939 BOOLEAN LastData = (Piece + 1 == Pieces);
1953 if (Piece == 0 && ExtendedTbc)
1956 SizeField = Ring->TdSize(Ring->PacketCount(Carried), Mapped, LastData);
1979 Ring->m_EnqueueIndex++;
1989 Ring->m_Trbs[Ring->m_EnqueueIndex] = Trb;
1990 Ring->m_EnqueueIndex++;
2008 Ring->m_Trbs[Ring->m_EnqueueIndex] = Trb;
2009 Ring->m_EnqueueIndex++;
2012 Stage->EndIndex = Ring->m_EnqueueIndex;
2023 Stage->OnHardware =
TRUE;
2029 if (Stage->Truncated)
2038 CycleByte =
reinterpret_cast<volatile UCHAR*
>(&
First->Dword[3]);
2045 Ring->RingDoorbell();
2051 return Commit ? Placed : Fit;
2071 Ring->BuildLinkTrb(&Trb, FirstOfTd, !FirstOfTd);
2072 Trb.
Dword[0] =
Next->LogicalAddress.LowPart;
2074 Ring->m_Trbs[Ring->m_EnqueueIndex] = Trb;
2079 Ring->m_Segment =
Next;
2080 Ring->m_Trbs =
static_cast<PXHCI_TRB>(
Next->VirtualAddress);
2081 Ring->m_EnqueueIndex = 0;
2082 Stage->LastSegment =
Next;
2083 Stage->EndIndex = 0;
2113 Stage->Transfer != Transfer)
2119 Urb = Transfer->Urb;
2120 Packet = Stage->NextPacket - 1;
2121 if (
Packet >= Transfer->PacketsInUrb)
2123 DPRINT1(
"Isoch DCI %lu: event for packet %lu of %lu\n",
2124 Ring->m_Endpoint->Dci(),
Packet, Transfer->PacketsInUrb);
2132 DPRINT1(
"Isoch DCI %lu: packet %lu was skipped by the controller\n",
2133 Ring->m_Endpoint->Dci(),
Index - 1);
2140 Transfer->BytesTransferred +=
Bytes;
2145 if (
Packet != Stage->LastPacket || !CloseStage)
2151 if (!Stage->OnHardware)
2153 DPRINT1(
"Isoch DCI %lu: end of a stage still being written was reported\n", Ring->m_Endpoint->Dci());
2159 Stage->SgList =
NULL;
2172 Transfer->TdsRetired++;
2213 DPRINT(
"Isoch DCI %lu: completing stale request %p\n", Ring->m_Endpoint->Dci(), Transfer->
Request);
2240 Transfer->StageCount == 0)
2247 if (Oldest == Stage)
2256 CompleteTd(Ring, Transfer, Oldest, Sequence,
static_cast<ULONG>(XhciCompletionCode::MissedService), 0,
TRUE);
2282 if (Transfer->StageCount == 0)
2299 Transfer->TdsRetired++;
2325 Urb->TransferBufferLength = Transfer->BytesTransferred;
2330 Urb->IsoPacket[
Index].Status = PacketStatus;
2345 else if (
Urb->ErrorCount == Transfer->PacketsInUrb)
2354 Self->
m_Bytes += Transfer->BytesTransferred;
2361 DPRINT1(
"Isoch DCI %lu request %p failed, 0x%08lx USBD 0x%08lx, %lu of %lu packets in error\n",
2362 Ring->m_Endpoint->Dci(), Transfer->Request, Transfer->Status,
Status,
2363 Urb->ErrorCount, Transfer->PacketsInUrb);
2367 if (Transfer->OwnMdl)
2370 Transfer->OwnMdl =
FALSE;
2372 Transfer->Mdl =
NULL;
2373 Transfer->Initialized = 0;
2388 Finalize(Ring, Transfer, PacketStatus, HeaderStatus);
2392 WdfRequestComplete(Transfer->Request, Transfer->Status);
2397 InsertTailList(&Ring->m_Type.Isoch.m_Completion, &Transfer->Link);
2400 WdfDpcEnqueue(Ring->m_CompletionDpc);
2416 switch (Transfer->CancelState)
2428 Status = WdfRequestUnmarkCancelable(Transfer->Request);
2440 if (!FinishCanceled)
2459 Finalize(Ring, Transfer, PacketStatus, HeaderStatus);
2466 WdfDpcEnqueue(Ring->m_CompletionDpc);
2470 WdfRequestComplete(Transfer->Request, Transfer->Status);
2529 if (Transfer->
CancelState == XhciIsochCancel::Armed)
2548 if (Transfer->
CancelState == XhciIsochCancel::CancelRoutinePending)
2583 DPRINT1(
"Isoch DCI %lu: Event Data 0x%I64x is not an isoch tag, resetting\n",
2584 Ring->m_Endpoint->Dci(),
Value);
2604 Transfer = Candidate;
2609 if (Transfer !=
NULL)
2626 DPRINT1(
"Isoch DCI %lu: no stage holds packet %lu of request %p\n",
2645 Ring->m_Endpoint->OnStoppedEvent();
2677 case XhciCompletionCode::RingUnderrun:
2678 case XhciCompletionCode::RingOverrun:
2682 case XhciCompletionCode::MissedService:
2690 case XhciCompletionCode::NoPingResponse:
2691 UcxEndpointNoPingResponseError(Ring->m_Endpoint->Handle());
2698 case XhciCompletionCode::Stopped:
2699 case XhciCompletionCode::StoppedLengthInvalid:
2700 case XhciCompletionCode::StoppedShortPacket:
2701 case XhciCompletionCode::DataBufferError:
2702 case XhciCompletionCode::BabbleDetected:
2703 case XhciCompletionCode::IsochBufferOverrun:
2704 case XhciCompletionCode::UsbTransactionError:
2705 case XhciCompletionCode::StallError:
2706 case XhciCompletionCode::EventLost:
2707 case XhciCompletionCode::SplitTransactionError:
2711 DPRINT1(
"Isoch DCI %lu: unexpected code %lu without Event Data\n", Ring->m_Endpoint->Dci(),
Code);
2739 Ring->m_Endpoint->OnStoppedEvent();
2749 DPRINT(
"Isoch DCI %lu: event at 0x%I64x code %lu matched no stage, dropped\n",
2750 Ring->m_Endpoint->Dci(), Pointer,
Code);
2792 DPRINT1(
"Isoch DCI %lu: event code %lu without a TRB pointer\n", Ring->m_Endpoint->Dci(),
Code);
2796 if (Pointer == Ring->EnqueuePointer())
2851 DPRINT1(
"Isoch DCI %lu: TRB type %lu inside a stage\n", Ring->m_Endpoint->Dci(),
Type);
2878 DPRINT1(
"Isoch DCI %lu: TRB 0x%I64x not found past the scan position\n", Ring->m_Endpoint->Dci(), Pointer);
2908 DPRINT1(
"Isoch DCI %lu: Link TRB inside a TD\n", Ring->m_Endpoint->Dci());
2913 DPRINT1(
"Isoch DCI %lu: TRB type %lu before the Event Data TRB\n", Ring->m_Endpoint->Dci(),
Type);
2938 Abort = Ring->m_Controller->HasErrata(XhciErrata::IsochMissedServiceSilent) &&
2948 DPRINT1(
"Isoch DCI %lu: ring empty with stages unreported, reclaiming\n", Ring->m_Endpoint->Dci());
2949 Ring->m_Endpoint->OnTransferCanceled();
3008 DPRINT1(
"Isoch DCI %lu: closing a stage whose events never came\n", Ring->m_Endpoint->Dci());
3009 CompleteTd(Ring, Transfer, Stage, Sequence,
static_cast<ULONG>(XhciCompletionCode::MissedService), 0,
TRUE);
static _Out_opt_ PULONGLONG Start
#define InterlockedExchange
static FCRET Finalize(FILECOMPARE *pFC, struct list *ptr0, struct list *ptr1, BOOL fDifferent)
VOID OnTransferCanceled()
VOID OnTransfersReclaimed()
static VOID AllowReclaimOnCancel(_In_ XhciTransferRing *Ring)
static ULONG EstimateSegments(_In_ XhciTransferRing *Ring, _In_ const XhciIsochStage *Stage)
static VOID SuspendRingFill(_In_ XhciTransferRing *Ring)
static EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE EvtIoCanceledOnQueue
static XhciIsochStage * AcquireStage(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochTransfer *Transfer)
static VOID OnRingStarved(_In_ XhciTransferRing *Ring)
static BOOLEAN OnTransferEvent(_In_ XhciTransferRing *Ring, _In_ const XHCI_TRB *Event)
static BOOLEAN TakeRequest(_In_ XhciTransferRing *Ring, _In_ WDFREQUEST Request, _Out_ XhciIsochTransfer **Taken)
static EVT_WDF_REQUEST_CANCEL EvtRequestCancel
static ULONG ReleaseAllStages(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochTransfer *Transfer)
static VOID ReleaseParkedMapping(_In_ XhciTransferRing *Ring)
static EVT_WDF_TIMER EvtWatchdog
volatile LONG m_SegmentWait
static BOOLEAN TransferDone(_In_ const XhciIsochTransfer *Transfer)
static VOID Enable(_In_ XhciTransferRing *Ring)
static Outcome EncodeStage(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochStage *Stage)
static VOID AwaitRingEmpty(_In_ XhciTransferRing *Ring)
static VOID SkipUnmapped(_Inout_ XhciIsochTransfer *Transfer)
static VOID RecoverTransfers(_In_ XhciTransferRing *Ring)
static VOID FinishExpiredIsoch(_In_ XhciTransferRing *Ring, _In_ const XhciIsochTransfer *Newest, _In_ ULONG Sequence)
BOOLEAN m_DoorbellAfterFirstTd
static VOID WriteStage(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochStage *Stage)
static EVT_WDF_DPC EvtCompletionDpc
static VOID FreeStage(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochStage *Stage)
static VOID FillLoop(_In_ XhciTransferRing *Ring)
static VOID CompleteAfterUncancel(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochTransfer *Transfer, _In_ USBD_STATUS PacketStatus, _In_ USBD_STATUS HeaderStatus, _In_ BOOLEAN FinishCanceled, _In_ BOOLEAN Async)
XhciIsochStage * m_CurrentStage
static NTSTATUS Initialize(_In_ XhciTransferRing *Ring)
static NTSTATUS AcquireStageMdl(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochStage *Stage)
static Outcome FailStage(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochStage *Stage)
volatile LONG m_FillWanted
static DRIVER_LIST_CONTROL DmaCallback
static BOOLEAN HasQueuedWork(_In_ const XhciTransferRing *Ring)
static VOID CompletePlain(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochTransfer *Transfer, _In_ USBD_STATUS PacketStatus, _In_ USBD_STATUS HeaderStatus, _In_ BOOLEAN Async)
static VOID InsertLink(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochStage *Stage, _In_ BOOLEAN FirstOfTd)
static Outcome PrimeStage(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochStage *Stage)
static BOOLEAN SizeStage(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochStage *Stage)
static VOID CompleteBatch(_In_ XhciTransferRing *Ring, _Inout_ PLIST_ENTRY Batch)
static VOID CompleteTd(_In_ XhciTransferRing *Ring, _In_ XhciIsochTransfer *Transfer, _In_ XhciIsochStage *Stage, _In_ ULONG Sequence, _In_ ULONG Code, _In_ ULONG Bytes, _In_ BOOLEAN CloseStage)
ULONG m_MissedServiceErrors
static VOID Ed0Event(_In_ XhciTransferRing *Ring, _In_ const XHCI_TRB *Event)
static VOID OnClientPipeReset(_In_ XhciTransferRing *Ring)
static BOOLEAN ParkOnSegments(_In_ XhciTransferRing *Ring)
static VOID KickAfterStage(_In_ XhciTransferRing *Ring, _In_ ULONG InFlight)
static BOOLEAN FindTrb(_In_ XhciTransferRing *Ring, _In_ const XHCI_TRB *Event, _Outptr_result_maybenull_ XhciIsochStage **Found, _Out_ PULONG Bytes)
static XhciIsochStage * NextTdSlot(_In_ XhciTransferRing *Ring)
LIST_ENTRY m_WaitingForCancel
static VOID Disable(_In_ XhciTransferRing *Ring)
static VOID Ed1Event(_In_ XhciTransferRing *Ring, _In_ const XHCI_TRB *Event)
static BOOLEAN PacketsValid(_In_ const XhciIsochTransfer *Transfer)
static VOID ConsumePendingEvents(_In_ XhciTransferRing *Ring)
static BOOLEAN DoorbellRungSinceFill(_In_ const XhciTransferRing *Ring)
static BOOLEAN FinishLostStages(_In_ XhciTransferRing *Ring)
static VOID Finalize(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochTransfer *Transfer, _In_ USBD_STATUS PacketStatus, _In_ USBD_STATUS HeaderStatus)
static VOID PutScatterGather(_In_ XhciTransferRing *Ring, _In_opt_ PSCATTER_GATHER_LIST SgList)
volatile LONG m_RingEmptySeen
static VOID Cleanup(_In_ XhciTransferRing *Ring)
static ULONG LayoutStage(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochStage *Stage, _In_ BOOLEAN Commit)
static VOID SegmentsArrived(_In_ XhciTransferRing *Ring, _In_ NTSTATUS Status)
static EVT_WDF_IO_QUEUE_STATE ReadyNotification
static BOOLEAN OwnsRequests(_In_ const XhciTransferRing *Ring)
ULONG m_LastScheduledFrame
volatile LONG m_LateStage
static VOID FlagMissedPackets(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochTransfer *Transfer)
static VOID BuildTdsFromQueue(_In_ XhciTransferRing *Ring)
static VOID RetireExpiredStages(_In_ XhciTransferRing *Ring, _In_ XhciIsochTransfer *Transfer, _In_ XhciIsochStage *Stage, _In_ ULONG Sequence)
static NTSTATUS ScheduleStartFrame(_In_ XhciTransferRing *Ring, _Inout_ XhciIsochTransfer *Transfer)
static BOOLEAN LeaveRingEmptyWait(_In_ XhciTransferRing *Ring)
static VOID ResumeRingFill(_In_ XhciTransferRing *Ring)
volatile LONG m_FillAgain
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 RemoveHeadList(ListHead)
#define InitializeListHead(ListHead)
static void Report(const char *msg)
#define InterlockedCompareExchange
VOID NTAPI IoBuildPartialMdl(IN PMDL SourceMdl, IN PMDL TargetMdl, IN PVOID VirtualAddress, IN ULONG Length)
static const ULONG XhciIsochTrbBytesMax
static const ULONG XhciIsochAsapDelay
static ULONG NTAPI XhciIsochFrames(_In_ ULONG Packets, _In_ ULONG PerFrame)
static const ULONG XhciIsochBiasLate
static const LONG XhciIsochStoppedSeen
static const ULONG XhciIsochTransferTag
static const LONG XhciIsochOkToReclaim
static XhciIsochStage *NTAPI XhciIsochStageAt(_In_ XhciIsochTransfer *Transfer, _In_ ULONG Position)
static VOID NTAPI XhciIsochTakePiece(_In_ const SCATTER_GATHER_LIST *SgList, _Inout_ PULONG Element, _Inout_ PULONG Offset, _In_ ULONG Bytes, _Out_ PULONG64 Address, _Out_ PULONG Chunk)
static BOOLEAN NTAPI XhciIsochStoppedCode(_In_ ULONG Code)
static const ULONG XhciIsochMaxPackets
static const LONG XhciIsochWaitIdle
static struct _URB_ISOCH_TRANSFER *NTAPI XhciIsochUrbOf(_In_ WDFREQUEST Request)
static ULONG NTAPI XhciIsochMatchBytes(_In_ const XhciTransferRing *Ring, _In_ ULONG Code, _In_ ULONG Length, _In_ ULONG Residual, _In_ ULONG Sum)
static BOOLEAN NTAPI XhciIsochSegmentHas(_In_ const XhciDmaBuffer *Segment, _In_ ULONG Start, _In_ ULONG OnePastEnd, _In_ ULONG64 Address)
static ULONG NTAPI XhciIsochSegmentLimit(_In_ const XhciIsochStage *Stage, _In_ const XhciDmaBuffer *Segment)
static const ULONG XhciIsochRestartFast
static VOID NTAPI XhciIsochMoveList(_Inout_ PLIST_ENTRY Destination, _Inout_ PLIST_ENTRY Source)
static const ULONG XhciIsochWatchdogMs
static ULONG NTAPI XhciIsochCountPieces(_In_ const SCATTER_GATHER_LIST *SgList, _In_ ULONG Element, _In_ ULONG Offset, _In_ ULONG Bytes)
static BOOLEAN NTAPI XhciIsochIsActive(_In_ const LIST_ENTRY *Pending, _In_ const XhciIsochTransfer *Transfer, _In_ ULONG Sequence)
static const ULONG XhciIsochBiasNow
static XhciDmaBuffer *NTAPI XhciIsochNextSegment(_In_ const XhciIsochStage *Stage, _In_ const XhciDmaBuffer *Segment)
static const USBD_STATUS XhciIsochNotSet
static const LONG XhciIsochCanceled
static const LONG XhciIsochWaitArrived
static const LONG XhciIsochWaitAbandoned
static ULONG NTAPI XhciIsochPacketLength(_In_ const XhciIsochTransfer *Transfer, _In_ ULONG Packet)
static const LONG XhciIsochLastFrameValid
static const LONG XhciIsochDoorbellRung
static BOOLEAN NTAPI XhciIsochStageHas(_In_ const XhciIsochStage *Stage, _In_ ULONG64 Address)
static BOOLEAN NTAPI XhciIsochNeedsLinkGuard(_In_ const XhciTransferRing *Ring)
static BOOLEAN NTAPI XhciIsochEndpointIn(_In_ const XhciTransferRing *Ring)
static VOID NTAPI XhciIsochSkipEmpty(_In_ const SCATTER_GATHER_LIST *SgList, _Inout_ PULONG Element, _Inout_ PULONG Offset)
static const ULONG XhciIsochInterruptEvery
static const LONG XhciIsochReclaimAck
static const LONG XhciIsochFrameWindow
static const ULONG XhciIsochRestartSlow
static const ULONG XhciIsochMaxInFlight
static ULONG NTAPI XhciIsochCountList(_In_ const LIST_ENTRY *Head)
static const LONG XhciIsochWaitParked
static const ULONG XhciIsochReasonBadEventData
static const LONG XhciIsochEmptyExpected
static VOID NTAPI XhciIsochAdvance(_In_ const SCATTER_GATHER_LIST *SgList, _Inout_ PULONG Element, _Inout_ PULONG Offset, _In_ ULONG Bytes)
static const ULONG XhciIsochBufferRetryLimit
static ULONG NTAPI XhciIsochEsitPayload(_In_ const XhciTransferRing *Ring)
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
unsigned __int64 * PULONG64
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
_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
FORCEINLINE VOID KeMemoryBarrier(VOID)
#define KeAcquireSpinLockAtDpcLevel(SpinLock)
#define KeReleaseSpinLockFromDpcLevel(SpinLock)
PACPI_METHOD_ARGUMENT Next
PSCATTER_GATHER_LIST SgList
XhciDmaBuffer * ScanSegment
XhciIsochTransfer * Transfer
XhciDmaBuffer * FirstSegment
XhciDmaBuffer * LastSegment
static const ULONG StageSlots
XhciIsochCancel CancelState
struct _URB_ISOCH_TRANSFER * Urb
struct _DMA_OPERATIONS * DmaOperations
struct _LIST_ENTRY * Blink
struct _LIST_ENTRY * Flink
static MOUSE_PACKET LastPacket
#define FIELD_OFFSET(t, f)
#define RtlZeroMemory(Destination, Length)
#define CONTAINING_RECORD(address, type, field)
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFREQUEST Request
#define STATUS_UNSUCCESSFUL
#define STATUS_INVALID_DEVICE_STATE
#define STATUS_INSUFFICIENT_RESOURCES
#define USB_ENDPOINT_TYPE_ISOCHRONOUS
#define USB_ENDPOINT_DIRECTION_MASK
enum _USB_DEVICE_SPEED USB_DEVICE_SPEED
#define USBD_STATUS_ISO_NOT_ACCESSED_BY_HW
#define USBD_STATUS_CANCELED
#define USBD_STATUS_ISO_TD_ERROR
#define USBD_STATUS_SUCCESS
#define USBD_STATUS_INSUFFICIENT_RESOURCES
#define USBD_STATUS_INVALID_PARAMETER
#define USBD_START_ISO_TRANSFER_ASAP
#define USBD_STATUS_ISO_NOT_ACCESSED_LATE
#define USBD_STATUS_BAD_START_FRAME
#define USBD_STATUS_ISOCH_REQUEST_FAILED
#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
FORCEINLINE LONGLONG WDF_REL_TIMEOUT_IN_MS(_In_ ULONGLONG Time)
_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
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
_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_ PFN_WDF_REQUEST_CANCEL EvtRequestCancel
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
FORCEINLINE VOID WDF_TIMER_CONFIG_INIT(_Out_ PWDF_TIMER_CONFIG Config, _In_ PFN_WDF_TIMER EvtTimerFunc)
_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 SCATTER_GATHER_LIST
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
_In_ LARGE_INTEGER _In_ ULONG Period
#define MmGetMdlByteCount(_Mdl)
#define MmGetMdlVirtualAddress(_Mdl)
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
#define XHCI_TRB_LENGTH_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_INTERRUPTER_MASK
#define XHCI_ISOCH_FRAME_ID_MASK
#define XHCI_TRB_INTERRUPTER_SHIFT
#define XHCI_ISOCH_FRAME_ID_SHIFT
#define XHCI_ISOCH_TLBPC_SHIFT
#define XHCI_TRANSFER_EVENT_LENGTH_MASK
#define XHCI_EVENT_DATA_TYPE_MASK
struct _XHCI_TRB XHCI_TRB
#define XHCI_ISOCH_TBC_SHIFT
FORCEINLINE ULONG NTAPI XhciTrbCompletionCode(_In_ const XHCI_TRB *Trb)
FORCEINLINE BOOLEAN NTAPI XhciIsListEntryLinked(_In_ const LIST_ENTRY *Entry)
FORCEINLINE VOID NTAPI XhciClearListEntry(_Out_ PLIST_ENTRY Entry)