ReactOS 0.4.17-dev-1281-g065abb3
XhciInterrupters Class Reference

#include <intr.h>

Collaboration diagram for XhciInterrupters:

Classes

struct  Interrupter
 

Public Member Functions

NTSTATUS Create (_In_ XhciController *Controller)
 
NTSTATUS FilterResourceRequirements (_In_ WDFIORESREQLIST Requirements)
 
NTSTATUS Prepare (_In_ WDFCMRESLIST Raw, _In_ WDFCMRESLIST Translated)
 
VOID Release ()
 
NTSTATUS D0Entry (_In_ BOOLEAN StatePreserved)
 
VOID D0ExitPreInterruptsDisabled ()
 
VOID D0Exit ()
 
VOID PostReset ()
 
ULONG Count () const
 
ULONG TargetForCurrentProcessor () const
 
ULONG TargetForProcessor (_In_ ULONG ProcessorIndex) const
 
NTSTATUS AffinitizeResourceRequirements (_In_ WDFIORESREQLIST Requirements)
 

Private Types

enum class  Mechanism : ULONG { Line , Msi , MsiX }
 

Private Member Functions

NTSTATUS PrepareOne (_Inout_ Interrupter *Entry, _In_ WDFINTERRUPT Interrupt, _In_ ULONG Index, _In_ BOOLEAN MessageSignaled)
 
VOID ReleaseOne (_Inout_ Interrupter *Entry)
 
NTSTATUS CreateInterrupt (_In_opt_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw, _In_opt_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated, _Out_ WDFINTERRUPT *Interrupt)
 
ULONG SecondaryCountFor (_In_ ULONG Messages) const
 
NTSTATUS BuildLookup ()
 

Private Attributes

XhciController * m_Controller
 
WDFINTERRUPT m_PrimaryInterrupt
 
Mechanism m_Mechanism
 
ULONG m_SecondaryCount
 
ULONG m_Count
 
ULONG m_Capacity
 
Interrupter * m_Table
 
PUSHORT m_Lookup
 
ULONG m_LookupSize
 

Detailed Description

All interrupters of a controller.

Definition at line 13 of file intr.h.

Member Enumeration Documentation

◆ Mechanism

Enumerator
Line 
Msi 
MsiX 

Definition at line 88 of file intr.h.

Member Function Documentation

◆ AffinitizeResourceRequirements()

NTSTATUS XhciInterrupters::AffinitizeResourceRequirements ( _In_ WDFIORESREQLIST  Requirements)

Called from EvtDeviceFilterAddResourceRequirements.

Definition at line 952 of file intr.cpp.

954{
955 WDFIORESLIST List;
960 ULONG PerInterrupter;
961 ULONG NextProcessor = 0;
962 ULONG Index;
963 ULONG Step;
964 BOOLEAN Primary = TRUE;
965
966 PAGED_CODE();
967
968 if (m_SecondaryCount == 0)
969 return STATUS_SUCCESS;
970
971 if (!XhciFindMessageList(Requirements, &ListIndex, &Messages))
972 {
973 DPRINT1("Secondary interrupters planned but no MSI-X list found\n");
974 return STATUS_SUCCESS;
975 }
976
977 PerInterrupter = XhciActiveProcessors(0) / m_SecondaryCount;
978 List = WdfIoResourceRequirementsListGetIoResList(Requirements, ListIndex);
979
980 for (Index = 0; Index < WdfIoResourceListGetCount(List); Index++)
981 {
982 Descriptor = WdfIoResourceListGetDescriptor(List, Index);
984 continue;
985
986 Pinned = *Descriptor;
988 Pinned.u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
989 Pinned.u.Interrupt.TargetedProcessors = 0;
990
991 /* The primary gets an empty processor set */
992 if (!Primary)
993 {
994 for (Step = 0; Step < PerInterrupter && NextProcessor < RTL_BITS_OF(KAFFINITY); Step++)
995 {
996 Pinned.u.Interrupt.TargetedProcessors |= (KAFFINITY)1 << NextProcessor;
997 NextProcessor++;
998 }
999 }
1000
1001 Primary = FALSE;
1002 WdfIoResourceListUpdateDescriptor(List, &Pinned, Index);
1003 }
1004
1005 return STATUS_SUCCESS;
1006}
#define PAGED_CODE()
unsigned char BOOLEAN
Definition: actypes.h:127
#define DPRINT1
Definition: precomp.h:8
ULONG m_SecondaryCount
Definition: intr.h:121
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
ULONG_PTR KAFFINITY
Definition: compat.h:85
static BOOLEAN NTAPI XhciIsMessageRequirement(_In_ PIO_RESOURCE_DESCRIPTOR Descriptor)
Definition: intr.cpp:630
_Out_ PULONG ListIndex
Definition: intr.cpp:722
static ULONG NTAPI XhciActiveProcessors(_In_ USHORT Group)
Definition: intr.cpp:67
_Out_ PULONG _Out_ PULONG Messages
Definition: intr.cpp:724
#define CM_RESOURCE_INTERRUPT_POLICY_INCLUDED
Definition: cmtypes.h:160
#define RTL_BITS_OF(sizeOfArg)
Definition: ntbasedef.h:680
@ IrqPolicySpecifiedProcessors
Definition: miniport.h:133
#define STATUS_SUCCESS
Definition: shellext.h:65
union _IO_RESOURCE_DESCRIPTOR::@2507 u
struct _IO_RESOURCE_DESCRIPTOR::@2507::@2510 Interrupt
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550

