ReactOS 0.4.17-dev-1281-g065abb3
slots.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS xHCI Host Controller Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Device context base address array, scratchpad and slot map
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8#include "xhcidrv.h"
9
10#define NDEBUG
11#include <debug.h>
12
13/* The register module only accepts controllers with a 4 KB page, so scratchpads are 4 KB */
14#define XHCI_SCRATCHPAD_BYTES 4096
15
19{
21
22 /* Release walks this list even when Prepare never ran */
24 return STATUS_SUCCESS;
25}
26
30{
32 volatile ULONG64* Entries;
33 PULONG64 Array;
35 SIZE_T MapBytes;
38
40
41 m_Dcbaa = Pool->Acquire(XHCI_DCBAA_ENTRIES * sizeof(ULONG64));
42 if (m_Dcbaa == NULL)
43 {
44 DPRINT1("No common buffer for the DCBAA\n");
46 goto Fail;
47 }
48
50
52 if (m_ScratchpadCount != 0)
53 {
54 /* QUIRK: above 512 scratchpads the array no longer fits a pool page and this fails */
55 m_ScratchpadArray = Pool->Acquire(m_ScratchpadCount * sizeof(ULONG64));
57 {
58 DPRINT1("No common buffer for the array of %lu scratchpads\n", m_ScratchpadCount);
60 goto Fail;
61 }
62
64 if (!NT_SUCCESS(Status))
65 {
66 DPRINT1("Acquiring %lu scratchpad pages failed 0x%lx\n", m_ScratchpadCount, Status);
67 goto Fail;
68 }
69
71 Index = 0;
73 {
75
76 Array[Index++] = Page->LogicalAddress.QuadPart;
77 }
78
80 }
81
83
84 /* Index 0 is never a slot id; keeping it makes the slot id the index */
85 MapBytes = (m_SlotCount + 1) * sizeof(*m_SlotMap);
87 if (m_SlotMap == NULL)
88 {
89 DPRINT1("No pool for the map of %lu slots\n", m_SlotCount);
91 goto Fail;
92 }
93
94 DPRINT("Slot table: %lu slots, %lu scratchpads, DCBAA at 0x%I64x\n",
96 return STATUS_SUCCESS;
97
98Fail:
99 FreeTables();
100 return Status;
101}
102
103VOID
105{
107
109 Pool->FreeList(&m_ScratchpadPages);
110
111 if (m_ScratchpadArray != NULL)
112 {
113 Pool->Free(m_ScratchpadArray);
115 }
116
117 if (m_Dcbaa != NULL)
118 {
119 Pool->Free(m_Dcbaa);
120 m_Dcbaa = NULL;
121 }
122
123 if (m_SlotMap != NULL)
124 {
126 m_SlotMap = NULL;
127 }
128
129 m_SlotCount = 0;
131}
132
134VOID
136{
137 if (m_Dcbaa != NULL)
138 {
139 /* QUIRK: written even when the controller is no longer accessible */
142 }
143
144 FreeTables();
145}
146
147VOID
149{
151 return;
152
153 /* CIE stays 0: configuration information is not used */
158}
159
160VOID
162{
163 Program();
164}
165
166VOID
168{
170
172 return;
173
175 {
177
178 RtlZeroMemory(Page->VirtualAddress, Page->Size);
179 }
180}
181
182VOID
184{
186 DisableAll();
187}
188
189static
191NTAPI
194{
195 return static_cast<XhciUsbDevice*>(Entry);
196}
197
198VOID
200{
201 ULONG SlotId;
202
203 for (SlotId = 1; IsValidSlot(SlotId); SlotId++)
204 {
205 if (m_SlotMap[SlotId] == NULL)
206 continue;
207
208 DPRINT("Slot %lu lost its device %p\n", SlotId, m_SlotMap[SlotId]);
209
210 /* This clears the map entry */
211 XhciSlotDevice(m_SlotMap[SlotId])->SetDisabled();
212 }
213}
214
215VOID
216XhciSlotTable::PreReset()
217{
218 ULONG SlotId;
219
220 DPRINT("Controller reset starting, %lu slots\n", m_SlotCount);
221
222 for (SlotId = 1; IsValidSlot(SlotId); SlotId++)
223 {
224 if (m_SlotMap[SlotId] != NULL)
226 }
227}
228
230VOID
231XhciSlotTable::PostReset()
232{
233 ULONG SlotId;
234
235 for (SlotId = 1; IsValidSlot(SlotId); SlotId++)
236 {
237 if (m_SlotMap[SlotId] != NULL)
238 XhciSlotDevice(m_SlotMap[SlotId])->ControllerResetDone();
239 }
240
241 DisableAll();
243 Program();
244}
245
246VOID
248{
249 ULONG SlotId;
250
251 DPRINT("Controller gone, %lu slots\n", m_SlotCount);
252
253 for (SlotId = 1; IsValidSlot(SlotId); SlotId++)
254 {
255 if (m_SlotMap[SlotId] != NULL)
257 }
258}
259
262XhciSlotTable::SetSlot(
263 _In_ ULONG SlotId,
265 _In_ ULONG64 OutputContextAddress)
266{
267 volatile ULONG64* Entries;
268
269 if (!IsValidSlot(SlotId) || m_Dcbaa == NULL)
270 {
271 DPRINT1("Slot id %lu is outside the slot table\n", SlotId);
273 }
274
276
277 /* Software clears the entry once the slot is disabled (xHCI 4.6.4) */
279 {
280 ASSERT(Device == NULL || m_SlotMap[SlotId] == Device);
281 m_SlotMap[SlotId] = NULL;
282 Entries[SlotId] = 0;
283 return STATUS_SUCCESS;
284 }
285
286 /* QUIRK: nothing is recorded while the controller is inaccessible */
288 return STATUS_SUCCESS;
289
290 if (Entries[SlotId] != 0)
291 {
292 DPRINT1("DCBAA entry of slot %lu is already 0x%I64x\n", SlotId, (ULONG64)Entries[SlotId]);
294 }
295
296 m_SlotMap[SlotId] = Device;
298 return STATUS_SUCCESS;
299}
300
302PVOID
303XhciSlotTable::LookupSlot(
304 _In_ ULONG SlotId) const
305{
306 if (!IsValidSlot(SlotId))
307 return NULL;
308
309 return m_SlotMap[SlotId];
310}
311
312VOID
314 _In_ const XHCI_TRB* Event)
315{
316 PVOID Device = LookupSlot(XhciTrbSlotId(Event));
317
318 if (Device != NULL)
319 {
321 return;
322 }
323
324 /* An isochronous endpoint may be torn down with events still on the way */
326 {
327 DPRINT1("Transfer event for slot %lu endpoint %lu code %lu has no device, dropped\n",
330 }
331}
332
333VOID
335 _In_ const XHCI_TRB* Event)
336{
337 PVOID Device = LookupSlot(XhciTrbSlotId(Event));
338
339 if (Device == NULL)
340 {
341 DPRINT("Device notification for empty slot %lu dropped\n", XhciTrbSlotId(Event));
342 return;
343 }
344
346}
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
Definition: bufpool.h:50
XhciCommonBuffer m_Buffers
Definition: hc.h:92
BOOLEAN IsAccessible() const
Definition: hc.cpp:193
XhciRegisters m_Registers
Definition: hc.h:91
ULONG MaxSlots() const
Definition: mmio.cpp:543
ULONG ScratchpadCount() const
Definition: mmio.cpp:573
VOID WriteOperational64(_In_ ULONG Offset, _In_ ULONG64 Value)
Definition: mmio.cpp:460
VOID WriteOperational32(_In_ ULONG Offset, _In_ ULONG Value)
Definition: mmio.cpp:441
XhciDmaBuffer * m_Dcbaa
Definition: slots.h:72
VOID D0Entry()
Definition: slots.cpp:161
VOID FreeTables()
Definition: slots.cpp:104
XhciController * m_Controller
Definition: slots.h:69
VOID OnDeviceNotificationEvent(_In_ const XHCI_TRB *Event)
Definition: slots.cpp:334
_In_ PVOID Device
Definition: slots.h:38
NTSTATUS Create(_In_ XhciController *Controller)
Definition: slots.cpp:17
BOOLEAN IsValidSlot(_In_ ULONG SlotId) const
Definition: slots.h:63
ULONG m_SlotCount
Definition: slots.h:70
PVOID * m_SlotMap
Definition: slots.h:75
_In_ PVOID _In_ ULONG64 OutputContextAddress
Definition: slots.h:39
XhciDmaBuffer * m_ScratchpadArray
Definition: slots.h:73
LIST_ENTRY m_ScratchpadPages
Definition: slots.h:74
VOID OnHostLost()
Definition: slots.cpp:247
VOID OnTransferEvent(_In_ const XHCI_TRB *Event)
VOID ZeroScratchpads()
Definition: slots.cpp:167
ULONG m_ScratchpadCount
Definition: slots.h:71
VOID DiscardState()
Definition: slots.cpp:183
VOID DisableAll()
Definition: slots.cpp:199
VOID Program()
Definition: slots.cpp:148
NTSTATUS Prepare()
VOID OnTransferEvent(_In_ const XHCI_TRB *Event)
Definition: slotdev.cpp:1707
VOID ControllerResetStarting()
Definition: slotdev.cpp:1746
VOID OnHostLost()
Definition: slotdev.cpp:1773
VOID OnDeviceNotificationEvent(_In_ const XHCI_TRB *Event)
Definition: slotdev.cpp:1728
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
Definition: dispmprt.h:1287
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define _IRQL_requires_(irql)
Definition: driverspecs.h:229
int Fail
Definition: ehthrow.cxx:24
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
Status
Definition: gdiplustypes.h:24
_Must_inspect_result_ _In_ PUCXHUB_DEVICE_CREATE_INFO _Out_ UCXUSBDEVICE * Device
Definition: hubucx.h:258
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
unsigned __int64 ULONG64
Definition: imports.h:198
unsigned __int64 * PULONG64
Definition: imports.h:198
static const ENTRY Entries[]
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define _In_
Definition: no_sal2.h:158
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1287
#define STATUS_SUCCESS
Definition: shellext.h:65
static XhciUsbDevice *NTAPI XhciSlotDevice(_In_ PVOID Entry)
Definition: slots.cpp:192
#define XHCI_SCRATCHPAD_BYTES
Definition: slots.cpp:14
#define DPRINT
Definition: sndvol32.h:73
PHYSICAL_ADDRESS LogicalAddress
Definition: dmapool.h:17
PVOID VirtualAddress
Definition: dmapool.h:16
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ PUCX_CONTROLLER_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ UCXCONTROLLER * Controller
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
#define USB_ENDPOINT_TYPE_ISOCHRONOUS
Definition: usb100.h:63
for(Attempt=0;Attempt< UCX_LEGACY_NAME_ATTEMPTS;Attempt++)
Definition: userreq.cpp:715
_In_ WDFCOLLECTION _In_ ULONG Index
#define XHCI_OP_CONFIG
Definition: xhcihw.h:190
#define XHCI_TRB_ENDPOINT_MASK
Definition: xhcihw.h:27
#define XHCI_TRB_ENDPOINT_SHIFT
Definition: xhcihw.h:26
#define XHCI_DCBAA_ENTRIES
Definition: xhcihw.h:194
#define XHCI_EVENT_DATA_TYPE_MASK
Definition: xhcihw.h:324
#define XHCI_OP_DCBAAP
Definition: xhcihw.h:189
#define XHCI_CONFIG_MAX_SLOTS_MASK
Definition: xhcihw.h:191
FORCEINLINE ULONG NTAPI XhciTrbCompletionCode(_In_ const XHCI_TRB *Trb)
Definition: xhcihw.h:42
FORCEINLINE ULONG NTAPI XhciTrbSlotId(_In_ const XHCI_TRB *Trb)
Definition: xhcihw.h:51
#define XHCI_TAG_SLOT
Definition: xhciutil.h:17