◆ BuildLookup()

NTSTATUS XhciInterrupters::BuildLookup ( )
private

Definition at line 1228 of file intr.cpp.

1229{
1230 Interrupter* Entry;
1231 ULONG Size;
1232 ULONG Number;
1233 ULONG Target;
1234 ULONG Index;
1235
1238 max(Size, 1UL) * sizeof(*m_Lookup),
1240 if (m_Lookup == NULL)
1241 {
1242 DPRINT1("Processor lookup table allocation for %lu processors failed\n", Size);
1244 }
1245
1247
1248 /* Zero entries mean the primary; group 0 masks only */
1249 for (Target = 1; Target < m_Count; Target++)
1250 {
1251 Entry = &m_Table[Target];
1252 for (Number = 0; Number < RTL_BITS_OF(KAFFINITY); Number++)
1253 {
1254 if ((Entry->Affinity & ((KAFFINITY)1 << Number)) == 0)
1255 continue;
1256
1258 if (Index < m_LookupSize)
1260 }
1261 }
1262
1263 return STATUS_SUCCESS;
1264}
PUSHORT m_Lookup
Definition: intr.h:125
Interrupter * m_Table
Definition: intr.h:124
ULONG m_Count
Definition: intr.h:122
ULONG m_LookupSize
Definition: intr.h:126
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
#define NULL
Definition: types.h:112
#define NonPagedPool
Definition: env_spec_w32.h:307
static ULONG NTAPI XhciProcessorIndex(_In_ USHORT Group, _In_ ULONG Number)
Definition: intr.cpp:79
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
_In_ ULONG Number
Definition: haltypes.h:1940
#define ALL_PROCESSOR_GROUPS
Definition: ntbasedef.h:656
unsigned short USHORT
Definition: pedump.c:61
#define max(a, b)
Definition: svc.c:63
uint16_t * PUSHORT
Definition: typedefs.h:56
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
#define XHCI_TAG_INTERRUPTER
Definition: xhciutil.h:15

Referenced by Prepare().

◆ Count()

ULONG XhciInterrupters::Count ( ) const

Definition at line 1407 of file intr.cpp.

1408{
1409 return m_Count;
1410}

Referenced by SecondaryCountFor().

◆ Create()

NTSTATUS XhciInterrupters::Create ( _In_ XhciController *  Controller)

Definition at line 831 of file intr.cpp.

833{
835
836 PAGED_CODE();
837
842 m_Count = 0;
843 m_Capacity = 0;
844 m_Table = NULL;
845 m_Lookup = NULL;
846 m_LookupSize = 0;
847
849 (PFN_XHCI_ACTIVE_COUNT)XhciFindKernelRoutine(L"KeQueryActiveProcessorCountEx");
851 (PFN_XHCI_INDEX_FROM_NUMBER)XhciFindKernelRoutine(L"KeGetProcessorIndexFromNumber");
853 (PFN_XHCI_CURRENT_NUMBER)XhciFindKernelRoutine(L"KeGetCurrentProcessorNumberEx");
855 (PFN_XHCI_DPC_WATCHDOG)XhciFindKernelRoutine(L"KeQueryDpcWatchdogInformation");
856
857 /* The primary takes the first interrupt resource KMDF finds at start */
859 if (!NT_SUCCESS(Status))
860 DPRINT1("Primary interrupt creation failed 0x%lx\n", Status);
861
862 return Status;
863}
LONG NTSTATUS
Definition: precomp.h:26
XhciController * m_Controller
Definition: intr.h:118
Mechanism m_Mechanism
Definition: intr.h:120
WDFINTERRUPT m_PrimaryInterrupt
Definition: intr.h:119
ULONG m_Capacity
Definition: intr.h:123
NTSTATUS CreateInterrupt(_In_opt_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw, _In_opt_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated, _Out_ WDFINTERRUPT *Interrupt)
Definition: intr.cpp:866
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define L(x)
Definition: resources.c:13
Status
Definition: gdiplustypes.h:24
ULONG(NTAPI * PFN_XHCI_CURRENT_NUMBER)(_Out_opt_ PPROCESSOR_NUMBER Number)
Definition: intr.cpp:35
static PFN_XHCI_INDEX_FROM_NUMBER XhciIndexFromNumberRoutine
Definition: intr.cpp:39
static PFN_XHCI_ACTIVE_COUNT XhciActiveCountRoutine
Definition: intr.cpp:38
NTSTATUS(NTAPI * PFN_XHCI_DPC_WATCHDOG)(_Out_ PKDPC_WATCHDOG_INFORMATION Information)
Definition: intr.cpp:36
ULONG(NTAPI * PFN_XHCI_INDEX_FROM_NUMBER)(_In_ PPROCESSOR_NUMBER Number)
Definition: intr.cpp:34
static PFN_XHCI_DPC_WATCHDOG XhciDpcWatchdogRoutine
Definition: intr.cpp:41
static PFN_XHCI_CURRENT_NUMBER XhciCurrentNumberRoutine
Definition: intr.cpp:40
ULONG(NTAPI * PFN_XHCI_ACTIVE_COUNT)(_In_ USHORT GroupNumber)
Definition: intr.cpp:33
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ UCXCONTROLLER * Controller

Referenced by XhciController::Initialize().

◆ CreateInterrupt()

NTSTATUS XhciInterrupters::CreateInterrupt ( _In_opt_ PCM_PARTIAL_RESOURCE_DESCRIPTOR  Raw,
_In_opt_ PCM_PARTIAL_RESOURCE_DESCRIPTOR  Translated,
_Out_ WDFINTERRUPT *  Interrupt 
)
private

Definition at line 866 of file intr.cpp.

870{
874
876 Config.EvtInterruptEnable = XhciEvtInterruptEnable;
877 Config.EvtInterruptDisable = XhciEvtInterruptDisable;
878 Config.InterruptRaw = Raw;
879 Config.InterruptTranslated = Translated;
880
882
883 Status = WdfInterruptCreate(m_Controller->m_Device, &Config, &Attributes, Interrupt);
884 if (!NT_SUCCESS(Status))
885 {
886 DPRINT1("WdfInterruptCreate failed 0x%lx\n", Status);
887 *Interrupt = NULL;
888 }
889
890 return Status;
891}
WDFDEVICE m_Device
Definition: hc.h:85
_In_ ULONG Attributes
Definition: dispmprt.h:1077
static EVT_WDF_INTERRUPT_DPC XhciEvtInterruptDpc
Definition: intr.cpp:44
static EVT_WDF_INTERRUPT_DISABLE XhciEvtInterruptDisable
Definition: intr.cpp:46
static EVT_WDF_INTERRUPT_ISR XhciEvtInterruptIsr
Definition: intr.cpp:43
static EVT_WDF_INTERRUPT_ENABLE XhciEvtInterruptEnable
Definition: intr.cpp:45
@ Raw
Definition: sacdrv.h:279
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG Config
FORCEINLINE VOID WDF_INTERRUPT_CONFIG_INIT(_Out_ PWDF_INTERRUPT_CONFIG Configuration, _In_ PFN_WDF_INTERRUPT_ISR EvtInterruptIsr, _In_opt_ PFN_WDF_INTERRUPT_DPC EvtInterruptDpc)
Definition: wdfinterrupt.h:271
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_INTERRUPT_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFINTERRUPT * Interrupt
Definition: wdfinterrupt.h:379
#define WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(_attributes, _contexttype)
Definition: wdfobject.h:170

Referenced by Create(), and Prepare().

◆ D0Entry()

NTSTATUS XhciInterrupters::D0Entry ( _In_ BOOLEAN  StatePreserved)

Programs ERST, ERDP and IMAN for every interrupter before Run.

Definition at line 1326 of file intr.cpp.

1328{
1329 ULONG Index;
1330
1331 if (!m_Controller->IsAccessible())
1332 return STATUS_SUCCESS;
1333
1334 /* On a restore the ring contents and positions from before D0 exit stay valid */
1335 for (Index = 0; Index < m_Count; Index++)
1336 {
1337 if (!StatePreserved)
1339
1341 }
1342
1343 return STATUS_SUCCESS;
1344}
BOOLEAN IsAccessible() const
Definition: hc.cpp:193
static VOID NTAPI XhciResetEventRing(_Inout_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:181
static VOID NTAPI XhciProgramEventRing(_In_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:206

Referenced by XhciController::RunD0Pass().

◆ D0Exit()

VOID XhciInterrupters::D0Exit ( )

Definition at line 1380 of file intr.cpp.

1381{
1382 DPRINT("Interrupters stopped, %lu in use\n", m_Count);
1383}
#define DPRINT
Definition: sndvol32.h:73

Referenced by XhciController::D0Exit().

◆ D0ExitPreInterruptsDisabled()

VOID XhciInterrupters::D0ExitPreInterruptsDisabled ( )

Definition at line 1347 of file intr.cpp.

1348{
1349 Interrupter* Entry;
1351 KIRQL OldIrql;
1352 ULONG Index;
1353
1354 PAGED_CODE();
1355
1356 for (Index = 0; Index < m_Count; Index++)
1357 {
1358 Entry = &m_Table[Index];
1359 if (Entry->Requeue == NULL)
1360 continue;
1361
1363 Entry->PendingDisable = TRUE;
1365
1366 /* Freeing state under a running work item is worse than waiting */
1368 while (KeWaitForSingleObject(&Entry->RequeueIdle,
1369 Executive,
1370 KernelMode,
1371 FALSE,
1373 {
1374 DPRINT1("Interrupter %lu requeue work item still running after 60 s\n", Index);
1375 }
1376 }
1377}
#define STATUS_TIMEOUT
Definition: d3dkmdt.h:49
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define XHCI_DRAIN_WAIT_MS
Definition: intr.cpp:30
#define KernelMode
Definition: asm.h:38
static ULONG Timeout
Definition: ping.c:61
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ Executive
Definition: ketypes.h:467
FORCEINLINE LARGE_INTEGER NTAPI XhciRelativeMs(_In_ ULONG Milliseconds)
Definition: xhciutil.h:137

Referenced by XhciController::D0ExitPreInterruptsDisabled().

◆ FilterResourceRequirements()

NTSTATUS XhciInterrupters::FilterResourceRequirements ( _In_ WDFIORESREQLIST  Requirements)

Called from EvtDeviceFilterRemoveResourceRequirements.

Definition at line 921 of file intr.cpp.

923{
927
928 PAGED_CODE();
929
930 if (m_Controller->HasErrata(XhciErrata::IntLegacyLineOnly))
931 {
933 return XhciStripMessageRequirements(Requirements);
934 }
935
936 MsiX = XhciFindMessageList(Requirements, &ListIndex, &Messages);
938
939 DPRINT("Requirements list %lu offers %lu messages (MSI-X %u), %lu secondary interrupters\n",
941
942 if (WdfIoResourceRequirementsListGetCount(Requirements) != 0)
943 {
944 XhciTrimMessageRequirements(WdfIoResourceRequirementsListGetIoResList(Requirements, ListIndex),
945 1 + m_SecondaryCount);
946 }
947
948 return STATUS_SUCCESS;
949}
BOOLEAN HasErrata(_In_ XhciErrata Bit) const
Definition: hc.h:58
ULONG SecondaryCountFor(_In_ ULONG Messages) const
Definition: intr.cpp:894

◆ PostReset()

VOID XhciInterrupters::PostReset ( )

Definition at line 1386 of file intr.cpp.

1387{
1388 ULONG Index;
1389
1390 if (!m_Controller->IsAccessible())
1391 return;
1392
1393 for (Index = 0; Index < m_Count; Index++)
1394 {
1397 }
1398
1399 for (Index = 0; Index < m_Count; Index++)
1400 {
1401 if (m_Table[Index].Enabled)
1403 }
1404}
static VOID NTAPI XhciUnmaskInterrupter(_In_ PXHCI_INTERRUPTER Entry)
Definition: intr.cpp:217
@ Enabled
Definition: mountmgr.h:179

Referenced by XhciController::InternalReset().

◆ Prepare()

NTSTATUS XhciInterrupters::Prepare ( _In_ WDFCMRESLIST  Raw,
_In_ WDFCMRESLIST  Translated 
)

Definition at line 1104 of file intr.cpp.

1107{
1109 WDFINTERRUPT Interrupt;
1110 ULONG Assigned = 0;
1111 ULONG Index;
1112 ULONG Message;
1113 ULONG Limit;
1114 BOOLEAN FirstSkipped;
1116
1117 PAGED_CODE();
1118
1120 for (Index = 0; Index < WdfCmResourceListGetCount(Raw); Index++)
1121 {
1122 Descriptor = WdfCmResourceListGetDescriptor(Raw, Index);
1124 continue;
1125
1127 {
1128 m_Mechanism = (Assigned != 0) ? Mechanism::MsiX : Mechanism::Msi;
1129 Assigned += Descriptor->u.MessageInterrupt.Raw.MessageCount;
1130 }
1131 else
1132 {
1133 Assigned++;
1134 }
1135 }
1136
1137 if (Assigned == 0)
1138 {
1139 DPRINT1("No interrupt resources were assigned\n");
1141 }
1142
1143 m_Table = (Interrupter*)ExAllocatePoolZero(NonPagedPool,
1144 Assigned * sizeof(*m_Table),
1146 if (m_Table == NULL)
1147 {
1148 DPRINT1("Interrupter table allocation for %lu entries failed\n", Assigned);
1150 }
1151
1152 m_Capacity = Assigned;
1153
1155 if (!NT_SUCCESS(Status))
1156 {
1157 DPRINT1("Primary interrupter prepare failed 0x%lx\n", Status);
1158 return Status;
1159 }
1160
1161 m_Count = 1;
1162
1163 /* Register parsing may have asked for a single interrupter after filtering */
1164 if (m_Controller->HasErrata(XhciErrata::IntPrimaryOnly))
1165 m_SecondaryCount = 0;
1166
1167 /* The MSI-X table alone may allow more than MaxIntrs */
1169 if (Limit != 0 && m_SecondaryCount > Limit - 1)
1170 m_SecondaryCount = Limit - 1;
1171
1172 if (m_SecondaryCount != 0 && Assigned > 1 && m_Mechanism == Mechanism::MsiX)
1173 {
1174 FirstSkipped = FALSE;
1175 Message = 0;
1176
1177 for (Index = 0; Index < WdfCmResourceListGetCount(Translated); Index++)
1178 {
1179 Descriptor = WdfCmResourceListGetDescriptor(Translated, Index);
1180 if (Descriptor->Type != CmResourceTypeInterrupt ||
1182 {
1183 continue;
1184 }
1185
1186 /* The first message belongs to the primary */
1187 if (!FirstSkipped)
1188 {
1189 FirstSkipped = TRUE;
1190 continue;
1191 }
1192
1193 Message++;
1195 break;
1196
1197 Status = CreateInterrupt(WdfCmResourceListGetDescriptor(Raw, Index), Descriptor, &Interrupt);
1198 if (!NT_SUCCESS(Status))
1199 {
1200 DPRINT1("Secondary interrupter %lu creation failed 0x%lx\n", Message, Status);
1201 return Status;
1202 }
1203
1205 if (!NT_SUCCESS(Status))
1206 {
1207 DPRINT1("Secondary interrupter %lu prepare failed 0x%lx\n", Message, Status);
1208 return Status;
1209 }
1210
1211#if defined(NT_PROCESSOR_GROUPS)
1212 m_Table[Message].Group = Descriptor->u.MessageInterrupt.Translated.Group;
1213#endif
1214 m_Table[Message].Affinity = Descriptor->u.MessageInterrupt.Translated.Affinity;
1215
1216 /* Count only the interrupters actually set up */
1217 m_Count = Message + 1;
1218 }
1219 }
1220
1221 DPRINT("%lu interrupt messages assigned, mechanism %lu, %lu interrupters in use\n",
1222 Assigned, static_cast<ULONG>(m_Mechanism), m_Count);
1223
1224 return BuildLookup();
1225}
XhciRegisters m_Registers
Definition: hc.h:91
NTSTATUS PrepareOne(_Inout_ Interrupter *Entry, _In_ WDFINTERRUPT Interrupt, _In_ ULONG Index, _In_ BOOLEAN MessageSignaled)
Definition: intr.cpp:1009
NTSTATUS BuildLookup()
Definition: intr.cpp:1228
ULONG MaxInterrupters() const
Definition: mmio.cpp:549
PUCHAR Limit
Definition: desccheck.cpp:2230
static const WCHAR Message[]
Definition: register.c:74
static BOOLEAN NTAPI XhciIsMessageResource(_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor)
Definition: intr.cpp:642
#define CM_RESOURCE_INTERRUPT_MESSAGE
Definition: restypes.h:118
#define CmResourceTypeInterrupt
Definition: restypes.h:105

Referenced by XhciController::PrepareHardware().

◆ PrepareOne()

NTSTATUS XhciInterrupters::PrepareOne ( _Inout_ Interrupter *  Entry,
_In_ WDFINTERRUPT  Interrupt,
_In_ ULONG  Index,
_In_ BOOLEAN  MessageSignaled 
)
private

Definition at line 1009 of file intr.cpp.

1014{
1016 WDF_WORKITEM_CONFIG WorkConfig;
1021 ULONG Segments;
1023 ULONG Slot;
1025
1026 Entry->Controller = Controller;
1027 Entry->Interrupt = Interrupt;
1028 Entry->Index = Index;
1030 Entry->MessageSignaled = MessageSignaled;
1031 InitializeListHead(&Entry->SegmentList);
1034
1035 /* Segment count: software default capped by ERST Max, then by the errata */
1036 Segments = Controller->HasErrata(XhciErrata::EvtResetOnRingOverflow) ?
1038 Hardware = max(Controller->m_Registers.EventRingSegmentTableMax(), 1UL);
1039 Segments = min(Segments, Hardware);
1040 if (Segments > XHCI_SEGMENTS_LIMITED && Controller->HasErrata(XhciErrata::EvtTwoSegmentRingCap))
1041 Segments = XHCI_SEGMENTS_LIMITED;
1042
1043 Entry->SegmentCount = Segments;
1044 Entry->SegmentSize = PAGE_SIZE;
1045 Entry->TrbsPerSegment = PAGE_SIZE / sizeof(XHCI_TRB);
1046
1047 Entry->Erst = Controller->m_Buffers.Acquire(Segments * sizeof(XHCI_ERST_ENTRY));
1048 if (Entry->Erst == NULL)
1049 {
1050 DPRINT1("Interrupter %lu: no buffer for the segment table\n", Index);
1052 }
1053
1054 Status = Controller->m_Buffers.AcquireList(Entry->SegmentSize, Segments, &Entry->SegmentList);
1055 if (!NT_SUCCESS(Status))
1056 {
1057 DPRINT1("Interrupter %lu: no buffers for %lu event ring segments 0x%lx\n",
1058 Index, Segments, Status);
1059 goto Fail;
1060 }
1061
1063
1064 /* The table is written once here and survives power transitions */
1065 Table = (PXHCI_ERST_ENTRY)Entry->Erst->VirtualAddress;
1066 Slot = 0;
1067 for (Link = Entry->SegmentList.Flink; Link != &Entry->SegmentList; Link = Link->Flink)
1068 {
1070 Table[Slot].SegmentAddress = (ULONG64)Buffer->LogicalAddress.QuadPart;
1071 Table[Slot].SegmentSize = Entry->TrbsPerSegment;
1072 Table[Slot].Reserved = 0;
1073 Slot++;
1074 }
1075
1077 WorkConfig.AutomaticSerialization = FALSE;
1079 Attributes.ParentObject = Interrupt;
1080
1081 Status = WdfWorkItemCreate(&WorkConfig, &Attributes, &Entry->Requeue);
1082 if (!NT_SUCCESS(Status))
1083 {
1084 DPRINT1("Interrupter %lu: requeue work item creation failed 0x%lx\n", Index, Status);
1085 Entry->Requeue = NULL;
1086 goto Fail;
1087 }
1088
1089 Entry->Segment = CONTAINING_RECORD(Entry->SegmentList.Flink, XhciDmaBuffer, Link);
1090 Entry->CycleState = XHCI_TRB_CYCLE;
1091 Entry->Prepared = TRUE;
1092 XhciInterruptContext(Interrupt)->Entry = Entry;
1093 return STATUS_SUCCESS;
1094
1095Fail:
1096 if (!IsListEmpty(&Entry->SegmentList))
1097 Controller->m_Buffers.FreeList(&Entry->SegmentList);
1098 Controller->m_Buffers.Free(Entry->Erst);
1099 Entry->Erst = NULL;
1100 return Status;
1101}
Definition: bufpool.h:45
_Inout_ HubConfiguration ** Slot
Definition: devhcd.cpp:1260
int Fail
Definition: ehthrow.cxx:24
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
ASMGENDATA Table[]
Definition: genincdata.c:61
#define XHCI_SEGMENTS_DEFAULT
Definition: intr.cpp:24
#define XHCI_SEGMENTS_RING_FULL
Definition: intr.cpp:25
static VOID NTAPI XhciWriteInterrupter(_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset, _In_ ULONG Value)
Definition: intr.cpp:138
static EVT_WDF_WORKITEM XhciEvtRequeueWorkItem
Definition: intr.cpp:47
#define XHCI_SEGMENTS_LIMITED
Definition: intr.cpp:26
unsigned __int64 ULONG64
Definition: imports.h:198
#define min(a, b)
Definition: monoChain.cc:55
@ NotificationEvent
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
BOOLEAN AutomaticSerialization
Definition: wdfworkitem.h:79
Definition: xhcihw.h:165
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
for(Attempt=0;Attempt< UCX_LEGACY_NAME_ATTEMPTS;Attempt++)
Definition: userreq.cpp:715
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
FORCEINLINE VOID WDF_WORKITEM_CONFIG_INIT(_Out_ PWDF_WORKITEM_CONFIG Config, _In_ PFN_WDF_WORKITEM EvtWorkItemFunc)
Definition: wdfworkitem.h:85
#define XHCI_ERSTSZ
Definition: xhcihw.h:155
struct _XHCI_ERST_ENTRY * PXHCI_ERST_ENTRY
#define XHCI_INTERRUPTER_STRIDE
Definition: xhcihw.h:152
#define XHCI_RUNTIME_INTERRUPTER_BASE
Definition: xhcihw.h:151
#define XHCI_TRB_CYCLE
Definition: xhcihw.h:22
struct _XHCI_TRB XHCI_TRB

Referenced by Prepare().

◆ Release()

VOID XhciInterrupters::Release ( )

Definition at line 1296 of file intr.cpp.

1297{
1298 ULONG Index;
1299
1300 PAGED_CODE();
1301
1302 if (m_Table != NULL)
1303 {
1304 for (Index = 0; Index < m_Capacity; Index++)
1305 {
1306 if (m_Table[Index].Prepared)
1308 }
1309
1311 m_Table = NULL;
1312 }
1313
1314 if (m_Lookup != NULL)
1315 {
1317 m_Lookup = NULL;
1318 }
1319
1320 m_Count = 0;
1321 m_Capacity = 0;
1322 m_LookupSize = 0;
1323}
VOID ReleaseOne(_Inout_ Interrupter *Entry)
Definition: intr.cpp:1267
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109

Referenced by XhciController::ReleaseHardware().

◆ ReleaseOne()

VOID XhciInterrupters::ReleaseOne ( _Inout_ Interrupter *  Entry)
private

Definition at line 1267 of file intr.cpp.

1269{
1271
1272 if (Controller->IsAccessible())
1273 {
1277 }
1278
1279 Controller->m_Buffers.FreeList(&Entry->SegmentList);
1280 Controller->m_Buffers.Free(Entry->Erst);
1281 Entry->Erst = NULL;
1282 Entry->Segment = NULL;
1283
1284 if (Entry->Requeue != NULL)
1285 {
1286 WdfWorkItemFlush(Entry->Requeue);
1287 WdfObjectDelete(Entry->Requeue);
1288 Entry->Requeue = NULL;
1289 }
1290
1291 XhciInterruptContext(Entry->Interrupt)->Entry = NULL;
1292 Entry->Prepared = FALSE;
1293}
static VOID NTAPI XhciWriteInterrupter64(_In_ PXHCI_INTERRUPTER Entry, _In_ ULONG Offset, _In_ ULONG64 Value)
Definition: intr.cpp:149
WdfObjectDelete(String)
#define XHCI_ERSTBA
Definition: xhcihw.h:156
#define XHCI_ERDP
Definition: xhcihw.h:157

Referenced by Release().

◆ SecondaryCountFor()

ULONG XhciInterrupters::SecondaryCountFor ( _In_ ULONG  Messages) const
private

Definition at line 894 of file intr.cpp.

896{
897 ULONG Limit;
898 ULONG Processors;
899 ULONG Count;
900
901 if (m_Controller->HasErrata(XhciErrata::IntPrimaryOnly) || Messages <= 1)
902 return 0;
903
904 /* One message always goes to the primary */
906
907 /* A single processor still gets its own secondary */
908 Processors = XhciActiveProcessors(0);
909 if (Processors <= Limit)
910 return Processors;
911
912 /* Halve until the processors split evenly over what is available */
913 Count = Processors / 2;
914 while (Count > Limit)
915 Count /= 2;
916
917 return Count;
918}
ULONG Count() const
Definition: intr.cpp:1407
#define XHCI_SECONDARY_MAX
Definition: intr.cpp:23

Referenced by FilterResourceRequirements().

◆ TargetForCurrentProcessor()

ULONG XhciInterrupters::TargetForCurrentProcessor ( ) const

Interrupter target for work issued on the current processor.

Definition at line 1413 of file intr.cpp.

1414{
1416}
ULONG TargetForProcessor(_In_ ULONG ProcessorIndex) const
Definition: intr.cpp:1419
static ULONG NTAPI XhciCurrentProcessorIndex(VOID)
Definition: intr.cpp:108

Referenced by XhciTransferRing::UpdateInterrupterTarget().

◆ TargetForProcessor()

ULONG XhciInterrupters::TargetForProcessor ( _In_ ULONG  ProcessorIndex) const

Interrupter target for work issued on the processor with this system wide index.

Definition at line 1419 of file intr.cpp.

1421{
1422 /* Processors added after start are not in the table and use the primary */
1423 if (m_Lookup == NULL || ProcessorIndex >= m_LookupSize)
1424 return 0;
1425
1426 return m_Lookup[ProcessorIndex];
1427}

Referenced by TargetForCurrentProcessor(), and XhciTransferRing::UpdateInterrupterTarget().

Member Data Documentation

◆ m_Capacity

ULONG XhciInterrupters::m_Capacity
private

Definition at line 123 of file intr.h.

Referenced by Create(), Prepare(), and Release().

◆ m_Controller

XhciController* XhciInterrupters::m_Controller
private

◆ m_Count

ULONG XhciInterrupters::m_Count
private

Interrupters actually prepared

Definition at line 122 of file intr.h.

Referenced by BuildLookup(), Count(), Create(), D0Entry(), D0Exit(), D0ExitPreInterruptsDisabled(), PostReset(), Prepare(), and Release().

◆ m_Lookup

PUSHORT XhciInterrupters::m_Lookup
private

Definition at line 125 of file intr.h.

Referenced by BuildLookup(), Create(), Release(), and TargetForProcessor().

◆ m_LookupSize

ULONG XhciInterrupters::m_LookupSize
private

Definition at line 126 of file intr.h.

Referenced by BuildLookup(), Create(), Release(), and TargetForProcessor().

◆ m_Mechanism

Mechanism XhciInterrupters::m_Mechanism
private

Definition at line 120 of file intr.h.

Referenced by Create(), and Prepare().

◆ m_PrimaryInterrupt

WDFINTERRUPT XhciInterrupters::m_PrimaryInterrupt
private

Definition at line 119 of file intr.h.

Referenced by Create(), and Prepare().

◆ m_SecondaryCount

ULONG XhciInterrupters::m_SecondaryCount
private

◆ m_Table

Interrupter* XhciInterrupters::m_Table
private

The documentation for this class was generated from the following files: