VirtualBox

source: vbox/trunk/src/VBox/Devices/USB/DevXHCI.cpp@ 104125

Last change on this file since 104125 was 104125, checked in by vboxsync, 3 months ago

VUSB: Added vusbRhAbortEpByAddr(), renamed vusbRhAbortEp() to vusbRhAbortEpByPort() for clarity. New function will be useful for OHCI/EHCI HCs which do not keep track of devices by port but rather by address.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 323.7 KB
Line 
1/* $Id: DevXHCI.cpp 104125 2024-03-30 11:18:05Z vboxsync $ */
2/** @file
3 * DevXHCI - eXtensible Host Controller Interface for USB.
4 */
5
6/*
7 * Copyright (C) 2012-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/** @page pg_dev_xhci xHCI - eXtensible Host Controller Interface Emulation.
29 *
30 * This component implements an xHCI USB controller.
31 *
32 * The xHCI device is significantly different from the EHCI and OHCI
33 * controllers in that it is not timer driven. A worker thread is responsible
34 * for transferring data between xHCI and VUSB.
35 *
36 * Since there can be dozens or even hundreds of USB devices, and because USB
37 * transfers must share the same bus, only one worker thread is created (per
38 * host controller).
39 *
40 *
41 * The xHCI operational model is heavily based around a producer/consumer
42 * model utilizing rings -- Command, Event, and Transfer rings. The Event ring
43 * is only written by the xHC and is read-only for the HCD (Host Controller
44 * Driver). The Command/Transfer rings are only written by the HCD and are
45 * read-only for the xHC.
46 *
47 * The rings contain TRBs (Transfer Request Blocks). The TRBs represent not
48 * only data transfers but also commands and status information. Each type of
49 * ring only produces/consumes specific TRB types.
50 *
51 * When processing a ring, the xHC simply keeps advancing an internal pointer.
52 * For the Command/Transfer rings, the HCD uses Link TRBs to manage the ring
53 * storage in a fairly arbitrary manner. Since the HCD cannot write to the
54 * Event ring, the Event Ring Segment Table (ERST) is used to manage the ring
55 * storage instead.
56 *
57 * The Cycle bit is used to manage the ring buffer full/empty condition. The
58 * Producer and Consumer both have their own Cycle State (PCS/CCS). The Cycle
59 * bit of each TRB determines who owns it. The consumer only processes TRBs
60 * whose Cycle bit matches the CCS. HCD software typically toggles the Cycle
61 * bit on each pass through the ring. The Link TRB can be used to toggle the
62 * CCS accordingly.
63 *
64 * Multiple Transfer TRBs can be chained together (via the Chain bit) into a
65 * single Transfer Descriptor (TD). This provides a convenient capability for
66 * the HCD to turn a URB into a single TD regardless of how the URB is laid
67 * out in physical memory. If a transfer encounters an error or is terminated
68 * by a short packet, the entire TD (i.e. chain of TRBs) is retired.
69 *
70 * Note that the xHC detects and handles short packets on its own. Backends
71 * are always asked not to consider a short packet to be an error condition.
72 *
73 * Command and Event TRBs cannot be chained, thus an ED (Event Descriptor)
74 * or a Command Descriptor (CD) always consists of a single TRB.
75 *
76 * There is one Command ring per xHC, one Event ring per interrupter (one or
77 * more), and a potentially very large number of Transfer rings. There is a
78 * 1:1 mapping between Transfer Rings and USB pipes, hence each USB device
79 * uses 1-31 Transfer rings (at least one for the default control endpoint,
80 * up to 31 if all IN/OUT endpoints are used). USB 3.0 devices may also use
81 * up to 64K streams per endpoint, each with its Transfer ring, massively
82 * increasing the potential number of Transfer rings in use.
83 *
84 * When building a Transfer ring, it's possible to queue up a large number
85 * of TDs and as soon as the oldest ones are retired, queue up new TDs. The
86 * Transfer ring might thus never be empty.
87 *
88 * For tracking ring buffer position, the TRDP and TREP fields in an endpoint
89 * context are used. The TRDP is the 'TR Dequeue Pointer', i.e. the position
90 * of the next TRB to be completed. This field is visible by the HCD when the
91 * endpoint isn't running. It reflects TRBs completely processed by the xHC
92 * and hence no longer owned by the xHC.
93 *
94 * The TREP field is the 'TR Enqueue Pointer' and tracks the position of the
95 * next TRB to start processing (submit). This is purely internal to the
96 * xHC. The TREP can potentially get far ahead of the TRDP, but only in the
97 * part of the ring owned by the xHC (i.e. with matching DCS bit).
98 *
99 * Unlike most other xHCI data structures, transfer TRBs may describe memory
100 * buffers with no alignment restrictions (both starting position and size).
101 * In addition, there is no relationship between TRB boundaries and USB
102 * packet boundaries.
103 *
104 *
105 * Typically an event would be generated via the IOC bit (Interrupt On
106 * Completion) when the last TRB of a TD is completed. However, multiple IOC
107 * bits may be set per TD. This may be required when a TD equal or larger
108 * than 16MB is used, since transfer events utilize a 24-bit length field.
109 *
110 * There is also the option of using Transfer Event TRBs to report TRB
111 * completion. Transfer Event TRBs may be freely intermixed with transfer
112 * TRBs. Note that an event TRB will produce an event reporting the size of
113 * data transferred since the last event TRB or since the beginning of a TD.
114 * The xHC submits URBs such that they either comprise the entire TD or end
115 * at a Transfer Event TRB, thus there is no need to track the EDTLA
116 * separately.
117 *
118 * Transfer errors always generate events, irrespective of IOC settings. The
119 * xHC has always the option to generate events at implementation-specific
120 * points so that the HCD does not fall too far behind.
121 *
122 * Control transfers use special TDs. A Setup Stage TD consists of only a
123 * single Setup Stage TRB (there's no Chain bit). The optional Data Stage
124 * TD consists of a Data Stage TRB chained to zero or more Normal TRBs
125 * and/or Event Data TRBs. The Status Stage TD then consists of a Status
126 * Stage TRB optionally chained to an Event Data TRB. The HCD is responsible
127 * for building the TDs correctly.
128 *
129 * For isochronous transfers, only the first TRB of a TD is actually an
130 * isochronous TRB. If the TD is chained, it will contain Normal TRBs (and
131 * possibly Event Data TRBs).
132 *
133 *
134 * Isochronous transfers require multiple TDs/URBs to be in flight at a
135 * time. This complicates dealing with non-data TRBs (such as link or event
136 * data TRBs). These TRBs cannot be completed while a previous TRB is still
137 * in flight. They are completed either: a) when submitting URBs and there
138 * are no in-flight URBs, or b) just prior to completing an URB.
139 *
140 * This approach works because URBs must be completed strictly in-order. The
141 * TRDP and TREP determine whether there are in-flight TRBs (TREP equals
142 * TRDP if and only if there are no in-flight TRBs).
143 *
144 * When submitting TRBs and there is in-flight traffic, non-data TRBs must
145 * be examined and skipped over. Link TRBs need to be taken into account.
146 *
147 * Unfortunately, certain HCDs (looking at you, Microsoft!) violate the xHCI
148 * specification and make assumptions about how far ahead of the TRDP the
149 * xHC can get. We have to artificially limit the number of in-flight TDs
150 * for this reason.
151 *
152 * Non-isochronous TRBs do not require this treatment for correct function
153 * but are likely to benefit performance-wise from the pipelining.
154 *
155 * With high-speed and faster transfers, there is an added complication for
156 * endpoints with more than one transfer per frame, i.e. short intervals. At
157 * least some host USB stacks require URBs to cover an entire frame, which
158 * means we may have to glue together several TDs into a single URB.
159 *
160 *
161 * A buggy or malicious guest can create a transfer or command ring that
162 * loops in on itself (in the simplest case using a sequence of one or more
163 * link TRBs where the last TRB points to the beginning of the sequence).
164 * Such a loop would effectively hang the processing thread. Since we cannot
165 * easily detect a generic loop, and because even non-looped TRB/command
166 * rings might contain extremely large number of items, we limit the number
167 * of entries that we are willing to process at once. If the limit is
168 * crossed, the xHC reports a host controller error and shuts itself down
169 * until it's reset.
170 *
171 * Note that for TRB lists, both URB submission and completion must protect
172 * against loops because the lists in guest memory are not guaranteed to stay
173 * unchanged between submitting and completing URBs.
174 *
175 * The event ring is not susceptible to loops because the xHC is the producer,
176 * not consumer. The event ring can run out of space but that is not a fatal
177 * problem.
178 *
179 *
180 * The interrupt logic uses an internal IPE (Interrupt Pending Enable) bit
181 * which controls whether the register-visible IP (Interrupt Pending) bit
182 * can be set. The IPE bit is set when a non-blocking event (BEI bit clear)
183 * is enqueued. The IPE bit is cleared when the event ring is initialized or
184 * transitions to empty (i.e. ERDP == EREP). When IPE transtitions to set,
185 * it will set IP unless the EHB (Event Handler Busy) bit is set or IMODC
186 * (Interrupt Moderation Counter) is non-zero. When IMODC counts down to
187 * zero, it sets the IP bit if IPE is set and EHB is not. Setting the IP bit
188 * triggers interrupt delivery. Note that clearing the IPE bit does not
189 * change the IP bit state.
190 *
191 * Interrupt delivery depends on whether MSI/MSI-X is in use or not. With MSI,
192 * an interrupter's IP (Interrupt Pending) bit is cleared as soon as the MSI
193 * message is written; with classic PCI interrupt delivery, the HCD must clear
194 * the IP bit. However, the EHB (Event Handler Busy) bit is always set, which
195 * causes further interrupts to be blocked on the interrupter until the HCD
196 * processes pending events and clears the EHB bit.
197 *
198 * Note that clearing the EHB bit may immediately trigger an interrupt if
199 * additional event TRBs were queued up while the HCD was processing previous
200 * ones.
201 *
202 *
203 * Each enabled USB device has a corresponding slot ID, a doorbell, as well as
204 * a device context which can be accessed through the DCBAA (Device Context
205 * Base Address Array). Valid slot IDs are in the 1-255 range; the first entry
206 * (i.e. index 0) in the DCBAA may optionally point to the Scratchpad Buffer
207 * Array, while doorbell 0 is associated with the Command Ring.
208 *
209 * While 255 valid slot IDs is an xHCI architectural limit, existing xHC
210 * implementations usually set a considerably lower limit, such as 32. See
211 * the XHCI_NDS constant.
212 *
213 * It would be tempting to use the DCBAA to determine which slots are free.
214 * Unfortunately the xHC is not allowed to access DCBAA entries which map to
215 * disabled slots (see section 6.1). A parallel aSlotState array is hence used
216 * to internally track the slot state and find available slots. Once a slot
217 * is enabled, the slot context entry in the DCBAA is used to track the
218 * slot state.
219 *
220 *
221 * Unlike OHCI/UHCI/EHCI, the xHC much more closely tracks USB device state.
222 * HCDs are not allowed to issue SET_ADDRESS requests at all and must use
223 * the Address Device xHCI command instead.
224 *
225 * HCDs can use SET_CONFIGURATION and SET_INTERFACE requests normally, but
226 * must inform the xHC of the changes via Configure Endpoint and Evaluate
227 * Context commands. Similarly there are Reset Endpoint and Stop Endpoint
228 * commands to manage endpoint state.
229 *
230 * A corollary of the above is that unlike OHCI/UHCI/EHCI, with xHCI there
231 * are very clear rules and a straightforward protocol for managing
232 * ownership of structures in physical memory. During normal operation, the
233 * xHC owns all device context memory and the HCD must explicitly ask the xHC
234 * to relinquish the ownership.
235 *
236 * The xHCI architecture offers an interesting feature in that it reserves
237 * opaque fields for xHCI use in certain data structures (slot and endpoint
238 * contexts) and gives the xHC an option to request scratchpad buffers that
239 * a HCD must provide. The xHC may use the opaque storage and/or scratchpad
240 * buffers for saving internal state.
241 *
242 * For implementation reasons, the xHCI device creates two root hubs on the
243 * VUSB level; one for USB2 devices (USB 1.x and 2.0), one for USB3. The
244 * behavior of USB2 vs. USB3 ports is different, and a device can only be
245 * attached to either one or the other hub. However, there is a single array
246 * of ports to avoid overly complicating the code, given that port numbering
247 * is linear and encompasses both USB2 and USB3 ports.
248 *
249 *
250 * The default emulated device is an Intel 7-Series xHC aka Panther Point.
251 * This was Intel's first xHC and is widely supported. It is also possible
252 * to select an Intel 8-Series xHC aka Lynx Point; this is only useful for
253 * debugging and requires the 'other' set of Windows 7 drivers.
254 *
255 * For Windows XP guest support, it is possible to emulate a Renesas
256 * (formerly NEC) uPD720201 xHC. It would be possible to emulate the earlier
257 * NEC chips but those a) only support xHCI 0.96, and b) their drivers
258 * require a reboot during installation. Renesas' drivers also support
259 * Windows Vista and 7.
260 *
261 *
262 * NB: Endpoints are addressed differently in xHCI and USB. In USB,
263 * endpoint addresses are 8-bit values with the low four bits identifying
264 * the endpoint number and the high bit indicating the direction (0=OUT,
265 * 1=IN); see e.g. 9.3.4 in USB 2.0 spec. In xHCI, endpoint addresses are
266 * used as DCIs (Device Context Index) and for that reason, they're
267 * compressed into 5 bits where the lowest bit(!) indicates direction (again
268 * 1=IN) and bits 1-4 designate the endpoint number. Endpoint 0 is somewhat
269 * special and uses DCI 1. See 4.8.1 in xHCI spec.
270 *
271 *
272 * NB: A variable named iPort is a zero-based index into the port array.
273 * On the other hand, a variable named uPort is a one-based port number!
274 * The implementation (obviously) uses zero-based indexing, but USB ports
275 * are numbered starting with 1. The same is true of xHCI slot numbering.
276 * The macros IDX_TO_ID() and ID_TO_IDX(a) should be used to convert between
277 * the two numbering conventions to make the intent clear.
278 *
279 */
280
281
282/*********************************************************************************************************************************
283* Header Files *
284*********************************************************************************************************************************/
285#define LOG_GROUP LOG_GROUP_DEV_XHCI
286#include <VBox/pci.h>
287#include <VBox/msi.h>
288#include <VBox/vmm/pdm.h>
289#include <VBox/err.h>
290#include <VBox/log.h>
291#include <iprt/assert.h>
292#ifdef IN_RING3
293# include <iprt/uuid.h>
294# include <iprt/critsect.h>
295#endif
296#include <VBox/vusb.h>
297#ifdef VBOX_IN_EXTPACK_R3
298# include <VBox/version.h>
299#endif
300#ifndef VBOX_IN_EXTPACK
301# include "VBoxDD.h"
302#endif
303
304
305/*********************************************************************************************************************************
306* (Most of the) Defined Constants, Macros and Structures *
307*********************************************************************************************************************************/
308
309/* Optional error injection support via DBGF. */
310//#define XHCI_ERROR_INJECTION
311
312/** The saved state version. */
313#define XHCI_SAVED_STATE_VERSION 1
314
315
316/** Convert a zero-based index to a 1-based ID. */
317#define IDX_TO_ID(a) (a + 1)
318/** Convert a 1-based ID to a zero-based index. */
319#define ID_TO_IDX(a) (a - 1)
320
321/** PCI device related constants. */
322#define XHCI_PCI_MSI_CAP_OFS 0x80
323
324/** Number of LUNs/root hubs. One each for USB2/USB3. */
325#define XHCI_NUM_LUNS 2
326
327/** @name The following two constants were determined experimentally.
328 * They determine the maximum number of TDs allowed to be in flight.
329 * NB: For isochronous TDs, the number *must* be limited because
330 * Windows 8+ violates the xHCI specification and does not keep
331 * the transfer rings consistent.
332 * @{
333 */
334//#define XHCI_MAX_ISOC_IN_FLIGHT 3 /* Scarlett needs 3; was 12 */
335#define XHCI_MAX_ISOC_IN_FLIGHT 12
336#define XHCI_MAX_BULK_IN_FLIGHT 8
337/** @} */
338
339/** @name Implementation limit on the number of TRBs and commands
340 * the xHC is willing to process at once. A larger number is taken
341 * to indicate a broken or malicious guest, and causes a HC error.
342 * @{
343 */
344#define XHCI_MAX_NUM_CMDS 128
345#define XHCI_MAX_NUM_TRBS 1024
346/** @} */
347
348/** Implementation TD size limit. Prevents EDTLA wrap-around. */
349#define XHCI_MAX_TD_SIZE (16 * _1M - 1)
350
351/** Special value to prevent further queuing. */
352#define XHCI_NO_QUEUING_IN_FLIGHT (XHCI_MAX_BULK_IN_FLIGHT * 2)
353
354/* Structural Parameters #1 (HCSPARAMS1) values. */
355
356/** Maximum allowed Number of Downstream Ports on the root hub. Careful
357 * when changing -- other structures may need adjusting!
358 */
359#define XHCI_NDP_MAX 32
360
361/** Default number of USB 2.0 ports.
362 *
363 * @note AppleUSBXHCI does not handle more than 15 ports. At least OS X
364 * 10.8.2 crashes if we report more than 15 ports! Hence the default
365 * is 8 USB2 + 6 USB3 ports for a total of 14 so that OS X is happy.
366 */
367#define XHCI_NDP_20_DEFAULT 8
368
369/** Default number of USB 3.0 ports. */
370#define XHCI_NDP_30_DEFAULT 6
371
372/** Number of interrupters. */
373#define XHCI_NINTR 8
374
375/** Mask for interrupter indexing. */
376#define XHCI_INTR_MASK (XHCI_NINTR - 1)
377
378/* The following is only true if XHCI_NINTR is a (non-zero) power of two. */
379AssertCompile((XHCI_NINTR & XHCI_INTR_MASK) == 0);
380
381/** Number of Device Slots. Determines the number of doorbell
382 * registers and device slots, among other things. */
383#define XHCI_NDS 32
384
385/* Enforce xHCI architectural limits on HCSPARAMS1. */
386AssertCompile(XHCI_NDP_MAX < 255 && XHCI_NINTR < 1024 && XHCI_NDS < 255);
387AssertCompile(XHCI_NDP_20_DEFAULT + XHCI_NDP_30_DEFAULT <= XHCI_NDP_MAX);
388AssertCompile(XHCI_NDP_MAX <= XHCI_NDS);
389
390/* Structural Parameters #2 (HCSPARAMS2) values. */
391
392/** Isochronous Scheduling Threshold. */
393#define XHCI_IST (RT_BIT(3) | 1) /* One frame. */
394
395/** Max number of Event Ring Segment Table entries as a power of two. */
396#define XHCI_ERSTMAX_LOG2 5
397/** Max number of Event Ring Segment Table entries. */
398#define XHCI_ERSTMAX RT_BIT(XHCI_ERSTMAX_LOG2)
399
400/* Enforce xHCI architectural limits on HCSPARAMS2. */
401AssertCompile(XHCI_ERSTMAX_LOG2 < 16);
402
403
404/** Size of the xHCI memory-mapped I/O region. */
405#define XHCI_MMIO_SIZE _64K
406
407/** Size of the capability part of the MMIO region. */
408#define XHCI_CAPS_REG_SIZE 0x80
409
410/** Offset of the port registers in operational register space. */
411#define XHCI_PORT_REG_OFFSET 0x400
412
413/** Offset of xHCI extended capabilities in MMIO region. */
414#define XHCI_XECP_OFFSET 0x1000
415
416/** Offset of the run-time registers in MMIO region. */
417#define XHCI_RTREG_OFFSET 0x2000
418
419/** Offset of the doorbell registers in MMIO region. */
420#define XHCI_DOORBELL_OFFSET 0x3000
421
422/** Size of the extended capability area. */
423#define XHCI_EXT_CAP_SIZE 1024
424
425/* Make sure we can identify MMIO register accesses properly. */
426AssertCompile(XHCI_DOORBELL_OFFSET > XHCI_RTREG_OFFSET);
427AssertCompile(XHCI_XECP_OFFSET > XHCI_PORT_REG_OFFSET + XHCI_CAPS_REG_SIZE);
428AssertCompile(XHCI_RTREG_OFFSET > XHCI_XECP_OFFSET + XHCI_EXT_CAP_SIZE);
429
430
431/** Maximum size of a single extended capability. */
432#define MAX_XCAP_SIZE 256
433
434/** @name xHCI Extended capability types.
435 * @{ */
436#define XHCI_XCP_USB_LEGACY 1 /**< USB legacy support. */
437#define XHCI_XCP_PROTOCOL 2 /**< Protocols supported by ports. */
438#define XHCI_XCP_EXT_PM 3 /**< Extended power management (non-PCI). */
439#define XHCI_XCP_IOVIRT 4 /**< Hardware xHCI virtualization support. */
440#define XHCI_XCP_MSI 5 /**< Message interrupts (non-PCI). */
441#define XHCI_XCP_LOCAL_MEM 6 /**< Local memory (for debug support). */
442#define XHCI_XCP_USB_DEBUG 10 /**< USB debug capability. */
443#define XHCI_XCP_EXT_MSI 17 /**< MSI-X (non-PCI). */
444/** @} */
445
446
447/* xHCI Register Bits. */
448
449
450/** @name Capability Parameters (HCCPARAMS) bits
451 * @{ */
452#define XHCI_HCC_AC64 RT_BIT(0) /**< RO */
453#define XHCI_HCC_BNC RT_BIT(1) /**< RO */
454#define XHCI_HCC_CSZ RT_BIT(2) /**< RO */
455#define XHCI_HCC_PPC RT_BIT(3) /**< RO */
456#define XHCI_HCC_PIND RT_BIT(4) /**< RO */
457#define XHCI_HCC_LHRC RT_BIT(5) /**< RO */
458#define XHCI_HCC_LTC RT_BIT(6) /**< RO */
459#define XHCI_HCC_NSS RT_BIT(7) /**< RO */
460#define XHCI_HCC_MAXPSA_MASK (RT_BIT(12)|RT_BIT(13)|RT_BIT(14)| RT_BIT(15)) /**< RO */
461#define XHCI_HCC_MAXPSA_SHIFT 12
462#define XHCI_HCC_XECP_MASK 0xFFFF0000 /**< RO */
463#define XHCI_HCC_XECP_SHIFT 16
464/** @} */
465
466
467/** @name Command Register (USBCMD) bits
468 * @{ */
469#define XHCI_CMD_RS RT_BIT(0) /**< RW - Run/Stop */
470#define XHCI_CMD_HCRST RT_BIT(1) /**< RW - Host Controller Reset */
471#define XHCI_CMD_INTE RT_BIT(2) /**< RW - Interrupter Enable */
472#define XHCI_CMD_HSEE RT_BIT(3) /**< RW - Host System Error Enable */
473#define XHCI_CMD_LCRST RT_BIT(7) /**< RW - Light HC Reset */
474#define XHCI_CMD_CSS RT_BIT(8) /**< RW - Controller Save State */
475#define XHCI_CMD_CRS RT_BIT(9) /**< RW - Controller Restore State */
476#define XHCI_CMD_EWE RT_BIT(10) /**< RW - Enable Wrap Event */
477#define XHCI_CMD_EU3S RT_BIT(11) /**< RW - Enable U3 MFINDEX Stop */
478
479#define XHCI_CMD_MASK ( XHCI_CMD_RS | XHCI_CMD_HCRST | XHCI_CMD_INTE | XHCI_CMD_HSEE | XHCI_CMD_LCRST \
480 | XHCI_CMD_CSS | XHCI_CMD_CRS | XHCI_CMD_EWE | XHCI_CMD_EU3S)
481/** @} */
482
483
484/** @name Status Register (USBSTS) bits
485 * @{ */
486#define XHCI_STATUS_HCH RT_BIT(0) /**< RO - HC Halted */
487#define XHCI_STATUS_HSE RT_BIT(2) /**< RW1C - Host System Error */
488#define XHCI_STATUS_EINT RT_BIT(3) /**< RW1C - Event Interrupt */
489#define XHCI_STATUS_PCD RT_BIT(4) /**< RW1C - Port Change Detect */
490#define XHCI_STATUS_SSS RT_BIT(8) /**< RO - Save State Status */
491#define XHCI_STATUS_RSS RT_BIT(9) /**< RO - Resture State Status */
492#define XHCI_STATUS_SRE RT_BIT(10) /**< RW1C - Save/Restore Error */
493#define XHCI_STATUS_CNR RT_BIT(11) /**< RO - Controller Not Ready */
494#define XHCI_STATUS_HCE RT_BIT(12) /**< RO - Host Controller Error */
495
496#define XHCI_STATUS_WRMASK (XHCI_STATUS_HSE | XHCI_STATUS_EINT | XHCI_STATUS_PCD | XHCI_STATUS_SRE)
497/** @} */
498
499
500/** @name Default xHCI speed definitions (7.2.2.1.1)
501 * @{ */
502#define XHCI_SPD_FULL 1
503#define XHCI_SPD_LOW 2
504#define XHCI_SPD_HIGH 3
505#define XHCI_SPD_SUPER 4
506/** @} */
507
508/** @name Port Status and Control Register bits (PORTSCUSB2/PORTSCUSB3)
509 * @{ */
510#define XHCI_PORT_CCS RT_BIT(0) /**< ROS - Current Connection Status */
511#define XHCI_PORT_PED RT_BIT(1) /**< RW1S - Port Enabled/Disabled */
512#define XHCI_PORT_OCA RT_BIT(3) /**< RO - Over-current Active */
513#define XHCI_PORT_PR RT_BIT(4) /**< RW1S - Port Reset */
514#define XHCI_PORT_PLS_MASK (RT_BIT(5) | RT_BIT(6) | RT_BIT(7) | RT_BIT(8)) /**< RWS */
515#define XHCI_PORT_PLS_SHIFT 5
516#define XHCI_PORT_PP RT_BIT(9) /**< RWS - Port Power */
517#define XHCI_PORT_SPD_MASK (RT_BIT(10) | RT_BIT(11) | RT_BIT(12) | RT_BIT(13)) /**< ROS */
518#define XHCI_PORT_SPD_SHIFT 10
519#define XHCI_PORT_LWS RT_BIT(16) /**< RW - Link State Write Strobe */
520#define XHCI_PORT_CSC RT_BIT(17) /**< RW1CS - Connect Status Change */
521#define XHCI_PORT_PEC RT_BIT(18) /**< RW1CS - Port Enabled/Disabled Change */
522#define XHCI_PORT_WRC RT_BIT(19) /**< RW1CS - Warm Port Reset Change */
523#define XHCI_PORT_OCC RT_BIT(20) /**< RW1CS - Over-current Change */
524#define XHCI_PORT_PRC RT_BIT(21) /**< RW1CS - Port Reset Change */
525#define XHCI_PORT_PLC RT_BIT(22) /**< RW1CS - Port Link State Change */
526#define XHCI_PORT_CEC RT_BIT(23) /**< RW1CS - Port Config Error Change */
527#define XHCI_PORT_CAS RT_BIT(24) /**< RO - Cold Attach Status */
528#define XHCI_PORT_WCE RT_BIT(25) /**< RWS - Wake on Connect Enable */
529#define XHCI_PORT_WDE RT_BIT(26) /**< RWS - Wake on Disconnect Enable */
530#define XHCI_PORT_WOE RT_BIT(27) /**< RWS - Wake on Over-current Enable */
531#define XHCI_PORT_DR RT_BIT(30) /**< RO - Device (Not) Removable */
532#define XHCI_PORT_WPR RT_BIT(31) /**< RW1S - Warm Port Reset */
533
534#define XHCI_PORT_RESERVED (RT_BIT(2) | RT_BIT(14) | RT_BIT(15) | RT_BIT(28) | RT_BIT(29))
535
536#define XHCI_PORT_WAKE_MASK (XHCI_PORT_WCE|XHCI_PORT_WDE|XHCI_PORT_WOE)
537#define XHCI_PORT_CHANGE_MASK (XHCI_PORT_CSC|XHCI_PORT_PEC|XHCI_PORT_WRC|XHCI_PORT_OCC|XHCI_PORT_PRC|XHCI_PORT_PLC|XHCI_PORT_CEC)
538#define XHCI_PORT_CTL_RW_MASK (XHCI_PORT_PP|XHCI_PORT_LWS)
539#define XHCI_PORT_CTL_W1_MASK (XHCI_PORT_PED|XHCI_PORT_PR|XHCI_PORT_WPR)
540#define XHCI_PORT_RO_MASK (XHCI_PORT_CCS|XHCI_PORT_OCA|XHCI_PORT_SPD_MASK|XHCI_PORT_CAS|XHCI_PORT_DR)
541/** @} */
542
543/** @name Port Link State values
544 * @{ */
545#define XHCI_PLS_U0 0 /**< U0 State. */
546#define XHCI_PLS_U1 1 /**< U1 State. */
547#define XHCI_PLS_U2 2 /**< U2 State. */
548#define XHCI_PLS_U3 3 /**< U3 State (Suspended). */
549#define XHCI_PLS_DISABLED 4 /**< Disabled. */
550#define XHCI_PLS_RXDETECT 5 /**< RxDetect. */
551#define XHCI_PLS_INACTIVE 6 /**< Inactive. */
552#define XHCI_PLS_POLLING 7 /**< Polling. */
553#define XHCI_PLS_RECOVERY 8 /**< Recovery. */
554#define XHCI_PLS_HOTRST 9 /**< Hot Reset. */
555#define XHCI_PLS_CMPLMODE 10 /**< Compliance Mode. */
556#define XHCI_PLS_TSTMODE 11 /**< Test Mode. */
557/* Values 12-14 are reserved. */
558#define XHCI_PLS_RESUME 15 /**< Resume. */
559/** @} */
560
561
562/** @name Command Ring Control Register (CRCR) bits
563 * @{ */
564#define XHCI_CRCR_RCS RT_BIT(0) /**< RW - Ring Cycle State */
565#define XHCI_CRCR_CS RT_BIT(1) /**< RW1S - Command Stop */
566#define XHCI_CRCR_CA RT_BIT(2) /**< RW1S - Command Abort */
567#define XHCI_CRCR_CRR RT_BIT(3) /**< RO - Command Ring Running */
568
569#define XHCI_CRCR_RD_MASK UINT64_C(0xFFFFFFFFFFFFFFF8) /* Mask off bits always read as zero. */
570#define XHCI_CRCR_ADDR_MASK UINT64_C(0xFFFFFFFFFFFFFFC0)
571#define XHCI_CRCR_UPD_MASK (XHCI_CRCR_ADDR_MASK | XHCI_CRCR_RCS)
572/** @} */
573
574
575/** @name Interrupter Management Register (IMAN) bits
576 * @{ */
577#define XHCI_IMAN_IP RT_BIT(0) /**< RW1C - Interrupt Pending */
578#define XHCI_IMAN_IE RT_BIT(1) /**< RW - Interrupt Enable */
579
580#define XHCI_IMAN_VALID_MASK (XHCI_IMAN_IP | XHCI_IMAN_IE)
581/** @} */
582
583
584/** @name Interrupter Moderation Register (IMOD) bits
585 * @{ */
586#define XHCI_IMOD_IMODC_MASK 0xFFFF0000 /**< RW */
587#define XHCI_IMOD_IMODC_SHIFT 16
588#define XHCI_IMOD_IMODI_MASK 0x0000FFFF /**< RW */
589/** @} */
590
591
592/** @name Event Ring Segment Table Size Register (ERSTSZ) bits
593 * @{ */
594#define XHCI_ERSTSZ_MASK 0x0000FFFF /**< RW */
595/** @} */
596
597/** @name Event Ring Segment Table Base Address Register (ERSTBA) bits
598 * @{ */
599#define XHCI_ERST_ADDR_MASK UINT64_C(0xFFFFFFFFFFFFFFC0)
600/** @} */
601
602/** For reasons that are not obvious, NEC/Renesas xHCs only require 16-bit
603 * alignment for the ERST base. This is not in line with the xHCI spec
604 * (which requires 64-bit alignment) but is clearly documented by NEC.
605 */
606#define NEC_ERST_ADDR_MASK UINT64_C(0xFFFFFFFFFFFFFFF0)
607
608/** Firmware revision reported in NEC/Renesas mode. Value chosen based on
609 * OS X driver check (OS X supports these chips since they're commonly
610 * found in ExpressCards).
611 */
612#define NEC_FW_REV 0x3028
613
614/** @name Event Ring Deqeue Pointer Register (ERDP) bits
615 * @{ */
616#define XHCI_ERDP_DESI_MASK 0x00000007 /**< RW - Dequeue ERST Segment Index */
617#define XHCI_ERDP_EHB RT_BIT(3) /**< RW1C - Event Handler Busy */
618#define XHCI_ERDP_ADDR_MASK UINT64_C(0xFFFFFFFFFFFFFFF0) /**< RW - ERDP address mask */
619/** @} */
620
621/** @name Device Context Base Address Array (DCBAA) definitions
622 * @{ */
623#define XHCI_DCBAA_ADDR_MASK UINT64_C(0xFFFFFFFFFFFFFFC0) /**< Applies to DCBAAP and its entries. */
624/** @} */
625
626/** @name Doorbell Register bits
627 * @{ */
628#define XHCI_DB_TGT_MASK 0x000000FF /**< DB Target mask. */
629#define XHCI_DB_STRMID_SHIFT 16 /**< DB Stream ID shift. */
630#define XHCI_DB_STRMID_MASK 0xFFFF0000 /**< DB Stream ID mask. */
631/** @} */
632
633/** Address mask for device/endpoint/input contexts. */
634#define XHCI_CTX_ADDR_MASK UINT64_C(0xFFFFFFFFFFFFFFF0)
635
636/** @name TRB Completion Codes
637 * @{ */
638#define XHCI_TCC_INVALID 0 /**< CC field not updated. */
639#define XHCI_TCC_SUCCESS 1 /**< Successful TRB completion. */
640#define XHCI_TCC_DATA_BUF_ERR 2 /**< Overrun/underrun. */
641#define XHCI_TCC_BABBLE 3 /**< Babble detected. */
642#define XHCI_TCC_USB_XACT_ERR 4 /**< USB transaction error. */
643#define XHCI_TCC_TRB_ERR 5 /**< TRB error detected. */
644#define XHCI_TCC_STALL 6 /**< USB Stall detected. */
645#define XHCI_TCC_RSRC_ERR 7 /**< Inadequate xHC resources. */
646#define XHCI_TCC_BWIDTH_ERR 8 /**< Unable to allocate bandwidth. */
647#define XHCI_TCC_NO_SLOTS 9 /**< MaxSlots (NDS) exceeded. */
648#define XHCI_TCC_INV_STRM_TYP 10 /**< Invalid stream context type. */
649#define XHCI_TCC_SLOT_NOT_ENB 11 /**< Slot not enabled. */
650#define XHCI_TCC_EP_NOT_ENB 12 /**< Endpoint not enabled. */
651#define XHCI_TCC_SHORT_PKT 13 /**< Short packet detected. */
652#define XHCI_TCC_RING_UNDERRUN 14 /**< Transfer ring underrun. */
653#define XHCI_TCC_RING_OVERRUN 15 /**< Transfer ring overrun. */
654#define XHCI_TCC_VF_RING_FULL 16 /**< VF event ring full. */
655#define XHCI_TCC_PARM_ERR 17 /**< Invalid context parameter. */
656#define XHCI_TCC_BWIDTH_OVER 18 /**< Isoc bandwidth overrun. */
657#define XHCI_TCC_CTX_STATE_ERR 19 /**< Transition from illegal context state. */
658#define XHCI_TCC_NO_PING 20 /**< No ping response in time. */
659#define XHCI_TCC_EVT_RING_FULL 21 /**< Event Ring full. */
660#define XHCI_TCC_DEVICE_COMPAT 22 /**< Incompatible device detected. */
661#define XHCI_TCC_MISS_SVC 23 /**< Missed isoc service. */
662#define XHCI_TCC_CMDR_STOPPED 24 /**< Command ring stopped. */
663#define XHCI_TCC_CMD_ABORTED 25 /**< Command aborted. */
664#define XHCI_TCC_STOPPED 26 /**< Endpoint stopped. */
665#define XHCI_TCC_STP_INV_LEN 27 /**< EP stopped, invalid transfer length. */
666 /* 28 Reserved. */
667#define XHCI_TCC_MAX_EXIT_LAT 29 /**< Max exit latency too large. */
668 /* 30 Reserved. */
669#define XHCI_TCC_ISOC_OVERRUN 31 /**< Isochronous buffer overrun. */
670#define XHCI_TCC_EVT_LOST 32 /**< Event lost due to overrun. */
671#define XHCI_TCC_ERR_OTHER 33 /**< Implementation specific error. */
672#define XHCI_TCC_INV_STRM_ID 34 /**< Invalid stream ID. */
673#define XHCI_TCC_SEC_BWIDTH_ERR 35 /**< Secondary bandwidth error. */
674#define XHCI_TCC_SPLIT_ERR 36 /**< Split transaction error. */
675/** @} */
676
677#if defined(IN_RING3) && defined(LOG_ENABLED)
678/** Human-readable completion code descriptions for debugging. */
679static const char * const g_apszCmplCodes[] = {
680 "CC field not updated", "Successful TRB completion", "Overrun/underrun", "Babble detected", /* 0-3 */
681 "USB transaction error", "TRB error detected", "USB Stall detected", "Inadequate xHC resources", /* 4-7 */
682 "Unable to allocate bandwidth", "MaxSlots (NDS) exceeded", "Invalid stream context type", "Slot not enabled", /* 8-11 */
683 "Endpoint not enabled", "Short packet detected", "Transfer ring underrun", "Transfer ring overrun", /* 12-15 */
684 "VF event ring full", "Invalid context param", "Isoc bandwidth overrun", "Transition from illegal ctx state", /* 16-19 */
685 "No ping response in time", "Event Ring full", "Incompatible device detected", "Missed isoc service", /* 20-23 */
686 "Command ring stopped", "Command aborted", "Endpoint stopped", "EP stopped, invalid transfer length", /* 24-27 */
687 "Reserved", "Max exit latency too large", "Reserved", "Isochronous buffer overrun", /* 28-31 */
688 "Event lost due to overrun", "Implementation specific error", "Invalid stream ID", "Secondary bandwidth error", /* 32-35 */
689 "Split transaction error" /* 36 */
690};
691#endif
692
693
694/* TRBs marked as 'TRB' are only valid in the transfer ring. TRBs marked
695 * as 'Command' are only valid in the command ring. TRBs marked as 'Event'
696 * are the only ones generated in the event ring. The Link TRB is valid
697 * in both the transfer and command rings.
698 */
699
700/** @name TRB Types
701 * @{ */
702#define XHCI_TRB_INVALID 0 /**< Reserved/unused TRB type. */
703#define XHCI_TRB_NORMAL 1 /**< Normal TRB. */
704#define XHCI_TRB_SETUP_STG 2 /**< Setup Stage TRB. */
705#define XHCI_TRB_DATA_STG 3 /**< Data Stage TRB. */
706#define XHCI_TRB_STATUS_STG 4 /**< Status Stage TRB. */
707#define XHCI_TRB_ISOCH 5 /**< Isochronous TRB. */
708#define XHCI_TRB_LINK 6 /**< Link. */
709#define XHCI_TRB_EVT_DATA 7 /**< Event Data TRB. */
710#define XHCI_TRB_NOOP_XFER 8 /**< No-op transfer TRB. */
711#define XHCI_TRB_ENB_SLOT 9 /**< Enable Slot Command. */
712#define XHCI_TRB_DIS_SLOT 10 /**< Disable Slot Command. */
713#define XHCI_TRB_ADDR_DEV 11 /**< Address Device Command. */
714#define XHCI_TRB_CFG_EP 12 /**< Configure Endpoint Command. */
715#define XHCI_TRB_EVAL_CTX 13 /**< Evaluate Context Command. */
716#define XHCI_TRB_RESET_EP 14 /**< Reset Endpoint Command. */
717#define XHCI_TRB_STOP_EP 15 /**< Stop Endpoint Command. */
718#define XHCI_TRB_SET_DEQ_PTR 16 /**< Set TR Dequeue Pointer Command. */
719#define XHCI_TRB_RESET_DEV 17 /**< Reset Device Command. */
720#define XHCI_TRB_FORCE_EVT 18 /**< Force Event Command. */
721#define XHCI_TRB_NEG_BWIDTH 19 /**< Negotiate Bandwidth Command. */
722#define XHCI_TRB_SET_LTV 20 /**< Set Latency Tolerate Value Command. */
723#define XHCI_TRB_GET_PORT_BW 21 /**< Get Port Bandwidth Command. */
724#define XHCI_TRB_FORCE_HDR 22 /**< Force Header Command. */
725#define XHCI_TRB_NOOP_CMD 23 /**< No-op Command. */
726 /* 24-31 Reserved. */
727#define XHCI_TRB_XFER 32 /**< Transfer Event. */
728#define XHCI_TRB_CMD_CMPL 33 /**< Command Completion Event. */
729#define XHCI_TRB_PORT_SC 34 /**< Port Status Change Event. */
730#define XHCI_TRB_BW_REQ 35 /**< Bandwidth Request Event. */
731#define XHCI_TRB_DBELL 36 /**< Doorbell Event. */
732#define XHCI_TRB_HC_EVT 37 /**< Host Controller Event. */
733#define XHCI_TRB_DEV_NOTIFY 38 /**< Device Notification Event. */
734#define XHCI_TRB_MFIDX_WRAP 39 /**< MFINDEX Wrap Event. */
735 /* 40-47 Reserved. */
736#define NEC_TRB_CMD_CMPL 48 /**< Command Completion Event, NEC specific. */
737#define NEC_TRB_GET_FW_VER 49 /**< Get Firmware Version Command, NEC specific. */
738#define NEC_TRB_AUTHENTICATE 50 /**< Authenticate Command, NEC specific. */
739/** @} */
740
741#if defined(IN_RING3) && defined(LOG_ENABLED)
742/** Human-readable TRB names for debugging. */
743static const char * const g_apszTrbNames[] = {
744 "Reserved/unused TRB!!", "Normal TRB", "Setup Stage TRB", "Data Stage TRB", /* 0-3 */
745 "Status Stage TRB", "Isochronous TRB", "Link", "Event Data TRB", /* 4-7 */
746 "No-op transfer TRB", "Enable Slot", "Disable Slot", "Address Device", /* 8-11 */
747 "Configure Endpoint", "Evaluate Context", "Reset Endpoint", "Stop Endpoint", /* 12-15 */
748 "Set TR Dequeue Pointer", "Reset Device", "Force Event", "Negotiate Bandwidth", /* 16-19 */
749 "Set Latency Tolerate Value", "Get Port Bandwidth", "Force Header", "No-op", /* 20-23 */
750 "UNDEF", "UNDEF", "UNDEF", "UNDEF", "UNDEF", "UNDEF", "UNDEF", "UNDEF", /* 24-31 */
751 "Transfer", "Command Completion", "Port Status Change", "BW Request", /* 32-35 */
752 "Doorbell", "Host Controller", "Device Notification", "MFINDEX Wrap", /* 36-39 */
753 "UNDEF", "UNDEF", "UNDEF", "UNDEF", "UNDEF", "UNDEF", "UNDEF", "UNDEF", /* 40-47 */
754 "NEC FW Version Completion", "NEC Get FW Version", "NEC Authenticate" /* 48-50 */
755};
756#endif
757
758/** Generic TRB template. */
759typedef struct sXHCI_TRB_G {
760 uint32_t resvd0;
761 uint32_t resvd1;
762 uint32_t resvd2 : 24;
763 uint32_t cc : 8; /**< Completion Code. */
764 uint32_t cycle : 1; /**< Cycle bit. */
765 uint32_t resvd3 : 9;
766 uint32_t type : 6; /**< TRB Type. */
767 uint32_t resvd4 : 16;
768} XHCI_TRB_G;
769AssertCompile(sizeof(XHCI_TRB_G) == 0x10);
770
771/** Generic transfer TRB template. */
772typedef struct sXHCI_TRB_GX {
773 uint32_t resvd0;
774 uint32_t resvd1;
775 uint32_t xfr_len : 17; /**< Transfer length. */
776 uint32_t resvd2 : 5;
777 uint32_t int_tgt : 10; /**< Interrupter target. */
778 uint32_t cycle : 1; /**< Cycle bit. */
779 uint32_t ent : 1; /**< Evaluate Next TRB. */
780 uint32_t isp : 1; /**< Interrupt on Short Packet. */
781 uint32_t ns : 1; /**< No Snoop. */
782 uint32_t ch : 1; /**< Chain bit. */
783 uint32_t ioc : 1; /**< Interrupt On Completion. */
784 uint32_t idt : 1; /**< Immediate Data. */
785 uint32_t resvd3 : 3;
786 uint32_t type : 6; /**< TRB Type. */
787 uint32_t resvd4 : 16;
788} XHCI_TRB_GX;
789AssertCompile(sizeof(XHCI_TRB_GX) == 0x10);
790
791
792/* -= Transfer TRB types =- */
793
794
795/** Normal Transfer TRB. */
796typedef struct sXHCI_TRB_NORM {
797 uint64_t data_ptr; /**< Pointer or data. */
798 uint32_t xfr_len : 17; /**< Transfer length. */
799 uint32_t td_size : 5; /**< Remaining packets. */
800 uint32_t int_tgt : 10; /**< Interrupter target. */
801 uint32_t cycle : 1; /**< Cycle bit. */
802 uint32_t ent : 1; /**< Evaluate Next TRB. */
803 uint32_t isp : 1; /**< Interrupt on Short Packet. */
804 uint32_t ns : 1; /**< No Snoop. */
805 uint32_t ch : 1; /**< Chain bit. */
806 uint32_t ioc : 1; /**< Interrupt On Completion. */
807 uint32_t idt : 1; /**< Immediate Data. */
808 uint32_t resvd0 : 2;
809 uint32_t bei : 1; /**< Block Event Interrupt. */
810 uint32_t type : 6; /**< TRB Type. */
811 uint32_t resvd1 : 16;
812} XHCI_TRB_NORM;
813AssertCompile(sizeof(XHCI_TRB_NORM) == 0x10);
814
815/** Control Transfer - Setup Stage TRB. */
816typedef struct sXHCI_TRB_CTSP {
817 uint8_t bmRequestType; /**< See the USB spec. */
818 uint8_t bRequest;
819 uint16_t wValue;
820 uint16_t wIndex;
821 uint16_t wLength;
822 uint32_t xfr_len : 17; /**< Transfer length (8). */
823 uint32_t resvd0 : 5;
824 uint32_t int_tgt : 10; /**< Interrupter target. */
825 uint32_t cycle : 1; /**< Cycle bit. */
826 uint32_t resvd1 : 4;
827 uint32_t ioc : 1; /**< Interrupt On Completion. */
828 uint32_t idt : 1; /**< Immediate Data. */
829 uint32_t resvd2 : 2;
830 uint32_t bei : 1; /**< Block Event Interrupt. */
831 uint32_t type : 6; /**< TRB Type. */
832 uint32_t trt : 2; /**< Transfer Type. */
833 uint32_t resvd3 : 14;
834} XHCI_TRB_CTSP;
835AssertCompile(sizeof(XHCI_TRB_CTSP) == 0x10);
836
837/** Control Transfer - Data Stage TRB. */
838typedef struct sXHCI_TRB_CTDT {
839 uint64_t data_ptr; /**< Pointer or data. */
840 uint32_t xfr_len : 17; /**< Transfer length. */
841 uint32_t td_size : 5; /**< Remaining packets. */
842 uint32_t int_tgt : 10; /**< Interrupter target. */
843 uint32_t cycle : 1; /**< Cycle bit. */
844 uint32_t ent : 1; /**< Evaluate Next TRB. */
845 uint32_t isp : 1; /**< Interrupt on Short Packet. */
846 uint32_t ns : 1; /**< No Snoop. */
847 uint32_t ch : 1; /**< Chain bit. */
848 uint32_t ioc : 1; /**< Interrupt On Completion. */
849 uint32_t idt : 1; /**< Immediate Data. */
850 uint32_t resvd0 : 3;
851 uint32_t type : 6; /**< TRB Type. */
852 uint32_t dir : 1; /**< Direction (1=IN). */
853 uint32_t resvd1 : 15;
854} XHCI_TRB_CTDT;
855AssertCompile(sizeof(XHCI_TRB_CTDT) == 0x10);
856
857/** Control Transfer - Status Stage TRB. */
858typedef struct sXHCI_TRB_CTSS {
859 uint64_t resvd0;
860 uint32_t resvd1 : 22;
861 uint32_t int_tgt : 10; /**< Interrupter target. */
862 uint32_t cycle : 1; /**< Cycle bit. */
863 uint32_t ent : 1; /**< Evaluate Next TRB. */
864 uint32_t resvd2 : 2;
865 uint32_t ch : 1; /**< Chain bit. */
866 uint32_t ioc : 1; /**< Interrupt On Completion. */
867 uint32_t resvd3 : 4;
868 uint32_t type : 6; /**< TRB Type. */
869 uint32_t dir : 1; /**< Direction (1=IN). */
870 uint32_t resvd4 : 15;
871} XHCI_TRB_CTSS;
872AssertCompile(sizeof(XHCI_TRB_CTSS) == 0x10);
873
874/** Isochronous Transfer TRB. */
875typedef struct sXHCI_TRB_ISOC {
876 uint64_t data_ptr; /**< Pointer or data. */
877 uint32_t xfr_len : 17; /**< Transfer length. */
878 uint32_t td_size : 5; /**< Remaining packets. */
879 uint32_t int_tgt : 10; /**< Interrupter target. */
880 uint32_t cycle : 1; /**< Cycle bit. */
881 uint32_t ent : 1; /**< Evaluate Next TRB. */
882 uint32_t isp : 1; /**< Interrupt on Short Packet. */
883 uint32_t ns : 1; /**< No Snoop. */
884 uint32_t ch : 1; /**< Chain bit. */
885 uint32_t ioc : 1; /**< Interrupt On Completion. */
886 uint32_t idt : 1; /**< Immediate Data. */
887 uint32_t tbc : 2; /**< Transfer Burst Count. */
888 uint32_t bei : 1; /**< Block Event Interrupt. */
889 uint32_t type : 6; /**< TRB Type. */
890 uint32_t tlbpc : 4; /**< Transfer Last Burst Packet Count. */
891 uint32_t frm_id : 11; /**< Frame ID. */
892 uint32_t sia : 1; /**< Start Isoch ASAP. */
893} XHCI_TRB_ISOC;
894AssertCompile(sizeof(XHCI_TRB_ISOC) == 0x10);
895
896/* Number of bits in the frame ID. */
897#define XHCI_FRAME_ID_BITS 11
898
899/** No Op Transfer TRB. */
900typedef struct sXHCI_TRB_NOPT {
901 uint64_t resvd0;
902 uint32_t resvd1 : 22;
903 uint32_t int_tgt : 10; /**< Interrupter target. */
904 uint32_t cycle : 1; /**< Cycle bit. */
905 uint32_t ent : 1; /**< Evaluate Next TRB. */
906 uint32_t resvd2 : 2;
907 uint32_t ch : 1; /**< Chain bit. */
908 uint32_t ioc : 1; /**< Interrupt On Completion. */
909 uint32_t resvd3 : 4;
910 uint32_t type : 6; /**< TRB Type. */
911 uint32_t resvd4 : 16;
912} XHCI_TRB_NOPT;
913AssertCompile(sizeof(XHCI_TRB_NOPT) == 0x10);
914
915
916/* -= Event TRB types =- */
917
918
919/** Transfer Event TRB. */
920typedef struct sXHCI_TRB_TE {
921 uint64_t trb_ptr; /**< TRB pointer. */
922 uint32_t xfr_len : 24; /**< Transfer length. */
923 uint32_t cc : 8; /**< Completion Code. */
924 uint32_t cycle : 1; /**< Cycle bit. */
925 uint32_t resvd0 : 1;
926 uint32_t ed : 1; /**< Event Data flag. */
927 uint32_t resvd1 : 7;
928 uint32_t type : 6; /**< TRB Type. */
929 uint32_t ep_id : 5; /**< Endpoint ID. */
930 uint32_t resvd2 : 3;
931 uint32_t slot_id : 8; /**< Slot ID. */
932} XHCI_TRB_TE;
933AssertCompile(sizeof(XHCI_TRB_TE) == 0x10);
934
935/** Command Completion Event TRB. */
936typedef struct sXHCI_TRB_CCE {
937 uint64_t trb_ptr; /**< Command TRB pointer. */
938 uint32_t resvd0 : 24;
939 uint32_t cc : 8; /**< Completion Code. */
940 uint32_t cycle : 1; /**< Cycle bit. */
941 uint32_t resvd1 : 9;
942 uint32_t type : 6; /**< TRB Type. */
943 uint32_t vf_id : 8; /**< Virtual Function ID. */
944 uint32_t slot_id : 8; /**< Slot ID. */
945} XHCI_TRB_CCE;
946AssertCompile(sizeof(XHCI_TRB_CCE) == 0x10);
947
948/** Port Staus Change Event TRB. */
949typedef struct sXHCI_TRB_PSCE {
950 uint32_t resvd0 : 24;
951 uint32_t port_id : 8; /**< Port ID. */
952 uint32_t resvd1;
953 uint32_t resvd2 : 24;
954 uint32_t cc : 8; /**< Completion Code. */
955 uint32_t cycle : 1; /**< Cycle bit. */
956 uint32_t resvd3 : 9;
957 uint32_t type : 6; /**< TRB Type. */
958 uint32_t resvd4 : 16;
959} XHCI_TRB_PSCE;
960AssertCompile(sizeof(XHCI_TRB_PSCE) == 0x10);
961
962/** Bandwidth Request Event TRB. */
963typedef struct sXHCI_TRB_BRE {
964 uint32_t resvd0;
965 uint32_t resvd1;
966 uint32_t resvd2 : 24;
967 uint32_t cc : 8; /**< Completion Code. */
968 uint32_t cycle : 1; /**< Cycle bit. */
969 uint32_t resvd3 : 9;
970 uint32_t type : 6; /**< TRB Type. */
971 uint32_t resvd4 : 8;
972 uint32_t slot_id : 8; /**< Slot ID. */
973} XHCI_TRB_BRE;
974AssertCompile(sizeof(XHCI_TRB_BRE) == 0x10);
975
976/** Doorbell Event TRB. */
977typedef struct sXHCI_TRB_DBE {
978 uint32_t reason : 5; /**< DB Reason/target. */
979 uint32_t resvd0 : 27;
980 uint32_t resvd1;
981 uint32_t resvd2 : 24;
982 uint32_t cc : 8; /**< Completion Code. */
983 uint32_t cycle : 1; /**< Cycle bit. */
984 uint32_t resvd3 : 9;
985 uint32_t type : 6; /**< TRB Type. */
986 uint32_t vf_id : 8; /**< Virtual Function ID. */
987 uint32_t slot_id : 8; /**< Slot ID. */
988} XHCI_TRB_DBE;
989AssertCompile(sizeof(XHCI_TRB_DBE) == 0x10);
990
991/** Host Controller Event TRB. */
992typedef struct sXHCI_TRB_HCE {
993 uint32_t resvd0;
994 uint32_t resvd1;
995 uint32_t resvd2 : 24;
996 uint32_t cc : 8; /**< Completion Code. */
997 uint32_t cycle : 1; /**< Cycle bit. */
998 uint32_t resvd3 : 9;
999 uint32_t type : 6; /**< TRB Type. */
1000 uint32_t resvd4 : 16;
1001} XHCI_TRB_HCE;
1002AssertCompile(sizeof(XHCI_TRB_HCE) == 0x10);
1003
1004/** Device Notification Event TRB. */
1005typedef struct sXHCI_TRB_DNE {
1006 uint32_t resvd0 : 4;
1007 uint32_t dn_type : 4; /**< Device Notification Type. */
1008 uint32_t dnd_lo : 5; /**< Device Notification Data Lo. */
1009 uint32_t dnd_hi; /**< Device Notification Data Hi. */
1010 uint32_t resvd1 : 24;
1011 uint32_t cc : 8; /**< Completion Code. */
1012 uint32_t cycle : 1; /**< Cycle bit. */
1013 uint32_t resvd2 : 9;
1014 uint32_t type : 6; /**< TRB Type. */
1015 uint32_t resvd3 : 8;
1016 uint32_t slot_id : 8; /**< Slot ID. */
1017} XHCI_TRB_DNE;
1018AssertCompile(sizeof(XHCI_TRB_DNE) == 0x10);
1019
1020/** MFINDEX Wrap Event TRB. */
1021typedef struct sXHCI_TRB_MWE {
1022 uint32_t resvd0;
1023 uint32_t resvd1;
1024 uint32_t resvd2 : 24;
1025 uint32_t cc : 8; /**< Completion Code. */
1026 uint32_t cycle : 1; /**< Cycle bit. */
1027 uint32_t resvd3 : 9;
1028 uint32_t type : 6; /**< TRB Type. */
1029 uint32_t resvd4 : 16;
1030} XHCI_TRB_MWE;
1031AssertCompile(sizeof(XHCI_TRB_MWE) == 0x10);
1032
1033/** NEC Specific Command Completion Event TRB. */
1034typedef struct sXHCI_TRB_NCE {
1035 uint64_t trb_ptr; /**< Command TRB pointer. */
1036 uint32_t word1 : 16; /**< First result word. */
1037 uint32_t resvd0 : 8;
1038 uint32_t cc : 8; /**< Completion Code. */
1039 uint32_t cycle : 1; /**< Cycle bit. */
1040 uint32_t resvd1 : 9;
1041 uint32_t type : 6; /**< TRB Type. */
1042 uint32_t word2 : 16; /**< Second result word. */
1043} XHCI_TRB_NCE;
1044AssertCompile(sizeof(XHCI_TRB_NCE) == 0x10);
1045
1046
1047
1048/* -= Command TRB types =- */
1049
1050
1051/** No Op Command TRB. */
1052typedef struct sXHCI_TRB_NOPC {
1053 uint32_t resvd0;
1054 uint32_t resvd1;
1055 uint32_t resvd2;
1056 uint32_t cycle : 1; /**< Cycle bit. */
1057 uint32_t resvd3 : 9;
1058 uint32_t type : 6; /**< TRB Type. */
1059 uint32_t resvd4 : 16;
1060} XHCI_TRB_NOPC;
1061AssertCompile(sizeof(XHCI_TRB_NOPC) == 0x10);
1062
1063/** Enable Slot Command TRB. */
1064typedef struct sXHCI_TRB_ESL {
1065 uint32_t resvd0;
1066 uint32_t resvd1;
1067 uint32_t resvd2;
1068 uint32_t cycle : 1; /**< Cycle bit. */
1069 uint32_t resvd3 : 9;
1070 uint32_t type : 6; /**< TRB Type. */
1071 uint32_t resvd4 : 16;
1072} XHCI_TRB_ESL;
1073AssertCompile(sizeof(XHCI_TRB_ESL) == 0x10);
1074
1075/** Disable Slot Command TRB. */
1076typedef struct sXHCI_TRB_DSL {
1077 uint32_t resvd0;
1078 uint32_t resvd1;
1079 uint32_t resvd2;
1080 uint32_t cycle : 1; /**< Cycle bit. */
1081 uint32_t resvd3 : 9;
1082 uint32_t type : 6; /**< TRB Type. */
1083 uint32_t resvd4 : 8;
1084 uint32_t slot_id : 8; /**< Slot ID. */
1085} XHCI_TRB_DSL;
1086AssertCompile(sizeof(XHCI_TRB_DSL) == 0x10);
1087
1088/** Address Device Command TRB. */
1089typedef struct sXHCI_TRB_ADR {
1090 uint64_t ctx_ptr; /**< Input Context pointer. */
1091 uint32_t resvd0;
1092 uint32_t cycle : 1; /**< Cycle bit. */
1093 uint32_t resvd1 : 8;
1094 uint32_t bsr : 1; /**< Block Set Address Request. */
1095 uint32_t type : 6; /**< TRB Type. */
1096 uint32_t resvd2 : 8;
1097 uint32_t slot_id : 8; /**< Slot ID. */
1098} XHCI_TRB_ADR;
1099AssertCompile(sizeof(XHCI_TRB_ADR) == 0x10);
1100
1101/** Configure Endpoint Command TRB. */
1102typedef struct sXHCI_TRB_CFG {
1103 uint64_t ctx_ptr; /**< Input Context pointer. */
1104 uint32_t resvd0;
1105 uint32_t cycle : 1; /**< Cycle bit. */
1106 uint32_t resvd1 : 8;
1107 uint32_t dc : 1; /**< Deconfigure. */
1108 uint32_t type : 6; /**< TRB Type. */
1109 uint32_t resvd2 : 8;
1110 uint32_t slot_id : 8; /**< Slot ID. */
1111} XHCI_TRB_CFG;
1112AssertCompile(sizeof(XHCI_TRB_CFG) == 0x10);
1113
1114/** Evaluate Context Command TRB. */
1115typedef struct sXHCI_TRB_EVC {
1116 uint64_t ctx_ptr; /**< Input Context pointer. */
1117 uint32_t resvd0;
1118 uint32_t cycle : 1; /**< Cycle bit. */
1119 uint32_t resvd1 : 9;
1120 uint32_t type : 6; /**< TRB Type. */
1121 uint32_t resvd2 : 8;
1122 uint32_t slot_id : 8; /**< Slot ID. */
1123} XHCI_TRB_EVC;
1124AssertCompile(sizeof(XHCI_TRB_EVC) == 0x10);
1125
1126/** Reset Endpoint Command TRB. */
1127typedef struct sXHCI_TRB_RSE {
1128 uint32_t resvd0;
1129 uint32_t resvd1;
1130 uint32_t resvd2;
1131 uint32_t cycle : 1; /**< Cycle bit. */
1132 uint32_t resvd3 : 8;
1133 uint32_t tsp : 1; /**< Transfer State Preserve. */
1134 uint32_t type : 6; /**< TRB Type. */
1135 uint32_t ep_id : 5; /**< Endpoint ID. */
1136 uint32_t resvd4 : 3;
1137 uint32_t slot_id : 8; /**< Slot ID. */
1138} XHCI_TRB_RSE;
1139AssertCompile(sizeof(XHCI_TRB_RSE) == 0x10);
1140
1141/** Stop Endpoint Command TRB. */
1142typedef struct sXHCI_TRB_STP {
1143 uint32_t resvd0;
1144 uint32_t resvd1;
1145 uint32_t resvd2;
1146 uint32_t cycle : 1; /**< Cycle bit. */
1147 uint32_t resvd3 : 9;
1148 uint32_t type : 6; /**< TRB Type. */
1149 uint32_t ep_id : 5; /**< Endpoint ID. */
1150 uint32_t resvd4 : 2;
1151 uint32_t sp : 1; /**< Suspend. */
1152 uint32_t slot_id : 8; /**< Slot ID. */
1153} XHCI_TRB_STP;
1154AssertCompile(sizeof(XHCI_TRB_STP) == 0x10);
1155
1156/** Set TR Dequeue Pointer Command TRB. */
1157typedef struct sXHCI_TRB_STDP {
1158#if 0
1159 uint64_t dcs : 1; /**< Dequeue Cycle State. */
1160 uint64_t sct : 3; /**< Stream Context Type. */
1161 uint64_t tr_dqp : 60; /**< New TR Dequeue Pointer (63:4). */
1162#else
1163 uint64_t tr_dqp;
1164#endif
1165 uint16_t resvd0;
1166 uint16_t strm_id; /**< Stream ID. */
1167 uint32_t cycle : 1; /**< Cycle bit. */
1168 uint32_t resvd1 : 9;
1169 uint32_t type : 6; /**< TRB Type. */
1170 uint32_t ep_id : 5; /**< Endpoint ID. */
1171 uint32_t resvd2 : 3;
1172 uint32_t slot_id : 8; /**< Slot ID. */
1173} XHCI_TRB_STDP;
1174AssertCompile(sizeof(XHCI_TRB_STDP) == 0x10);
1175
1176/** Reset Device Command TRB. */
1177typedef struct sXHCI_TRB_RSD {
1178 uint32_t resvd0;
1179 uint32_t resvd1;
1180 uint32_t resvd2;
1181 uint32_t cycle : 1; /**< Cycle bit. */
1182 uint32_t resvd3 : 9;
1183 uint32_t type : 6; /**< TRB Type. */
1184 uint32_t resvd4 : 8;
1185 uint32_t slot_id : 8; /**< Slot ID. */
1186} XHCI_TRB_RSD;
1187AssertCompile(sizeof(XHCI_TRB_RSD) == 0x10);
1188
1189/** Get Port Bandwidth Command TRB. */
1190typedef struct sXHCI_TRB_GPBW {
1191 uint64_t pbctx_ptr; /**< Port Bandwidth Context pointer. */
1192 uint32_t resvd0;
1193 uint32_t cycle : 1; /**< Cycle bit. */
1194 uint32_t resvd1 : 9;
1195 uint32_t type : 6; /**< TRB Type. */
1196 uint32_t spd : 4; /**< Dev Speed. */
1197 uint32_t resvd2 : 4;
1198 uint32_t slot_id : 8; /**< Slot ID. */
1199} XHCI_TRB_GPBW;
1200AssertCompile(sizeof(XHCI_TRB_GPBW) == 0x10);
1201
1202/** Force Header Command TRB. */
1203typedef struct sXHCI_TRB_FHD {
1204 uint32_t pkt_typ : 5; /**< Packet Type. */
1205 uint32_t hdr_lo : 27; /**< Header Info Lo. */
1206 uint32_t hdr_mid; /**< Header Info Mid. */
1207 uint32_t hdr_hi; /**< Header Info Hi. */
1208 uint32_t cycle : 1; /**< Cycle bit. */
1209 uint32_t resvd0 : 9;
1210 uint32_t type : 6; /**< TRB Type. */
1211 uint32_t resvd1 : 8;
1212 uint32_t slot_id : 8; /**< Slot ID. */
1213} XHCI_TRB_FHD;
1214AssertCompile(sizeof(XHCI_TRB_FHD) == 0x10);
1215
1216/** NEC Specific Authenticate Command TRB. */
1217typedef struct sXHCI_TRB_NAC {
1218 uint64_t cookie; /**< Cookie to munge. */
1219 uint32_t resvd0;
1220 uint32_t cycle : 1; /**< Cycle bit. */
1221 uint32_t resvd1 : 9;
1222 uint32_t type : 6; /**< TRB Type. */
1223 uint32_t resvd2 : 8;
1224 uint32_t slot_id : 8; /**< Slot ID. */
1225} XHCI_TRB_NAC;
1226AssertCompile(sizeof(XHCI_TRB_NAC) == 0x10);
1227
1228
1229/* -= Other TRB types =- */
1230
1231
1232/** Link TRB. */
1233typedef struct sXHCI_TRB_LNK {
1234 uint64_t rseg_ptr; /**< Ring Segment Pointer. */
1235 uint32_t resvd0 : 22;
1236 uint32_t int_tgt : 10; /**< Interrupter target. */
1237 uint32_t cycle : 1; /**< Cycle bit. */
1238 uint32_t toggle : 1; /**< Toggle Cycle flag. */
1239 uint32_t resvd1 : 2;
1240 uint32_t chain : 1; /**< Chain flag. */
1241 uint32_t ioc : 1; /**< Interrupt On Completion flag. */
1242 uint32_t resvd2 : 4;
1243 uint32_t type : 6; /**< TRB Type. */
1244 uint32_t resvd3 : 16;
1245} XHCI_TRB_LNK;
1246AssertCompile(sizeof(XHCI_TRB_LNK) == 0x10);
1247
1248/** Event Data TRB. */
1249typedef struct sXHCI_TRB_EVTD {
1250 uint64_t evt_data; /**< Event Data. */
1251 uint32_t resvd0 : 22;
1252 uint32_t int_tgt : 10; /**< Interrupter target. */
1253 uint32_t cycle : 1; /**< Cycle bit. */
1254 uint32_t ent : 1; /**< Evaluate Next Target flag. */
1255 uint32_t resvd1 : 2;
1256 uint32_t chain : 1; /**< Chain flag. */
1257 uint32_t ioc : 1; /**< Interrupt On Completion flag. */
1258 uint32_t resvd2 : 3;
1259 uint32_t bei : 1; /**< Block Event Interrupt flag. */
1260 uint32_t type : 6; /**< TRB Type. */
1261 uint32_t resvd3 : 16;
1262} XHCI_TRB_EVTD;
1263AssertCompile(sizeof(XHCI_TRB_EVTD) == 0x10);
1264
1265
1266/* -= Union TRB types for the three rings =- */
1267
1268
1269typedef union sXHCI_XFER_TRB {
1270 XHCI_TRB_NORM norm;
1271 XHCI_TRB_CTSP setup;
1272 XHCI_TRB_CTDT data;
1273 XHCI_TRB_CTSS status;
1274 XHCI_TRB_ISOC isoc;
1275 XHCI_TRB_EVTD evtd;
1276 XHCI_TRB_NOPT nop;
1277 XHCI_TRB_LNK link;
1278 XHCI_TRB_GX gen;
1279} XHCI_XFER_TRB;
1280AssertCompile(sizeof(XHCI_XFER_TRB) == 0x10);
1281
1282typedef union sXHCI_COMMAND_TRB {
1283 XHCI_TRB_ESL esl;
1284 XHCI_TRB_DSL dsl;
1285 XHCI_TRB_ADR adr;
1286 XHCI_TRB_CFG cfg;
1287 XHCI_TRB_EVC evc;
1288 XHCI_TRB_RSE rse;
1289 XHCI_TRB_STP stp;
1290 XHCI_TRB_STDP stdp;
1291 XHCI_TRB_RSD rsd;
1292 XHCI_TRB_GPBW gpbw;
1293 XHCI_TRB_FHD fhd;
1294 XHCI_TRB_NAC nac;
1295 XHCI_TRB_NOPC nopc;
1296 XHCI_TRB_LNK link;
1297 XHCI_TRB_G gen;
1298} XHCI_COMMAND_TRB;
1299AssertCompile(sizeof(XHCI_COMMAND_TRB) == 0x10);
1300
1301typedef union sXHCI_EVENT_TRB {
1302 XHCI_TRB_TE te;
1303 XHCI_TRB_CCE cce;
1304 XHCI_TRB_PSCE psce;
1305 XHCI_TRB_BRE bre;
1306 XHCI_TRB_DBE dbe;
1307 XHCI_TRB_HCE hce;
1308 XHCI_TRB_DNE dne;
1309 XHCI_TRB_MWE mwe;
1310 XHCI_TRB_NCE nce;
1311 XHCI_TRB_G gen;
1312} XHCI_EVENT_TRB;
1313AssertCompile(sizeof(XHCI_EVENT_TRB) == 0x10);
1314
1315
1316
1317/* -=-=-= Contexts =-=-=- */
1318
1319/** Slot Context. */
1320typedef struct sXHCI_SLOT_CTX {
1321 uint32_t route_str : 20; /**< Route String. */
1322 uint32_t speed : 4; /**< Device speed. */
1323 uint32_t resvd0 : 1;
1324 uint32_t mtt : 1; /**< Multi-TT flag. */
1325 uint32_t hub : 1; /**< Hub flag. */
1326 uint32_t ctx_ent : 5; /**< Context entries. */
1327 uint32_t max_lat : 16; /**< Max exit latency in usec. */
1328 uint32_t rh_port : 8; /**< Root hub port number (1-based). */
1329 uint32_t n_ports : 8; /**< No. of ports for hubs. */
1330 uint32_t tt_slot : 8; /**< TT hub slot ID. */
1331 uint32_t tt_port : 8; /**< TT port number. */
1332 uint32_t ttt : 2; /**< TT Think Time. */
1333 uint32_t resvd1 : 4;
1334 uint32_t intr_tgt : 10; /**< Interrupter Target. */
1335 uint32_t dev_addr : 8; /**< Device Address. */
1336 uint32_t resvd2 : 19;
1337 uint32_t slot_state : 5; /**< Slot State. */
1338 uint32_t opaque[4]; /**< For xHC (i.e. our own) use. */
1339} XHCI_SLOT_CTX;
1340AssertCompile(sizeof(XHCI_SLOT_CTX) == 0x20);
1341
1342/** @name Slot Context states
1343 * @{ */
1344#define XHCI_SLTST_ENDIS 0 /**< Enabled/Disabled. */
1345#define XHCI_SLTST_DEFAULT 1 /**< Default. */
1346#define XHCI_SLTST_ADDRESSED 2 /**< Addressed. */
1347#define XHCI_SLTST_CONFIGURED 3 /**< Configured. */
1348/** @} */
1349
1350#ifdef IN_RING3
1351/** Human-readable slot state descriptions for debugging. */
1352static const char * const g_apszSltStates[] = {
1353 "Enabled/Disabled", "Default", "Addressed", "Configured" /* 0-3 */
1354};
1355#endif
1356
1357/** Endpoint Context. */
1358typedef struct sXHCI_EP_CTX {
1359 uint32_t ep_state : 3; /**< Endpoint state. */
1360 uint32_t resvd0 : 5;
1361 uint32_t mult : 2; /**< SS isoc burst count. */
1362 uint32_t maxps : 5; /**< Max Primary Streams. */
1363 uint32_t lsa : 1; /**< Linear Stream Array. */
1364 uint32_t interval : 8; /**< USB request interval. */
1365 uint32_t resvd1 : 8;
1366 uint32_t resvd2 : 1;
1367 uint32_t c_err : 2; /**< Error count. */
1368 uint32_t ep_type : 3; /**< Endpoint type. */
1369 uint32_t resvd3 : 1;
1370 uint32_t hid : 1; /**< Host Initiate Disable. */
1371 uint32_t max_brs_sz : 8; /**< Max Burst Size. */
1372 uint32_t max_pkt_sz : 16; /**< Max Packet Size. */
1373 uint64_t trdp; /**< TR Dequeue Pointer. */
1374 uint32_t avg_trb_len : 16; /**< Average TRB Length. */
1375 uint32_t max_esit : 16; /**< Max EP Service Interval Time Payload. */
1376 /**< The rest for xHC (i.e. our own) use. */
1377 uint32_t last_frm : 16; /**< Last isochronous frame used (opaque). */
1378 uint32_t ifc : 8; /**< isoch in-flight TD count (opaque). */
1379 uint32_t last_cc : 8; /**< Last TRB completion code (opaque). */
1380 uint64_t trep; /**< TR Enqueue Pointer (opaque). */
1381} XHCI_EP_CTX;
1382AssertCompile(sizeof(XHCI_EP_CTX) == 0x20);
1383
1384/** @name Endpoint Context states
1385 * @{ */
1386#define XHCI_EPST_DISABLED 0 /**< Disabled. */
1387#define XHCI_EPST_RUNNING 1 /**< Running. */
1388#define XHCI_EPST_HALTED 2 /**< Halted. */
1389#define XHCI_EPST_STOPPED 3 /**< Not running/stopped. */
1390#define XHCI_EPST_ERROR 4 /**< Not running/error. */
1391/** @} */
1392
1393/** @name Endpoint Type values
1394 * @{ */
1395#define XHCI_EPTYPE_INVALID 0 /**< Not valid. */
1396#define XHCI_EPTYPE_ISOCH_OUT 1 /**< Isochronous Out. */
1397#define XHCI_EPTYPE_BULK_OUT 2 /**< Bulk Out. */
1398#define XHCI_EPTYPE_INTR_OUT 3 /**< Interrupt Out. */
1399#define XHCI_EPTYPE_CONTROL 4 /**< Control Bidi. */
1400#define XHCI_EPTYPE_ISOCH_IN 5 /**< Isochronous In. */
1401#define XHCI_EPTYPE_BULK_IN 6 /**< Bulk In. */
1402#define XHCI_EPTYPE_INTR_IN 7 /**< Interrupt In. */
1403/** @} */
1404
1405/* Pick out transfer type from endpoint. */
1406#define XHCI_EP_XTYPE(a) (a & 3)
1407
1408/* Endpoint transfer types. */
1409#define XHCI_XFTYPE_CONTROL 0
1410#define XHCI_XFTYPE_ISOCH XHCI_EPTYPE_ISOCH_OUT
1411#define XHCI_XFTYPE_BULK XHCI_EPTYPE_BULK_OUT
1412#define XHCI_XFTYPE_INTR XHCI_EPTYPE_INTR_OUT
1413
1414/* Transfer Ring Dequeue Pointer address mask. */
1415#define XHCI_TRDP_ADDR_MASK UINT64_C(0xFFFFFFFFFFFFFFF0)
1416#define XHCI_TRDP_DCS_MASK RT_BIT(0) /* Dequeue Cycle State bit. */
1417
1418
1419#ifdef IN_RING3
1420
1421/* Human-readable endpoint state descriptions for debugging. */
1422static const char * const g_apszEpStates[] = {
1423 "Disabled", "Running", "Halted", "Stopped", "Error" /* 0-4 */
1424};
1425
1426/* Human-readable endpoint type descriptions for debugging. */
1427static const char * const g_apszEpTypes[] = {
1428 "Not Valid", "Isoch Out", "Bulk Out", "Interrupt Out", /* 0-3 */
1429 "Control", "Isoch In", "Bulk In", "Interrupt In" /* 4-7 */
1430};
1431
1432#endif /* IN_RING3 */
1433
1434/* Input Control Context. */
1435typedef struct sXHCI_INPC_CTX {
1436 uint32_t drop_flags; /* Drop Context flags (2-31). */
1437 uint32_t add_flags; /* Add Context flags (0-31). */
1438 uint32_t resvd[6];
1439} XHCI_INPC_CTX;
1440AssertCompile(sizeof(XHCI_INPC_CTX) == 0x20);
1441
1442/* Make sure all contexts are the same size. */
1443AssertCompile(sizeof(XHCI_EP_CTX) == sizeof(XHCI_SLOT_CTX));
1444AssertCompile(sizeof(XHCI_EP_CTX) == sizeof(XHCI_INPC_CTX));
1445
1446/* -= Event Ring Segment Table =- */
1447
1448/** Event Ring Segment Table Entry. */
1449typedef struct sXHCI_ERSTE {
1450 uint64_t addr;
1451 uint16_t size;
1452 uint16_t resvd0;
1453 uint32_t resvd1;
1454} XHCI_ERSTE;
1455AssertCompile(sizeof(XHCI_ERSTE) == 0x10);
1456
1457
1458/* -=-= Internal data structures not defined by xHCI =-=- */
1459
1460
1461/** Device slot entry -- either slot context or endpoint context. */
1462typedef union sXHCI_DS_ENTRY {
1463 XHCI_SLOT_CTX sc; /**< Slot context. */
1464 XHCI_EP_CTX ep; /**< Endpoint context. */
1465} XHCI_DS_ENTRY;
1466
1467/** Full device context (slot context + 31 endpoint contexts). */
1468typedef struct sXHCI_DEV_CTX {
1469 XHCI_DS_ENTRY entry[32];
1470} XHCI_DEV_CTX;
1471AssertCompile(sizeof(XHCI_DEV_CTX) == 32 * sizeof(XHCI_EP_CTX));
1472AssertCompile(sizeof(XHCI_DEV_CTX) == 32 * sizeof(XHCI_SLOT_CTX));
1473
1474/** Pointer to the xHCI device state. */
1475typedef struct XHCI *PXHCI;
1476
1477#ifndef VBOX_DEVICE_STRUCT_TESTCASE
1478/**
1479 * The xHCI controller data associated with each URB.
1480 */
1481typedef struct VUSBURBHCIINT
1482{
1483 /** The slot index. */
1484 uint8_t uSlotID;
1485 /** Number of Tds in the array. */
1486 uint32_t cTRB;
1487} VUSBURBHCIINT;
1488#endif
1489
1490/**
1491 * An xHCI root hub port, shared.
1492 */
1493typedef struct XHCIHUBPORT
1494{
1495 /** PORTSC: Port status/control register (R/W). */
1496 uint32_t portsc;
1497 /** PORTPM: Power management status/control register (R/W). */
1498 uint32_t portpm;
1499 /** PORTLI: USB3 port link information (R/O). */
1500 uint32_t portli;
1501} XHCIHUBPORT;
1502/** Pointer to a shared xHCI root hub port. */
1503typedef XHCIHUBPORT *PXHCIHUBPORT;
1504
1505/**
1506 * An xHCI root hub port, ring-3.
1507 */
1508typedef struct XHCIHUBPORTR3
1509{
1510 /** Flag whether there is a device attached to the port. */
1511 bool fAttached;
1512} XHCIHUBPORTR3;
1513/** Pointer to a ring-3 xHCI root hub port. */
1514typedef XHCIHUBPORTR3 *PXHCIHUBPORTR3;
1515
1516/**
1517 * The xHCI root hub, ring-3 only.
1518 *
1519 * @implements PDMIBASE
1520 * @implements VUSBIROOTHUBPORT
1521 */
1522typedef struct XHCIROOTHUBR3
1523{
1524 /** Pointer to the parent xHC. */
1525 R3PTRTYPE(struct XHCIR3 *) pXhciR3;
1526 /** Pointer to the base interface of the VUSB RootHub. */
1527 R3PTRTYPE(PPDMIBASE) pIBase;
1528 /** Pointer to the connector interface of the VUSB RootHub. */
1529 R3PTRTYPE(PVUSBIROOTHUBCONNECTOR) pIRhConn;
1530 /** The base interface exposed to the roothub driver. */
1531 PDMIBASE IBase;
1532 /** The roothub port interface exposed to the roothub driver. */
1533 VUSBIROOTHUBPORT IRhPort;
1534
1535 /** The LED for this hub. */
1536 PDMLED Led;
1537
1538 /** Number of actually implemented ports. */
1539 uint8_t cPortsImpl;
1540 /** Index of first port for this hub. */
1541 uint8_t uPortBase;
1542
1543 uint16_t Alignment0; /**< Force alignment. */
1544#if HC_ARCH_BITS == 64
1545 uint32_t Alignment1;
1546#endif
1547} XHCIROOTHUBR3;
1548/** Pointer to a xHCI root hub (ring-3 only). */
1549typedef XHCIROOTHUBR3 *PXHCIROOTHUBR3;
1550
1551/**
1552 * An xHCI interrupter.
1553 */
1554typedef struct sXHCIINTRPTR
1555{
1556 /* Registers defined by xHCI. */
1557 /** IMAN: Interrupt Management Register (R/W). */
1558 uint32_t iman;
1559 /** IMOD: Interrupt Moderation Register (R/W). */
1560 uint32_t imod;
1561 /** ERSTSZ: Event Ring Segment Table Size (R/W). */
1562 uint32_t erstsz;
1563 /* Reserved/padding. */
1564 uint32_t reserved;
1565 /** ERSTBA: Event Ring Segment Table Base Address (R/W). */
1566 uint64_t erstba;
1567 /** ERDP: Event Ring Dequeue Pointer (R/W). */
1568 uint64_t erdp;
1569 /* Interrupter lock. */
1570 PDMCRITSECT lock;
1571 /* Internal xHCI non-register state. */
1572 /** Internal Event Ring enqueue pointer. */
1573 uint64_t erep;
1574 /** Internal ERDP re-write counter. */
1575 uint32_t erdp_rewrites;
1576 /** This interrupter's index (for logging). */
1577 uint32_t index;
1578 /** Internal index into Event Ring Segment Table. */
1579 uint16_t erst_idx;
1580 /** Internal index into Event Ring Segment. */
1581 uint16_t trb_count;
1582 /** Internal Event Ring Producer Cycle State. */
1583 bool evtr_pcs;
1584 /** Internal Interrupt Pending Enable flag. */
1585 bool ipe;
1586} XHCIINTRPTR, *PXHCIINTRPTR;
1587
1588/**
1589 * xHCI device state.
1590 * @implements PDMILEDPORTS
1591 */
1592typedef struct XHCI
1593{
1594 /** MFINDEX wraparound timer. */
1595 TMTIMERHANDLE hWrapTimer;
1596
1597#ifdef XHCI_ERROR_INJECTION
1598 bool fDropIntrHw;
1599 bool fDropIntrIpe;
1600 bool fDropUrb;
1601 uint8_t Alignment00[1];
1602#else
1603 uint32_t Alignment00; /**< Force alignment. */
1604#endif
1605
1606 /** Flag indicating a pending worker thread notification. */
1607 volatile bool fNotificationSent;
1608 volatile bool afPadding[3];
1609
1610 /** The event semaphore the worker thread waits on. */
1611 SUPSEMEVENT hEvtProcess;
1612
1613 /** Bitmap for finished tasks (R3 -> Guest). */
1614 volatile uint32_t u32TasksFinished;
1615 /** Bitmap for finished queued tasks (R3 -> Guest). */
1616 volatile uint32_t u32QueuedTasksFinished;
1617 /** Bitmap for new queued tasks (Guest -> R3). */
1618 volatile uint32_t u32TasksNew;
1619
1620 /** Copy of XHCIR3::RootHub2::cPortsImpl. */
1621 uint8_t cUsb2Ports;
1622 /** Copy of XHCIR3::RootHub3::cPortsImpl. */
1623 uint8_t cUsb3Ports;
1624 /** Sum of cUsb2Ports and cUsb3Ports. */
1625 uint8_t cTotalPorts;
1626 /** Explicit padding. */
1627 uint8_t bPadding;
1628
1629 /** Start of current frame. */
1630 uint64_t SofTime;
1631 /** State of the individual ports. */
1632 XHCIHUBPORT aPorts[XHCI_NDP_MAX];
1633 /** Interrupters array. */
1634 XHCIINTRPTR aInterrupters[XHCI_NINTR];
1635
1636 /** @name Host Controller Capability Registers
1637 * @{ */
1638 /** CAPLENGTH: base + CAPLENGTH = operational register start (R/O). */
1639 uint32_t cap_length;
1640 /** HCIVERSION: host controller interface version (R/O). */
1641 uint32_t hci_version;
1642 /** HCSPARAMS: Structural parameters 1 (R/O). */
1643 uint32_t hcs_params1;
1644 /** HCSPARAMS: Structural parameters 2 (R/O). */
1645 uint32_t hcs_params2;
1646 /** HCSPARAMS: Structural parameters 3 (R/O). */
1647 uint32_t hcs_params3;
1648 /** HCCPARAMS: Capability parameters (R/O). */
1649 uint32_t hcc_params;
1650 /** DBOFF: Doorbell offset (R/O). */
1651 uint32_t dbell_off;
1652 /** RTSOFF: Run-time register space offset (R/O). */
1653 uint32_t rts_off;
1654 /** @} */
1655
1656 /** @name Host Controller Operational Registers
1657 * @{ */
1658 /** USB command register - USBCMD (R/W). */
1659 uint32_t cmd;
1660 /** USB status register - USBSTS (R/W).*/
1661 uint32_t status;
1662 /** Device Control Notification register - DNCTRL (R/W). */
1663 uint32_t dnctrl;
1664 /** Configure Register (R/W). */
1665 uint32_t config;
1666 /** Command Ring Control Register - CRCR (R/W). */
1667 uint64_t crcr;
1668 /** Device Context Base Address Array Pointer (R/W). */
1669 uint64_t dcbaap;
1670 /** @} */
1671
1672 /** Extended Capabilities storage. */
1673 uint8_t abExtCap[XHCI_EXT_CAP_SIZE];
1674 /** Size of valid extended capabilities. */
1675 uint32_t cbExtCap;
1676
1677 uint32_t Alignment1; /**< Align cmdr_dqp. */
1678
1679 /** @name Internal xHCI non-register state
1680 * @{ */
1681 /** Internal Command Ring dequeue pointer. */
1682 uint64_t cmdr_dqp;
1683 /** Internal Command Ring Consumer Cycle State. */
1684 bool cmdr_ccs;
1685 uint8_t aAlignment2[7]; /**< Force alignment. */
1686 /** Internal Device Slot states. */
1687 uint8_t aSlotState[XHCI_NDS];
1688 /** Internal doorbell states. Each bit corresponds to an endpoint. */
1689 uint32_t aBellsRung[XHCI_NDS];
1690 /** @} */
1691
1692 /** @name Model specific configuration
1693 * @{ */
1694 /** ERST address mask. */
1695 uint64_t erst_addr_mask;
1696 /** @} */
1697
1698 /** The MMIO region. */
1699 IOMMMIOHANDLE hMmio;
1700
1701 /** Detected isochronous URBs completed with error. */
1702 STAMCOUNTER StatErrorIsocUrbs;
1703 /** Detected isochronous packets (not URBs!) with error. */
1704 STAMCOUNTER StatErrorIsocPkts;
1705
1706 /** Event TRBs written to event ring(s). */
1707 STAMCOUNTER StatEventsWritten;
1708 /** Event TRBs not written to event ring(s) due to HC being stopped. */
1709 STAMCOUNTER StatEventsDropped;
1710 /** Requests to set the IP bit. */
1711 STAMCOUNTER StatIntrsPending;
1712 /** Actual interrupt deliveries. */
1713 STAMCOUNTER StatIntrsSet;
1714 /** Interrupts not raised because they were disabled. */
1715 STAMCOUNTER StatIntrsNotSet;
1716 /** A pending interrupt was cleared. */
1717 STAMCOUNTER StatIntrsCleared;
1718 /** Number of TRBs that formed a single control URB. */
1719 STAMCOUNTER StatTRBsPerCtlUrb;
1720 /** Number of TRBs that formed a single data (bulk/interrupt) URB. */
1721 STAMCOUNTER StatTRBsPerDtaUrb;
1722 /** Number of TRBs that formed a single isochronous URB. */
1723 STAMCOUNTER StatTRBsPerIsoUrb;
1724 /** Size of a control URB in bytes. */
1725 STAMCOUNTER StatUrbSizeCtrl;
1726 /** Size of a data URB in bytes. */
1727 STAMCOUNTER StatUrbSizeData;
1728 /** Size of an isochronous URB in bytes. */
1729 STAMCOUNTER StatUrbSizeIsoc;
1730
1731#ifdef VBOX_WITH_STATISTICS
1732 /** @name Register access counters.
1733 * @{ */
1734 STAMCOUNTER StatRdCaps;
1735 STAMCOUNTER StatRdCmdRingCtlHi;
1736 STAMCOUNTER StatRdCmdRingCtlLo;
1737 STAMCOUNTER StatRdConfig;
1738 STAMCOUNTER StatRdDevCtxBaapHi;
1739 STAMCOUNTER StatRdDevCtxBaapLo;
1740 STAMCOUNTER StatRdDevNotifyCtrl;
1741 STAMCOUNTER StatRdDoorBell;
1742 STAMCOUNTER StatRdEvtRingDeqPtrHi;
1743 STAMCOUNTER StatRdEvtRingDeqPtrLo;
1744 STAMCOUNTER StatRdEvtRsTblBaseHi;
1745 STAMCOUNTER StatRdEvtRsTblBaseLo;
1746 STAMCOUNTER StatRdEvtRstblSize;
1747 STAMCOUNTER StatRdEvtRsvd;
1748 STAMCOUNTER StatRdIntrMgmt;
1749 STAMCOUNTER StatRdIntrMod;
1750 STAMCOUNTER StatRdMfIndex;
1751 STAMCOUNTER StatRdPageSize;
1752 STAMCOUNTER StatRdPortLinkInfo;
1753 STAMCOUNTER StatRdPortPowerMgmt;
1754 STAMCOUNTER StatRdPortRsvd;
1755 STAMCOUNTER StatRdPortStatusCtrl;
1756 STAMCOUNTER StatRdUsbCmd;
1757 STAMCOUNTER StatRdUsbSts;
1758 STAMCOUNTER StatRdUnknown;
1759
1760 STAMCOUNTER StatWrCmdRingCtlHi;
1761 STAMCOUNTER StatWrCmdRingCtlLo;
1762 STAMCOUNTER StatWrConfig;
1763 STAMCOUNTER StatWrDevCtxBaapHi;
1764 STAMCOUNTER StatWrDevCtxBaapLo;
1765 STAMCOUNTER StatWrDevNotifyCtrl;
1766 STAMCOUNTER StatWrDoorBell0;
1767 STAMCOUNTER StatWrDoorBellN;
1768 STAMCOUNTER StatWrEvtRingDeqPtrHi;
1769 STAMCOUNTER StatWrEvtRingDeqPtrLo;
1770 STAMCOUNTER StatWrEvtRsTblBaseHi;
1771 STAMCOUNTER StatWrEvtRsTblBaseLo;
1772 STAMCOUNTER StatWrEvtRstblSize;
1773 STAMCOUNTER StatWrIntrMgmt;
1774 STAMCOUNTER StatWrIntrMod;
1775 STAMCOUNTER StatWrPortPowerMgmt;
1776 STAMCOUNTER StatWrPortStatusCtrl;
1777 STAMCOUNTER StatWrUsbCmd;
1778 STAMCOUNTER StatWrUsbSts;
1779 STAMCOUNTER StatWrUnknown;
1780 /** @} */
1781#endif
1782} XHCI;
1783
1784/**
1785 * xHCI device state, ring-3 edition.
1786 * @implements PDMILEDPORTS
1787 */
1788typedef struct XHCIR3
1789{
1790 /** The async worker thread. */
1791 R3PTRTYPE(PPDMTHREAD) pWorkerThread;
1792 /** The device instance.
1793 * @note This is only so interface functions can get their bearings. */
1794 PPDMDEVINSR3 pDevIns;
1795
1796 /** Status LUN: The base interface. */
1797 PDMIBASE IBase;
1798 /** Status LUN: Leds interface. */
1799 PDMILEDPORTS ILeds;
1800 /** Status LUN: Partner of ILeds. */
1801 R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector;
1802
1803 /** USB 2.0 Root hub device. */
1804 XHCIROOTHUBR3 RootHub2;
1805 /** USB 3.0 Root hub device. */
1806 XHCIROOTHUBR3 RootHub3;
1807
1808 /** State of the individual ports. */
1809 XHCIHUBPORTR3 aPorts[XHCI_NDP_MAX];
1810
1811 /** Critsect to synchronize worker and I/O completion threads. */
1812 RTCRITSECT CritSectThrd;
1813} XHCIR3;
1814/** Pointer to ring-3 xHCI device state. */
1815typedef XHCIR3 *PXHCIR3;
1816
1817/**
1818 * xHCI device data, ring-0 edition.
1819 */
1820typedef struct XHCIR0
1821{
1822 uint32_t uUnused;
1823} XHCIR0;
1824/** Pointer to ring-0 xHCI device data. */
1825typedef struct XHCIR0 *PXHCIR0;
1826
1827
1828/**
1829 * xHCI device data, raw-mode edition.
1830 */
1831typedef struct XHCIRC
1832{
1833 uint32_t uUnused;
1834} XHCIRC;
1835/** Pointer to raw-mode xHCI device data. */
1836typedef struct XHCIRC *PXHCIRC;
1837
1838
1839/** @typedef XHCICC
1840 * The xHCI device data for the current context. */
1841typedef CTX_SUFF(XHCI) XHCICC;
1842/** @typedef PXHCICC
1843 * Pointer to the xHCI device for the current context. */
1844typedef CTX_SUFF(PXHCI) PXHCICC;
1845
1846
1847/* -=-= Local implementation details =-=- */
1848
1849typedef enum sXHCI_JOB {
1850 XHCI_JOB_PROCESS_CMDRING, /**< Process the command ring. */
1851 XHCI_JOB_DOORBELL, /**< A doorbell (other than DB0) was rung. */
1852 XHCI_JOB_XFER_DONE, /**< Transfer completed, look for more work. */
1853 XHCI_JOB_MAX
1854} XHCI_JOB;
1855
1856/* -=-=- Local xHCI definitions -=-=- */
1857
1858/** @name USB states.
1859 * @{ */
1860#define XHCI_USB_RESET 0x00
1861#define XHCI_USB_RESUME 0x40
1862#define XHCI_USB_OPERATIONAL 0x80
1863#define XHCI_USB_SUSPEND 0xc0
1864/** @} */
1865
1866/* Primary interrupter (for readability). */
1867#define XHCI_PRIMARY_INTERRUPTER 0
1868
1869/** @name Device Slot states.
1870 * @{ */
1871#define XHCI_DEVSLOT_EMPTY 0
1872#define XHCI_DEVSLOT_ENABLED 1
1873#define XHCI_DEVSLOT_DEFAULT 2
1874#define XHCI_DEVSLOT_ADDRESSED 3
1875#define XHCI_DEVSLOT_CONFIGURED 4
1876/** @} */
1877
1878/** Get the pointer to a root hub corresponding to given port index. */
1879#define GET_PORT_PRH(a_pThisCC, a_uPort) \
1880 ((a_uPort) >= (a_pThisCC)->RootHub2.cPortsImpl ? &(a_pThisCC)->RootHub3 : &(a_pThisCC)->RootHub2)
1881#define GET_VUSB_PORT_FROM_XHCI_PORT(a_pRh, a_iPort) \
1882 (((a_iPort) - (a_pRh)->uPortBase) + 1)
1883#define GET_XHCI_PORT_FROM_VUSB_PORT(a_pRh, a_uPort) \
1884 ((a_pRh)->uPortBase + (a_uPort) - 1)
1885
1886/** Check if port corresponding to index is USB3, using shared data. */
1887#define IS_USB3_PORT_IDX_SHR(a_pThis, a_uPort) ((a_uPort) >= (a_pThis)->cUsb2Ports)
1888
1889/** Check if port corresponding to index is USB3, using ring-3 data. */
1890#define IS_USB3_PORT_IDX_R3(a_pThisCC, a_uPort) ((a_uPort) >= (a_pThisCC)->RootHub2.cPortsImpl)
1891
1892/** Query the number of configured USB2 ports. */
1893#define XHCI_NDP_USB2(a_pThisCC) ((unsigned)(a_pThisCC)->RootHub2.cPortsImpl)
1894
1895/** Query the number of configured USB3 ports. */
1896#define XHCI_NDP_USB3(a_pThisCC) ((unsigned)(a_pThisCC)->RootHub3.cPortsImpl)
1897
1898/** Query the total number of configured ports. */
1899#define XHCI_NDP_CFG(a_pThis) ((unsigned)RT_MIN((a_pThis)->cTotalPorts, XHCI_NDP_MAX))
1900
1901
1902#ifndef VBOX_DEVICE_STRUCT_TESTCASE
1903
1904
1905/*********************************************************************************************************************************
1906* Internal Functions *
1907*********************************************************************************************************************************/
1908
1909#ifdef IN_RING3
1910
1911/** Build a Protocol extended capability. */
1912static uint32_t xhciR3BuildProtocolCaps(uint8_t *pbCap, uint32_t cbMax, int cPorts, int nPortOfs, int ver)
1913{
1914 uint32_t *pu32Cap = (uint32_t *)pbCap;
1915 unsigned cPsi;
1916
1917 Assert(nPortOfs + cPorts < 255);
1918 Assert(ver == 2 || ver == 3);
1919
1920 cPsi = 0; /* Currently only implied port speed IDs. */
1921
1922 /* Make sure there's enough room. */
1923 if (cPsi * 4 + 16 > cbMax)
1924 return 0;
1925
1926 /* Header - includes (USB) specification version. */
1927 *pu32Cap++ = (ver << 24) | (0 << 16) | XHCI_XCP_PROTOCOL;
1928 /* Specification - 'USB ' */
1929 *pu32Cap++ = 0x20425355;
1930 /* Port offsets and counts. 1-based! */
1931 *pu32Cap++ = (cPsi << 28) | (cPorts << 8) | (nPortOfs + 1);
1932 /* Reserved dword. */
1933 *pu32Cap++ = 0;
1934
1935 return (uint8_t *)pu32Cap - pbCap;
1936}
1937
1938
1939/** Add an extended capability and link it into the chain. */
1940static int xhciR3AddExtCap(PXHCI pThis, const uint8_t *pCap, uint32_t cbCap, uint32_t *puPrevOfs)
1941{
1942 Assert(*puPrevOfs <= pThis->cbExtCap);
1943 Assert(!(cbCap & 3));
1944
1945 /* Check that the extended capability is sane. */
1946 if (cbCap == 0)
1947 return VERR_BUFFER_UNDERFLOW;
1948 if (pThis->cbExtCap + cbCap > XHCI_EXT_CAP_SIZE)
1949 return VERR_BUFFER_OVERFLOW;
1950 if (cbCap > 255 * 4) /* Size must fit into 8-bit dword count. */
1951 return VERR_BUFFER_OVERFLOW;
1952
1953 /* Copy over the capability data and update offsets. */
1954 memcpy(pThis->abExtCap + pThis->cbExtCap, pCap, cbCap);
1955 pThis->abExtCap[*puPrevOfs + 1] = cbCap >> 2;
1956 pThis->abExtCap[pThis->cbExtCap + 1] = 0;
1957 *puPrevOfs = pThis->cbExtCap;
1958 pThis->cbExtCap += cbCap;
1959 return VINF_SUCCESS;
1960}
1961
1962/** Build the xHCI Extended Capabilities region. */
1963static int xhciR3BuildExtCaps(PXHCI pThis, PXHCICC pThisCC)
1964{
1965 int rc;
1966 uint8_t abXcp[MAX_XCAP_SIZE];
1967 uint32_t cbXcp;
1968 uint32_t uPrevOfs = 0;
1969
1970 Assert(XHCI_NDP_USB2(pThisCC));
1971 Assert(XHCI_NDP_USB3(pThisCC));
1972
1973 /* Most of the extended capabilities are optional or not relevant for PCI
1974 * implementations. However, the Supported Protocol caps are required.
1975 */
1976 cbXcp = xhciR3BuildProtocolCaps(abXcp, sizeof(abXcp), XHCI_NDP_USB2(pThisCC), 0, 2);
1977 rc = xhciR3AddExtCap(pThis, abXcp, cbXcp, &uPrevOfs);
1978 AssertReturn(RT_SUCCESS(rc), rc);
1979
1980 cbXcp = xhciR3BuildProtocolCaps(abXcp, sizeof(abXcp), XHCI_NDP_USB3(pThisCC), XHCI_NDP_USB2(pThisCC), 3);
1981 rc = xhciR3AddExtCap(pThis, abXcp, cbXcp, &uPrevOfs);
1982 AssertReturn(RT_SUCCESS(rc), rc);
1983
1984 return VINF_SUCCESS;
1985}
1986
1987
1988/**
1989 * Select an unused device address. Note that this may fail in the unlikely
1990 * case where all possible addresses are exhausted.
1991 */
1992static uint8_t xhciR3SelectNewAddress(PXHCI pThis, uint8_t uSlotID)
1993{
1994 RT_NOREF(pThis, uSlotID);
1995
1996 /*
1997 * Since there is a 1:1 mapping between USB devices and device slots, we
1998 * should be able to assign a USB address which equals slot ID to any USB
1999 * device. However, the address selection algorithm could be completely
2000 * different (it is not defined by the xHCI spec).
2001 */
2002 return uSlotID;
2003}
2004
2005
2006/**
2007 * Read the address of a device context for a slot from the DCBAA.
2008 *
2009 * @returns Given slot's device context base address.
2010 * @param pDevIns The device instance.
2011 * @param pThis Pointer to the xHCI state.
2012 * @param uSlotID Slot ID to get the context address of.
2013 */
2014static uint64_t xhciR3FetchDevCtxAddr(PPDMDEVINS pDevIns, PXHCI pThis, uint8_t uSlotID)
2015{
2016 uint64_t uCtxAddr;
2017 RTGCPHYS GCPhysDCBAAE;
2018
2019 Assert(uSlotID > 0);
2020 Assert(uSlotID < XHCI_NDS);
2021
2022 /* Fetch the address of the output slot context from the DCBAA. */
2023 GCPhysDCBAAE = pThis->dcbaap + uSlotID * sizeof(uint64_t);
2024 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysDCBAAE, &uCtxAddr, sizeof(uCtxAddr));
2025 LogFlowFunc(("Slot ID %u, device context @ %RGp\n", uSlotID, uCtxAddr));
2026 Assert(uCtxAddr);
2027
2028 return uCtxAddr & XHCI_CTX_ADDR_MASK;
2029}
2030
2031
2032/**
2033 * Fetch a device's slot or endpoint context from memory.
2034 *
2035 * @param pDevIns The device instance.
2036 * @param pThis The xHCI device state.
2037 * @param uSlotID Slot ID to access.
2038 * @param uDCI Device Context Index.
2039 * @param pCtx Pointer to storage for the context.
2040 */
2041static int xhciR3FetchDevCtx(PPDMDEVINS pDevIns, PXHCI pThis, uint8_t uSlotID, uint8_t uDCI, void *pCtx)
2042{
2043 RTGCPHYS GCPhysCtx;
2044
2045 GCPhysCtx = xhciR3FetchDevCtxAddr(pDevIns, pThis, uSlotID);
2046 LogFlowFunc(("Reading device context @ %RGp, DCI %u\n", GCPhysCtx, uDCI));
2047 GCPhysCtx += uDCI * sizeof(XHCI_SLOT_CTX);
2048 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysCtx, pCtx, sizeof(XHCI_SLOT_CTX));
2049 return VINF_SUCCESS;
2050}
2051
2052
2053/**
2054 * Fetch a device's slot and endpoint contexts from guest memory.
2055 *
2056 * @param pDevIns The device instance.
2057 * @param pThis The xHCI device state.
2058 * @param uSlotID Slot ID to access.
2059 * @param uDCI Endpoint Device Context Index.
2060 * @param pSlot Pointer to storage for the slot context.
2061 * @param pEp Pointer to storage for the endpoint context.
2062 */
2063static int xhciR3FetchCtxAndEp(PPDMDEVINS pDevIns, PXHCI pThis, uint8_t uSlotID, uint8_t uDCI, XHCI_SLOT_CTX *pSlot, XHCI_EP_CTX *pEp)
2064{
2065 AssertPtr(pSlot);
2066 AssertPtr(pEp);
2067 Assert(uDCI); /* Can't be 0 -- that's the device context. */
2068
2069 /* Load the slot context. */
2070 xhciR3FetchDevCtx(pDevIns, pThis, uSlotID, 0, pSlot);
2071 /// @todo sanity check the slot context here?
2072 Assert(pSlot->ctx_ent >= uDCI);
2073
2074 /* Load the endpoint context. */
2075 xhciR3FetchDevCtx(pDevIns, pThis, uSlotID, uDCI, pEp);
2076 /// @todo sanity check the endpoint context here?
2077
2078 return VINF_SUCCESS;
2079}
2080
2081
2082/**
2083 * Update an endpoint context in guest memory.
2084 *
2085 * @param pDevIns The device instance.
2086 * @param pThis The xHCI device state.
2087 * @param uSlotID Slot ID to access.
2088 * @param uDCI Endpoint Device Context Index.
2089 * @param pEp Pointer to storage of the endpoint context.
2090 */
2091static int xhciR3WriteBackEp(PPDMDEVINS pDevIns, PXHCI pThis, uint8_t uSlotID, uint8_t uDCI, XHCI_EP_CTX *pEp)
2092{
2093 RTGCPHYS GCPhysCtx;
2094
2095 AssertPtr(pEp);
2096 Assert(uDCI); /* Can't be 0 -- that's the device context. */
2097
2098 /// @todo sanity check the endpoint context here?
2099 /* Find the physical address. */
2100 GCPhysCtx = xhciR3FetchDevCtxAddr(pDevIns, pThis, uSlotID);
2101 LogFlowFunc(("Writing device context @ %RGp, DCI %u\n", GCPhysCtx, uDCI));
2102 GCPhysCtx += uDCI * sizeof(XHCI_SLOT_CTX);
2103 /* Write the updated context. */
2104 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysCtx, pEp, sizeof(XHCI_EP_CTX));
2105
2106 return VINF_SUCCESS;
2107}
2108
2109
2110/**
2111 * Modify an endpoint context such that it enters the running state.
2112 *
2113 * @param pEpCtx Pointer to the endpoint context.
2114 */
2115static void xhciR3EnableEP(XHCI_EP_CTX *pEpCtx)
2116{
2117 LogFlow(("Enabling EP, TRDP @ %RGp, DCS=%u\n", pEpCtx->trdp & XHCI_TRDP_ADDR_MASK, pEpCtx->trdp & XHCI_TRDP_DCS_MASK));
2118 pEpCtx->ep_state = XHCI_EPST_RUNNING;
2119 pEpCtx->trep = pEpCtx->trdp;
2120}
2121
2122#endif /* IN_RING3 */
2123
2124#define MFIND_PERIOD_NS (UINT64_C(2048) * 1000000)
2125
2126/**
2127 * Set up the MFINDEX wrap timer.
2128 */
2129static void xhciSetWrapTimer(PPDMDEVINS pDevIns, PXHCI pThis)
2130{
2131 uint64_t u64Now;
2132 uint64_t u64LastWrap;
2133 uint64_t u64Expire;
2134 int rc;
2135
2136 /* Try to avoid drift. */
2137 u64Now = PDMDevHlpTimerGet(pDevIns, pThis->hWrapTimer);
2138// u64LastWrap = u64Now - (u64Now % (0x3FFF * 125000));
2139 u64LastWrap = u64Now / MFIND_PERIOD_NS * MFIND_PERIOD_NS;
2140 /* The MFINDEX counter wraps around every 2048 milliseconds. */
2141 u64Expire = u64LastWrap + (uint64_t)2048 * 1000000;
2142 rc = PDMDevHlpTimerSet(pDevIns, pThis->hWrapTimer, u64Expire);
2143 AssertRC(rc);
2144}
2145
2146/**
2147 * Determine whether MSI/MSI-X is enabled for this PCI device.
2148 *
2149 * This influences interrupt handling in xHCI. NB: There should be a PCIDevXxx
2150 * function for this.
2151 */
2152static bool xhciIsMSIEnabled(PPDMPCIDEV pDevIns)
2153{
2154 uint16_t uMsgCtl;
2155
2156 uMsgCtl = PDMPciDevGetWord(pDevIns, XHCI_PCI_MSI_CAP_OFS + VBOX_MSI_CAP_MESSAGE_CONTROL);
2157 return !!(uMsgCtl & VBOX_PCI_MSI_FLAGS_ENABLE);
2158}
2159
2160/**
2161 * Get the worker thread going -- there's something to do.
2162 */
2163static void xhciKickWorker(PPDMDEVINS pDevIns, PXHCI pThis, XHCI_JOB enmJob, uint32_t uWorkDesc)
2164{
2165 RT_NOREF(enmJob, uWorkDesc);
2166
2167 /* Tell the worker thread there's something to do. */
2168 if (!ASMAtomicXchgBool(&pThis->fNotificationSent, true))
2169 {
2170 LogFlowFunc(("Signal event semaphore\n"));
2171 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtProcess);
2172 AssertRC(rc);
2173 }
2174}
2175
2176/**
2177 * Fetch the current ERST entry from guest memory.
2178 */
2179static void xhciFetchErstEntry(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip)
2180{
2181 RTGCPHYS GCPhysErste;
2182 XHCI_ERSTE entry;
2183
2184 Assert(ip->erst_idx < ip->erstsz);
2185 GCPhysErste = ip->erstba + ip->erst_idx * sizeof(XHCI_ERSTE);
2186 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysErste, &entry, sizeof(entry));
2187
2188 /*
2189 * 6.5 claims values in 16-4096 range are valid, but does not say what
2190 * happens for values outside of that range...
2191 */
2192 Assert((pThis->status & XHCI_STATUS_HCH) || (entry.size >= 16 && entry.size <= 4096));
2193
2194 /* Cache the entry data internally. */
2195 ip->erep = entry.addr & pThis->erst_addr_mask;
2196 ip->trb_count = entry.size;
2197 Log(("Fetched ERST Entry at %RGp: %u entries at %RGp\n", GCPhysErste, ip->trb_count, ip->erep));
2198}
2199
2200/**
2201 * Set the interrupter's IP and EHB bits and trigger an interrupt if required.
2202 *
2203 * @param pDevIns The PDM device instance.
2204 * @param pThis Pointer to the xHCI state.
2205 * @param ip Pointer to the interrupter structure.
2206 *
2207 */
2208static void xhciSetIntr(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip)
2209{
2210 Assert(pThis && ip);
2211 LogFlowFunc(("old IP: %u\n", !!(ip->iman & XHCI_IMAN_IP)));
2212
2213 if (!(ip->iman & XHCI_IMAN_IP))
2214 {
2215 /// @todo assert that we own the interrupter lock
2216 ASMAtomicOrU32(&pThis->status, XHCI_STATUS_EINT);
2217 ASMAtomicOrU64(&ip->erdp, XHCI_ERDP_EHB);
2218 ASMAtomicOrU32(&ip->iman, XHCI_IMAN_IP);
2219 if ((ip->iman & XHCI_IMAN_IE) && (pThis->cmd & XHCI_CMD_INTE))
2220 {
2221#ifdef XHCI_ERROR_INJECTION
2222 if (pThis->fDropIntrHw)
2223 {
2224 pThis->fDropIntrHw = false;
2225 ASMAtomicAndU32(&ip->iman, ~XHCI_IMAN_IP);
2226 }
2227 else
2228#endif
2229 {
2230 Log2(("Triggering interrupt on interrupter %u\n", ip->index));
2231 PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_HIGH);
2232 STAM_COUNTER_INC(&pThis->StatIntrsSet);
2233 }
2234 }
2235 else
2236 {
2237 Log2(("Not triggering interrupt on interrupter %u (interrupts disabled)\n", ip->index));
2238 STAM_COUNTER_INC(&pThis->StatIntrsNotSet);
2239 }
2240
2241 /* If MSI/MSI-X is in use, the IP bit is immediately cleared again. */
2242 if (xhciIsMSIEnabled(pDevIns->apPciDevs[0]))
2243 ASMAtomicAndU32(&ip->iman, ~XHCI_IMAN_IP);
2244 }
2245}
2246
2247#ifdef IN_RING3
2248
2249/**
2250 * Set the interrupter's IPE bit. If this causes a 0->1 transition, an
2251 * interrupt may be triggered.
2252 *
2253 * @param pDevIns The PDM device instance.
2254 * @param pThis Pointer to the xHCI state.
2255 * @param ip Pointer to the interrupter structure.
2256 */
2257static void xhciR3SetIntrPending(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip)
2258{
2259 uint16_t imodc = (ip->imod >> XHCI_IMOD_IMODC_SHIFT) & XHCI_IMOD_IMODC_MASK;
2260
2261 Assert(pThis && ip);
2262 LogFlowFunc(("old IPE: %u, IMODC: %u, EREP: %RGp, EHB: %u\n", ip->ipe, imodc, (RTGCPHYS)ip->erep, !!(ip->erdp & XHCI_ERDP_EHB)));
2263 STAM_COUNTER_INC(&pThis->StatIntrsPending);
2264
2265 if (!ip->ipe)
2266 {
2267#ifdef XHCI_ERROR_INJECTION
2268 if (pThis->fDropIntrIpe)
2269 {
2270 pThis->fDropIntrIpe = false;
2271 }
2272 else
2273#endif
2274 {
2275 ip->ipe = true;
2276 if (!(ip->erdp & XHCI_ERDP_EHB) && (imodc == 0))
2277 xhciSetIntr(pDevIns, pThis, ip);
2278 }
2279 }
2280}
2281
2282
2283/**
2284 * Check if there is space available for writing at least two events on the
2285 * event ring. See 4.9.4 for the state machine (right hand side of diagram).
2286 * If there's only room for one event, the Event Ring Full TRB will need to
2287 * be written out, hence the ring is considered full.
2288 *
2289 * @returns True if space is available, false otherwise.
2290 * @param pDevIns The PDM device instance.
2291 * @param pThis Pointer to the xHCI state.
2292 * @param pIntr Pointer to the interrupter structure.
2293 */
2294static bool xhciR3IsEvtRingFull(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR pIntr)
2295{
2296 uint64_t next_ptr;
2297 uint64_t erdp = pIntr->erdp & XHCI_ERDP_ADDR_MASK;
2298
2299 if (pIntr->trb_count > 1)
2300 {
2301 /* Check the current segment. */
2302 next_ptr = pIntr->erep + sizeof(XHCI_EVENT_TRB);
2303 }
2304 else
2305 {
2306 uint16_t erst_idx;
2307 XHCI_ERSTE entry;
2308 RTGCPHYS GCPhysErste;
2309
2310 /* Need to check the next segment. */
2311 erst_idx = pIntr->erst_idx + 1;
2312 if (erst_idx == pIntr->erstsz)
2313 erst_idx = 0;
2314 GCPhysErste = pIntr->erstba + erst_idx * sizeof(XHCI_ERSTE);
2315 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysErste, &entry, sizeof(entry));
2316 next_ptr = entry.addr & pThis->erst_addr_mask;
2317 }
2318
2319 /// @todo We'll have to remember somewhere that the ring is full
2320 return erdp == next_ptr;
2321}
2322
2323/**
2324 * Write an event to the given Event Ring. This implements a good chunk of
2325 * the event ring state machine in section 4.9.4 of the xHCI spec.
2326 *
2327 * @returns VBox status code. Error if event could not be enqueued.
2328 * @param pDevIns The PDM device instance.
2329 * @param pThis Pointer to the xHCI state.
2330 * @param pEvent Pointer to the Event TRB to be enqueued.
2331 * @param iIntr Index of the interrupter to write to.
2332 * @param fBlockInt Set if interrupt should be blocked (BEI bit).
2333 */
2334static int xhciR3WriteEvent(PPDMDEVINS pDevIns, PXHCI pThis, XHCI_EVENT_TRB *pEvent, unsigned iIntr, bool fBlockInt)
2335{
2336 PXHCIINTRPTR pIntr;
2337 int rc = VINF_SUCCESS;
2338
2339 LogFlowFunc(("Interrupter: %u\n", iIntr));
2340
2341 /* If the HC isn't running, events can not be generated. However,
2342 * especially port change events can be triggered at any time. We just
2343 * drop them here -- it's often not an error condition.
2344 */
2345 if (pThis->cmd & XHCI_CMD_RS)
2346 {
2347 STAM_COUNTER_INC(&pThis->StatEventsWritten);
2348 Assert(iIntr < XHCI_NINTR); /* Supplied by guest, potentially invalid. */
2349 pIntr = &pThis->aInterrupters[iIntr & XHCI_INTR_MASK];
2350
2351 /*
2352 * If the interrupter/event ring isn't in a sane state, just
2353 * give up and report Host Controller Error (HCE).
2354 */
2355 // pIntr->erst_idx
2356
2357 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pIntr->lock, VERR_IGNORED); /* R3 only, no rcBusy. */
2358 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pIntr->lock, rcLock); /* eventually, most call chains ignore the status. */
2359
2360 if (xhciR3IsEvtRingFull(pDevIns, pThis, pIntr))
2361 {
2362 LogRel(("xHCI: Event ring full!\n"));
2363 }
2364
2365 /* Set the TRB's Cycle bit as appropriate. */
2366 pEvent->gen.cycle = pIntr->evtr_pcs;
2367
2368 /* Write out the TRB and advance the EREP. */
2369 /// @todo This either has to be atomic from the guest's POV or the cycle bit needs to be toggled last!!
2370 PDMDevHlpPCIPhysWriteMeta(pDevIns, pIntr->erep, pEvent, sizeof(*pEvent));
2371 pIntr->erep += sizeof(*pEvent);
2372 --pIntr->trb_count;
2373
2374 /* Advance to the next ERST entry if necessary. */
2375 if (pIntr->trb_count == 0)
2376 {
2377 ++pIntr->erst_idx;
2378 /* If necessary, roll over back to the beginning. */
2379 if (pIntr->erst_idx == pIntr->erstsz)
2380 {
2381 pIntr->erst_idx = 0;
2382 pIntr->evtr_pcs = !pIntr->evtr_pcs;
2383 }
2384 xhciFetchErstEntry(pDevIns, pThis, pIntr);
2385 }
2386
2387 /* Set the IPE bit unless interrupts are blocked. */
2388 if (!fBlockInt)
2389 xhciR3SetIntrPending(pDevIns, pThis, pIntr);
2390
2391 PDMDevHlpCritSectLeave(pDevIns, &pIntr->lock);
2392 }
2393 else
2394 {
2395 STAM_COUNTER_INC(&pThis->StatEventsDropped);
2396 Log(("Event dropped because HC is not running.\n"));
2397 }
2398
2399 return rc;
2400}
2401
2402
2403/**
2404 * Post a port change TRB to an Event Ring.
2405 */
2406static int xhciR3GenPortChgEvent(PPDMDEVINS pDevIns, PXHCI pThis, uint8_t uPort)
2407{
2408 XHCI_EVENT_TRB ed; /* Event Descriptor */
2409 LogFlowFunc(("Port ID: %u\n", uPort));
2410
2411 /*
2412 * Devices can be "physically" attached/detached regardless of whether
2413 * the HC is running or not, but the port status change events can only
2414 * be generated when R/S is set; xhciR3WriteEvent() takes care of that.
2415 */
2416 RT_ZERO(ed);
2417 ed.psce.cc = XHCI_TCC_SUCCESS;
2418 ed.psce.port_id = uPort;
2419 ed.psce.type = XHCI_TRB_PORT_SC;
2420 return xhciR3WriteEvent(pDevIns, pThis, &ed, XHCI_PRIMARY_INTERRUPTER, false);
2421}
2422
2423
2424/**
2425 * Post a command completion TRB to an Event Ring.
2426 */
2427static int xhciR3PostCmdCompletion(PPDMDEVINS pDevIns, PXHCI pThis, unsigned cc, unsigned uSlotID)
2428{
2429 XHCI_EVENT_TRB ed; /* Event Descriptor */
2430 LogFlowFunc(("Cmd @ %RGp, Completion Code: %u (%s), Slot ID: %u\n", (RTGCPHYS)pThis->cmdr_dqp, cc,
2431 cc < RT_ELEMENTS(g_apszCmplCodes) ? g_apszCmplCodes[cc] : "WHAT?!!", uSlotID));
2432
2433 /* The Command Ring dequeue pointer still holds the address of the current
2434 * command TRB. It is written to the completion event TRB as the command
2435 * TRB pointer.
2436 */
2437 RT_ZERO(ed);
2438 ed.cce.trb_ptr = pThis->cmdr_dqp;
2439 ed.cce.cc = cc;
2440 ed.cce.type = XHCI_TRB_CMD_CMPL;
2441 ed.cce.slot_id = uSlotID;
2442 return xhciR3WriteEvent(pDevIns, pThis, &ed, XHCI_PRIMARY_INTERRUPTER, false);
2443}
2444
2445
2446/**
2447 * Post a transfer event TRB to an Event Ring.
2448 */
2449static int xhciR3PostXferEvent(PPDMDEVINS pDevIns, PXHCI pThis, unsigned uIntTgt, unsigned uXferLen, unsigned cc,
2450 unsigned uSlotID, unsigned uEpDCI, uint64_t uEvtData, bool fBlockInt, bool fEvent)
2451{
2452 XHCI_EVENT_TRB ed; /* Event Descriptor */
2453 LogFlowFunc(("Xfer @ %RGp, Completion Code: %u (%s), Slot ID=%u DCI=%u Target=%u EvtData=%RX64 XfrLen=%u BEI=%u ED=%u\n",
2454 (RTGCPHYS)pThis->cmdr_dqp, cc, cc < RT_ELEMENTS(g_apszCmplCodes) ? g_apszCmplCodes[cc] : "WHAT?!!",
2455 uSlotID, uEpDCI, uIntTgt, uEvtData, uXferLen, fBlockInt, fEvent));
2456
2457 /* A transfer event may be either generated by TRB completion (in case
2458 * fEvent=false) or by a special transfer event TRB (fEvent=true). In
2459 * either case, interrupts may be suppressed.
2460 */
2461 RT_ZERO(ed);
2462 ed.te.trb_ptr = uEvtData;
2463 ed.te.xfr_len = uXferLen;
2464 ed.te.cc = cc;
2465 ed.te.ed = fEvent;
2466 ed.te.type = XHCI_TRB_XFER;
2467 ed.te.ep_id = uEpDCI;
2468 ed.te.slot_id = uSlotID;
2469 return xhciR3WriteEvent(pDevIns, pThis, &ed, uIntTgt, fBlockInt); /* Sets the cycle bit, too. */
2470}
2471
2472
2473static int xhciR3FindRhDevBySlot(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThisCC, uint8_t uSlotID, PXHCIROOTHUBR3 *ppRh, uint32_t *puPort)
2474{
2475 XHCI_SLOT_CTX slot_ctx;
2476 PXHCIROOTHUBR3 pRh;
2477 unsigned iPort;
2478 int rc;
2479
2480 /// @todo Do any of these need to be release assertions?
2481 Assert(uSlotID <= RT_ELEMENTS(pThis->aSlotState));
2482 Assert(pThis->aSlotState[ID_TO_IDX(uSlotID)] > XHCI_DEVSLOT_EMPTY);
2483
2484 /* Load the slot context. */
2485 xhciR3FetchDevCtx(pDevIns, pThis, uSlotID, 0, &slot_ctx);
2486
2487 /* The port ID is stored in the slot context. */
2488 iPort = ID_TO_IDX(slot_ctx.rh_port);
2489 if (iPort < XHCI_NDP_CFG(pThis))
2490 {
2491 /* Find the corresponding root hub. */
2492 pRh = GET_PORT_PRH(pThisCC, iPort);
2493 Assert(pRh);
2494
2495 /* And the device; if the device was ripped out fAttached will be false. */
2496 if (pThisCC->aPorts[iPort].fAttached)
2497 {
2498 /* Provide the information the caller asked for. */
2499 if (ppRh)
2500 *ppRh = pRh;
2501 if (puPort)
2502 *puPort = GET_VUSB_PORT_FROM_XHCI_PORT(pRh, iPort);
2503 rc = VINF_SUCCESS;
2504 }
2505 else
2506 {
2507 LogFunc(("No device attached (port index %u)!\n", iPort));
2508 rc = VERR_VUSB_DEVICE_NOT_ATTACHED;
2509 }
2510 }
2511 else
2512 {
2513 LogFunc(("Port out of range (index %u)!\n", iPort));
2514 rc = VERR_INVALID_PARAMETER;
2515 }
2516 return rc;
2517}
2518
2519
2520static void xhciR3EndlessTrbError(PPDMDEVINS pDevIns, PXHCI pThis)
2521{
2522 /* Clear the R/S bit and indicate controller error. */
2523 ASMAtomicAndU32(&pThis->cmd, ~XHCI_CMD_RS);
2524 ASMAtomicOrU32(&pThis->status, XHCI_STATUS_HCE);
2525
2526 /* Ensure that XHCI_STATUS_HCH gets set by the worker thread. */
2527 xhciKickWorker(pDevIns, pThis, XHCI_JOB_XFER_DONE, 0);
2528
2529 LogRelMax(10, ("xHCI: Attempted to process too many TRBs, stopping xHC!\n"));
2530}
2531
2532/**
2533 * TRB walker callback prototype.
2534 *
2535 * @returns true if walking should continue.
2536 * @returns false if walking should be terminated.
2537 * @param pDevIns The device instance.
2538 * @param pThis The xHCI device state.
2539 * @param pXferTRB Pointer to the transfer TRB to handle.
2540 * @param GCPhysXfrTRB Physical address of the TRB.
2541 * @param pvContext User-defined walk context.
2542 * @remarks We don't need to use DECLCALLBACKPTR here, since all users are in
2543 * the same source file, but having the functions marked with
2544 * DECLCALLBACK helps readability.
2545 */
2546typedef DECLCALLBACKPTR(bool, PFNTRBWALKCB,(PPDMDEVINS pDevIns, PXHCI pThis, const XHCI_XFER_TRB *pXferTRB,
2547 RTGCPHYS GCPhysXfrTRB, void *pvContext));
2548
2549
2550/**
2551 * Walk a chain of TRBs which comprise a single TD.
2552 *
2553 * This is something we need to do potentially more than once when submitting a
2554 * URB and then often again when completing the URB. Note that the walker does
2555 * not update the endpoint state (TRDP/TREP/DCS) so that it can be re-run
2556 * multiple times.
2557 *
2558 * @param pDevIns The device instance.
2559 * @param pThis The xHCI device state.
2560 * @param uTRP Initial TR pointer and DCS.
2561 * @param pfnCbk Callback routine.
2562 * @param pvContext User-defined walk context.
2563 * @param pTREP Pointer to storage for final TR Enqueue Pointer/DCS.
2564 */
2565static int xhciR3WalkXferTrbChain(PPDMDEVINS pDevIns, PXHCI pThis, uint64_t uTRP,
2566 PFNTRBWALKCB pfnCbk, void *pvContext, uint64_t *pTREP)
2567{
2568 RTGCPHYS GCPhysXfrTRB;
2569 uint64_t uTREP;
2570 XHCI_XFER_TRB XferTRB;
2571 bool fContinue = true;
2572 bool dcs;
2573 int rc = VINF_SUCCESS;
2574 unsigned cTrbs = 0;
2575
2576 AssertPtr(pvContext);
2577 AssertPtr(pTREP);
2578 Assert(uTRP);
2579
2580 /* Find the transfer TRB address and the DCS. */
2581 GCPhysXfrTRB = uTRP & XHCI_TRDP_ADDR_MASK;
2582 dcs = !!(uTRP & XHCI_TRDP_DCS_MASK); /* MSC upgrades bool to signed something when comparing with a uint8_t:1. */
2583 LogFlowFunc(("Walking Transfer Ring, TREP:%RGp DCS=%u\n", GCPhysXfrTRB, dcs));
2584
2585 do {
2586 /* Fetch the transfer TRB. */
2587 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysXfrTRB, &XferTRB, sizeof(XferTRB));
2588
2589 if ((bool)XferTRB.gen.cycle == dcs)
2590 {
2591 Log2(("Walking TRB@%RGp, type %u (%s) %u bytes ENT=%u ISP=%u NS=%u CH=%u IOC=%u IDT=%u\n", GCPhysXfrTRB, XferTRB.gen.type,
2592 XferTRB.gen.type < RT_ELEMENTS(g_apszTrbNames) ? g_apszTrbNames[XferTRB.gen.type] : "WHAT?!!",
2593 XferTRB.gen.xfr_len, XferTRB.gen.ent, XferTRB.gen.isp, XferTRB.gen.ns, XferTRB.gen.ch, XferTRB.gen.ioc, XferTRB.gen.idt));
2594
2595 /* DCS matches, the TRB is ours to process. */
2596 switch (XferTRB.gen.type) {
2597 case XHCI_TRB_LINK:
2598 Log2(("Link intra-TD: Ptr=%RGp IOC=%u TC=%u CH=%u\n", XferTRB.link.rseg_ptr, XferTRB.link.ioc, XferTRB.link.toggle, XferTRB.link.chain));
2599 Assert(XferTRB.link.chain);
2600 /* Do not update the actual TRDP/TREP and DCS yet, just the temporary images. */
2601 GCPhysXfrTRB = XferTRB.link.rseg_ptr & XHCI_TRDP_ADDR_MASK;
2602 if (XferTRB.link.toggle)
2603 dcs = !dcs;
2604 Assert(!XferTRB.link.ioc); /// @todo Needs to be reported.
2605 break;
2606 case XHCI_TRB_NORMAL:
2607 case XHCI_TRB_ISOCH:
2608 case XHCI_TRB_SETUP_STG:
2609 case XHCI_TRB_DATA_STG:
2610 case XHCI_TRB_STATUS_STG:
2611 case XHCI_TRB_EVT_DATA:
2612 fContinue = pfnCbk(pDevIns, pThis, &XferTRB, GCPhysXfrTRB, pvContext);
2613 GCPhysXfrTRB += sizeof(XferTRB);
2614 break;
2615 default:
2616 /* NB: No-op TRBs are not allowed within TDs (4.11.7). */
2617 Log(("Bad TRB type %u found within TD!!\n", XferTRB.gen.type));
2618 fContinue = false;
2619 /// @todo Stop EP etc.?
2620 }
2621 }
2622 else
2623 {
2624 /* We don't have a complete TD. Interesting times. */
2625 Log2(("DCS mismatch, no more TRBs available.\n"));
2626 fContinue = false;
2627 rc = VERR_TRY_AGAIN;
2628 }
2629
2630 /* Kill the xHC if the TRB list has no end in sight. */
2631 if (++cTrbs > XHCI_MAX_NUM_TRBS)
2632 {
2633 /* Stop the xHC with an error. */
2634 xhciR3EndlessTrbError(pDevIns, pThis);
2635
2636 /* Get out of the loop. */
2637 fContinue = false;
2638 rc = VERR_NOT_SUPPORTED; /* No good error code really... */
2639 }
2640 } while (fContinue);
2641
2642 /* Inform caller of the new TR Enqueue Pointer/DCS (not necessarily changed). */
2643 Assert(!(GCPhysXfrTRB & ~XHCI_TRDP_ADDR_MASK));
2644 uTREP = GCPhysXfrTRB | (unsigned)dcs;
2645 Log2(("Final TRP after walk: %RGp\n", uTREP));
2646 *pTREP = uTREP;
2647
2648 return rc;
2649}
2650
2651
2652/** Context for probing TD size. */
2653typedef struct {
2654 uint32_t uXferLen;
2655 uint32_t cTRB;
2656 uint32_t uXfrLenLastED;
2657 uint32_t cTRBLastED;
2658} XHCI_CTX_XFER_PROBE;
2659
2660
2661/** Context for submitting 'out' TDs. */
2662typedef struct {
2663 PVUSBURB pUrb;
2664 uint32_t uXferPos;
2665 unsigned cTRB;
2666} XHCI_CTX_XFER_SUBMIT;
2667
2668
2669/** Context for completing TDs. */
2670typedef struct {
2671 PVUSBURB pUrb;
2672 uint32_t uXferPos;
2673 uint32_t uXferLeft;
2674 unsigned cTRB;
2675 uint32_t uEDTLA : 24;
2676 uint32_t uLastCC : 8;
2677 uint8_t uSlotID;
2678 uint8_t uEpDCI;
2679 bool fMaxCount;
2680} XHCI_CTX_XFER_COMPLETE;
2681
2682
2683/** Context for building isochronous URBs. */
2684typedef struct {
2685 PVUSBURB pUrb;
2686 unsigned iPkt;
2687 uint32_t offCur;
2688 uint64_t uInitTREP;
2689 bool fSubmitFailed;
2690} XHCI_CTX_ISOCH;
2691
2692
2693/**
2694 * @callback_method_impl{PFNTRBWALKCB,
2695 * Probe a TD and figure out how big it is so that a URB can be allocated to back it.}
2696 */
2697static DECLCALLBACK(bool)
2698xhciR3WalkDataTRBsProbe(PPDMDEVINS pDevIns, PXHCI pThis, const XHCI_XFER_TRB *pXferTRB, RTGCPHYS GCPhysXfrTRB, void *pvContext)
2699{
2700 RT_NOREF(pDevIns, pThis, GCPhysXfrTRB);
2701 XHCI_CTX_XFER_PROBE *pCtx = (XHCI_CTX_XFER_PROBE *)pvContext;
2702
2703 pCtx->cTRB++;
2704
2705 /* Only consider TRBs which transfer data. */
2706 switch (pXferTRB->gen.type)
2707 {
2708 case XHCI_TRB_NORMAL:
2709 case XHCI_TRB_ISOCH:
2710 case XHCI_TRB_SETUP_STG:
2711 case XHCI_TRB_DATA_STG:
2712 case XHCI_TRB_STATUS_STG:
2713 pCtx->uXferLen += pXferTRB->norm.xfr_len;
2714 if (RT_UNLIKELY(pCtx->uXferLen > XHCI_MAX_TD_SIZE))
2715 {
2716 /* NB: We let the TD size get a bit past the max so that we don't lose anything,
2717 * but the EDTLA will wrap around.
2718 */
2719 LogRelMax(10, ("xHCI: TD size (%u) too big, not continuing!\n", pCtx->uXferLen));
2720 return false;
2721 }
2722 break;
2723 case XHCI_TRB_EVT_DATA:
2724 /* Remember where the last seen Event Data TRB was. */
2725 pCtx->cTRBLastED = pCtx->cTRB;
2726 pCtx->uXfrLenLastED = pCtx->uXferLen;
2727 break;
2728 default: /* Could be a link TRB, too. */
2729 break;
2730 }
2731
2732 return pXferTRB->gen.ch;
2733}
2734
2735
2736/**
2737 * @callback_method_impl{PFNTRBWALKCB,
2738 * Copy data from a TD (TRB chain) into the corresponding TD. OUT direction only.}
2739 */
2740static DECLCALLBACK(bool)
2741xhciR3WalkDataTRBsSubmit(PPDMDEVINS pDevIns, PXHCI pThis, const XHCI_XFER_TRB *pXferTRB, RTGCPHYS GCPhysXfrTRB, void *pvContext)
2742{
2743 RT_NOREF(pThis, GCPhysXfrTRB);
2744 XHCI_CTX_XFER_SUBMIT *pCtx = (XHCI_CTX_XFER_SUBMIT *)pvContext;
2745 uint32_t uXferLen = pXferTRB->norm.xfr_len;
2746
2747
2748 /* Only consider TRBs which transfer data. */
2749 switch (pXferTRB->gen.type)
2750 {
2751 case XHCI_TRB_NORMAL:
2752 case XHCI_TRB_ISOCH:
2753 case XHCI_TRB_SETUP_STG:
2754 case XHCI_TRB_DATA_STG:
2755 case XHCI_TRB_STATUS_STG:
2756 /* NB: Transfer length may be zero! */
2757 /// @todo explain/verify abuse of various TRB types here (data stage mapped to normal etc.).
2758 if (uXferLen)
2759 {
2760 /* Sanity check for broken guests (TRBs may have changed since probing). */
2761 if (pCtx->uXferPos + uXferLen <= pCtx->pUrb->cbData)
2762 {
2763 /* Data might be immediate or elsewhere in memory. */
2764 if (pXferTRB->norm.idt)
2765 {
2766 /* If an immediate data TRB claims there's more than 8 bytes, we have a problem. */
2767 if (uXferLen > 8)
2768 {
2769 LogRelMax(10, ("xHCI: Immediate data TRB length %u bytes, ignoring!\n", uXferLen));
2770 return false; /* Stop walking the chain immediately. */
2771 }
2772
2773 Assert(uXferLen >= 1 && uXferLen <= 8);
2774 Log2(("Copying %u bytes to URB offset %u (immediate data)\n", uXferLen, pCtx->uXferPos));
2775 memcpy(pCtx->pUrb->abData + pCtx->uXferPos, pXferTRB, uXferLen);
2776 }
2777 else
2778 {
2779 PDMDevHlpPCIPhysReadUser(pDevIns, pXferTRB->norm.data_ptr, pCtx->pUrb->abData + pCtx->uXferPos, uXferLen);
2780 Log2(("Copying %u bytes to URB offset %u (from %RGp)\n", uXferLen, pCtx->uXferPos, pXferTRB->norm.data_ptr));
2781 }
2782 pCtx->uXferPos += uXferLen;
2783 }
2784 else
2785 {
2786 LogRelMax(10, ("xHCI: Attempted to submit too much data, ignoring!\n"));
2787 return false; /* Stop walking the chain immediately. */
2788 }
2789
2790 }
2791 break;
2792 default: /* Could be an event or status stage TRB, too. */
2793 break;
2794 }
2795 pCtx->cTRB++;
2796
2797 /// @todo Maybe have to make certain that the number of probed TRBs matches? Potentially
2798 /// by the time TRBs get submitted, there might be more of them available if the TD was
2799 /// initially not fully written by HCD.
2800
2801 return pXferTRB->gen.ch;
2802}
2803
2804
2805/**
2806 * Perform URB completion processing.
2807 *
2808 * Figure out how much data was really transferred, post events if required, and
2809 * for IN transfers, copy data from the URB.
2810 *
2811 * @callback_method_impl{PFNTRBWALKCB}
2812 */
2813static DECLCALLBACK(bool)
2814xhciR3WalkDataTRBsComplete(PPDMDEVINS pDevIns, PXHCI pThis, const XHCI_XFER_TRB *pXferTRB, RTGCPHYS GCPhysXfrTRB, void *pvContext)
2815{
2816 XHCI_CTX_XFER_COMPLETE *pCtx = (XHCI_CTX_XFER_COMPLETE *)pvContext;
2817 int rc;
2818 unsigned uXferLen;
2819 unsigned uResidue;
2820 uint8_t cc;
2821 bool fKeepGoing = true;
2822
2823 switch (pXferTRB->gen.type)
2824 {
2825 case XHCI_TRB_NORMAL:
2826 case XHCI_TRB_ISOCH:
2827 case XHCI_TRB_SETUP_STG:
2828 case XHCI_TRB_DATA_STG: /// @todo document abuse; esp. check BEI bit
2829 case XHCI_TRB_STATUS_STG:
2830 /* Assume successful transfer. */
2831 uXferLen = pXferTRB->norm.xfr_len;
2832 cc = XHCI_TCC_SUCCESS;
2833
2834 /* If there was a short packet, handle it accordingly. */
2835 if (pCtx->uXferLeft < uXferLen)
2836 {
2837 /* The completion code is set regardless of IOC/ISP. It may be
2838 * reported later via an Event Data TRB (4.10.1.1)
2839 */
2840 uXferLen = pCtx->uXferLeft;
2841 cc = XHCI_TCC_SHORT_PKT;
2842 }
2843
2844 if (pCtx->pUrb->enmDir == VUSBDIRECTION_IN)
2845 {
2846 Assert(!pXferTRB->norm.idt);
2847
2848 /* NB: Transfer length may be zero! */
2849 if (uXferLen)
2850 {
2851 if (uXferLen <= pCtx->uXferLeft)
2852 {
2853 Log2(("Writing %u bytes to %RGp from URB offset %u (TRB@%RGp)\n", uXferLen, pXferTRB->norm.data_ptr, pCtx->uXferPos, GCPhysXfrTRB));
2854 PDMDevHlpPCIPhysWriteUser(pDevIns, pXferTRB->norm.data_ptr, pCtx->pUrb->abData + pCtx->uXferPos, uXferLen);
2855 }
2856 else
2857 {
2858 LogRelMax(10, ("xHCI: Attempted to read too much data, ignoring!\n"));
2859 }
2860 }
2861 }
2862
2863 /* Update position within TD. */
2864 pCtx->uXferLeft -= uXferLen;
2865 pCtx->uXferPos += uXferLen;
2866 Log2(("Current uXferLeft=%u, uXferPos=%u (length was %u)\n", pCtx->uXferLeft, pCtx->uXferPos, uXferLen));
2867
2868 /* Keep track of the EDTLA and last completion status. */
2869 pCtx->uEDTLA += uXferLen; /* May wrap around! */
2870 pCtx->uLastCC = cc;
2871
2872 /* Report events as required. */
2873 uResidue = pXferTRB->norm.xfr_len - uXferLen;
2874 if (pXferTRB->norm.ioc || (pXferTRB->norm.isp && uResidue))
2875 {
2876 rc = xhciR3PostXferEvent(pDevIns, pThis, pXferTRB->norm.int_tgt, uResidue, cc,
2877 pCtx->uSlotID, pCtx->uEpDCI, GCPhysXfrTRB, pXferTRB->norm.bei, false);
2878 }
2879 break;
2880 case XHCI_TRB_EVT_DATA:
2881 if (pXferTRB->evtd.ioc)
2882 {
2883 rc = xhciR3PostXferEvent(pDevIns, pThis, pXferTRB->evtd.int_tgt, pCtx->uEDTLA, pCtx->uLastCC,
2884 pCtx->uSlotID, pCtx->uEpDCI, pXferTRB->evtd.evt_data, pXferTRB->evtd.bei, true);
2885 }
2886 /* Clear the EDTLA. */
2887 pCtx->uEDTLA = 0;
2888 break;
2889 default:
2890 AssertMsgFailed(("%#x\n", pXferTRB->gen.type));
2891 break;
2892 }
2893
2894 pCtx->cTRB--;
2895 /* For TD fragments, enforce the maximum count, but only as long as the transfer
2896 * is successful. In case of error we have to complete the entire TD! */
2897 if (!pCtx->cTRB && pCtx->fMaxCount && pCtx->uLastCC == XHCI_TCC_SUCCESS)
2898 {
2899 Log2(("Stopping at the end of TD Fragment.\n"));
2900 fKeepGoing = false;
2901 }
2902
2903 /* NB: We currently do not enforce that the number of TRBs can't change between
2904 * submission and completion. If we do, we'll have to store it somewhere for
2905 * isochronous URBs.
2906 */
2907 return pXferTRB->gen.ch && fKeepGoing;
2908}
2909
2910/**
2911 * Process (consume) non-data TRBs on a transfer ring. This function
2912 * completes TRBs which do not have any URB associated with them. Only
2913 * used with running endpoints. Usable regardless of whether there are
2914 * in-flight TRBs or not. Returns the next TRB and its address to the
2915 * caller. May modify the endpoint context!
2916 *
2917 * @param pDevIns The device instance.
2918 * @param pThis The xHCI device state.
2919 * @param uSlotID The slot corresponding to this USB device.
2920 * @param uEpDCI The DCI of this endpoint.
2921 * @param pEpCtx Endpoint context. May be modified.
2922 * @param pXfer Storage for returning the next TRB to caller.
2923 * @param pGCPhys Storage for returning the physical address of TRB.
2924 */
2925static int xhciR3ConsumeNonXferTRBs(PPDMDEVINS pDevIns, PXHCI pThis, uint8_t uSlotID, uint8_t uEpDCI,
2926 XHCI_EP_CTX *pEpCtx, XHCI_XFER_TRB *pXfer, RTGCPHYS *pGCPhys)
2927{
2928 XHCI_XFER_TRB xfer;
2929 RTGCPHYS GCPhysXfrTRB = 0;
2930 bool dcs;
2931 bool fInFlight;
2932 bool fContinue = true;
2933 int rc;
2934 unsigned cTrbs = 0;
2935
2936 LogFlowFunc(("Slot ID: %u, EP DCI %u\n", uSlotID, uEpDCI));
2937 Assert(uSlotID > 0);
2938 Assert(uSlotID <= XHCI_NDS);
2939
2940 Assert(pEpCtx->ep_state == XHCI_EPST_RUNNING);
2941 do
2942 {
2943 /* Find the transfer TRB address. */
2944 GCPhysXfrTRB = pEpCtx->trdp & XHCI_TRDP_ADDR_MASK;
2945 dcs = !!(pEpCtx->trdp & XHCI_TRDP_DCS_MASK);
2946
2947 /* Determine whether there are any in-flight TRBs or not. This affects TREP
2948 * processing -- when nothing is in flight, we have to move both TREP and TRDP;
2949 * otherwise only the TRDP must be updated.
2950 */
2951 fInFlight = pEpCtx->trep != pEpCtx->trdp;
2952 LogFlowFunc(("Skipping non-data TRBs, TREP:%RGp, TRDP:%RGp, in-flight: %RTbool\n", pEpCtx->trep, pEpCtx->trdp, fInFlight));
2953
2954 /* Fetch the transfer TRB. */
2955 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysXfrTRB, &xfer, sizeof(xfer));
2956
2957 /* Make sure the Cycle State matches. */
2958 if ((bool)xfer.gen.cycle == dcs)
2959 {
2960 Log2(("TRB @ %RGp, type %u (%s) %u bytes ENT=%u ISP=%u NS=%u CH=%u IOC=%u IDT=%u\n", GCPhysXfrTRB, xfer.gen.type,
2961 xfer.gen.type < RT_ELEMENTS(g_apszTrbNames) ? g_apszTrbNames[xfer.gen.type] : "WHAT?!!",
2962 xfer.gen.xfr_len, xfer.gen.ent, xfer.gen.isp, xfer.gen.ns, xfer.gen.ch, xfer.gen.ioc, xfer.gen.idt));
2963
2964 switch (xfer.gen.type) {
2965 case XHCI_TRB_LINK:
2966 Log2(("Link extra-TD: Ptr=%RGp IOC=%u TC=%u CH=%u\n", xfer.link.rseg_ptr, xfer.link.ioc, xfer.link.toggle, xfer.link.chain));
2967 Assert(!xfer.link.chain);
2968 /* Set new TRDP but leave DCS bit alone... */
2969 pEpCtx->trdp = (xfer.link.rseg_ptr & XHCI_TRDP_ADDR_MASK) | (pEpCtx->trdp & XHCI_TRDP_DCS_MASK);
2970 /* ...and flip the DCS bit if required. Then update the TREP. */
2971 if (xfer.link.toggle)
2972 pEpCtx->trdp = (pEpCtx->trdp & ~XHCI_TRDP_DCS_MASK) | (pEpCtx->trdp ^ XHCI_TRDP_DCS_MASK);
2973 if (!fInFlight)
2974 pEpCtx->trep = pEpCtx->trdp;
2975 if (xfer.link.ioc)
2976 rc = xhciR3PostXferEvent(pDevIns, pThis, xfer.link.int_tgt, 0, XHCI_TCC_SUCCESS, uSlotID, uEpDCI,
2977 GCPhysXfrTRB, false, false);
2978 break;
2979 case XHCI_TRB_NOOP_XFER:
2980 Log2(("No op xfer: IOC=%u CH=%u ENT=%u\n", xfer.nop.ioc, xfer.nop.ch, xfer.nop.ent));
2981 /* A no-op transfer TRB must not be part of a chain. See 4.11.7. */
2982 Assert(!xfer.link.chain);
2983 /* Update enqueue/dequeue pointers. */
2984 pEpCtx->trdp += sizeof(XHCI_XFER_TRB);
2985 if (!fInFlight)
2986 pEpCtx->trep += sizeof(XHCI_XFER_TRB);
2987 if (xfer.nop.ioc)
2988 rc = xhciR3PostXferEvent(pDevIns, pThis, xfer.nop.int_tgt, 0, XHCI_TCC_SUCCESS, uSlotID, uEpDCI,
2989 GCPhysXfrTRB, false, false);
2990 break;
2991 default:
2992 fContinue = false;
2993 break;
2994 }
2995 }
2996 else
2997 {
2998 LogFunc(("Transfer Ring empty\n"));
2999 fContinue = false;
3000 }
3001
3002 /* Kill the xHC if the TRB list has no end in sight. */
3003 /* NB: The limit here could perhaps be much lower because a sequence of Link
3004 * and No-op TRBs with no real work to be done would be highly suspect.
3005 */
3006 if (++cTrbs > XHCI_MAX_NUM_TRBS)
3007 {
3008 /* Stop the xHC with an error. */
3009 xhciR3EndlessTrbError(pDevIns, pThis);
3010
3011 /* Get out of the loop. */
3012 fContinue = false;
3013 rc = VERR_NOT_SUPPORTED; /* No good error code really... */
3014 }
3015 } while (fContinue);
3016
3017 /* The caller will need the next TRB. Hand it over. */
3018 Assert(GCPhysXfrTRB);
3019 *pGCPhys = GCPhysXfrTRB;
3020 *pXfer = xfer;
3021 LogFlowFunc(("Final TREP:%RGp, TRDP:%RGp GCPhysXfrTRB:%RGp\n", pEpCtx->trep, pEpCtx->trdp, GCPhysXfrTRB));
3022
3023 return VINF_SUCCESS;
3024}
3025
3026/**
3027 * Transfer completion callback routine.
3028 *
3029 * VUSB will call this when a transfer have been completed
3030 * in a one or another way.
3031 *
3032 * @param pInterface Pointer to XHCI::ROOTHUB::IRhPort.
3033 * @param pUrb Pointer to the URB in question.
3034 */
3035static DECLCALLBACK(void) xhciR3RhXferCompletion(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb)
3036{
3037 PXHCIROOTHUBR3 pRh = RT_FROM_MEMBER(pInterface, XHCIROOTHUBR3, IRhPort);
3038 PXHCICC pThisCC = pRh->pXhciR3;
3039 PPDMDEVINS pDevIns = pThisCC->pDevIns;
3040 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
3041 XHCI_SLOT_CTX slot_ctx;
3042 XHCI_EP_CTX ep_ctx;
3043 XHCI_XFER_TRB xfer;
3044 RTGCPHYS GCPhysXfrTRB;
3045 int rc;
3046 unsigned uResidue = 0;
3047 uint8_t uSlotID = pUrb->pHci->uSlotID;
3048 uint8_t cc = XHCI_TCC_SUCCESS;
3049 uint8_t uEpDCI;
3050
3051 /* Check for URBs completed synchronously as part of xHCI command execution.
3052 * The URB will have zero cTRB as it's not associated with a TD.
3053 */
3054 if (!pUrb->pHci->cTRB)
3055 {
3056 LogFlow(("%s: xhciR3RhXferCompletion: uSlotID=%u EP=%u cTRB=%d cbData=%u status=%u\n",
3057 pUrb->pszDesc, uSlotID, pUrb->EndPt, pUrb->pHci->cTRB, pUrb->cbData, pUrb->enmStatus));
3058 LogFlow(("%s: xhciR3RhXferCompletion: Completing xHCI-generated request\n", pUrb->pszDesc));
3059 return;
3060 }
3061
3062 /* If the xHC isn't running, just drop the URB right here. */
3063 if (pThis->status & XHCI_STATUS_HCH)
3064 {
3065 LogFlow(("%s: xhciR3RhXferCompletion: uSlotID=%u EP=%u cTRB=%d cbData=%u status=%u\n",
3066 pUrb->pszDesc, uSlotID, pUrb->EndPt, pUrb->pHci->cTRB, pUrb->cbData, pUrb->enmStatus));
3067 LogFlow(("%s: xhciR3RhXferCompletion: xHC halted, skipping URB completion\n", pUrb->pszDesc));
3068 return;
3069 }
3070
3071#ifdef XHCI_ERROR_INJECTION
3072 if (pThis->fDropUrb)
3073 {
3074 LogFlow(("%s: xhciR3RhXferCompletion: Error injection, dropping URB!\n", pUrb->pszDesc));
3075 pThis->fDropUrb = false;
3076 return;
3077 }
3078#endif
3079
3080 RTCritSectEnter(&pThisCC->CritSectThrd);
3081
3082 /* Convert USB endpoint address to xHCI format. */
3083 if (pUrb->EndPt)
3084 uEpDCI = pUrb->EndPt * 2 + (pUrb->enmDir == VUSBDIRECTION_IN ? 1 : 0);
3085 else
3086 uEpDCI = 1; /* EP 0 */
3087
3088 LogFlow(("%s: xhciR3RhXferCompletion: uSlotID=%u EP=%u cTRB=%d\n",
3089 pUrb->pszDesc, uSlotID, pUrb->EndPt, pUrb->pHci->cTRB));
3090 LogFlow(("%s: xhciR3RhXferCompletion: EP DCI=%u, cbData=%u status=%u\n", pUrb->pszDesc, uEpDCI, pUrb->cbData, pUrb->enmStatus));
3091
3092 /* Load the slot/endpoint contexts from guest memory. */
3093 xhciR3FetchCtxAndEp(pDevIns, pThis, uSlotID, uEpDCI, &slot_ctx, &ep_ctx);
3094
3095 /* If the EP is disabled, we don't own it so we can't complete the URB.
3096 * Leave this EP alone and drop the URB.
3097 */
3098 if (ep_ctx.ep_state != XHCI_EPST_RUNNING)
3099 {
3100 Log(("EP DCI %u not running (state %u), skipping URB completion\n", uEpDCI, ep_ctx.ep_state));
3101 RTCritSectLeave(&pThisCC->CritSectThrd);
3102 return;
3103 }
3104
3105 /* Now complete any non-transfer TRBs that might be on the transfer ring before
3106 * the TRB(s) corresponding to this URB. Preloads the TRB as a side effect.
3107 * Endpoint state now must be written back in case it was modified!
3108 */
3109 xhciR3ConsumeNonXferTRBs(pDevIns, pThis, uSlotID, uEpDCI, &ep_ctx, &xfer, &GCPhysXfrTRB);
3110
3111 /* Deal with failures which halt the EP first. */
3112 if (RT_UNLIKELY(pUrb->enmStatus != VUSBSTATUS_OK))
3113 {
3114 switch(pUrb->enmStatus)
3115 {
3116 case VUSBSTATUS_STALL:
3117 /* Halt the endpoint and inform the HCD.
3118 * NB: The TRDP is NOT advanced in case of error.
3119 */
3120 ep_ctx.ep_state = XHCI_EPST_HALTED;
3121 cc = XHCI_TCC_STALL;
3122 rc = xhciR3PostXferEvent(pDevIns, pThis, xfer.gen.int_tgt, uResidue, cc,
3123 uSlotID, uEpDCI, GCPhysXfrTRB, false, false);
3124 break;
3125 case VUSBSTATUS_DNR:
3126 /* Halt the endpoint and inform the HCD.
3127 * NB: The TRDP is NOT advanced in case of error.
3128 */
3129 ep_ctx.ep_state = XHCI_EPST_HALTED;
3130 cc = XHCI_TCC_USB_XACT_ERR;
3131 rc = xhciR3PostXferEvent(pDevIns, pThis, xfer.gen.int_tgt, uResidue, cc,
3132 uSlotID, uEpDCI, GCPhysXfrTRB, false, false);
3133 break;
3134 case VUSBSTATUS_CRC: /// @todo Separate status for canceling?!
3135 ep_ctx.ep_state = XHCI_EPST_HALTED;
3136 cc = XHCI_TCC_USB_XACT_ERR;
3137 rc = xhciR3PostXferEvent(pDevIns, pThis, xfer.gen.int_tgt, uResidue, cc,
3138 uSlotID, uEpDCI, GCPhysXfrTRB, false, false);
3139
3140 /* NB: The TRDP is *not* advanced and TREP is reset. */
3141 ep_ctx.trep = ep_ctx.trdp;
3142 break;
3143 case VUSBSTATUS_DATA_OVERRUN:
3144 case VUSBSTATUS_DATA_UNDERRUN:
3145 /* Halt the endpoint and inform the HCD.
3146 * NB: The TRDP is NOT advanced in case of error.
3147 */
3148 ep_ctx.ep_state = XHCI_EPST_HALTED;
3149 cc = XHCI_TCC_DATA_BUF_ERR;
3150 rc = xhciR3PostXferEvent(pDevIns, pThis, xfer.gen.int_tgt, uResidue, cc,
3151 uSlotID, uEpDCI, GCPhysXfrTRB, false, false);
3152 break;
3153 default:
3154 AssertMsgFailed(("Unexpected URB status %u\n", pUrb->enmStatus));
3155 }
3156
3157 if (pUrb->enmType == VUSBXFERTYPE_ISOC)
3158 STAM_COUNTER_INC(&pThis->StatErrorIsocUrbs);
3159 }
3160 else if (xfer.gen.type == XHCI_TRB_NORMAL)
3161 {
3162 XHCI_CTX_XFER_COMPLETE ctxComplete;
3163 uint64_t uTRDP;
3164
3165 ctxComplete.pUrb = pUrb;
3166 ctxComplete.uXferPos = 0;
3167 ctxComplete.uXferLeft = pUrb->cbData;
3168 ctxComplete.cTRB = pUrb->pHci->cTRB;
3169 ctxComplete.uSlotID = uSlotID;
3170 ctxComplete.uEpDCI = uEpDCI;
3171 ctxComplete.uEDTLA = 0; // Always zero at the beginning of a new TD.
3172 ctxComplete.uLastCC = cc;
3173 ctxComplete.fMaxCount = ep_ctx.ifc >= XHCI_NO_QUEUING_IN_FLIGHT;
3174 xhciR3WalkXferTrbChain(pDevIns, pThis, ep_ctx.trdp, xhciR3WalkDataTRBsComplete, &ctxComplete, &uTRDP);
3175 ep_ctx.last_cc = ctxComplete.uLastCC;
3176 ep_ctx.trdp = uTRDP;
3177
3178 if (ep_ctx.ifc >= XHCI_NO_QUEUING_IN_FLIGHT)
3179 ep_ctx.ifc -= XHCI_NO_QUEUING_IN_FLIGHT; /* TD fragment done, allow further queuing. */
3180 else
3181 ep_ctx.ifc--; /* TD done, decrement in-flight counter. */
3182 }
3183 else if (xfer.gen.type == XHCI_TRB_ISOCH)
3184 {
3185 XHCI_CTX_XFER_COMPLETE ctxComplete;
3186 uint64_t uTRDP;
3187 unsigned iPkt;
3188
3189 ctxComplete.pUrb = pUrb;
3190 ctxComplete.uSlotID = uSlotID;
3191 ctxComplete.uEpDCI = uEpDCI;
3192
3193 for (iPkt = 0; iPkt < pUrb->cIsocPkts; ++iPkt) {
3194 ctxComplete.uXferPos = pUrb->aIsocPkts[iPkt].off;
3195 ctxComplete.uXferLeft = pUrb->aIsocPkts[iPkt].cb;
3196 ctxComplete.cTRB = pUrb->pHci->cTRB;
3197 ctxComplete.uEDTLA = 0; // Zero at TD start.
3198 ctxComplete.uLastCC = cc;
3199 ctxComplete.fMaxCount = false;
3200 if (pUrb->aIsocPkts[iPkt].enmStatus != VUSBSTATUS_OK)
3201 STAM_COUNTER_INC(&pThis->StatErrorIsocPkts);
3202 xhciR3WalkXferTrbChain(pDevIns, pThis, ep_ctx.trdp, xhciR3WalkDataTRBsComplete, &ctxComplete, &uTRDP);
3203 ep_ctx.last_cc = ctxComplete.uLastCC;
3204 ep_ctx.trdp = uTRDP;
3205 xhciR3ConsumeNonXferTRBs(pDevIns, pThis, uSlotID, uEpDCI, &ep_ctx, &xfer, &GCPhysXfrTRB);
3206 }
3207 ep_ctx.ifc--; /* TD done, decrement in-flight counter. */
3208 }
3209 else if (xfer.gen.type == XHCI_TRB_SETUP_STG || xfer.gen.type == XHCI_TRB_DATA_STG || xfer.gen.type == XHCI_TRB_STATUS_STG)
3210 {
3211 XHCI_CTX_XFER_COMPLETE ctxComplete;
3212 uint64_t uTRDP;
3213
3214 ctxComplete.pUrb = pUrb;
3215 ctxComplete.uXferPos = 0;
3216 ctxComplete.uXferLeft = pUrb->cbData;
3217 ctxComplete.cTRB = pUrb->pHci->cTRB;
3218 ctxComplete.uSlotID = uSlotID;
3219 ctxComplete.uEpDCI = uEpDCI;
3220 ctxComplete.uEDTLA = 0; // Always zero at the beginning of a new TD.
3221 ctxComplete.uLastCC = cc;
3222 ctxComplete.fMaxCount = ep_ctx.ifc >= XHCI_NO_QUEUING_IN_FLIGHT;
3223 xhciR3WalkXferTrbChain(pDevIns, pThis, ep_ctx.trdp, xhciR3WalkDataTRBsComplete, &ctxComplete, &uTRDP);
3224 ep_ctx.last_cc = ctxComplete.uLastCC;
3225 ep_ctx.trdp = uTRDP;
3226 }
3227 else
3228 {
3229 AssertMsgFailed(("Unexpected TRB type %u\n", xfer.gen.type));
3230 Log2(("TRB @ %RGp, type %u unexpected!\n", GCPhysXfrTRB, xfer.gen.type));
3231 /* Advance the TRDP anyway so that the endpoint isn't completely stuck. */
3232 ep_ctx.trdp += sizeof(XHCI_XFER_TRB);
3233 }
3234
3235 /* Update the endpoint state. */
3236 xhciR3WriteBackEp(pDevIns, pThis, uSlotID, uEpDCI, &ep_ctx);
3237
3238 RTCritSectLeave(&pThisCC->CritSectThrd);
3239
3240 if (pUrb->enmStatus == VUSBSTATUS_OK)
3241 {
3242 /* Completion callback usually runs on a separate thread. Let the worker do more. */
3243 Log2(("Ring bell for slot %u, DCI %u\n", uSlotID, uEpDCI));
3244 ASMAtomicOrU32(&pThis->aBellsRung[ID_TO_IDX(uSlotID)], 1 << uEpDCI);
3245 xhciKickWorker(pDevIns, pThis, XHCI_JOB_XFER_DONE, 0);
3246 }
3247}
3248
3249
3250/**
3251 * Handle transfer errors.
3252 *
3253 * VUSB calls this when a transfer attempt failed. This function will respond
3254 * indicating whether to retry or complete the URB with failure.
3255 *
3256 * @returns true if the URB should be retired.
3257 * @returns false if the URB should be re-tried.
3258 * @param pInterface Pointer to XHCI::ROOTHUB::IRhPort.
3259 * @param pUrb Pointer to the URB in question.
3260 */
3261static DECLCALLBACK(bool) xhciR3RhXferError(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb)
3262{
3263 PXHCIROOTHUBR3 pRh = RT_FROM_MEMBER(pInterface, XHCIROOTHUBR3, IRhPort);
3264 PXHCICC pThisCC = pRh->pXhciR3;
3265 PXHCI pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PXHCI);
3266 bool fRetire = true;
3267
3268 /* If the xHC isn't running, get out of here immediately. */
3269 if (pThis->status & XHCI_STATUS_HCH)
3270 {
3271 Log(("xHC halted, skipping URB error handling\n"));
3272 return fRetire;
3273 }
3274
3275 RTCritSectEnter(&pThisCC->CritSectThrd);
3276
3277 Assert(pUrb->pHci->cTRB); /* xHCI-generated URBs should not fail! */
3278 if (!pUrb->pHci->cTRB)
3279 {
3280 Log(("%s: Failing xHCI-generated request!\n", pUrb->pszDesc));
3281 }
3282 else if (pUrb->enmStatus == VUSBSTATUS_STALL)
3283 {
3284 /* Don't retry on stall. */
3285 Log2(("%s: xhciR3RhXferError: STALL, giving up.\n", pUrb->pszDesc));
3286 } else if (pUrb->enmStatus == VUSBSTATUS_CRC) {
3287 /* Don't retry on CRC errors either. These indicate canceled URBs, among others. */
3288 Log2(("%s: xhciR3RhXferError: CRC, giving up.\n", pUrb->pszDesc));
3289 } else if (pUrb->enmStatus == VUSBSTATUS_DNR) {
3290 /* Don't retry on DNR errors. These indicate the device vanished. */
3291 Log2(("%s: xhciR3RhXferError: DNR, giving up.\n", pUrb->pszDesc));
3292 } else if (pUrb->enmStatus == VUSBSTATUS_DATA_OVERRUN) {
3293 /* Don't retry on OVERRUN errors. These indicate a fatal error. */
3294 Log2(("%s: xhciR3RhXferError: OVERRUN, giving up.\n", pUrb->pszDesc));
3295 } else if (pUrb->enmStatus == VUSBSTATUS_DATA_UNDERRUN) {
3296 /* Don't retry on UNDERRUN errors. These indicate a fatal error. */
3297 Log2(("%s: xhciR3RhXferError: UNDERRUN, giving up.\n", pUrb->pszDesc));
3298 } else {
3299 /// @todo
3300 AssertMsgFailed(("%#x\n", pUrb->enmStatus));
3301 }
3302
3303 RTCritSectLeave(&pThisCC->CritSectThrd);
3304 return fRetire;
3305}
3306
3307
3308/**
3309 * Queue a TD composed of normal TRBs, event data TRBs, and suchlike.
3310 *
3311 * @returns VBox status code.
3312 * @param pDevIns The device instance.
3313 * @param pThis The xHCI device state, shared edition.
3314 * @param pThisCC The xHCI device state, ring-3 edition.
3315 * @param pRh Root hub for the device.
3316 * @param GCPhysTRB Physical gues address of the TRB.
3317 * @param pTrb Pointer to the contents of the first TRB.
3318 * @param pEpCtx Pointer to the cached EP context.
3319 * @param uSlotID ID of the associated slot context.
3320 * @param uAddr The device address.
3321 * @param uEpDCI The DCI(!) of the endpoint.
3322 */
3323static int xhciR3QueueDataTD(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThisCC, PXHCIROOTHUBR3 pRh, RTGCPHYS GCPhysTRB,
3324 XHCI_XFER_TRB *pTrb, XHCI_EP_CTX *pEpCtx, uint8_t uSlotID, uint8_t uAddr, uint8_t uEpDCI)
3325{
3326 RT_NOREF(GCPhysTRB);
3327 XHCI_CTX_XFER_PROBE ctxProbe;
3328 XHCI_CTX_XFER_SUBMIT ctxSubmit;
3329 uint64_t uTREP;
3330 bool fFragOnly = false;
3331 int rc;
3332 VUSBXFERTYPE enmType;
3333 VUSBDIRECTION enmDir;
3334
3335 /* Discover how big this TD is. */
3336 RT_ZERO(ctxProbe);
3337 rc = xhciR3WalkXferTrbChain(pDevIns, pThis, pEpCtx->trep, xhciR3WalkDataTRBsProbe, &ctxProbe, &uTREP);
3338 if (RT_SUCCESS(rc))
3339 LogFlowFunc(("Probed %u TRBs, %u bytes total, TREP@%RX64\n", ctxProbe.cTRB, ctxProbe.uXferLen, uTREP));
3340 else
3341 {
3342 LogFlowFunc(("Probing failed after %u TRBs, %u bytes total (last ED after %u TRBs and %u bytes), TREP@%RX64\n", ctxProbe.cTRB, ctxProbe.uXferLen, ctxProbe.cTRBLastED, ctxProbe.uXfrLenLastED, uTREP));
3343 if (rc == VERR_TRY_AGAIN && pTrb->gen.type == XHCI_TRB_NORMAL && ctxProbe.cTRBLastED)
3344 {
3345 /* The TD is incomplete, but we have at least one TD fragment. We can create a URB for
3346 * what we have but we can't safely queue any more because if any error occurs, the
3347 * TD needs to fail as a whole.
3348 * OS X Mavericks and Yosemite tend to trigger this case when reading from USB 3.0
3349 * MSDs (transfers up to 1MB).
3350 */
3351 fFragOnly = true;
3352
3353 /* Because we currently do not maintain the EDTLA across URBs, we have to only submit
3354 * TD fragments up to where we last saw an Event Data TRB. If there was no Event Data
3355 * TRB, we'll just try waiting a bit longer for the TD to be complete or an Event Data
3356 * TRB to show up. The guest is extremely likely to do one or the other, since otherwise
3357 * it has no way to tell when the transfer completed.
3358 */
3359 ctxProbe.cTRB = ctxProbe.cTRBLastED;
3360 ctxProbe.uXferLen = ctxProbe.uXfrLenLastED;
3361 }
3362 else
3363 return rc;
3364 }
3365
3366 /* Determine the transfer kind based on endpoint type. */
3367 switch (pEpCtx->ep_type)
3368 {
3369 case XHCI_EPTYPE_BULK_IN:
3370 case XHCI_EPTYPE_BULK_OUT:
3371 enmType = VUSBXFERTYPE_BULK;
3372 break;
3373 case XHCI_EPTYPE_INTR_IN:
3374 case XHCI_EPTYPE_INTR_OUT:
3375 enmType = VUSBXFERTYPE_INTR;
3376 break;
3377 case XHCI_EPTYPE_CONTROL:
3378 enmType = VUSBXFERTYPE_CTRL;
3379 break;
3380 case XHCI_EPTYPE_ISOCH_IN:
3381 case XHCI_EPTYPE_ISOCH_OUT:
3382 default:
3383 enmType = VUSBXFERTYPE_INVALID;
3384 AssertMsgFailed(("%#x\n", pEpCtx->ep_type));
3385 }
3386
3387 /* Determine the direction based on endpoint type. */
3388 switch (pEpCtx->ep_type)
3389 {
3390 case XHCI_EPTYPE_BULK_IN:
3391 case XHCI_EPTYPE_INTR_IN:
3392 enmDir = VUSBDIRECTION_IN;
3393 break;
3394 case XHCI_EPTYPE_BULK_OUT:
3395 case XHCI_EPTYPE_INTR_OUT:
3396 enmDir = VUSBDIRECTION_OUT;
3397 break;
3398 default:
3399 enmDir = VUSBDIRECTION_INVALID;
3400 AssertMsgFailed(("%#x\n", pEpCtx->ep_type));
3401 }
3402
3403 /* Allocate and initialize a URB. */
3404 PVUSBURB pUrb = VUSBIRhNewUrb(pRh->pIRhConn, uAddr, VUSB_DEVICE_PORT_INVALID, enmType, enmDir, ctxProbe.uXferLen, ctxProbe.cTRB, NULL);
3405 if (!pUrb)
3406 return VERR_OUT_OF_RESOURCES; /// @todo handle error!
3407
3408 STAM_COUNTER_ADD(&pThis->StatTRBsPerDtaUrb, ctxProbe.cTRB);
3409
3410 /* See 4.5.1 about xHCI vs. USB endpoint addressing. */
3411 Assert(uEpDCI);
3412
3413 pUrb->EndPt = uEpDCI / 2; /* DCI = EP * 2 + direction */
3414 pUrb->fShortNotOk = false; /* We detect short packets ourselves. */
3415 pUrb->enmStatus = VUSBSTATUS_OK;
3416
3417 /// @todo Cross check that the EP type corresponds to direction. Probably
3418 //should check when configuring device?
3419 pUrb->pHci->uSlotID = uSlotID;
3420
3421 /* For OUT transfers, copy the TD data into the URB. */
3422 if (pUrb->enmDir == VUSBDIRECTION_OUT)
3423 {
3424 ctxSubmit.pUrb = pUrb;
3425 ctxSubmit.uXferPos = 0;
3426 ctxSubmit.cTRB = 0;
3427 xhciR3WalkXferTrbChain(pDevIns, pThis, pEpCtx->trep, xhciR3WalkDataTRBsSubmit, &ctxSubmit, &uTREP);
3428 Assert(ctxProbe.cTRB == ctxSubmit.cTRB);
3429 ctxProbe.cTRB = ctxSubmit.cTRB;
3430 }
3431
3432 /* If only completing a fragment, remember the TRB count and increase
3433 * the in-flight count past the limit so we won't queue any more.
3434 */
3435 pUrb->pHci->cTRB = ctxProbe.cTRB;
3436 if (fFragOnly)
3437 /* Bit of a hack -- prevent further queuing. */
3438 pEpCtx->ifc += XHCI_NO_QUEUING_IN_FLIGHT;
3439 else
3440 /* Increment the in-flight counter before queuing more. */
3441 pEpCtx->ifc++;
3442
3443 /* Commit the updated TREP; submitting the URB may already invoke completion callbacks. */
3444 pEpCtx->trep = uTREP;
3445 xhciR3WriteBackEp(pDevIns, pThis, uSlotID, uEpDCI, pEpCtx);
3446
3447 /*
3448 * Submit the URB.
3449 */
3450 STAM_COUNTER_ADD(&pThis->StatUrbSizeData, pUrb->cbData);
3451 Log(("%s: xhciR3QueueDataTD: Addr=%u, EndPt=%u, enmDir=%u cbData=%u\n",
3452 pUrb->pszDesc, pUrb->DstAddress, pUrb->EndPt, pUrb->enmDir, pUrb->cbData));
3453 RTCritSectLeave(&pThisCC->CritSectThrd);
3454 rc = VUSBIRhSubmitUrb(pRh->pIRhConn, pUrb, &pRh->Led);
3455 RTCritSectEnter(&pThisCC->CritSectThrd);
3456 if (RT_SUCCESS(rc))
3457 return VINF_SUCCESS;
3458
3459 /* Failure cleanup. Can happen if we're still resetting the device or out of resources,
3460 * or the user just ripped out the device.
3461 */
3462 /// @todo Mark the EP as halted and inactive and write back the changes.
3463
3464 return VERR_OUT_OF_RESOURCES;
3465}
3466
3467
3468/**
3469 * Queue an isochronous TD composed of isochronous and normal TRBs, event
3470 * data TRBs, and suchlike. This TD may either correspond to a single URB or
3471 * form one packet of an isochronous URB.
3472 *
3473 * @returns VBox status code.
3474 * @param pDevIns The device instance.
3475 * @param pThis The xHCI device state, shared edition.
3476 * @param pThisCC The xHCI device state, ring-3 edition.
3477 * @param pRh Root hub for the device.
3478 * @param GCPhysTRB Physical guest address of the TRB.
3479 * @param pTrb Pointer to the contents of the first TRB.
3480 * @param pEpCtx Pointer to the cached EP context.
3481 * @param uSlotID ID of the associated slot context.
3482 * @param uAddr The device address.
3483 * @param uEpDCI The DCI(!) of the endpoint.
3484 * @param pCtxIso Additional isochronous URB context.
3485 */
3486static int xhciR3QueueIsochTD(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThisCC, PXHCIROOTHUBR3 pRh, RTGCPHYS GCPhysTRB,
3487 XHCI_XFER_TRB *pTrb, XHCI_EP_CTX *pEpCtx, uint8_t uSlotID, uint8_t uAddr, uint8_t uEpDCI,
3488 XHCI_CTX_ISOCH *pCtxIso)
3489{
3490 RT_NOREF(GCPhysTRB, pTrb);
3491 XHCI_CTX_XFER_PROBE ctxProbe;
3492 XHCI_CTX_XFER_SUBMIT ctxSubmit;
3493 uint64_t uTREP;
3494 PVUSBURB pUrb;
3495 unsigned cIsoPackets;
3496 uint32_t cbPktMax;
3497
3498 /* Discover how big this TD is. */
3499 RT_ZERO(ctxProbe);
3500 xhciR3WalkXferTrbChain(pDevIns, pThis, pEpCtx->trep, xhciR3WalkDataTRBsProbe, &ctxProbe, &uTREP);
3501 LogFlowFunc(("Probed %u TRBs, %u bytes total, TREP@%RX64\n", ctxProbe.cTRB, ctxProbe.uXferLen, uTREP));
3502
3503 /* See 4.5.1 about xHCI vs. USB endpoint addressing. */
3504 Assert(uEpDCI);
3505
3506 /* For isochronous transfers, there's a bit of extra work to do. The interval
3507 * is key and determines whether the TD will directly correspond to a URB or
3508 * if it will only form part of a larger URB. In any case, one TD equals one
3509 * 'packet' of an isochronous URB.
3510 */
3511 switch (pEpCtx->interval)
3512 {
3513 case 0: /* Every 2^0 * 125us, i.e. 8 per frame. */
3514 cIsoPackets = 8;
3515 break;
3516 case 1: /* Every 2^1 * 125us, i.e. 4 per frame. */
3517 cIsoPackets = 4;
3518 break;
3519 case 2: /* Every 2^2 * 125us, i.e. 2 per frame. */
3520 cIsoPackets = 2;
3521 break;
3522 case 3: /* Every 2^3 * 125us, i.e. 1 per frame. */
3523 default:/* Or any larger interval (every n frames).*/
3524 cIsoPackets = 1;
3525 break;
3526 }
3527
3528 /* We do not know exactly how much data might be transferred until we
3529 * look at all TDs/packets that constitute the URB. However, we do know
3530 * the maximum possible size even without probing any TDs at all.
3531 * The actual size is expected to be the same or at most slightly smaller,
3532 * hence it makes sense to allocate the URB right away and copy data into
3533 * it as we go, rather than doing complicated probing first.
3534 * The Max Endpoint Service Interval Time (ESIT) Payload defines the
3535 * maximum number of bytes that can be transferred per interval (4.14.2).
3536 * Unfortunately Apple was lazy and their driver leaves the Max ESIT
3537 * Payload as zero, so we have to do the math ourselves.
3538 */
3539
3540 /* Calculate the maximum transfer size per (micro)frame. */
3541 /// @todo This ought to be stored within the URB somewhere.
3542 cbPktMax = pEpCtx->max_pkt_sz * (pEpCtx->max_brs_sz + 1) * (pEpCtx->mult + 1);
3543 if (!pCtxIso->pUrb)
3544 {
3545 uint32_t cbUrbMax = cIsoPackets * cbPktMax;
3546
3547 /* Validate endpoint type. */
3548 AssertMsg(pEpCtx->ep_type == XHCI_EPTYPE_ISOCH_IN || pEpCtx->ep_type == XHCI_EPTYPE_ISOCH_OUT,
3549 ("%#x\n", pEpCtx->ep_type));
3550
3551 /* Allocate and initialize a new URB. */
3552 pUrb = VUSBIRhNewUrb(pRh->pIRhConn, uAddr, VUSB_DEVICE_PORT_INVALID, VUSBXFERTYPE_ISOC,
3553 (pEpCtx->ep_type == XHCI_EPTYPE_ISOCH_IN) ? VUSBDIRECTION_IN : VUSBDIRECTION_OUT,
3554 cbUrbMax, ctxProbe.cTRB, NULL);
3555 if (!pUrb)
3556 return VERR_OUT_OF_RESOURCES; /// @todo handle error!
3557
3558 STAM_COUNTER_ADD(&pThis->StatTRBsPerIsoUrb, ctxProbe.cTRB);
3559
3560 LogFlowFunc(("Allocated URB with %u packets, %u bytes total (ESIT payload %u)\n", cIsoPackets, cbUrbMax, cbPktMax));
3561
3562 pUrb->EndPt = uEpDCI / 2; /* DCI = EP * 2 + direction */
3563 pUrb->fShortNotOk = false; /* We detect short packets ourselves. */
3564 pUrb->enmStatus = VUSBSTATUS_OK;
3565 pUrb->cIsocPkts = cIsoPackets;
3566 pUrb->pHci->uSlotID = uSlotID;
3567 pUrb->pHci->cTRB = ctxProbe.cTRB;
3568
3569 /* If TRB says so or if there are multiple packets per interval, don't even
3570 * bother with frame counting and schedule everything ASAP.
3571 */
3572 if (pTrb->isoc.sia || cIsoPackets != 1)
3573 pUrb->uStartFrameDelta = 0;
3574 else
3575 {
3576 uint16_t uFrameDelta;
3577 uint32_t uPort;
3578
3579 /* Abort the endpoint, i.e. cancel any outstanding URBs. This needs to be done after
3580 * writing back the EP state so that the completion callback can operate.
3581 */
3582 if (RT_SUCCESS(xhciR3FindRhDevBySlot(pDevIns, pThis, pThisCC, uSlotID, NULL, &uPort)))
3583 {
3584
3585 uFrameDelta = pRh->pIRhConn->pfnUpdateIsocFrameDelta(pRh->pIRhConn, uPort, uEpDCI / 2,
3586 uEpDCI & 1 ? VUSBDIRECTION_IN : VUSBDIRECTION_OUT,
3587 pTrb->isoc.frm_id, XHCI_FRAME_ID_BITS);
3588 pUrb->uStartFrameDelta = uFrameDelta;
3589 Log(("%s: Isoch frame delta set to %u\n", pUrb->pszDesc, uFrameDelta));
3590 }
3591 else
3592 {
3593 Log(("%s: Failed to find device for slot! Setting frame delta to zero.\n", pUrb->pszDesc));
3594 pUrb->uStartFrameDelta = 0;
3595 }
3596 }
3597
3598 Log(("%s: Addr=%u, EndPt=%u, enmDir=%u cIsocPkts=%u cbData=%u FrmID=%u Isoch URB created\n",
3599 pUrb->pszDesc, pUrb->DstAddress, pUrb->EndPt, pUrb->enmDir, pUrb->cIsocPkts, pUrb->cbData, pTrb->isoc.frm_id));
3600
3601 /* Set up the context for later use. */
3602 pCtxIso->pUrb = pUrb;
3603 /* Save the current TREP in case we need to rewind. */
3604 pCtxIso->uInitTREP = pEpCtx->trep;
3605 }
3606 else
3607 {
3608 Assert(cIsoPackets > 1);
3609 /* Grab the URB we initialized earlier. */
3610 pUrb = pCtxIso->pUrb;
3611 }
3612
3613 /* Set up the packet corresponding to this TD. */
3614 pUrb->aIsocPkts[pCtxIso->iPkt].cb = RT_MIN(ctxProbe.uXferLen, cbPktMax);
3615 pUrb->aIsocPkts[pCtxIso->iPkt].off = pCtxIso->offCur;
3616 pUrb->aIsocPkts[pCtxIso->iPkt].enmStatus = VUSBSTATUS_NOT_ACCESSED;
3617
3618 /* For OUT transfers, copy the TD data into the URB. */
3619 if (pUrb->enmDir == VUSBDIRECTION_OUT)
3620 {
3621 ctxSubmit.pUrb = pUrb;
3622 ctxSubmit.uXferPos = pCtxIso->offCur;
3623 ctxSubmit.cTRB = 0;
3624 xhciR3WalkXferTrbChain(pDevIns, pThis, pEpCtx->trep, xhciR3WalkDataTRBsSubmit, &ctxSubmit, &uTREP);
3625 Assert(ctxProbe.cTRB == ctxSubmit.cTRB);
3626 }
3627
3628 /* Done preparing this packet. */
3629 Assert(pCtxIso->iPkt < 8);
3630 pCtxIso->iPkt++;
3631 pCtxIso->offCur += ctxProbe.uXferLen;
3632 Assert(pCtxIso->offCur <= pUrb->cbData);
3633
3634 /* Increment the in-flight counter before queuing more. */
3635 if (pCtxIso->iPkt == pUrb->cIsocPkts)
3636 pEpCtx->ifc++;
3637
3638 /* Commit the updated TREP; submitting the URB may already invoke completion callbacks. */
3639 pEpCtx->trep = uTREP;
3640 xhciR3WriteBackEp(pDevIns, pThis, uSlotID, uEpDCI, pEpCtx);
3641
3642 /* If the URB is complete, submit it. */
3643 if (pCtxIso->iPkt == pUrb->cIsocPkts)
3644 {
3645 /* Change cbData to reflect how much data should be transferred. This can differ
3646 * from how much data was allocated for the URB.
3647 */
3648 pUrb->cbData = pCtxIso->offCur;
3649 STAM_COUNTER_ADD(&pThis->StatUrbSizeIsoc, pUrb->cbData);
3650 Log(("%s: Addr=%u, EndPt=%u, enmDir=%u cIsocPkts=%u cbData=%u Isoch URB being submitted\n",
3651 pUrb->pszDesc, pUrb->DstAddress, pUrb->EndPt, pUrb->enmDir, pUrb->cIsocPkts, pUrb->cbData));
3652 RTCritSectLeave(&pThisCC->CritSectThrd);
3653 int rc = VUSBIRhSubmitUrb(pRh->pIRhConn, pUrb, &pRh->Led);
3654 RTCritSectEnter(&pThisCC->CritSectThrd);
3655 if (RT_FAILURE(rc))
3656 {
3657 /* Failure cleanup. Can happen if we're still resetting the device or out of resources,
3658 * or the user just ripped out the device.
3659 */
3660 pCtxIso->fSubmitFailed = true;
3661 /// @todo Mark the EP as halted and inactive and write back the changes.
3662 return VERR_OUT_OF_RESOURCES;
3663 }
3664 /* Clear the isochronous URB context. */
3665 RT_ZERO(*pCtxIso);
3666 }
3667
3668 return VINF_SUCCESS;
3669}
3670
3671
3672/**
3673 * Queue a control TD composed of setup/data/status stage TRBs, event data
3674 * TRBs, and suchlike.
3675 *
3676 * @returns VBox status code.
3677 * @param pDevIns The device instance.
3678 * @param pThis The xHCI device state, shared edition.
3679 * @param pThisCC The xHCI device state, ring-3 edition.
3680 * @param pRh Root hub for the device.
3681 * @param GCPhysTRB Physical guest address of th TRB.
3682 * @param pTrb Pointer to the contents of the first TRB.
3683 * @param pEpCtx Pointer to the cached EP context.
3684 * @param uSlotID ID of the associated slot context.
3685 * @param uAddr The device address.
3686 * @param uEpDCI The DCI(!) of the endpoint.
3687 */
3688static int xhciR3QueueControlTD(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThisCC, PXHCIROOTHUBR3 pRh, RTGCPHYS GCPhysTRB,
3689 XHCI_XFER_TRB *pTrb, XHCI_EP_CTX *pEpCtx, uint8_t uSlotID, uint8_t uAddr, uint8_t uEpDCI)
3690{
3691 RT_NOREF(GCPhysTRB);
3692 XHCI_CTX_XFER_PROBE ctxProbe;
3693 XHCI_CTX_XFER_SUBMIT ctxSubmit;
3694 uint64_t uTREP;
3695 int rc;
3696 VUSBDIRECTION enmDir;
3697
3698 /* Discover how big this TD is. */
3699 RT_ZERO(ctxProbe);
3700 rc = xhciR3WalkXferTrbChain(pDevIns, pThis, pEpCtx->trep, xhciR3WalkDataTRBsProbe, &ctxProbe, &uTREP);
3701 if (RT_SUCCESS(rc))
3702 LogFlowFunc(("Probed %u TRBs, %u bytes total, TREP@%RX64\n", ctxProbe.cTRB, ctxProbe.uXferLen, uTREP));
3703 else
3704 {
3705 LogFlowFunc(("Probing failed after %u TRBs, %u bytes total (last ED after %u TRBs and %u bytes), TREP@%RX64\n", ctxProbe.cTRB, ctxProbe.uXferLen, ctxProbe.cTRBLastED, ctxProbe.uXfrLenLastED, uTREP));
3706 return rc;
3707 }
3708
3709 /* Determine the transfer direction. */
3710 switch (pTrb->gen.type)
3711 {
3712 case XHCI_TRB_SETUP_STG:
3713 enmDir = VUSBDIRECTION_SETUP;
3714 /* For setup TRBs, there is always 8 bytes of immediate data. */
3715 Assert(sizeof(VUSBSETUP) == 8);
3716 Assert(ctxProbe.uXferLen == 8);
3717 Log2(("bmRequestType:%02X bRequest:%02X wValue:%04X wIndex:%04X wLength:%04X\n", pTrb->setup.bmRequestType,
3718 pTrb->setup.bRequest, pTrb->setup.wValue, pTrb->setup.wIndex, pTrb->setup.wLength));
3719 break;
3720 case XHCI_TRB_STATUS_STG:
3721 enmDir = pTrb->status.dir ? VUSBDIRECTION_IN : VUSBDIRECTION_OUT;
3722 break;
3723 case XHCI_TRB_DATA_STG:
3724 enmDir = pTrb->data.dir ? VUSBDIRECTION_IN : VUSBDIRECTION_OUT;
3725 break;
3726 default:
3727 AssertMsgFailed(("%#x\n", pTrb->gen.type)); /* Can't happen unless caller messed up. */
3728 return VERR_INTERNAL_ERROR;
3729 }
3730
3731 /* Allocate and initialize a URB. */
3732 PVUSBURB pUrb = VUSBIRhNewUrb(pRh->pIRhConn, uAddr, VUSB_DEVICE_PORT_INVALID, VUSBXFERTYPE_CTRL, enmDir, ctxProbe.uXferLen, ctxProbe.cTRB,
3733 NULL);
3734 if (!pUrb)
3735 return VERR_OUT_OF_RESOURCES; /// @todo handle error!
3736
3737 STAM_COUNTER_ADD(&pThis->StatTRBsPerCtlUrb, ctxProbe.cTRB);
3738
3739 /* See 4.5.1 about xHCI vs. USB endpoint addressing. */
3740 Assert(uEpDCI);
3741
3742 /* This had better be a control endpoint. */
3743 AssertMsg(pEpCtx->ep_type == XHCI_EPTYPE_CONTROL, ("%#x\n", pEpCtx->ep_type));
3744
3745 pUrb->EndPt = uEpDCI / 2; /* DCI = EP * 2 + direction */
3746 pUrb->fShortNotOk = false; /* We detect short packets ourselves. */
3747 pUrb->enmStatus = VUSBSTATUS_OK;
3748 pUrb->pHci->uSlotID = uSlotID;
3749
3750 /* For OUT/SETUP transfers, copy the TD data into the URB. */
3751 if (pUrb->enmDir == VUSBDIRECTION_OUT || pUrb->enmDir == VUSBDIRECTION_SETUP)
3752 {
3753 ctxSubmit.pUrb = pUrb;
3754 ctxSubmit.uXferPos = 0;
3755 ctxSubmit.cTRB = 0;
3756 xhciR3WalkXferTrbChain(pDevIns, pThis, pEpCtx->trep, xhciR3WalkDataTRBsSubmit, &ctxSubmit, &uTREP);
3757 Assert(ctxProbe.cTRB == ctxSubmit.cTRB);
3758 ctxProbe.cTRB = ctxSubmit.cTRB;
3759 }
3760
3761 pUrb->pHci->cTRB = ctxProbe.cTRB;
3762
3763 /* Commit the updated TREP; submitting the URB may already invoke completion callbacks. */
3764 pEpCtx->trep = uTREP;
3765 xhciR3WriteBackEp(pDevIns, pThis, uSlotID, uEpDCI, pEpCtx);
3766
3767 /*
3768 * Submit the URB.
3769 */
3770 STAM_COUNTER_ADD(&pThis->StatUrbSizeCtrl, pUrb->cbData);
3771 Log(("%s: xhciR3QueueControlTD: Addr=%u, EndPt=%u, enmDir=%u cbData=%u\n",
3772 pUrb->pszDesc, pUrb->DstAddress, pUrb->EndPt, pUrb->enmDir, pUrb->cbData));
3773 RTCritSectLeave(&pThisCC->CritSectThrd);
3774 rc = VUSBIRhSubmitUrb(pRh->pIRhConn, pUrb, &pRh->Led);
3775 RTCritSectEnter(&pThisCC->CritSectThrd);
3776 if (RT_SUCCESS(rc))
3777 return VINF_SUCCESS;
3778
3779 /* Failure cleanup. Can happen if we're still resetting the device or out of resources,
3780 * or the user just ripped out the device.
3781 */
3782 /// @todo Mark the EP as halted and inactive and write back the changes.
3783
3784 return VERR_OUT_OF_RESOURCES;
3785}
3786
3787
3788/**
3789 * Process a device context (transfer data).
3790 *
3791 * @param pDevIns The device instance.
3792 * @param pThis The xHCI device state, shared edition.
3793 * @param pThisCC The xHCI device state, ring-3 edition.
3794 * @param uSlotID Slot/doorbell which had been rung.
3795 * @param uDBVal Value written to the doorbell.
3796 */
3797static int xhciR3ProcessDevCtx(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThisCC, uint8_t uSlotID, uint32_t uDBVal)
3798{
3799 uint8_t uDBTarget = uDBVal & XHCI_DB_TGT_MASK;
3800 XHCI_CTX_ISOCH ctxIsoch = {0};
3801 XHCI_SLOT_CTX slot_ctx;
3802 XHCI_EP_CTX ep_ctx;
3803 XHCI_XFER_TRB xfer;
3804 RTGCPHYS GCPhysXfrTRB;
3805 PXHCIROOTHUBR3 pRh;
3806 bool dcs;
3807 bool fContinue = true;
3808 int rc;
3809 unsigned cTrbs = 0;
3810
3811 LogFlowFunc(("Slot ID: %u, DB target %u, DB stream ID %u\n", uSlotID, uDBTarget, (uDBVal & XHCI_DB_STRMID_MASK) >> XHCI_DB_STRMID_SHIFT));
3812 Assert(uSlotID > 0);
3813 Assert(uSlotID <= XHCI_NDS);
3814 /// @todo report errors for bogus DB targets
3815 Assert(uDBTarget > 0);
3816 Assert(uDBTarget < 32);
3817
3818 /// @todo Check for aborts and the like?
3819
3820 /* Load the slot and endpoint contexts. */
3821 xhciR3FetchCtxAndEp(pDevIns, pThis, uSlotID, uDBTarget, &slot_ctx, &ep_ctx);
3822 /// @todo sanity check the context in here?
3823
3824 /* Select the root hub corresponding to the port. */
3825 pRh = GET_PORT_PRH(pThisCC, ID_TO_IDX(slot_ctx.rh_port));
3826
3827 /* Stopped endpoints automatically transition to running state. */
3828 if (RT_UNLIKELY(ep_ctx.ep_state == XHCI_EPST_STOPPED))
3829 {
3830 Log(("EP DCI %u stopped -> running\n", uDBTarget));
3831 ep_ctx.ep_state = XHCI_EPST_RUNNING;
3832 /* Update EP right here. Theoretically could be postponed, but we
3833 * must ensure that the EP does get written back even if there is
3834 * no other work to do.
3835 */
3836 xhciR3WriteBackEp(pDevIns, pThis, uSlotID, uDBTarget, &ep_ctx);
3837 }
3838
3839 /* If the EP isn't running, get outta here. */
3840 if (RT_UNLIKELY(ep_ctx.ep_state != XHCI_EPST_RUNNING))
3841 {
3842 Log2(("EP DCI %u not running (state %u), bail!\n", uDBTarget, ep_ctx.ep_state));
3843 return VINF_SUCCESS;
3844 }
3845
3846 /* Get any non-transfer TRBs out of the way. */
3847 xhciR3ConsumeNonXferTRBs(pDevIns, pThis, uSlotID, uDBTarget, &ep_ctx, &xfer, &GCPhysXfrTRB);
3848 /// @todo This is inefficient.
3849 xhciR3WriteBackEp(pDevIns, pThis, uSlotID, uDBTarget, &ep_ctx);
3850
3851 do
3852 {
3853 /* Fetch the contexts again and find the TRB address at enqueue point. */
3854 xhciR3FetchCtxAndEp(pDevIns, pThis, uSlotID, uDBTarget, &slot_ctx, &ep_ctx);
3855 GCPhysXfrTRB = ep_ctx.trep & XHCI_TRDP_ADDR_MASK;
3856 dcs = !!(ep_ctx.trep & XHCI_TRDP_DCS_MASK);
3857 LogFlowFunc(("Processing Transfer Ring, TREP: %RGp\n", GCPhysXfrTRB));
3858
3859 /* Fetch the transfer TRB. */
3860 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysXfrTRB, &xfer, sizeof(xfer));
3861
3862 /* Make sure the Cycle State matches. */
3863 if ((bool)xfer.gen.cycle == dcs)
3864 {
3865 Log2(("TRB @ %RGp, type %u (%s) %u bytes ENT=%u ISP=%u NS=%u CH=%u IOC=%u IDT=%u\n", GCPhysXfrTRB, xfer.gen.type,
3866 xfer.gen.type < RT_ELEMENTS(g_apszTrbNames) ? g_apszTrbNames[xfer.gen.type] : "WHAT?!!",
3867 xfer.gen.xfr_len, xfer.gen.ent, xfer.gen.isp, xfer.gen.ns, xfer.gen.ch, xfer.gen.ioc, xfer.gen.idt));
3868
3869 /* If there is an "in-flight" TRDP, check if we need to wait until the transfer completes. */
3870 if ((ep_ctx.trdp & XHCI_TRDP_ADDR_MASK) != GCPhysXfrTRB)
3871 {
3872 switch (xfer.gen.type) {
3873 case XHCI_TRB_ISOCH:
3874 if (ep_ctx.ifc >= XHCI_MAX_ISOC_IN_FLIGHT)
3875 {
3876 Log(("%u isoch URBs in flight, backing off\n", ep_ctx.ifc));
3877 fContinue = false;
3878 break;
3879 }
3880 RT_FALL_THRU();
3881 case XHCI_TRB_LINK:
3882 Log2(("TRB OK, continuing @ %RX64\n", GCPhysXfrTRB));
3883 break;
3884 case XHCI_TRB_NORMAL:
3885 if (XHCI_EP_XTYPE(ep_ctx.ep_type) != XHCI_XFTYPE_BULK)
3886 {
3887 Log2(("Normal TRB not bulk, not continuing @ %RX64\n", GCPhysXfrTRB));
3888 fContinue = false;
3889 break;
3890 }
3891 if (ep_ctx.ifc >= XHCI_MAX_BULK_IN_FLIGHT)
3892 {
3893 Log(("%u normal URBs in flight, backing off\n", ep_ctx.ifc));
3894 fContinue = false;
3895 break;
3896 }
3897 Log2(("Bulk TRB OK, continuing @ %RX64\n", GCPhysXfrTRB));
3898 break;
3899 case XHCI_TRB_EVT_DATA:
3900 case XHCI_TRB_NOOP_XFER:
3901 Log2(("TRB not OK, not continuing @ %RX64\n", GCPhysXfrTRB));
3902 fContinue = false;
3903 break;
3904 default:
3905 Log2(("Some other TRB (type %u), not continuing @ %RX64\n", xfer.gen.type, GCPhysXfrTRB));
3906 fContinue = false;
3907 break;
3908 }
3909 }
3910 if (!fContinue)
3911 break;
3912
3913 switch (xfer.gen.type) {
3914 case XHCI_TRB_NORMAL:
3915 Log(("Normal TRB: Ptr=%RGp IOC=%u CH=%u\n", xfer.norm.data_ptr, xfer.norm.ioc, xfer.norm.ch));
3916 rc = xhciR3QueueDataTD(pDevIns, pThis, pThisCC, pRh, GCPhysXfrTRB, &xfer, &ep_ctx, uSlotID,
3917 slot_ctx.dev_addr, uDBTarget);
3918 break;
3919 case XHCI_TRB_SETUP_STG:
3920 Log(("Setup stage TRB: IOC=%u IDT=%u\n", xfer.setup.ioc, xfer.setup.idt));
3921 rc = xhciR3QueueControlTD(pDevIns, pThis, pThisCC, pRh, GCPhysXfrTRB, &xfer, &ep_ctx, uSlotID,
3922 slot_ctx.dev_addr, uDBTarget);
3923 break;
3924 case XHCI_TRB_DATA_STG:
3925 Log(("Data stage TRB: Ptr=%RGp IOC=%u CH=%u DIR=%u\n", xfer.data.data_ptr, xfer.data.ioc, xfer.data.ch, xfer.data.dir));
3926 rc = xhciR3QueueControlTD(pDevIns, pThis, pThisCC, pRh, GCPhysXfrTRB, &xfer, &ep_ctx, uSlotID,
3927 slot_ctx.dev_addr, uDBTarget);
3928 break;
3929 case XHCI_TRB_STATUS_STG:
3930 Log(("Status stage TRB: IOC=%u CH=%u DIR=%u\n", xfer.status.ioc, xfer.status.ch, xfer.status.dir));
3931 rc = xhciR3QueueControlTD(pDevIns, pThis, pThisCC, pRh, GCPhysXfrTRB, &xfer, &ep_ctx, uSlotID,
3932 slot_ctx.dev_addr, uDBTarget);
3933 break;
3934 case XHCI_TRB_ISOCH:
3935 Log(("Isoch TRB: Ptr=%RGp IOC=%u CH=%u TLBPC=%u TBC=%u SIA=%u FrmID=%u\n", xfer.isoc.data_ptr, xfer.isoc.ioc, xfer.isoc.ch, xfer.isoc.tlbpc, xfer.isoc.tbc, xfer.isoc.sia, xfer.isoc.frm_id));
3936 rc = xhciR3QueueIsochTD(pDevIns, pThis, pThisCC, pRh, GCPhysXfrTRB, &xfer, &ep_ctx, uSlotID,
3937 slot_ctx.dev_addr, uDBTarget, &ctxIsoch);
3938 break;
3939 case XHCI_TRB_LINK:
3940 Log2(("Link extra-TD: Ptr=%RGp IOC=%u TC=%u CH=%u\n", xfer.link.rseg_ptr, xfer.link.ioc, xfer.link.toggle, xfer.link.chain));
3941 Assert(!xfer.link.chain);
3942 /* Set new TREP but leave DCS bit alone... */
3943 ep_ctx.trep = (xfer.link.rseg_ptr & XHCI_TRDP_ADDR_MASK) | (ep_ctx.trep & XHCI_TRDP_DCS_MASK);
3944 /* ...and flip the DCS bit if required. Then update the TREP. */
3945 if (xfer.link.toggle)
3946 ep_ctx.trep = (ep_ctx.trep & ~XHCI_TRDP_DCS_MASK) | (ep_ctx.trep ^ XHCI_TRDP_DCS_MASK);
3947 rc = xhciR3WriteBackEp(pDevIns, pThis, uSlotID, uDBTarget, &ep_ctx);
3948 break;
3949 case XHCI_TRB_NOOP_XFER:
3950 Log2(("No op xfer: IOC=%u CH=%u ENT=%u\n", xfer.nop.ioc, xfer.nop.ch, xfer.nop.ent));
3951 /* A no-op transfer TRB must not be part of a chain. See 4.11.7. */
3952 Assert(!xfer.link.chain);
3953 /* Update enqueue pointer (TRB was not yet completed). */
3954 ep_ctx.trep += sizeof(XHCI_XFER_TRB);
3955 rc = xhciR3WriteBackEp(pDevIns, pThis, uSlotID, uDBTarget, &ep_ctx);
3956 break;
3957 default:
3958 Log(("Unsupported TRB!!\n"));
3959 rc = VERR_NOT_SUPPORTED;
3960 break;
3961 }
3962 /* If queuing failed, stop right here. */
3963 if (RT_FAILURE(rc))
3964 fContinue = false;
3965 }
3966 else
3967 {
3968 LogFunc(("Transfer Ring empty\n"));
3969 fContinue = false;
3970
3971 /* If an isochronous ring is empty, this is an overrun/underrun. At this point
3972 * the ring will no longer be scheduled (until the doorbell is rung again)
3973 * but it remains in the Running state. This error is only reported if someone
3974 * rang the doorbell and there are no TDs available or in-flight.
3975 */
3976 if ( (ep_ctx.trep == ep_ctx.trdp) /* Nothing in-flight? */
3977 && (ep_ctx.ep_type == XHCI_EPTYPE_ISOCH_IN || ep_ctx.ep_type == XHCI_EPTYPE_ISOCH_OUT))
3978 {
3979 /* There is no TRB associated with this error; the slot context
3980 * determines the interrupter.
3981 */
3982 Log(("Isochronous ring %s, TRDP:%RGp\n", ep_ctx.ep_type == XHCI_EPTYPE_ISOCH_IN ? "overrun" : "underrun", ep_ctx.trdp & XHCI_TRDP_ADDR_MASK));
3983 rc = xhciR3PostXferEvent(pDevIns, pThis, slot_ctx.intr_tgt, 0,
3984 ep_ctx.ep_type == XHCI_EPTYPE_ISOCH_IN ? XHCI_TCC_RING_OVERRUN : XHCI_TCC_RING_UNDERRUN,
3985 uSlotID, uDBTarget, 0, false, false);
3986 }
3987
3988 }
3989
3990 /* Kill the xHC if the TRB list has no end in sight. */
3991 if (++cTrbs > XHCI_MAX_NUM_TRBS)
3992 {
3993 /* Stop the xHC with an error. */
3994 xhciR3EndlessTrbError(pDevIns, pThis);
3995
3996 /* Get out of the loop. */
3997 fContinue = false;
3998 rc = VERR_NOT_SUPPORTED; /* No good error code really... */
3999 }
4000 } while (fContinue);
4001
4002 /* It can unfortunately happen that for endpoints with more than one
4003 * transfer per USB frame, there won't be a complete multi-packet URB ready
4004 * when we go looking for it. If that happens, we'll "rewind" the TREP and
4005 * try again later. Since the URB construction is done under a lock, this
4006 * is safe as we won't be accessing the endpoint concurrently.
4007 */
4008 if (ctxIsoch.pUrb)
4009 {
4010 Log(("Unfinished ISOC URB (%u packets out of %u)!\n", ctxIsoch.iPkt, ctxIsoch.pUrb->cIsocPkts));
4011 /* If submitting failed, the URB is already freed. */
4012 if (!ctxIsoch.fSubmitFailed)
4013 VUSBIRhFreeUrb(pRh->pIRhConn, ctxIsoch.pUrb);
4014 ep_ctx.trep = ctxIsoch.uInitTREP;
4015 xhciR3WriteBackEp(pDevIns, pThis, uSlotID, uDBTarget, &ep_ctx);
4016 }
4017 return VINF_SUCCESS;
4018}
4019
4020
4021/**
4022 * A worker routine for Address Device command. Builds a URB containing
4023 * a SET_ADDRESS requests and (synchronously) submits it to VUSB, then
4024 * follows up with a status stage URB.
4025 *
4026 * @returns true on success.
4027 * @returns false on failure to submit.
4028 * @param pThisCC The xHCI device state, ring-3 edition.
4029 * @param uSlotID Slot ID to assign address to.
4030 * @param uDevAddr New device address.
4031 * @param iPort The xHCI root hub port index.
4032 */
4033static bool xhciR3IssueSetAddress(PXHCICC pThisCC, uint8_t uSlotID, uint8_t uDevAddr, unsigned iPort)
4034{
4035 PXHCIROOTHUBR3 pRh = GET_PORT_PRH(pThisCC, iPort);
4036
4037 Assert(uSlotID);
4038 LogFlowFunc(("Slot %u port idx %u: new address is %u\n", uSlotID, iPort, uDevAddr));
4039
4040 /* For USB3 devices, force the port number. This simulates the fact that USB3 uses directed (unicast) traffic. */
4041 if (!IS_USB3_PORT_IDX_R3(pThisCC, iPort))
4042 iPort = VUSB_DEVICE_PORT_INVALID;
4043 else
4044 iPort = GET_VUSB_PORT_FROM_XHCI_PORT(pRh, iPort);
4045
4046 /* Allocate and initialize a URB. NB: Zero cTds indicates a URB not submitted by guest. */
4047 PVUSBURB pUrb = VUSBIRhNewUrb(pRh->pIRhConn, 0 /* address */, iPort, VUSBXFERTYPE_CTRL, VUSBDIRECTION_SETUP,
4048 sizeof(VUSBSETUP), 0 /* cTds */, NULL);
4049 if (!pUrb)
4050 return false;
4051
4052 pUrb->EndPt = 0;
4053 pUrb->fShortNotOk = true;
4054 pUrb->enmStatus = VUSBSTATUS_OK;
4055 pUrb->pHci->uSlotID = uSlotID;
4056 pUrb->pHci->cTRB = 0;
4057
4058 /* Build the request. */
4059 PVUSBSETUP pSetup = (PVUSBSETUP)pUrb->abData;
4060 pSetup->bmRequestType = VUSB_DIR_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_TO_DEVICE;
4061 pSetup->bRequest = VUSB_REQ_SET_ADDRESS;
4062 pSetup->wValue = uDevAddr;
4063 pSetup->wIndex = 0;
4064 pSetup->wLength = 0;
4065
4066 /* NB: We assume the address assignment is a synchronous operation. */
4067
4068 /* Submit the setup URB. */
4069 Log(("%s: xhciSetAddress setup: cbData=%u\n", pUrb->pszDesc, pUrb->cbData));
4070 RTCritSectLeave(&pThisCC->CritSectThrd);
4071 int rc = VUSBIRhSubmitUrb(pRh->pIRhConn, pUrb, &pRh->Led);
4072 RTCritSectEnter(&pThisCC->CritSectThrd);
4073 if (RT_FAILURE(rc))
4074 {
4075 Log(("xhciSetAddress: setup stage failed pUrb=%p!!\n", pUrb));
4076 return false;
4077 }
4078
4079 /* To complete the SET_ADDRESS request, the status stage must succeed. */
4080 pUrb = VUSBIRhNewUrb(pRh->pIRhConn, 0 /* address */, iPort, VUSBXFERTYPE_CTRL, VUSBDIRECTION_IN, 0 /* cbData */, 0 /* cTds */,
4081 NULL);
4082 if (!pUrb)
4083 return false;
4084
4085 pUrb->EndPt = 0;
4086 pUrb->fShortNotOk = true;
4087 pUrb->enmStatus = VUSBSTATUS_OK;
4088 pUrb->pHci->uSlotID = uSlotID;
4089 pUrb->pHci->cTRB = 0;
4090
4091 /* Submit the setup URB. */
4092 Log(("%s: xhciSetAddress status: cbData=%u\n", pUrb->pszDesc, pUrb->cbData));
4093 RTCritSectLeave(&pThisCC->CritSectThrd);
4094 rc = VUSBIRhSubmitUrb(pRh->pIRhConn, pUrb, &pRh->Led);
4095 RTCritSectEnter(&pThisCC->CritSectThrd);
4096 if (RT_FAILURE(rc))
4097 {
4098 Log(("xhciSetAddress: status stage failed pUrb=%p!!\n", pUrb));
4099 return false;
4100 }
4101
4102 Log(("xhciSetAddress: set address succeeded\n"));
4103 return true;
4104}
4105
4106
4107/**
4108 * Address a device.
4109 *
4110 * @returns TRB completion code.
4111 * @param pDevIns The device instance.
4112 * @param pThis The xHCI device state, shared edition.
4113 * @param pThisCC The xHCI device state, ring-3 edition.
4114 * @param uInpCtxAddr Address of the input context.
4115 * @param uSlotID Slot ID to assign address to.
4116 * @param fBSR Block Set address Request flag.
4117 */
4118static unsigned xhciR3AddressDevice(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThisCC, uint64_t uInpCtxAddr,
4119 uint8_t uSlotID, bool fBSR)
4120{
4121 RTGCPHYS GCPhysInpCtx = uInpCtxAddr & XHCI_CTX_ADDR_MASK;
4122 RTGCPHYS GCPhysInpSlot;
4123 RTGCPHYS GCPhysOutSlot;
4124 XHCI_INPC_CTX icc; /* Input Control Context (ICI=0). */
4125 XHCI_SLOT_CTX inp_slot_ctx; /* Input Slot Context (ICI=1). */
4126 XHCI_EP_CTX ep_ctx; /* Endpoint Context (ICI=2+). */
4127 XHCI_SLOT_CTX out_slot_ctx; /* Output Slot Context. */
4128 uint8_t dev_addr;
4129 unsigned cc = XHCI_TCC_SUCCESS;
4130
4131 Assert(GCPhysInpCtx);
4132 Assert(uSlotID);
4133 LogFlowFunc(("Slot ID %u, input control context @ %RGp\n", uSlotID, GCPhysInpCtx));
4134
4135 /* Determine the address of the output slot context. */
4136 GCPhysOutSlot = xhciR3FetchDevCtxAddr(pDevIns, pThis, uSlotID);
4137
4138 /* Fetch the output slot context. */
4139 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysOutSlot, &out_slot_ctx, sizeof(out_slot_ctx));
4140
4141 /// @todo Check for valid context (6.2.2.1, 6.2.3.1)
4142
4143 /* See 4.6.5 */
4144 do {
4145 /* Parameter validation depends on whether the BSR flag is set or not. */
4146 if (fBSR)
4147 {
4148 /* Check that the output slot context state is in Enabled state. */
4149 if (out_slot_ctx.slot_state >= XHCI_SLTST_DEFAULT)
4150 {
4151 Log(("Output slot context state (%u) wrong (BSR)!\n", out_slot_ctx.slot_state));
4152 cc = XHCI_TCC_CTX_STATE_ERR;
4153 break;
4154 }
4155 dev_addr = 0;
4156 }
4157 else
4158 {
4159 /* Check that the output slot context state is in Enabled or Default state. */
4160 if (out_slot_ctx.slot_state > XHCI_SLTST_DEFAULT)
4161 {
4162 Log(("Output slot context state (%u) wrong (no-BSR)!\n", out_slot_ctx.slot_state));
4163 cc = XHCI_TCC_CTX_STATE_ERR;
4164 break;
4165 }
4166 dev_addr = xhciR3SelectNewAddress(pThis, uSlotID);
4167 }
4168
4169 /* Fetch the input control context. */
4170 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysInpCtx, &icc, sizeof(icc));
4171 Assert(icc.add_flags == (RT_BIT(0) | RT_BIT(1))); /* Should have been already checked. */
4172 Assert(!icc.drop_flags);
4173
4174 /* Calculate the address of the input slot context (ICI=1/DCI=0). */
4175 GCPhysInpSlot = GCPhysInpCtx + sizeof(XHCI_INPC_CTX);
4176
4177 /* Read the input slot context. */
4178 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysInpSlot, &inp_slot_ctx, sizeof(inp_slot_ctx));
4179
4180 /* If BSR isn't set, issue the actual SET_ADDRESS request. */
4181 if (!fBSR) {
4182 unsigned iPort;
4183
4184 /* We have to dig out the port number/index to determine which virtual root hub to use. */
4185 iPort = ID_TO_IDX(inp_slot_ctx.rh_port);
4186 if (iPort >= XHCI_NDP_CFG(pThis))
4187 {
4188 Log(("Port out of range (index %u)!\n", iPort));
4189 cc = XHCI_TCC_USB_XACT_ERR;
4190 break;
4191 }
4192 if (!xhciR3IssueSetAddress(pThisCC, uSlotID, dev_addr, iPort))
4193 {
4194 Log(("SET_ADDRESS failed!\n"));
4195 cc = XHCI_TCC_USB_XACT_ERR;
4196 break;
4197 }
4198 }
4199
4200 /* Copy the slot context with appropriate modifications. */
4201 out_slot_ctx = inp_slot_ctx;
4202 if (fBSR)
4203 out_slot_ctx.slot_state = XHCI_SLTST_DEFAULT;
4204 else
4205 out_slot_ctx.slot_state = XHCI_SLTST_ADDRESSED;
4206 out_slot_ctx.dev_addr = dev_addr;
4207 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysOutSlot, &out_slot_ctx, sizeof(out_slot_ctx));
4208
4209 /* Point at the EP0 contexts. */
4210 GCPhysInpSlot += sizeof(inp_slot_ctx);
4211 GCPhysOutSlot += sizeof(out_slot_ctx);
4212
4213 /* Copy EP0 context with appropriate modifications. */
4214 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysInpSlot, &ep_ctx, sizeof(ep_ctx));
4215 xhciR3EnableEP(&ep_ctx);
4216 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysOutSlot, &ep_ctx, sizeof(ep_ctx));
4217 } while (0);
4218
4219 return cc;
4220}
4221
4222
4223/**
4224 * Reset a halted endpoint.
4225 *
4226 * @returns TRB completion code.
4227 * @param pDevIns The device instance.
4228 * @param pThis Pointer to the xHCI state.
4229 * @param uSlotID Slot ID to work with.
4230 * @param uDCI DCI of the endpoint to reset.
4231 * @param fTSP The Transfer State Preserve flag.
4232 */
4233static unsigned xhciR3ResetEndpoint(PPDMDEVINS pDevIns, PXHCI pThis, uint8_t uSlotID, uint8_t uDCI, bool fTSP)
4234{
4235 RT_NOREF(fTSP);
4236 RTGCPHYS GCPhysSlot;
4237 RTGCPHYS GCPhysEndp;
4238 XHCI_SLOT_CTX slot_ctx;
4239 XHCI_EP_CTX endp_ctx;
4240 unsigned cc = XHCI_TCC_SUCCESS;
4241
4242 Assert(uSlotID);
4243
4244 /* Determine the addresses of the contexts. */
4245 GCPhysSlot = xhciR3FetchDevCtxAddr(pDevIns, pThis, uSlotID);
4246 GCPhysEndp = GCPhysSlot + uDCI * sizeof(XHCI_EP_CTX);
4247
4248 /* Fetch the slot context. */
4249 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysSlot, &slot_ctx, sizeof(slot_ctx));
4250
4251 /* See 4.6.8 */
4252 do {
4253 /* Check that the slot context state is Default, Addressed, or Configured. */
4254 if (slot_ctx.slot_state < XHCI_SLTST_DEFAULT)
4255 {
4256 Log(("Slot context state wrong (%u)!\n", slot_ctx.slot_state));
4257 cc = XHCI_TCC_CTX_STATE_ERR;
4258 break;
4259 }
4260
4261 /* Fetch the endpoint context. */
4262 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysEndp, &endp_ctx, sizeof(endp_ctx));
4263
4264 /* Check that the endpoint context state is Halted. */
4265 if (endp_ctx.ep_state != XHCI_EPST_HALTED)
4266 {
4267 Log(("Endpoint context state wrong (%u)!\n", endp_ctx.ep_state));
4268 cc = XHCI_TCC_CTX_STATE_ERR;
4269 break;
4270 }
4271
4272 /* Transition EP state. */
4273 endp_ctx.ep_state = XHCI_EPST_STOPPED;
4274
4275 /// @todo What can we do with the TSP flag?
4276 /// @todo Anything to do WRT enabling the corresponding doorbell register?
4277
4278 /* Write back the updated endpoint context. */
4279 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysEndp, &endp_ctx, sizeof(endp_ctx));
4280 } while (0);
4281
4282 return cc;
4283}
4284
4285
4286/**
4287 * Stop a running endpoint.
4288 *
4289 * @returns TRB completion code.
4290 * @param pDevIns The device instance.
4291 * @param pThis The xHCI device state, shared edition.
4292 * @param pThisCC The xHCI device state, ring-3 edition.
4293 * @param uSlotID Slot ID to work with.
4294 * @param uDCI DCI of the endpoint to stop.
4295 * @param fTSP The Suspend flag.
4296 */
4297static unsigned xhciR3StopEndpoint(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThisCC, uint8_t uSlotID, uint8_t uDCI, bool fTSP)
4298{
4299 RT_NOREF(fTSP);
4300 RTGCPHYS GCPhysSlot;
4301 RTGCPHYS GCPhysEndp;
4302 XHCI_SLOT_CTX slot_ctx;
4303 XHCI_EP_CTX endp_ctx;
4304 unsigned cc = XHCI_TCC_SUCCESS;
4305
4306 Assert(uSlotID);
4307
4308 /* Determine the addresses of the contexts. */
4309 GCPhysSlot = xhciR3FetchDevCtxAddr(pDevIns, pThis, uSlotID);
4310 GCPhysEndp = GCPhysSlot + uDCI * sizeof(XHCI_EP_CTX);
4311
4312 /* Fetch the slot context. */
4313 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysSlot, &slot_ctx, sizeof(slot_ctx));
4314
4315 /* See 4.6.9 */
4316 do {
4317 /* Check that the slot context state is Default, Addressed, or Configured. */
4318 if (slot_ctx.slot_state < XHCI_SLTST_DEFAULT)
4319 {
4320 Log(("Slot context state wrong (%u)!\n", slot_ctx.slot_state));
4321 cc = XHCI_TCC_CTX_STATE_ERR;
4322 break;
4323 }
4324
4325 /* The doorbell could be ringing; stop it if so. */
4326 if (pThis->aBellsRung[ID_TO_IDX(uSlotID)] & (1 << uDCI))
4327 {
4328 Log(("Unring bell for slot ID %u, DCI %u\n", uSlotID, uDCI));
4329 ASMAtomicAndU32(&pThis->aBellsRung[ID_TO_IDX(uSlotID)], ~(1 << uDCI));
4330 }
4331
4332 /* Fetch the endpoint context. */
4333 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysEndp, &endp_ctx, sizeof(endp_ctx));
4334
4335 /* Check that the endpoint context state is Running. */
4336 if (endp_ctx.ep_state != XHCI_EPST_RUNNING)
4337 {
4338 Log(("Endpoint context state wrong (%u)!\n", endp_ctx.ep_state));
4339 cc = XHCI_TCC_CTX_STATE_ERR;
4340 break;
4341 }
4342
4343 /* Transition EP state. */
4344 endp_ctx.ep_state = XHCI_EPST_STOPPED;
4345
4346 /* Write back the updated endpoint context *now*, before actually canceling anyhing. */
4347 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysEndp, &endp_ctx, sizeof(endp_ctx));
4348
4349 /// @todo What can we do with the SP flag?
4350
4351 PXHCIROOTHUBR3 pRh;
4352 uint32_t uPort;
4353
4354 /* Abort the endpoint, i.e. cancel any outstanding URBs. This needs to be done after
4355 * writing back the EP state so that the completion callback can operate. Note that
4356 * the completion callback will not modify the TR when it sees that the EP is not in
4357 * the 'running' state.
4358 * NB: If a URB is canceled before it completed, we have no way to tell if any data
4359 * was already (partially) transferred.
4360 */
4361 if (RT_SUCCESS(xhciR3FindRhDevBySlot(pDevIns, pThis, pThisCC, uSlotID, &pRh, &uPort)))
4362 {
4363 /* Temporarily give up the lock so that the completion callbacks can run. */
4364 RTCritSectLeave(&pThisCC->CritSectThrd);
4365 Log(("Aborting DCI %u -> ep=%u d=%u\n", uDCI, uDCI / 2, uDCI & 1 ? VUSBDIRECTION_IN : VUSBDIRECTION_OUT));
4366 pRh->pIRhConn->pfnAbortEpByPort(pRh->pIRhConn, uPort, uDCI / 2, uDCI & 1 ? VUSBDIRECTION_IN : VUSBDIRECTION_OUT);
4367 RTCritSectEnter(&pThisCC->CritSectThrd);
4368 }
4369
4370 /* Once the completion callbacks had a chance to run, we have to adjust
4371 * the endpoint state.
4372 * NB: The guest may just ring the doorbell to continue and not execute
4373 * 'Set TRDP' after stopping the endpoint.
4374 */
4375 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysEndp, &endp_ctx, sizeof(endp_ctx));
4376
4377 /* If the enqueue and dequeue pointers are different, a transfer was
4378 * in progress.
4379 */
4380 bool fXferWasInProgress = endp_ctx.trep != endp_ctx.trdp;
4381
4382 /* Reset the TREP, but the EDTLA should be left alone. */
4383 endp_ctx.trep = endp_ctx.trdp;
4384
4385 if (fXferWasInProgress)
4386 {
4387 /* Fetch the transfer TRB to see the length. */
4388 RTGCPHYS GCPhysXfrTRB = endp_ctx.trdp & XHCI_TRDP_ADDR_MASK;
4389 XHCI_XFER_TRB XferTRB;
4390 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysXfrTRB, &XferTRB, sizeof(XferTRB));
4391
4392 xhciR3PostXferEvent(pDevIns, pThis, slot_ctx.intr_tgt, XferTRB.gen.xfr_len, XHCI_TCC_STOPPED, uSlotID, uDCI,
4393 GCPhysXfrTRB, false, false);
4394 }
4395 else
4396 {
4397 /* We need to generate a Force Stopped Event or FSE. Note that FSEs were optional
4398 * in xHCI 0.96 but aren't in 1.0.
4399 */
4400 xhciR3PostXferEvent(pDevIns, pThis, slot_ctx.intr_tgt, 0, XHCI_TCC_STP_INV_LEN, uSlotID, uDCI,
4401 endp_ctx.trdp & XHCI_TRDP_ADDR_MASK, false, false);
4402 }
4403
4404 /* Write back the updated endpoint context again. */
4405 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysEndp, &endp_ctx, sizeof(endp_ctx));
4406
4407 } while (0);
4408
4409 return cc;
4410}
4411
4412
4413/**
4414 * Set a new TR Dequeue Pointer for an endpoint.
4415 *
4416 * @returns TRB completion code.
4417 * @param pDevIns The device instance.
4418 * @param pThis Pointer to the xHCI state.
4419 * @param uSlotID Slot ID to work with.
4420 * @param uDCI DCI of the endpoint to reset.
4421 * @param uTRDP The TRDP including DCS/ flag.
4422 */
4423static unsigned xhciR3SetTRDP(PPDMDEVINS pDevIns, PXHCI pThis, uint8_t uSlotID, uint8_t uDCI, uint64_t uTRDP)
4424{
4425 RTGCPHYS GCPhysSlot;
4426 RTGCPHYS GCPhysEndp;
4427 XHCI_SLOT_CTX slot_ctx;
4428 XHCI_EP_CTX endp_ctx;
4429 unsigned cc = XHCI_TCC_SUCCESS;
4430
4431 Assert(uSlotID);
4432
4433 /* Determine the addresses of the contexts. */
4434 GCPhysSlot = xhciR3FetchDevCtxAddr(pDevIns, pThis, uSlotID);
4435 GCPhysEndp = GCPhysSlot + uDCI * sizeof(XHCI_EP_CTX);
4436
4437 /* Fetch the slot context. */
4438 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysSlot, &slot_ctx, sizeof(slot_ctx));
4439
4440 /* See 4.6.10 */
4441 do {
4442 /* Check that the slot context state is Default, Addressed, or Configured. */
4443 if (slot_ctx.slot_state < XHCI_SLTST_DEFAULT)
4444 {
4445 Log(("Slot context state wrong (%u)!\n", slot_ctx.slot_state));
4446 cc = XHCI_TCC_CTX_STATE_ERR;
4447 break;
4448 }
4449
4450 /* Fetch the endpoint context. */
4451 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysEndp, &endp_ctx, sizeof(endp_ctx));
4452
4453 /* Check that the endpoint context state is Stopped or Error. */
4454 if (endp_ctx.ep_state != XHCI_EPST_STOPPED && endp_ctx.ep_state != XHCI_EPST_ERROR)
4455 {
4456 Log(("Endpoint context state wrong (%u)!\n", endp_ctx.ep_state));
4457 cc = XHCI_TCC_CTX_STATE_ERR;
4458 break;
4459 }
4460
4461 /* Update the TRDP/TREP and DCS. */
4462 endp_ctx.trdp = uTRDP;
4463 endp_ctx.trep = uTRDP;
4464
4465 /* Also clear the in-flight counter! */
4466 endp_ctx.ifc = 0;
4467
4468 /// @todo Handle streams
4469
4470 /* Write back the updated endpoint context. */
4471 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysEndp, &endp_ctx, sizeof(endp_ctx));
4472 } while (0);
4473
4474 return cc;
4475}
4476
4477
4478/**
4479 * Prepare for a device reset.
4480 *
4481 * @returns TRB completion code.
4482 * @param pDevIns The device instance.
4483 * @param pThis Pointer to the xHCI state.
4484 * @param uSlotID Slot ID to work with.
4485 */
4486static unsigned xhciR3ResetDevice(PPDMDEVINS pDevIns, PXHCI pThis, uint8_t uSlotID)
4487{
4488 RTGCPHYS GCPhysSlot;
4489 XHCI_SLOT_CTX slot_ctx;
4490 XHCI_DEV_CTX dc;
4491 unsigned num_ctx;
4492 unsigned i;
4493 unsigned cc = XHCI_TCC_SUCCESS;
4494
4495 Assert(uSlotID);
4496
4497 /* Determine the address of the slot/device context. */
4498 GCPhysSlot = xhciR3FetchDevCtxAddr(pDevIns, pThis, uSlotID);
4499
4500 /* Fetch the slot context. */
4501 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysSlot, &slot_ctx, sizeof(slot_ctx));
4502
4503 /* See 4.6.11. */
4504 do {
4505 /* Check that the slot context state is Addressed or Configured. */
4506 if (slot_ctx.slot_state < XHCI_SLTST_ADDRESSED)
4507 {
4508 Log(("Slot context state wrong (%u)!\n", slot_ctx.slot_state));
4509 cc = XHCI_TCC_CTX_STATE_ERR;
4510 break;
4511 }
4512
4513 /* Read the entire Device Context. */
4514 num_ctx = slot_ctx.ctx_ent + 1; /* Slot context plus EPs. */
4515 Assert(num_ctx);
4516 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysSlot, &dc, num_ctx * sizeof(XHCI_SLOT_CTX));
4517
4518 /// @todo Abort any outstanding transfers!
4519
4520 /* Set slot state to Default and reset the USB device address. */
4521 dc.entry[0].sc.slot_state = XHCI_SLTST_DEFAULT;
4522 dc.entry[0].sc.dev_addr = 0;
4523
4524 /* Disable all endpoints except for EP 0 (aka DCI 1). */
4525 for (i = 2; i < num_ctx; ++i)
4526 dc.entry[i].ep.ep_state = XHCI_EPST_DISABLED;
4527
4528 /* Write back the updated device context. */
4529 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysSlot, &dc, num_ctx * sizeof(XHCI_SLOT_CTX));
4530 } while (0);
4531
4532 return cc;
4533}
4534
4535
4536/**
4537 * Configure a device (even though the relevant command is called 'Configure
4538 * Endpoint'. This includes adding/dropping endpoint contexts as directed by
4539 * the input control context bits.
4540 *
4541 * @returns TRB completion code.
4542 * @param pDevIns The device instance.
4543 * @param pThis Pointer to the xHCI state.
4544 * @param uInpCtxAddr Address of the input context.
4545 * @param uSlotID Slot ID associated with the context.
4546 * @param fDC Deconfigure flag set (input context unused).
4547 */
4548static unsigned xhciR3ConfigureDevice(PPDMDEVINS pDevIns, PXHCI pThis, uint64_t uInpCtxAddr, uint8_t uSlotID, bool fDC)
4549{
4550 RTGCPHYS GCPhysInpCtx = uInpCtxAddr & XHCI_CTX_ADDR_MASK;
4551 RTGCPHYS GCPhysInpSlot;
4552 RTGCPHYS GCPhysOutSlot;
4553 RTGCPHYS GCPhysOutEndp;
4554 XHCI_INPC_CTX icc; /* Input Control Context (ICI=0). */
4555 XHCI_SLOT_CTX out_slot_ctx; /* Slot context (DCI=0). */
4556 XHCI_EP_CTX out_endp_ctx; /* Endpoint Context (DCI=1). */
4557 unsigned cc = XHCI_TCC_SUCCESS;
4558 uint32_t uAddFlags;
4559 uint32_t uDropFlags;
4560 unsigned num_inp_ctx;
4561 unsigned num_out_ctx;
4562 XHCI_DEV_CTX dc_inp;
4563 XHCI_DEV_CTX dc_out;
4564 unsigned uDCI;
4565
4566 Assert(uSlotID);
4567 LogFlowFunc(("Slot ID %u, input control context @ %RGp\n", uSlotID, GCPhysInpCtx));
4568
4569 /* Determine the address of the output slot context. */
4570 GCPhysOutSlot = xhciR3FetchDevCtxAddr(pDevIns, pThis, uSlotID);
4571 Assert(GCPhysOutSlot);
4572
4573 /* Fetch the output slot context. */
4574 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysOutSlot, &out_slot_ctx, sizeof(out_slot_ctx));
4575
4576 /* See 4.6.6 */
4577 do {
4578 /* Check that the output slot context state is Addressed, or Configured. */
4579 if (out_slot_ctx.slot_state < XHCI_SLTST_ADDRESSED)
4580 {
4581 Log(("Output slot context state wrong (%u)!\n", out_slot_ctx.slot_state));
4582 cc = XHCI_TCC_CTX_STATE_ERR;
4583 break;
4584 }
4585
4586 /* Check for deconfiguration request. */
4587 if (fDC) {
4588 if (out_slot_ctx.slot_state == XHCI_SLTST_CONFIGURED) {
4589 /* Disable all enabled endpoints. */
4590 uDropFlags = 0xFFFFFFFC; /** @todo r=bird: Why do you set uDropFlags and uAddFlags in a code path that doesn't use
4591 * them? This is a _very_ difficult function to get the hang of the way it's written.
4592 * Stuff like this looks like there's a control flow flaw (as to the do-break-while-false
4593 * loop which doesn't do any clean up or logging at the end and seems only sever the very
4594 * dubious purpose of making sure ther's only one return statement). The insistance on
4595 * C-style variable declarations (top of function), makes checking state harder, which is
4596 * why it's discouraged. */
4597 uAddFlags = 0;
4598
4599 /* Start with EP1. */
4600 GCPhysOutEndp = GCPhysOutSlot + sizeof(XHCI_SLOT_CTX) + sizeof(XHCI_EP_CTX);
4601
4602 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysOutEndp, &out_endp_ctx, sizeof(out_endp_ctx));
4603 out_endp_ctx.ep_state = XHCI_EPST_DISABLED;
4604 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysOutEndp, &out_endp_ctx, sizeof(out_endp_ctx));
4605 GCPhysOutEndp += sizeof(XHCI_EP_CTX); /* Point to the next EP context. */
4606
4607 /* Finally update the output slot context. */
4608 out_slot_ctx.ctx_ent = 1; /* Only EP0 left. */
4609 out_slot_ctx.slot_state = XHCI_SLTST_ADDRESSED;
4610 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysOutSlot, &out_slot_ctx, sizeof(out_slot_ctx));
4611 LogFlow(("Setting Output Slot State to Addressed, Context Entries = %u\n", out_slot_ctx.ctx_ent));
4612 }
4613 else
4614 /* NB: Attempts to deconfigure a slot in Addressed state are ignored. */
4615 Log(("Ignoring attempt to deconfigure slot in Addressed state!\n"));
4616 break;
4617 }
4618
4619 /* Fetch the input control context. */
4620 Assert(GCPhysInpCtx);
4621 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysInpCtx, &icc, sizeof(icc));
4622 Assert(icc.add_flags || icc.drop_flags); /* Make sure there's something to do. */
4623
4624 uAddFlags = icc.add_flags;
4625 uDropFlags = icc.drop_flags;
4626 LogFlowFunc(("Add Flags=%08X, Drop Flags=%08X\n", uAddFlags, uDropFlags));
4627
4628 /* If and only if any 'add context' flag is set, fetch the corresponding
4629 * input device context.
4630 */
4631 if (uAddFlags) {
4632 /* Calculate the address of the input slot context (ICI=1/DCI=0). */
4633 GCPhysInpSlot = GCPhysInpCtx + sizeof(XHCI_INPC_CTX);
4634
4635 /* Read the input Slot Context plus all Endpoint Contexts up to and
4636 * including the one with the highest 'add' bit set.
4637 */
4638 num_inp_ctx = ASMBitLastSetU32(uAddFlags);
4639 Assert(num_inp_ctx);
4640 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysInpSlot, &dc_inp, num_inp_ctx * sizeof(XHCI_DS_ENTRY));
4641
4642 /// @todo Check that the highest set add flag isn't beyond input slot Context Entries
4643
4644 /// @todo Check input slot context according to 6.2.2.2
4645 /// @todo Check input EP contexts according to 6.2.3.2
4646 }
4647/** @todo r=bird: Looks like MSC is right that dc_inp can be used uninitalized.
4648 *
4649 * However, this function is so hard to read I'm leaving the exorcism of it to
4650 * the author and just zeroing it in the mean time.
4651 *
4652 */
4653 else
4654 RT_ZERO(dc_inp);
4655
4656 /* Read the output Slot Context plus all Endpoint Contexts up to and
4657 * including the one with the highest 'add' or 'drop' bit set.
4658 */
4659 num_out_ctx = ASMBitLastSetU32(uAddFlags | uDropFlags);
4660 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysOutSlot, &dc_out, num_out_ctx * sizeof(XHCI_DS_ENTRY));
4661
4662 /* Drop contexts as directed by flags. */
4663 for (uDCI = 2; uDCI < 32; ++uDCI)
4664 {
4665 if (!((1 << uDCI) & uDropFlags))
4666 continue;
4667
4668 Log2(("Dropping EP DCI %u\n", uDCI));
4669 dc_out.entry[uDCI].ep.ep_state = XHCI_EPST_DISABLED;
4670 /// @todo Do we need to bother tracking resources/bandwidth?
4671 }
4672
4673 /* Now add contexts as directed by flags. */
4674 for (uDCI = 2; uDCI < 32; ++uDCI)
4675 {
4676 if (!((1 << uDCI) & uAddFlags))
4677 continue;
4678
4679 Assert(!fDC);
4680 /* Copy over EP context, set to running. */
4681 Log2(("Adding EP DCI %u\n", uDCI));
4682 dc_out.entry[uDCI].ep = dc_inp.entry[uDCI].ep;
4683 xhciR3EnableEP(&dc_out.entry[uDCI].ep);
4684 /// @todo Do we need to bother tracking resources/bandwidth?
4685 }
4686
4687 /* Finally update the device context. */
4688 if (fDC || dc_inp.entry[0].sc.ctx_ent == 1)
4689 {
4690 dc_out.entry[0].sc.slot_state = XHCI_SLTST_ADDRESSED;
4691 dc_out.entry[0].sc.ctx_ent = 1;
4692 LogFlow(("Setting Output Slot State to Addressed\n"));
4693 }
4694 else
4695 {
4696 uint32_t uKillFlags = uDropFlags & ~uAddFlags; /* Endpoints going away. */
4697
4698 /* At least one EP enabled. Update Context Entries and state. */
4699 Assert(dc_inp.entry[0].sc.ctx_ent);
4700 dc_out.entry[0].sc.slot_state = XHCI_SLTST_CONFIGURED;
4701 if (ID_TO_IDX(ASMBitLastSetU32(uAddFlags)) > dc_out.entry[0].sc.ctx_ent)
4702 {
4703 /* Adding new endpoints. */
4704 dc_out.entry[0].sc.ctx_ent = ID_TO_IDX(ASMBitLastSetU32(uAddFlags));
4705 }
4706 else if (ID_TO_IDX(ASMBitLastSetU32(uKillFlags)) == dc_out.entry[0].sc.ctx_ent)
4707 {
4708 /* Removing the last endpoint, find the last non-disabled one. */
4709 unsigned num_ctx_ent;
4710
4711 Assert(dc_out.entry[0].sc.ctx_ent + 1u == num_out_ctx);
4712 for (num_ctx_ent = dc_out.entry[0].sc.ctx_ent; num_ctx_ent > 1; --num_ctx_ent)
4713 if (dc_out.entry[num_ctx_ent].ep.ep_state != XHCI_EPST_DISABLED)
4714 break;
4715 dc_out.entry[0].sc.ctx_ent = num_ctx_ent; /* Last valid index to be precise. */
4716 }
4717 LogFlow(("Setting Output Slot State to Configured, Context Entries = %u\n", dc_out.entry[0].sc.ctx_ent));
4718 }
4719
4720 /* If there were no errors, write back the updated output context. */
4721 LogFlow(("Success, updating Output Context @ %RGp\n", GCPhysOutSlot));
4722 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysOutSlot, &dc_out, num_out_ctx * sizeof(XHCI_DS_ENTRY));
4723 } while (0);
4724
4725 return cc;
4726}
4727
4728
4729/**
4730 * Evaluate an input context. This involves modifying device and endpoint
4731 * contexts as directed by the input control context add bits.
4732 *
4733 * @returns TRB completion code.
4734 * @param pDevIns The device instance.
4735 * @param pThis Pointer to the xHCI state.
4736 * @param uInpCtxAddr Address of the input context.
4737 * @param uSlotID Slot ID associated with the context.
4738 */
4739static unsigned xhciR3EvalContext(PPDMDEVINS pDevIns, PXHCI pThis, uint64_t uInpCtxAddr, uint8_t uSlotID)
4740{
4741 RTGCPHYS GCPhysInpCtx = uInpCtxAddr & XHCI_CTX_ADDR_MASK;
4742 RTGCPHYS GCPhysInpSlot;
4743 RTGCPHYS GCPhysOutSlot;
4744 XHCI_INPC_CTX icc; /* Input Control Context (ICI=0). */
4745 XHCI_SLOT_CTX out_slot_ctx; /* Slot context (DCI=0). */
4746 unsigned cc = XHCI_TCC_SUCCESS;
4747 uint32_t uAddFlags;
4748 uint32_t uDropFlags;
4749 unsigned num_inp_ctx;
4750 unsigned num_out_ctx;
4751 XHCI_DEV_CTX dc_inp;
4752 XHCI_DEV_CTX dc_out;
4753 unsigned uDCI;
4754
4755 Assert(GCPhysInpCtx);
4756 Assert(uSlotID);
4757 LogFlowFunc(("Slot ID %u, input control context @ %RGp\n", uSlotID, GCPhysInpCtx));
4758
4759 /* Determine the address of the output slot context. */
4760 GCPhysOutSlot = xhciR3FetchDevCtxAddr(pDevIns, pThis, uSlotID);
4761 Assert(GCPhysOutSlot);
4762
4763 /* Fetch the output slot context. */
4764 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysOutSlot, &out_slot_ctx, sizeof(out_slot_ctx));
4765
4766 /* See 4.6.7 */
4767 do {
4768 /* Check that the output slot context state is Default, Addressed, or Configured. */
4769 if (out_slot_ctx.slot_state < XHCI_SLTST_DEFAULT)
4770 {
4771 Log(("Output slot context state wrong (%u)!\n", out_slot_ctx.slot_state));
4772 cc = XHCI_TCC_CTX_STATE_ERR;
4773 break;
4774 }
4775
4776 /* Fetch the input control context. */
4777 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysInpCtx, &icc, sizeof(icc));
4778 uAddFlags = icc.add_flags;
4779 uDropFlags = icc.drop_flags;
4780 LogFlowFunc(("Add Flags=%08X, Drop Flags=%08X\n", uAddFlags, uDropFlags));
4781
4782 /* Drop flags "shall be cleared to 0" but also "do not apply" (4.6.7). Log & ignore. */
4783 if (uDropFlags)
4784 Log(("Drop flags set (%X) for evaluating context!\n", uDropFlags));
4785
4786 /* If no add flags are set, nothing will be done but an error is not reported
4787 * according to the logic flow in 4.6.7.
4788 */
4789 if (!uAddFlags)
4790 {
4791 Log(("Warning: no add flags set for evaluating context!\n"));
4792 break;
4793 }
4794
4795 /* Calculate the address of the input slot context (ICI=1/DCI=0). */
4796 GCPhysInpSlot = GCPhysInpCtx + sizeof(XHCI_INPC_CTX);
4797
4798 /* Read the output Slot Context plus all Endpoint Contexts up to and
4799 * including the one with the highest 'add' bit set.
4800 */
4801 num_inp_ctx = ASMBitLastSetU32(uAddFlags);
4802 Assert(num_inp_ctx);
4803 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysInpSlot, &dc_inp, num_inp_ctx * sizeof(XHCI_DS_ENTRY));
4804
4805 /* Read the output Slot Context plus all Endpoint Contexts up to and
4806 * including the one with the highest 'add' bit set.
4807 */
4808 num_out_ctx = ASMBitLastSetU32(uAddFlags);
4809 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysOutSlot, &dc_out, num_out_ctx * sizeof(XHCI_DS_ENTRY));
4810
4811 /// @todo Check input slot context according to 6.2.2.3
4812 /// @todo Check input EP contexts according to 6.2.3.3
4813 /// @todo Check that the highest set add flag isn't beyond input slot Context Entries
4814
4815 /* Evaluate endpoint contexts as directed by add flags. */
4816 /// @todo 6.2.3.3 suggests only the A1 bit matters? Anything besides A0/A1 is ignored??
4817 for (uDCI = 1; uDCI < 32; ++uDCI)
4818 {
4819 if (!((1 << uDCI) & uAddFlags))
4820 continue;
4821
4822 /* Evaluate Max Packet Size. */
4823 LogFunc(("DCI %u: Max Packet Size: %u -> %u\n", uDCI, dc_out.entry[uDCI].ep.max_pkt_sz, dc_inp.entry[uDCI].ep.max_pkt_sz));
4824 dc_out.entry[uDCI].ep.max_pkt_sz = dc_inp.entry[uDCI].ep.max_pkt_sz;
4825 }
4826
4827 /* Finally update the device context if directed to do so (A0 flag set). */
4828 if (uAddFlags & RT_BIT(0))
4829 {
4830 /* 6.2.2.3 - evaluate Interrupter Target and Max Exit Latency. */
4831 Log(("Interrupter Target: %u -> %u\n", dc_out.entry[0].sc.intr_tgt, dc_inp.entry[0].sc.intr_tgt));
4832 Log(("Max Exit Latency : %u -> %u\n", dc_out.entry[0].sc.max_lat, dc_inp.entry[0].sc.max_lat));
4833
4834 /// @todo Non-zero Max Exit Latency (see 4.6.7)
4835 dc_out.entry[0].sc.intr_tgt = dc_inp.entry[0].sc.intr_tgt;
4836 dc_out.entry[0].sc.max_lat = dc_inp.entry[0].sc.max_lat;
4837 }
4838
4839 /* If there were no errors, write back the updated output context. */
4840 LogFlow(("Success, updating Output Context @ %RGp\n", GCPhysOutSlot));
4841 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysOutSlot, &dc_out, num_out_ctx * sizeof(XHCI_DS_ENTRY));
4842 } while (0);
4843
4844 return cc;
4845}
4846
4847
4848/**
4849 * Query available port bandwidth.
4850 *
4851 * @returns TRB completion code.
4852 * @param pDevIns The device instance.
4853 * @param pThis Pointer to the xHCI state.
4854 * @param uDevSpd Speed of not yet attached devices.
4855 * @param uHubSlotID Hub Slot ID to query (unsupported).
4856 * @param uBwCtx Bandwidth context physical address.
4857 */
4858static unsigned xhciR3GetPortBandwidth(PPDMDEVINS pDevIns, PXHCI pThis, uint8_t uDevSpd, uint8_t uHubSlotID, uint64_t uBwCtx)
4859{
4860 RT_NOREF(uHubSlotID);
4861 RTGCPHYS GCPhysBwCtx;
4862 unsigned cc = XHCI_TCC_SUCCESS;
4863 unsigned ctx_size;
4864 unsigned iPort;
4865 uint8_t bw_ctx[RT_ALIGN_32(XHCI_NDP_MAX + 1, 4)] = {0};
4866 uint8_t dev_spd;
4867 uint8_t avail_bw;
4868
4869 Assert(!uHubSlotID);
4870 Assert(uBwCtx);
4871
4872 /* See 4.6.15. */
4873
4874 /* Hubs are not supported because guests will never see them. The
4875 * reported values are more or less dummy because we have no real
4876 * information about the bandwidth available on the host. The reported
4877 * values are optimistic, as if each port had its own separate Bus
4878 * Instance aka BI.
4879 */
4880
4881 GCPhysBwCtx = uBwCtx & XHCI_CTX_ADDR_MASK;
4882
4883 /* Number of ports + 1, rounded up to DWORDs. */
4884 ctx_size = RT_ALIGN_32(XHCI_NDP_CFG(pThis) + 1, 4);
4885 LogFlowFunc(("BW Context at %RGp, size %u\n", GCPhysBwCtx, ctx_size));
4886 Assert(ctx_size <= sizeof(bw_ctx));
4887
4888 /* Go over all the ports. */
4889 for (iPort = 0; iPort < XHCI_NDP_CFG(pThis); ++iPort)
4890 {
4891 /* Get the device speed from the port... */
4892 dev_spd = (pThis->aPorts[iPort].portsc & XHCI_PORT_PLS_MASK) >> XHCI_PORT_PLS_SHIFT;
4893 /* ...and if nothing is attached, use the provided default. */
4894 if (!dev_spd)
4895 dev_spd = uDevSpd;
4896
4897 /* For USB3 ports, report 90% available for SS devices (see 6.2.6). */
4898 if (IS_USB3_PORT_IDX_SHR(pThis, iPort))
4899 avail_bw = dev_spd == XHCI_SPD_SUPER ? 90 : 0;
4900 else
4901 /* For USB2 ports, report 80% available for HS and 90% for FS/LS. */
4902 switch (dev_spd)
4903 {
4904 case XHCI_SPD_HIGH:
4905 avail_bw = 80;
4906 break;
4907 case XHCI_SPD_FULL:
4908 case XHCI_SPD_LOW:
4909 avail_bw = 90;
4910 break;
4911 default:
4912 avail_bw = 0;
4913 }
4914
4915 /* The first entry in the context is reserved. */
4916 bw_ctx[iPort + 1] = avail_bw;
4917 }
4918
4919 /* Write back the bandwidth context. */
4920 PDMDevHlpPCIPhysWriteMeta(pDevIns, GCPhysBwCtx, &bw_ctx, ctx_size);
4921
4922 return cc;
4923}
4924
4925#define NEC_MAGIC ('x' | ('H' << 8) | ('C' << 16) | ('I' << 24))
4926
4927/**
4928 * Take a 64-bit input, shake well, produce 32-bit token. This mechanism
4929 * prevents NEC/Renesas drivers from running on 3rd party hardware. Mirrors
4930 * code found in vendor's drivers.
4931 */
4932static uint32_t xhciR3NecAuthenticate(uint64_t cookie)
4933{
4934 uint32_t cookie_lo = RT_LODWORD(cookie);
4935 uint32_t cookie_hi = RT_HIDWORD(cookie);
4936 uint32_t shift_cnt;
4937 uint32_t token;
4938
4939 shift_cnt = (cookie_hi >> 8) & 31;
4940 token = ASMRotateRightU32(cookie_lo - NEC_MAGIC, shift_cnt);
4941 shift_cnt = cookie_hi & 31;
4942 token += ASMRotateLeftU32(cookie_lo + NEC_MAGIC, shift_cnt);
4943 shift_cnt = (cookie_lo >> 16) & 31;
4944 token -= ASMRotateLeftU32(cookie_hi ^ NEC_MAGIC, shift_cnt);
4945
4946 return ~token;
4947}
4948
4949/**
4950 * Process a single command TRB and post completion information.
4951 */
4952static int xhciR3ExecuteCommand(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThisCC, XHCI_COMMAND_TRB *pCmd)
4953{
4954 XHCI_EVENT_TRB ed;
4955 uint32_t token;
4956 unsigned slot;
4957 unsigned cc;
4958 int rc = VINF_SUCCESS;
4959 LogFlowFunc(("Executing command %u (%s) @ %RGp\n", pCmd->gen.type,
4960 pCmd->gen.type < RT_ELEMENTS(g_apszTrbNames) ? g_apszTrbNames[pCmd->gen.type] : "WHAT?!!",
4961 (RTGCPHYS)pThis->cmdr_dqp));
4962
4963 switch (pCmd->gen.type)
4964 {
4965 case XHCI_TRB_NOOP_CMD:
4966 /* No-op, slot ID is always zero. */
4967 rc = xhciR3PostCmdCompletion(pDevIns, pThis, XHCI_TCC_SUCCESS, 0);
4968 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
4969 break;
4970
4971 case XHCI_TRB_LINK:
4972 /* Link; set the dequeue pointer. CH bit is ignored. */
4973 Log(("Link: Ptr=%RGp IOC=%u TC=%u\n", pCmd->link.rseg_ptr, pCmd->link.ioc, pCmd->link.toggle));
4974 if (pCmd->link.ioc) /* Command completion event is optional! */
4975 rc = xhciR3PostCmdCompletion(pDevIns, pThis, XHCI_TCC_SUCCESS, 0);
4976 /* Update the dequeue pointer and flip DCS if required. */
4977 pThis->cmdr_dqp = pCmd->link.rseg_ptr & XHCI_TRDP_ADDR_MASK;
4978 pThis->cmdr_ccs = pThis->cmdr_ccs ^ pCmd->link.toggle;
4979 break;
4980
4981 case XHCI_TRB_ENB_SLOT:
4982 /* Look for an empty device slot. */
4983 for (slot = 0; slot < RT_ELEMENTS(pThis->aSlotState); ++slot)
4984 {
4985 if (pThis->aSlotState[slot] == XHCI_DEVSLOT_EMPTY)
4986 {
4987 /* Found a slot - transition to enabled state. */
4988 pThis->aSlotState[slot] = XHCI_DEVSLOT_ENABLED;
4989 break;
4990 }
4991 }
4992 Log(("Enable Slot: found slot ID %u\n", IDX_TO_ID(slot)));
4993
4994 /* Post command completion event. */
4995 if (slot == RT_ELEMENTS(pThis->aSlotState))
4996 xhciR3PostCmdCompletion(pDevIns, pThis, XHCI_TCC_NO_SLOTS, 0);
4997 else
4998 xhciR3PostCmdCompletion(pDevIns, pThis, XHCI_TCC_SUCCESS, IDX_TO_ID(slot));
4999
5000 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5001 break;
5002
5003 case XHCI_TRB_DIS_SLOT:
5004 /* Disable the given device slot. */
5005 Log(("Disable Slot: slot ID %u\n", pCmd->dsl.slot_id));
5006 cc = XHCI_TCC_SUCCESS;
5007 slot = ID_TO_IDX(pCmd->dsl.slot_id);
5008 if ((slot >= RT_ELEMENTS(pThis->aSlotState)) || (pThis->aSlotState[slot] == XHCI_DEVSLOT_EMPTY))
5009 cc = XHCI_TCC_SLOT_NOT_ENB;
5010 else
5011 {
5012 /// @todo set slot state of assoc. context to disabled
5013 pThis->aSlotState[slot] = XHCI_DEVSLOT_EMPTY;
5014 }
5015 xhciR3PostCmdCompletion(pDevIns, pThis, cc, pCmd->dsl.slot_id);
5016 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5017 break;
5018
5019 case XHCI_TRB_ADDR_DEV:
5020 /* Address a device. */
5021 Log(("Address Device: slot ID %u, BSR=%u\n", pCmd->adr.slot_id, pCmd->adr.bsr));
5022 slot = ID_TO_IDX(pCmd->cfg.slot_id);
5023 if ((slot >= RT_ELEMENTS(pThis->aSlotState)) || (pThis->aSlotState[slot] == XHCI_DEVSLOT_EMPTY))
5024 cc = XHCI_TCC_SLOT_NOT_ENB;
5025 else
5026 cc = xhciR3AddressDevice(pDevIns, pThis, pThisCC, pCmd->adr.ctx_ptr, pCmd->adr.slot_id, pCmd->adr.bsr);
5027 xhciR3PostCmdCompletion(pDevIns, pThis, cc, pCmd->adr.slot_id);
5028 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5029 break;
5030
5031 case XHCI_TRB_CFG_EP:
5032 /* Configure endpoint. */
5033 Log(("Configure endpoint: slot ID %u, DC=%u, Ctx @ %RGp\n", pCmd->cfg.slot_id, pCmd->cfg.dc, pCmd->cfg.ctx_ptr));
5034 slot = ID_TO_IDX(pCmd->cfg.slot_id);
5035 if ((slot >= RT_ELEMENTS(pThis->aSlotState)) || (pThis->aSlotState[slot] == XHCI_DEVSLOT_EMPTY))
5036 cc = XHCI_TCC_SLOT_NOT_ENB;
5037 else
5038 cc = xhciR3ConfigureDevice(pDevIns, pThis, pCmd->cfg.ctx_ptr, pCmd->cfg.slot_id, pCmd->cfg.dc);
5039 xhciR3PostCmdCompletion(pDevIns, pThis, cc, pCmd->cfg.slot_id);
5040 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5041 break;
5042
5043 case XHCI_TRB_EVAL_CTX:
5044 /* Evaluate context. */
5045 Log(("Evaluate context: slot ID %u, Ctx @ %RGp\n", pCmd->evc.slot_id, pCmd->evc.ctx_ptr));
5046 slot = ID_TO_IDX(pCmd->evc.slot_id);
5047 if ((slot >= RT_ELEMENTS(pThis->aSlotState)) || (pThis->aSlotState[slot] == XHCI_DEVSLOT_EMPTY))
5048 cc = XHCI_TCC_SLOT_NOT_ENB;
5049 else
5050 cc = xhciR3EvalContext(pDevIns, pThis, pCmd->evc.ctx_ptr, pCmd->evc.slot_id);
5051 xhciR3PostCmdCompletion(pDevIns, pThis, cc, pCmd->evc.slot_id);
5052 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5053 break;
5054
5055 case XHCI_TRB_RESET_EP:
5056 /* Reset the given endpoint. */
5057 Log(("Reset Endpoint: slot ID %u, EP ID %u, TSP=%u\n", pCmd->rse.slot_id, pCmd->rse.ep_id, pCmd->rse.tsp));
5058 cc = XHCI_TCC_SUCCESS;
5059 slot = ID_TO_IDX(pCmd->rse.slot_id);
5060 if ((slot >= RT_ELEMENTS(pThis->aSlotState)) || (pThis->aSlotState[slot] == XHCI_DEVSLOT_EMPTY))
5061 cc = XHCI_TCC_SLOT_NOT_ENB;
5062 else
5063 cc = xhciR3ResetEndpoint(pDevIns, pThis, pCmd->rse.slot_id, pCmd->rse.ep_id, pCmd->rse.tsp);
5064 xhciR3PostCmdCompletion(pDevIns, pThis, cc, pCmd->stp.slot_id);
5065 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5066 break;
5067
5068 case XHCI_TRB_STOP_EP:
5069 /* Stop the given endpoint. */
5070 Log(("Stop Endpoint: slot ID %u, EP ID %u, SP=%u\n", pCmd->stp.slot_id, pCmd->stp.ep_id, pCmd->stp.sp));
5071 cc = XHCI_TCC_SUCCESS;
5072 slot = ID_TO_IDX(pCmd->stp.slot_id);
5073 if ((slot >= RT_ELEMENTS(pThis->aSlotState)) || (pThis->aSlotState[slot] == XHCI_DEVSLOT_EMPTY))
5074 cc = XHCI_TCC_SLOT_NOT_ENB;
5075 else
5076 cc = xhciR3StopEndpoint(pDevIns, pThis, pThisCC, pCmd->stp.slot_id, pCmd->stp.ep_id, pCmd->stp.sp);
5077 xhciR3PostCmdCompletion(pDevIns, pThis, cc, pCmd->stp.slot_id);
5078 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5079 break;
5080
5081 case XHCI_TRB_SET_DEQ_PTR:
5082 /* Set TR Dequeue Pointer. */
5083 Log(("Set TRDP: slot ID %u, EP ID %u, TRDP=%RX64\n", pCmd->stdp.slot_id, pCmd->stdp.ep_id, pCmd->stdp.tr_dqp));
5084 cc = XHCI_TCC_SUCCESS;
5085 slot = ID_TO_IDX(pCmd->stdp.slot_id);
5086 if ((slot >= RT_ELEMENTS(pThis->aSlotState)) || (pThis->aSlotState[slot] == XHCI_DEVSLOT_EMPTY))
5087 cc = XHCI_TCC_SLOT_NOT_ENB;
5088 else
5089 cc = xhciR3SetTRDP(pDevIns, pThis, pCmd->stdp.slot_id, pCmd->stdp.ep_id, pCmd->stdp.tr_dqp);
5090 xhciR3PostCmdCompletion(pDevIns, pThis, cc, pCmd->stdp.slot_id);
5091 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5092 break;
5093
5094 case XHCI_TRB_RESET_DEV:
5095 /* Reset a device. */
5096 Log(("Reset Device: slot ID %u\n", pCmd->rsd.slot_id));
5097 cc = XHCI_TCC_SUCCESS;
5098 slot = ID_TO_IDX(pCmd->rsd.slot_id);
5099 if ((slot >= RT_ELEMENTS(pThis->aSlotState)) || (pThis->aSlotState[slot] == XHCI_DEVSLOT_EMPTY))
5100 cc = XHCI_TCC_SLOT_NOT_ENB;
5101 else
5102 cc = xhciR3ResetDevice(pDevIns, pThis, pCmd->rsd.slot_id);
5103 xhciR3PostCmdCompletion(pDevIns, pThis, cc, pCmd->rsd.slot_id);
5104 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5105 break;
5106
5107 case XHCI_TRB_GET_PORT_BW:
5108 /* Get port bandwidth. */
5109 Log(("Get Port Bandwidth: Dev Speed %u, Hub Slot ID %u, Context=%RX64\n", pCmd->gpbw.spd, pCmd->gpbw.slot_id, pCmd->gpbw.pbctx_ptr));
5110 cc = XHCI_TCC_SUCCESS;
5111 if (pCmd->gpbw.slot_id)
5112 cc = XHCI_TCC_PARM_ERR; /* Potential undefined behavior, see 4.6.15. */
5113 else
5114 cc = xhciR3GetPortBandwidth(pDevIns, pThis, pCmd->gpbw.spd, pCmd->gpbw.slot_id, pCmd->gpbw.pbctx_ptr);
5115 xhciR3PostCmdCompletion(pDevIns, pThis, cc, 0);
5116 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5117 break;
5118
5119 case NEC_TRB_GET_FW_VER:
5120 /* Get NEC firmware version. */
5121 Log(("Get NEC firmware version\n"));
5122 cc = XHCI_TCC_SUCCESS;
5123
5124 RT_ZERO(ed);
5125 ed.nce.word1 = NEC_FW_REV;
5126 ed.nce.trb_ptr = pThis->cmdr_dqp;
5127 ed.nce.cc = cc;
5128 ed.nce.type = NEC_TRB_CMD_CMPL;
5129
5130 xhciR3WriteEvent(pDevIns, pThis, &ed, XHCI_PRIMARY_INTERRUPTER, false);
5131
5132 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5133 break;
5134
5135 case NEC_TRB_AUTHENTICATE:
5136 /* NEC authentication. */
5137 Log(("NEC authentication, cookie %RX64\n", pCmd->nac.cookie));
5138 cc = XHCI_TCC_SUCCESS;
5139
5140 token = xhciR3NecAuthenticate(pCmd->nac.cookie);
5141 RT_ZERO(ed);
5142 ed.nce.word1 = RT_LOWORD(token);
5143 ed.nce.word2 = RT_HIWORD(token);
5144 ed.nce.trb_ptr = pThis->cmdr_dqp;
5145 ed.nce.cc = cc;
5146 ed.nce.type = NEC_TRB_CMD_CMPL;
5147
5148 xhciR3WriteEvent(pDevIns, pThis, &ed, XHCI_PRIMARY_INTERRUPTER, false);
5149
5150 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5151 break;
5152
5153 default:
5154 Log(("Unsupported command!\n"));
5155 pThis->cmdr_dqp += sizeof(XHCI_COMMAND_TRB);
5156 break;
5157 }
5158
5159 return rc;
5160}
5161
5162
5163/**
5164 * Stop the Command Ring.
5165 */
5166static int xhciR3StopCommandRing(PPDMDEVINS pDevIns, PXHCI pThis)
5167{
5168 LogFlowFunc(("Command Ring stopping\n"));
5169
5170 Assert(pThis->crcr & (XHCI_CRCR_CA | XHCI_CRCR_CS));
5171 Assert(pThis->crcr & XHCI_CRCR_CRR);
5172 ASMAtomicAndU64(&pThis->crcr, ~(XHCI_CRCR_CRR | XHCI_CRCR_CA | XHCI_CRCR_CS));
5173 return xhciR3PostCmdCompletion(pDevIns, pThis, XHCI_TCC_CMDR_STOPPED, 0);
5174}
5175
5176
5177/**
5178 * Process the xHCI command ring.
5179 */
5180static int xhciR3ProcessCommandRing(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThisCC)
5181{
5182 RTGCPHYS GCPhysCmdTRB;
5183 XHCI_COMMAND_TRB cmd; /* Command Descriptor */
5184 unsigned cCmds;
5185
5186 Assert(pThis->crcr & XHCI_CRCR_CRR);
5187 LogFlowFunc(("Processing commands...\n"));
5188
5189 for (cCmds = 0;; cCmds++)
5190 {
5191 /* First check if the xHC is running at all. */
5192 if (!(pThis->cmd & XHCI_CMD_RS))
5193 {
5194 /* Note that this will call xhciR3PostCmdCompletion() which will
5195 * end up doing nothing because R/S is clear.
5196 */
5197 xhciR3StopCommandRing(pDevIns, pThis);
5198 break;
5199 }
5200
5201 /* Check if Command Ring was stopped in the meantime. */
5202 if (pThis->crcr & (XHCI_CRCR_CS | XHCI_CRCR_CA))
5203 {
5204 /* NB: We currently do not abort commands. If we did, we would
5205 * abort the currently running command and complete it with
5206 * the XHCI_TCC_CMD_ABORTED status.
5207 */
5208 xhciR3StopCommandRing(pDevIns, pThis);
5209 break;
5210 }
5211
5212 /* Fetch the command TRB. */
5213 GCPhysCmdTRB = pThis->cmdr_dqp;
5214 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysCmdTRB, &cmd, sizeof(cmd));
5215
5216 /* Make sure the Cycle State matches. */
5217 if ((bool)cmd.gen.cycle == pThis->cmdr_ccs)
5218 xhciR3ExecuteCommand(pDevIns, pThis, pThisCC, &cmd);
5219 else
5220 {
5221 Log(("Command Ring empty\n"));
5222 break;
5223 }
5224
5225 /* Check if we're being fed suspiciously many commands. */
5226 if (cCmds > XHCI_MAX_NUM_CMDS)
5227 {
5228 /* Clear the R/S bit and any command ring running bits.
5229 * Note that the caller (xhciR3WorkerLoop) will set XHCI_STATUS_HCH.
5230 */
5231 ASMAtomicAndU32(&pThis->cmd, ~XHCI_CMD_RS);
5232 ASMAtomicAndU64(&pThis->crcr, ~(XHCI_CRCR_CRR | XHCI_CRCR_CA | XHCI_CRCR_CS));
5233 ASMAtomicOrU32(&pThis->status, XHCI_STATUS_HCE);
5234 LogRelMax(10, ("xHCI: Attempted to execute too many commands, stopping xHC!\n"));
5235 break;
5236 }
5237 }
5238 return VINF_SUCCESS;
5239}
5240
5241
5242/**
5243 * The xHCI asynchronous worker thread.
5244 *
5245 * @returns VBox status code.
5246 * @param pDevIns The xHCI device instance.
5247 * @param pThread The worker thread.
5248 */
5249static DECLCALLBACK(int) xhciR3WorkerLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
5250{
5251 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
5252 PXHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PXHCICC);
5253 int rc;
5254
5255 LogFlow(("xHCI entering worker thread loop.\n"));
5256 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
5257 return VINF_SUCCESS;
5258
5259 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
5260 {
5261 uint8_t uSlotID;
5262
5263 bool fNotificationSent = ASMAtomicXchgBool(&pThis->fNotificationSent, false);
5264 if (!fNotificationSent)
5265 {
5266 rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEvtProcess, RT_INDEFINITE_WAIT);
5267 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
5268 if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
5269 break;
5270 LogFlowFunc(("Woken up with rc=%Rrc\n", rc));
5271 ASMAtomicWriteBool(&pThis->fNotificationSent, false);
5272 }
5273
5274 RTCritSectEnter(&pThisCC->CritSectThrd);
5275
5276 if (pThis->crcr & XHCI_CRCR_CRR)
5277 xhciR3ProcessCommandRing(pDevIns, pThis, pThisCC);
5278
5279 /* Run down the list of doorbells that are ringing. */
5280 for (uSlotID = 1; uSlotID < XHCI_NDS; ++uSlotID)
5281 {
5282 if (pThis->aSlotState[ID_TO_IDX(uSlotID)] >= XHCI_DEVSLOT_ENABLED)
5283 {
5284 while (pThis->aBellsRung[ID_TO_IDX(uSlotID)])
5285 {
5286 uint8_t bit;
5287 uint32_t uDBVal = 0;
5288
5289 for (bit = 0; bit < 32; ++bit)
5290 if (pThis->aBellsRung[ID_TO_IDX(uSlotID)] & (1 << bit))
5291 {
5292 uDBVal = bit;
5293 break;
5294 }
5295
5296 Log2(("Stop ringing bell for slot %u, DCI %u\n", uSlotID, uDBVal));
5297 ASMAtomicAndU32(&pThis->aBellsRung[ID_TO_IDX(uSlotID)], ~(1 << uDBVal));
5298 xhciR3ProcessDevCtx(pDevIns, pThis, pThisCC, uSlotID, uDBVal);
5299 }
5300 }
5301 }
5302
5303 /* If the R/S bit is no longer set, halt the xHC. */
5304 if (!(pThis->cmd & XHCI_CMD_RS))
5305 {
5306 Log(("R/S clear, halting the xHC.\n"));
5307 ASMAtomicOrU32(&pThis->status, XHCI_STATUS_HCH);
5308 }
5309
5310 RTCritSectLeave(&pThisCC->CritSectThrd);
5311 } /* While running */
5312
5313 LogFlow(("xHCI worker thread exiting.\n"));
5314 return VINF_SUCCESS;
5315}
5316
5317
5318/**
5319 * Unblock the worker thread so it can respond to a state change.
5320 *
5321 * @returns VBox status code.
5322 * @param pDevIns The xHCI device instance.
5323 * @param pThread The worker thread.
5324 */
5325static DECLCALLBACK(int) xhciR3WorkerWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
5326{
5327 NOREF(pThread);
5328 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
5329
5330 return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtProcess);
5331}
5332
5333
5334/**
5335 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
5336 */
5337static DECLCALLBACK(void *) xhciR3RhQueryInterface(PPDMIBASE pInterface, const char *pszIID)
5338{
5339 PXHCIROOTHUBR3 pRh = RT_FROM_MEMBER(pInterface, XHCIROOTHUBR3, IBase);
5340 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pRh->IBase);
5341 PDMIBASE_RETURN_INTERFACE(pszIID, VUSBIROOTHUBPORT, &pRh->IRhPort);
5342 return NULL;
5343}
5344
5345/**
5346 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
5347 */
5348static DECLCALLBACK(void *) xhciR3QueryStatusInterface(PPDMIBASE pInterface, const char *pszIID)
5349{
5350 PXHCIR3 pThisCC = RT_FROM_MEMBER(pInterface, XHCIR3, IBase);
5351 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThisCC->IBase);
5352 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThisCC->ILeds);
5353 return NULL;
5354}
5355
5356/**
5357 * Gets the pointer to the status LED of a unit.
5358 *
5359 * @returns VBox status code.
5360 * @param pInterface Pointer to the interface structure containing the called function pointer.
5361 * @param iLUN The unit which status LED we desire.
5362 * @param ppLed Where to store the LED pointer.
5363 */
5364static DECLCALLBACK(int) xhciR3QueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
5365{
5366 PXHCICC pThisCC = RT_FROM_MEMBER(pInterface, XHCIR3, ILeds);
5367
5368 if (iLUN < XHCI_NUM_LUNS)
5369 {
5370 *ppLed = iLUN ? &pThisCC->RootHub3.Led : &pThisCC->RootHub2.Led;
5371 Assert((*ppLed)->u32Magic == PDMLED_MAGIC);
5372 return VINF_SUCCESS;
5373 }
5374 return VERR_PDM_LUN_NOT_FOUND;
5375}
5376
5377
5378/**
5379 * Get the number of ports available in the hub.
5380 *
5381 * @returns The number of ports available.
5382 * @param pInterface Pointer to this structure.
5383 * @param pAvailable Bitmap indicating the available ports. Set bit == available port.
5384 */
5385static DECLCALLBACK(unsigned) xhciR3RhGetAvailablePorts(PVUSBIROOTHUBPORT pInterface, PVUSBPORTBITMAP pAvailable)
5386{
5387 PXHCIROOTHUBR3 pRh = RT_FROM_MEMBER(pInterface, XHCIROOTHUBR3, IRhPort);
5388 PXHCICC pThisCC = pRh->pXhciR3;
5389 PPDMDEVINS pDevIns = pThisCC->pDevIns;
5390 unsigned iPort;
5391 unsigned cPorts = 0;
5392 LogFlow(("xhciR3RhGetAvailablePorts\n"));
5393
5394 memset(pAvailable, 0, sizeof(*pAvailable));
5395
5396 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, pDevIns->pCritSectRoR3, VERR_IGNORED);
5397 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, pDevIns->pCritSectRoR3, rcLock);
5398
5399 for (iPort = pRh->uPortBase; iPort < (unsigned)pRh->uPortBase + pRh->cPortsImpl; iPort++)
5400 {
5401 Assert(iPort < XHCI_NDP_CFG(PDMDEVINS_2_DATA(pDevIns, PXHCI)));
5402 if (!pThisCC->aPorts[iPort].fAttached)
5403 {
5404 cPorts++;
5405 ASMBitSet(pAvailable, IDX_TO_ID(iPort - pRh->uPortBase));
5406 }
5407 }
5408
5409 PDMDevHlpCritSectLeave(pDevIns, pDevIns->pCritSectRoR3);
5410 return cPorts;
5411}
5412
5413
5414/**
5415 * Get the supported USB versions for USB2 hubs.
5416 *
5417 * @returns The mask of supported USB versions.
5418 * @param pInterface Pointer to this structure.
5419 */
5420static DECLCALLBACK(uint32_t) xhciR3RhGetUSBVersions2(PVUSBIROOTHUBPORT pInterface)
5421{
5422 RT_NOREF(pInterface);
5423 return VUSB_STDVER_11 | VUSB_STDVER_20;
5424}
5425
5426
5427/**
5428 * Get the supported USB versions for USB2 hubs.
5429 *
5430 * @returns The mask of supported USB versions.
5431 * @param pInterface Pointer to this structure.
5432 */
5433static DECLCALLBACK(uint32_t) xhciR3RhGetUSBVersions3(PVUSBIROOTHUBPORT pInterface)
5434{
5435 RT_NOREF(pInterface);
5436 return VUSB_STDVER_30;
5437}
5438
5439
5440/**
5441 * Start sending SOF tokens across the USB bus, lists are processed in the
5442 * next frame.
5443 */
5444static void xhciR3BusStart(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThisCC)
5445{
5446 unsigned iPort;
5447
5448 pThisCC->RootHub2.pIRhConn->pfnPowerOn(pThisCC->RootHub2.pIRhConn);
5449 pThisCC->RootHub3.pIRhConn->pfnPowerOn(pThisCC->RootHub3.pIRhConn);
5450// xhciR3BumpFrameNumber(pThis);
5451
5452 Log(("xHCI: Bus started\n"));
5453
5454 Assert(pThis->status & XHCI_STATUS_HCH);
5455 ASMAtomicAndU32(&pThis->status, ~XHCI_STATUS_HCH);
5456
5457 /* HCH gates PSCEG (4.19.2). When clearing HCH, re-evaluate port changes. */
5458 for (iPort = 0; iPort < XHCI_NDP_CFG(pThis); ++iPort)
5459 {
5460 if (pThis->aPorts[iPort].portsc & XHCI_PORT_CHANGE_MASK)
5461 xhciR3GenPortChgEvent(pDevIns, pThis, IDX_TO_ID(iPort));
5462 }
5463
5464 /// @todo record the starting time?
5465// pThis->SofTime = TMTimerGet(pThis->CTX_SUFF(pEndOfFrameTimer)) - pThis->cTicksPerFrame;
5466}
5467
5468/**
5469 * Stop sending SOF tokens on the bus and processing the data.
5470 */
5471static void xhciR3BusStop(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThisCC)
5472{
5473 LogFlow(("xhciR3BusStop\n"));
5474
5475 /* Stop the controller and Command Ring. */
5476 pThis->cmd &= ~XHCI_CMD_RS;
5477 pThis->crcr |= XHCI_CRCR_CS;
5478
5479 /* Power off the root hubs. */
5480 pThisCC->RootHub2.pIRhConn->pfnPowerOff(pThisCC->RootHub2.pIRhConn);
5481 pThisCC->RootHub3.pIRhConn->pfnPowerOff(pThisCC->RootHub3.pIRhConn);
5482
5483 /* The worker thread will halt the HC (set HCH) when done. */
5484 xhciKickWorker(pDevIns, pThis, XHCI_JOB_PROCESS_CMDRING, 0);
5485}
5486
5487
5488/**
5489 * Power a port up or down
5490 */
5491static void xhciR3PortPower(PXHCI pThis, PXHCICC pThisCC, unsigned iPort, bool fPowerUp)
5492{
5493 PXHCIHUBPORT pPort = &pThis->aPorts[iPort];
5494 PXHCIHUBPORTR3 pPortR3 = &pThisCC->aPorts[iPort];
5495 PXHCIROOTHUBR3 pRh = GET_PORT_PRH(pThisCC, iPort);
5496
5497 bool fOldPPS = !!(pPort->portsc & XHCI_PORT_PP);
5498 LogFlow(("xhciR3PortPower (port %u) %s\n", IDX_TO_ID(iPort), fPowerUp ? "UP" : "DOWN"));
5499
5500 if (fPowerUp)
5501 {
5502 /* Power up a port. */
5503 if (pPortR3->fAttached)
5504 ASMAtomicOrU32(&pPort->portsc, XHCI_PORT_CCS);
5505 if (pPort->portsc & XHCI_PORT_CCS)
5506 ASMAtomicOrU32(&pPort->portsc, XHCI_PORT_PP);
5507 if (pPortR3->fAttached && !fOldPPS)
5508 VUSBIRhDevPowerOn(pRh->pIRhConn, GET_VUSB_PORT_FROM_XHCI_PORT(pRh, iPort));
5509 }
5510 else
5511 {
5512 /* Power down. */
5513 ASMAtomicAndU32(&pPort->portsc, ~(XHCI_PORT_PP | XHCI_PORT_CCS));
5514 if (pPortR3->fAttached && fOldPPS)
5515 VUSBIRhDevPowerOff(pRh->pIRhConn, GET_VUSB_PORT_FROM_XHCI_PORT(pRh, iPort));
5516 }
5517}
5518
5519
5520/**
5521 * Port reset done callback.
5522 *
5523 * @param pDevIns The device instance data.
5524 * @param iPort The XHCI port index of the port being resetted.
5525 */
5526static void xhciR3PortResetDone(PPDMDEVINS pDevIns, unsigned iPort)
5527{
5528 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
5529
5530 Log2(("xhciR3PortResetDone\n"));
5531
5532 AssertReturnVoid(iPort < XHCI_NDP_CFG(pThis));
5533
5534 /*
5535 * Successful reset.
5536 */
5537 Log2(("xhciR3PortResetDone: Reset completed.\n"));
5538
5539 uint32_t fChangeMask = XHCI_PORT_PED | XHCI_PORT_PRC;
5540 /* For USB2 ports, transition the link state. */
5541 if (!IS_USB3_PORT_IDX_SHR(pThis, iPort))
5542 {
5543 pThis->aPorts[iPort].portsc &= ~XHCI_PORT_PLS_MASK;
5544 pThis->aPorts[iPort].portsc |= XHCI_PLS_U0 << XHCI_PORT_PLS_SHIFT;
5545 }
5546 else
5547 {
5548 if (pThis->aPorts[iPort].portsc & XHCI_PORT_WPR)
5549 fChangeMask |= XHCI_PORT_WRC;
5550 }
5551
5552 ASMAtomicAndU32(&pThis->aPorts[iPort].portsc, ~(XHCI_PORT_PR | XHCI_PORT_WPR));
5553 ASMAtomicOrU32(&pThis->aPorts[iPort].portsc, fChangeMask);
5554 /// @todo Set USBSTS.PCD and manage PSCEG correctly!
5555 /// @todo just guessing?!
5556// ASMAtomicOrU32(&pThis->aPorts[iPort].portsc, XHCI_PORT_CSC | XHCI_PORT_PLC);
5557
5558 /// @todo Is this the right place?
5559 xhciR3GenPortChgEvent(pDevIns, pThis, IDX_TO_ID(iPort));
5560}
5561
5562
5563/**
5564 * Sets a flag in a port status register, but only if a device is connected;
5565 * if not, set ConnectStatusChange flag to force HCD to reevaluate connect status.
5566 *
5567 * @returns true if device was connected and the flag was cleared.
5568 */
5569static bool xhciR3RhPortSetIfConnected(PXHCI pThis, int iPort, uint32_t fValue)
5570{
5571 /*
5572 * Writing a 0 has no effect
5573 */
5574 if (fValue == 0)
5575 return false;
5576
5577 /*
5578 * The port might be still/already disconnected.
5579 */
5580 if (!(pThis->aPorts[iPort].portsc & XHCI_PORT_CCS))
5581 return false;
5582
5583 bool fRc = !(pThis->aPorts[iPort].portsc & fValue);
5584
5585 /* Set the bit. */
5586 ASMAtomicOrU32(&pThis->aPorts[iPort].portsc, fValue);
5587
5588 return fRc;
5589}
5590
5591
5592/** Translate VUSB speed enum to xHCI definition. */
5593static unsigned xhciR3UsbSpd2XhciSpd(VUSBSPEED enmSpeed)
5594{
5595 unsigned uSpd;
5596
5597 switch (enmSpeed)
5598 {
5599 default: AssertMsgFailed(("%d\n", enmSpeed));
5600 RT_FALL_THRU();
5601 case VUSB_SPEED_LOW: uSpd = XHCI_SPD_LOW; break;
5602 case VUSB_SPEED_FULL: uSpd = XHCI_SPD_FULL; break;
5603 case VUSB_SPEED_HIGH: uSpd = XHCI_SPD_HIGH; break;
5604 case VUSB_SPEED_SUPER: uSpd = XHCI_SPD_SUPER; break;
5605 }
5606 return uSpd;
5607}
5608
5609/** @interface_method_impl{VUSBIROOTHUBPORT,pfnAttach} */
5610static DECLCALLBACK(int) xhciR3RhAttach(PVUSBIROOTHUBPORT pInterface, unsigned uPort, VUSBSPEED enmSpeed)
5611{
5612 PXHCIROOTHUBR3 pRh = RT_FROM_MEMBER(pInterface, XHCIROOTHUBR3, IRhPort);
5613 PXHCICC pThisCC = pRh->pXhciR3;
5614 PPDMDEVINS pDevIns = pThisCC->pDevIns;
5615 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
5616 PXHCIHUBPORT pPort;
5617 unsigned iPort;
5618 LogFlow(("xhciR3RhAttach: uPort=%u (iPort=%u)\n", uPort, ID_TO_IDX(uPort) + pRh->uPortBase));
5619
5620 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, pDevIns->pCritSectRoR3, VERR_IGNORED);
5621 AssertRCReturn(rcLock, rcLock);
5622
5623 /*
5624 * Validate and adjust input.
5625 */
5626 Assert(uPort >= 1 && uPort <= pRh->cPortsImpl);
5627 iPort = ID_TO_IDX(uPort) + pRh->uPortBase;
5628 Assert(iPort < XHCI_NDP_CFG(pThis));
5629 pPort = &pThis->aPorts[iPort];
5630 Assert(!pThisCC->aPorts[iPort].fAttached);
5631 Assert(enmSpeed != VUSB_SPEED_UNKNOWN);
5632
5633 /*
5634 * Attach it.
5635 */
5636 ASMAtomicOrU32(&pPort->portsc, XHCI_PORT_CCS | XHCI_PORT_CSC);
5637 pThisCC->aPorts[iPort].fAttached = true;
5638 xhciR3PortPower(pThis, pThisCC, iPort, 1 /* power on */);
5639
5640 /* USB3 ports automatically transition to Enabled state. */
5641 if (IS_USB3_PORT_IDX_R3(pThisCC, iPort))
5642 {
5643 Assert(enmSpeed == VUSB_SPEED_SUPER);
5644 pPort->portsc |= XHCI_PORT_PED;
5645 pPort->portsc &= ~XHCI_PORT_PLS_MASK;
5646 pPort->portsc |= XHCI_PLS_U0 << XHCI_PORT_PLS_SHIFT;
5647 pPort->portsc &= ~XHCI_PORT_SPD_MASK;
5648 pPort->portsc |= XHCI_SPD_SUPER << XHCI_PORT_SPD_SHIFT;
5649 VUSBIRhDevReset(pRh->pIRhConn, GET_VUSB_PORT_FROM_XHCI_PORT(pRh, iPort),
5650 false, NULL /* sync */, NULL, PDMDevHlpGetVM(pDevIns));
5651 }
5652 else
5653 {
5654 Assert(enmSpeed == VUSB_SPEED_LOW || enmSpeed == VUSB_SPEED_FULL || enmSpeed == VUSB_SPEED_HIGH);
5655 pPort->portsc &= ~XHCI_PORT_SPD_MASK;
5656 pPort->portsc |= xhciR3UsbSpd2XhciSpd(enmSpeed) << XHCI_PORT_SPD_SHIFT;
5657 }
5658
5659 xhciR3GenPortChgEvent(pDevIns, pThis, IDX_TO_ID(iPort));
5660
5661 PDMDevHlpCritSectLeave(pDevIns, pDevIns->pCritSectRoR3);
5662 return VINF_SUCCESS;
5663}
5664
5665
5666/**
5667 * A device is being detached from a port in the root hub.
5668 *
5669 * @param pInterface Pointer to this structure.
5670 * @param uPort The 1-based port number assigned to the device.
5671 */
5672static DECLCALLBACK(void) xhciR3RhDetach(PVUSBIROOTHUBPORT pInterface, unsigned uPort)
5673{
5674 PXHCIROOTHUBR3 pRh = RT_FROM_MEMBER(pInterface, XHCIROOTHUBR3, IRhPort);
5675 PXHCICC pThisCC = pRh->pXhciR3;
5676 PPDMDEVINS pDevIns = pThisCC->pDevIns;
5677 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
5678 PXHCIHUBPORT pPort;
5679 unsigned iPort;
5680 LogFlow(("xhciR3RhDetach: uPort=%u iPort=%u\n", uPort, ID_TO_IDX(uPort) + pRh->uPortBase));
5681 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, pDevIns->pCritSectRoR3, VERR_IGNORED);
5682 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, pDevIns->pCritSectRoR3, rcLock);
5683
5684 /*
5685 * Validate and adjust input.
5686 */
5687 Assert(uPort >= 1 && uPort <= pRh->cPortsImpl);
5688 iPort = ID_TO_IDX(uPort) + pRh->uPortBase;
5689 Assert(iPort < XHCI_NDP_CFG(pThis));
5690 pPort = &pThis->aPorts[iPort];
5691 Assert(pThisCC->aPorts[iPort].fAttached);
5692
5693 /*
5694 * Detach it.
5695 */
5696 pThisCC->aPorts[iPort].fAttached = false;
5697 ASMAtomicAndU32(&pPort->portsc, ~(XHCI_PORT_CCS | XHCI_PORT_SPD_MASK | XHCI_PORT_PLS_MASK));
5698 ASMAtomicOrU32(&pPort->portsc, XHCI_PORT_CSC);
5699 /* Link state goes to RxDetect. */
5700 ASMAtomicOrU32(&pPort->portsc, XHCI_PLS_RXDETECT << XHCI_PORT_PLS_SHIFT);
5701 /* Disconnect clears the port enable bit. */
5702 if (pPort->portsc & XHCI_PORT_PED)
5703 ASMAtomicAndU32(&pPort->portsc, ~XHCI_PORT_PED);
5704
5705 xhciR3GenPortChgEvent(pDevIns, pThis, IDX_TO_ID(iPort));
5706
5707 PDMDevHlpCritSectLeave(pDevIns, pDevIns->pCritSectRoR3);
5708}
5709
5710
5711/**
5712 * One of the root hub devices has completed its reset
5713 * operation.
5714 *
5715 * Currently, we don't think anything is required to be done here
5716 * so it's just a stub for forcing async resetting of the devices
5717 * during a root hub reset.
5718 *
5719 * @param pDev The root hub device.
5720 * @param rc The result of the operation.
5721 * @param uPort The port number of the device on the roothub being resetted.
5722 * @param pvUser Pointer to the controller.
5723 */
5724static DECLCALLBACK(void) xhciR3RhResetDoneOneDev(PVUSBIDEVICE pDev, uint32_t uPort, int rc, void *pvUser)
5725{
5726 LogRel(("xHCI: Root hub-attached device reset completed with %Rrc\n", rc));
5727 RT_NOREF(pDev, uPort, rc, pvUser);
5728}
5729
5730
5731/**
5732 * Does a software or hardware reset of the controller.
5733 *
5734 * This is called in response to setting HcCommandStatus.HCR, hardware reset,
5735 * and device construction.
5736 *
5737 * @param pThis The shared XHCI instance data
5738 * @param pThisCC The ring-3 XHCI instance data
5739 * @param fNewMode The new mode of operation. This is UsbSuspend if
5740 * it's a software reset, and UsbReset if it's a
5741 * hardware reset / cold boot.
5742 * @param fTrueReset Set if we can do a real reset of the devices
5743 * attached to the root hub. This is really a just a
5744 * hack for the non-working linux device reset. Linux
5745 * has this feature called 'logical disconnect' if
5746 * device reset fails which prevents us from doing
5747 * resets when the guest asks for it - the guest will
5748 * get confused when the device seems to be
5749 * reconnected everytime it tries to reset it. But if
5750 * we're at hardware reset time, we can allow a device
5751 * to be 'reconnected' without upsetting the guest.
5752 *
5753 * @remark This has nothing to do with software setting the
5754 * mode to UsbReset.
5755 */
5756static void xhciR3DoReset(PXHCI pThis, PXHCICC pThisCC, uint32_t fNewMode, bool fTrueReset)
5757{
5758 LogFunc(("%s reset%s\n", fNewMode == XHCI_USB_RESET ? "Hardware" : "Software",
5759 fTrueReset ? " (really reset devices)" : ""));
5760
5761 /*
5762 * Cancel all outstanding URBs.
5763 *
5764 * We can't, and won't, deal with URBs until we're moved out of the
5765 * suspend/reset state. Also, a real HC isn't going to send anything
5766 * any more when a reset has been signaled.
5767 */
5768 pThisCC->RootHub2.pIRhConn->pfnCancelAllUrbs(pThisCC->RootHub2.pIRhConn);
5769 pThisCC->RootHub3.pIRhConn->pfnCancelAllUrbs(pThisCC->RootHub3.pIRhConn);
5770
5771 /*
5772 * Reset the hardware registers.
5773 */
5774 /** @todo other differences between hardware reset and VM reset? */
5775
5776 pThis->cmd = 0;
5777 pThis->status = XHCI_STATUS_HCH;
5778 pThis->dnctrl = 0;
5779 pThis->crcr = 0;
5780 pThis->dcbaap = 0;
5781 pThis->config = 0;
5782
5783 /*
5784 * Reset the internal state.
5785 */
5786 pThis->cmdr_dqp = 0;
5787 pThis->cmdr_ccs = 0;
5788
5789 RT_ZERO(pThis->aSlotState);
5790 RT_ZERO(pThis->aBellsRung);
5791
5792 /* Zap everything but the lock. */
5793 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aInterrupters); ++i)
5794 {
5795 pThis->aInterrupters[i].iman = 0;
5796 pThis->aInterrupters[i].imod = 0;
5797 pThis->aInterrupters[i].erstsz = 0;
5798 pThis->aInterrupters[i].erstba = 0;
5799 pThis->aInterrupters[i].erdp = 0;
5800 pThis->aInterrupters[i].erep = 0;
5801 pThis->aInterrupters[i].erst_idx = 0;
5802 pThis->aInterrupters[i].trb_count = 0;
5803 pThis->aInterrupters[i].evtr_pcs = false;
5804 pThis->aInterrupters[i].ipe = false;
5805 }
5806
5807 if (fNewMode == XHCI_USB_RESET)
5808 {
5809 /* Only a hardware reset reinits the port registers. */
5810 for (unsigned i = 0; i < XHCI_NDP_CFG(pThis); i++)
5811 {
5812 /* Need to preserve the speed of attached devices. */
5813 pThis->aPorts[i].portsc &= XHCI_PORT_SPD_MASK;
5814 pThis->aPorts[i].portsc |= XHCI_PLS_RXDETECT << XHCI_PORT_PLS_SHIFT;
5815 /* If Port Power Control is not supported, ports are always powered on. */
5816 if (!(pThis->hcc_params & XHCI_HCC_PPC))
5817 pThis->aPorts[i].portsc |= XHCI_PORT_PP;
5818 }
5819 }
5820
5821 /*
5822 * If this is a hardware reset, we will initialize the root hub too.
5823 * Software resets doesn't do this according to the specs.
5824 * (It's not possible to have a device connected at the time of the
5825 * device construction, so nothing to worry about there.)
5826 */
5827 if (fNewMode == XHCI_USB_RESET)
5828 {
5829 pThisCC->RootHub2.pIRhConn->pfnReset(pThisCC->RootHub2.pIRhConn, fTrueReset);
5830 pThisCC->RootHub3.pIRhConn->pfnReset(pThisCC->RootHub3.pIRhConn, fTrueReset);
5831
5832 /*
5833 * Reattach the devices.
5834 */
5835 for (unsigned i = 0; i < XHCI_NDP_CFG(pThis); i++)
5836 {
5837 bool fAttached = pThisCC->aPorts[i].fAttached;
5838 PXHCIROOTHUBR3 pRh = GET_PORT_PRH(pThisCC, i);
5839 pThisCC->aPorts[i].fAttached = false;
5840
5841 if (fAttached)
5842 {
5843 VUSBSPEED enmSpeed = VUSBIRhDevGetSpeed(pRh->pIRhConn, GET_VUSB_PORT_FROM_XHCI_PORT(pRh, i));
5844 xhciR3RhAttach(&pRh->IRhPort, GET_VUSB_PORT_FROM_XHCI_PORT(pRh, i), enmSpeed);
5845 }
5846 }
5847 }
5848}
5849
5850/**
5851 * Reset the root hub.
5852 *
5853 * @returns VBox status code.
5854 * @param pInterface Pointer to this structure.
5855 * @param fTrueReset This is used to indicate whether we're at VM reset
5856 * time and can do real resets or if we're at any other
5857 * time where that isn't such a good idea.
5858 * @remark Do NOT call VUSBIDevReset on the root hub in an async fashion!
5859 * @thread EMT
5860 */
5861static DECLCALLBACK(int) xhciR3RhReset(PVUSBIROOTHUBPORT pInterface, bool fTrueReset)
5862{
5863 PXHCIROOTHUBR3 pRh = RT_FROM_MEMBER(pInterface, XHCIROOTHUBR3, IRhPort);
5864 PXHCICC pThisCC = pRh->pXhciR3;
5865 PPDMDEVINS pDevIns = pThisCC->pDevIns;
5866 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
5867
5868 Log(("xhciR3RhReset fTrueReset=%d\n", fTrueReset));
5869 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, pDevIns->pCritSectRoR3, VERR_IGNORED);
5870 AssertRCReturn(rcLock, rcLock);
5871
5872 /* Soft reset first */
5873 xhciR3DoReset(pThis, pThisCC, XHCI_USB_SUSPEND, false /* N/A */);
5874
5875 /*
5876 * We're pretending to _reattach_ the devices without resetting them.
5877 * Except, during VM reset where we use the opportunity to do a proper
5878 * reset before the guest comes along and expects things.
5879 *
5880 * However, it's very very likely that we're not doing the right thing
5881 * here when end up here on request from the guest (USB Reset state).
5882 * The docs talk about root hub resetting, however what exact behaviour
5883 * in terms of root hub status and changed bits, and HC interrupts aren't
5884 * stated clearly. IF we get trouble and see the guest doing "USB Resets"
5885 * we will have to look into this. For the time being we stick with simple.
5886 */
5887 for (unsigned iPort = pRh->uPortBase; iPort < XHCI_NDP_CFG(pThis); iPort++)
5888 {
5889 if (pThisCC->aPorts[iPort].fAttached)
5890 {
5891 ASMAtomicOrU32(&pThis->aPorts[iPort].portsc, XHCI_PORT_CCS | XHCI_PORT_CSC);
5892 if (fTrueReset)
5893 VUSBIRhDevReset(pRh->pIRhConn, GET_VUSB_PORT_FROM_XHCI_PORT(pRh, iPort), fTrueReset,
5894 xhciR3RhResetDoneOneDev, pDevIns, PDMDevHlpGetVM(pDevIns));
5895 }
5896 }
5897
5898 PDMDevHlpCritSectLeave(pDevIns, pDevIns->pCritSectRoR3);
5899 return VINF_SUCCESS;
5900}
5901
5902#endif /* IN_RING3 */
5903
5904
5905
5906/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
5907/* xHCI Operational Register access routines */
5908/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
5909
5910
5911
5912/**
5913 * Read the USBCMD register of the host controller.
5914 */
5915static VBOXSTRICTRC HcUsbcmd_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t *pu32Value)
5916{
5917 RT_NOREF(pDevIns, iReg);
5918 STAM_COUNTER_INC(&pThis->StatRdUsbCmd);
5919 *pu32Value = pThis->cmd;
5920 return VINF_SUCCESS;
5921}
5922
5923/**
5924 * Write to the USBCMD register of the host controller.
5925 */
5926static VBOXSTRICTRC HcUsbcmd_w(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t val)
5927{
5928#ifdef IN_RING3
5929 PXHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PXHCICC);
5930#endif
5931 RT_NOREF(iReg);
5932 STAM_COUNTER_INC(&pThis->StatWrUsbCmd);
5933#ifdef LOG_ENABLED
5934 Log(("HcUsbcmd_w old=%x new=%x\n", pThis->cmd, val));
5935 if (val & XHCI_CMD_RS)
5936 Log((" XHCI_CMD_RS\n"));
5937 if (val & XHCI_CMD_HCRST)
5938 Log((" XHCI_CMD_HCRST\n"));
5939 if (val & XHCI_CMD_INTE )
5940 Log((" XHCI_CMD_INTE\n"));
5941 if (val & XHCI_CMD_HSEE)
5942 Log((" XHCI_CMD_HSEE\n"));
5943 if (val & XHCI_CMD_LCRST)
5944 Log((" XHCI_CMD_LCRST\n"));
5945 if (val & XHCI_CMD_CSS)
5946 Log((" XHCI_CMD_CSS\n"));
5947 if (val & XHCI_CMD_CRS)
5948 Log((" XHCI_CMD_CRS\n"));
5949 if (val & XHCI_CMD_EWE)
5950 Log((" XHCI_CMD_EWE\n"));
5951 if (val & XHCI_CMD_EU3S)
5952 Log((" XHCI_CMD_EU3S\n"));
5953#endif
5954
5955 if (val & ~XHCI_CMD_MASK)
5956 Log(("Unknown USBCMD bits %#x are set!\n", val & ~XHCI_CMD_MASK));
5957
5958 uint32_t old_cmd = pThis->cmd;
5959#ifdef IN_RING3
5960 pThis->cmd = val;
5961#endif
5962
5963 if (val & XHCI_CMD_HCRST)
5964 {
5965#ifdef IN_RING3
5966 LogRel(("xHCI: Hardware reset\n"));
5967 xhciR3DoReset(pThis, pThisCC, XHCI_USB_RESET, true /* reset devices */);
5968#else
5969 return VINF_IOM_R3_MMIO_WRITE;
5970#endif
5971 }
5972 else if (val & XHCI_CMD_LCRST)
5973 {
5974#ifdef IN_RING3
5975 LogRel(("xHCI: Software reset\n"));
5976 xhciR3DoReset(pThis, pThisCC, XHCI_USB_SUSPEND, false /* N/A */);
5977#else
5978 return VINF_IOM_R3_MMIO_WRITE;
5979#endif
5980 }
5981 else if (pThis->status & XHCI_STATUS_HCE)
5982 {
5983 /* If HCE is set, don't restart the controller. Only a reset
5984 * will clear the HCE bit.
5985 */
5986 Log(("xHCI: HCE bit set, ignoring USBCMD register changes!\n"));
5987 pThis->cmd = old_cmd;
5988 return VINF_SUCCESS;
5989 }
5990 else
5991 {
5992 /* See what changed and take action on that. First the R/S bit. */
5993 uint32_t old_state = old_cmd & XHCI_CMD_RS;
5994 uint32_t new_state = val & XHCI_CMD_RS;
5995
5996 if (old_state != new_state)
5997 {
5998#ifdef IN_RING3
5999 switch (new_state)
6000 {
6001 case XHCI_CMD_RS:
6002 LogRel(("xHCI: USB Operational\n"));
6003 xhciR3BusStart(pDevIns, pThis, pThisCC);
6004 break;
6005 case 0:
6006 xhciR3BusStop(pDevIns, pThis, pThisCC);
6007 LogRel(("xHCI: USB Suspended\n"));
6008 break;
6009 }
6010#else
6011 return VINF_IOM_R3_MMIO_WRITE;
6012#endif
6013 }
6014
6015 /* Check EWE (Enable MFINDEX Wraparound Event) changes. */
6016 old_state = old_cmd & XHCI_CMD_EWE;
6017 new_state = val & XHCI_CMD_EWE;
6018
6019 if (old_state != new_state)
6020 {
6021 switch (new_state)
6022 {
6023 case XHCI_CMD_EWE:
6024 Log(("xHCI: MFINDEX Wrap timer started\n"));
6025 xhciSetWrapTimer(pDevIns, pThis);
6026 break;
6027 case 0:
6028 PDMDevHlpTimerStop(pDevIns, pThis->hWrapTimer);
6029 Log(("xHCI: MFINDEX Wrap timer stopped\n"));
6030 break;
6031 }
6032 }
6033
6034 /* INTE transitions need to twiddle interrupts. */
6035 old_state = old_cmd & XHCI_CMD_INTE;
6036 new_state = val & XHCI_CMD_INTE;
6037 if (old_state != new_state)
6038 {
6039 switch (new_state)
6040 {
6041 case XHCI_CMD_INTE:
6042 /* Check whether the event interrupt bit is set and trigger an interrupt. */
6043 if (pThis->status & XHCI_STATUS_EINT)
6044 PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_HIGH);
6045 break;
6046 case 0:
6047 PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW);
6048 break;
6049 }
6050 }
6051
6052 /* We currently do nothing for state save/restore. If we did, the CSS/CRS command bits
6053 * would set the SSS/RSS status bits until the operation is done. The CSS/CRS bits are
6054 * never read as one.
6055 */
6056 /// @todo 4.9.4 describes internal state that needs to be saved/restored:
6057 /// ERSTE, ERST Count, EREP, and TRB Count
6058 /// Command Ring Dequeue Pointer?
6059 if (val & XHCI_CMD_CSS)
6060 {
6061 Log(("xHCI: Save State requested\n"));
6062 val &= ~XHCI_CMD_CSS;
6063 }
6064
6065 if (val & XHCI_CMD_CRS)
6066 {
6067 Log(("xHCI: Restore State requested\n"));
6068 val &= ~XHCI_CMD_CRS;
6069 }
6070 }
6071#ifndef IN_RING3
6072 pThis->cmd = val;
6073#endif
6074 return VINF_SUCCESS;
6075}
6076
6077#ifdef LOG_ENABLED
6078static void HcUsbstsLogBits(uint32_t val)
6079{
6080 if (val & XHCI_STATUS_HCH)
6081 Log((" XHCI_STATUS_HCH (HC Halted)\n"));
6082 if (val & XHCI_STATUS_HSE)
6083 Log((" XHCI_STATUS_HSE (Host System Error)\n"));
6084 if (val & XHCI_STATUS_EINT)
6085 Log((" XHCI_STATUS_EINT (Event Interrupt)\n"));
6086 if (val & XHCI_STATUS_PCD)
6087 Log((" XHCI_STATUS_PCD (Port Change Detect)\n"));
6088 if (val & XHCI_STATUS_SSS)
6089 Log((" XHCI_STATUS_SSS (Save State Status)\n"));
6090 if (val & XHCI_STATUS_RSS)
6091 Log((" XHCI_STATUS_RSS (Restore State Status)\n"));
6092 if (val & XHCI_STATUS_SRE)
6093 Log((" XHCI_STATUS_SRE (Save/Restore Error)\n"));
6094 if (val & XHCI_STATUS_CNR)
6095 Log((" XHCI_STATUS_CNR (Controller Not Ready)\n"));
6096 if (val & XHCI_STATUS_HCE)
6097 Log((" XHCI_STATUS_HCE (Host Controller Error)\n"));
6098}
6099#endif
6100
6101/**
6102 * Read the USBSTS register of the host controller.
6103 */
6104static VBOXSTRICTRC HcUsbsts_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t *pu32Value)
6105{
6106#ifdef LOG_ENABLED
6107 Log(("HcUsbsts_r current value %x\n", pThis->status));
6108 HcUsbstsLogBits(pThis->status);
6109#endif
6110 RT_NOREF(pDevIns, iReg);
6111 STAM_COUNTER_INC(&pThis->StatRdUsbSts);
6112
6113 *pu32Value = pThis->status;
6114 return VINF_SUCCESS;
6115}
6116
6117/**
6118 * Write to the USBSTS register of the host controller.
6119 */
6120static VBOXSTRICTRC HcUsbsts_w(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t val)
6121{
6122#ifdef LOG_ENABLED
6123 Log(("HcUsbsts_w current value %x; new %x\n", pThis->status, val));
6124 HcUsbstsLogBits(val);
6125#endif
6126 RT_NOREF(pDevIns, iReg);
6127 STAM_COUNTER_INC(&pThis->StatWrUsbSts);
6128
6129 if ( (val & ~XHCI_STATUS_WRMASK)
6130 && val != 0xffffffff /* Ignore clear-all-like requests. */)
6131 Log(("Unknown USBSTS bits %#x are set!\n", val & ~XHCI_STATUS_WRMASK));
6132
6133 /* Most bits are read-only. */
6134 val &= XHCI_STATUS_WRMASK;
6135
6136 /* "The Host Controller Driver may clear specific bits in this
6137 * register by writing '1' to bit positions to be cleared"
6138 */
6139 ASMAtomicAndU32(&pThis->status, ~val);
6140
6141 return VINF_SUCCESS;
6142}
6143
6144/**
6145 * Read the PAGESIZE register of the host controller.
6146 */
6147static VBOXSTRICTRC HcPagesize_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t *pu32Value)
6148{
6149 RT_NOREF(pDevIns, pThis, iReg);
6150 STAM_COUNTER_INC(&pThis->StatRdPageSize);
6151 *pu32Value = 1; /* 2^(bit n + 12) -> 4K page size only. */
6152 return VINF_SUCCESS;
6153}
6154
6155/**
6156 * Read the DNCTRL (Device Notification Control) register.
6157 */
6158static VBOXSTRICTRC HcDevNotifyCtrl_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t *pu32Value)
6159{
6160 RT_NOREF(pDevIns, iReg);
6161 STAM_COUNTER_INC(&pThis->StatRdDevNotifyCtrl);
6162 *pu32Value = pThis->dnctrl;
6163 return VINF_SUCCESS;
6164}
6165
6166/**
6167 * Write the DNCTRL (Device Notification Control) register.
6168 */
6169static VBOXSTRICTRC HcDevNotifyCtrl_w(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t val)
6170{
6171 RT_NOREF(pDevIns, iReg);
6172 STAM_COUNTER_INC(&pThis->StatWrDevNotifyCtrl);
6173 pThis->dnctrl = val;
6174 return VINF_SUCCESS;
6175}
6176
6177/**
6178 * Read the low dword of CRCR (Command Ring Control) register.
6179 */
6180static VBOXSTRICTRC HcCmdRingCtlLo_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t *pu32Value)
6181{
6182 RT_NOREF(pDevIns, iReg);
6183 STAM_COUNTER_INC(&pThis->StatRdCmdRingCtlLo);
6184 *pu32Value = (uint32_t)(pThis->crcr & XHCI_CRCR_RD_MASK);
6185 return VINF_SUCCESS;
6186}
6187
6188/**
6189 * Write the low dword of CRCR (Command Ring Control) register.
6190 */
6191static VBOXSTRICTRC HcCmdRingCtlLo_w(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t val)
6192{
6193 RT_NOREF(iReg);
6194 STAM_COUNTER_INC(&pThis->StatWrCmdRingCtlLo);
6195 /* NB: A dword write to the low half clears the high half. */
6196
6197 /* Sticky Abort/Stop bits - update register and kick the worker thread. */
6198 if (val & (XHCI_CRCR_CA | XHCI_CRCR_CS))
6199 {
6200 pThis->crcr |= val & (XHCI_CRCR_CA | XHCI_CRCR_CS);
6201 xhciKickWorker(pDevIns, pThis, XHCI_JOB_PROCESS_CMDRING, 0);
6202 }
6203
6204 /*
6205 * If the command ring is not running, the internal dequeue pointer
6206 * and the cycle state is updated. Otherwise the update is ignored.
6207 */
6208 if (!(pThis->crcr & XHCI_CRCR_CRR))
6209 {
6210 pThis->crcr = (pThis->crcr & ~XHCI_CRCR_UPD_MASK) | (val & XHCI_CRCR_UPD_MASK);
6211 /// @todo cmdr_dqp: atomic? volatile?
6212 pThis->cmdr_dqp = pThis->crcr & XHCI_CRCR_ADDR_MASK;
6213 pThis->cmdr_ccs = pThis->crcr & XHCI_CRCR_RCS;
6214 }
6215
6216 return VINF_SUCCESS;
6217}
6218
6219/**
6220 * Read the high dword of CRCR (Command Ring Control) register.
6221 */
6222static VBOXSTRICTRC HcCmdRingCtlHi_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t *pu32Value)
6223{
6224 RT_NOREF(pDevIns, iReg);
6225 STAM_COUNTER_INC(&pThis->StatRdCmdRingCtlHi);
6226 *pu32Value = pThis->crcr >> 32;
6227 return VINF_SUCCESS;
6228}
6229
6230/**
6231 * Write the high dword of CRCR (Command Ring Control) register.
6232 */
6233static VBOXSTRICTRC HcCmdRingCtlHi_w(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t val)
6234{
6235 RT_NOREF(pDevIns, iReg);
6236 STAM_COUNTER_INC(&pThis->StatWrCmdRingCtlHi);
6237 if (!(pThis->crcr & XHCI_CRCR_CRR))
6238 {
6239 pThis->crcr = ((uint64_t)val << 32) | (uint32_t)pThis->crcr;
6240 pThis->cmdr_dqp = pThis->crcr & XHCI_CRCR_ADDR_MASK;
6241 }
6242 return VINF_SUCCESS;
6243}
6244
6245/**
6246 * Read the low dword of the DCBAAP register.
6247 */
6248static VBOXSTRICTRC HcDevCtxBAAPLo_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t *pu32Value)
6249{
6250 RT_NOREF(pDevIns, iReg);
6251 STAM_COUNTER_INC(&pThis->StatRdDevCtxBaapLo);
6252 *pu32Value = (uint32_t)pThis->dcbaap;
6253 return VINF_SUCCESS;
6254}
6255
6256/**
6257 * Write the low dword of the DCBAAP register.
6258 */
6259static VBOXSTRICTRC HcDevCtxBAAPLo_w(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t val)
6260{
6261 RT_NOREF(pDevIns, iReg);
6262 STAM_COUNTER_INC(&pThis->StatWrDevCtxBaapLo);
6263 /* NB: A dword write to the low half clears the high half. */
6264 /// @todo Should this mask off the reserved bits?
6265 pThis->dcbaap = val;
6266 return VINF_SUCCESS;
6267}
6268
6269/**
6270 * Read the high dword of the DCBAAP register.
6271 */
6272static VBOXSTRICTRC HcDevCtxBAAPHi_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t *pu32Value)
6273{
6274 RT_NOREF(pDevIns, iReg);
6275 STAM_COUNTER_INC(&pThis->StatRdDevCtxBaapHi);
6276 *pu32Value = pThis->dcbaap >> 32;
6277 return VINF_SUCCESS;
6278}
6279
6280/**
6281 * Write the high dword of the DCBAAP register.
6282 */
6283static VBOXSTRICTRC HcDevCtxBAAPHi_w(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t val)
6284{
6285 RT_NOREF(pDevIns, iReg);
6286 STAM_COUNTER_INC(&pThis->StatWrDevCtxBaapHi);
6287 pThis->dcbaap = ((uint64_t)val << 32) | (uint32_t)pThis->dcbaap;
6288 return VINF_SUCCESS;
6289}
6290
6291/**
6292 * Read the CONFIG register.
6293 */
6294static VBOXSTRICTRC HcConfig_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t *pu32Value)
6295{
6296 RT_NOREF(pDevIns, iReg);
6297 STAM_COUNTER_INC(&pThis->StatRdConfig);
6298 *pu32Value = pThis->config;
6299 return VINF_SUCCESS;
6300}
6301
6302/**
6303 * Write the CONFIG register.
6304 */
6305static VBOXSTRICTRC HcConfig_w(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t val)
6306{
6307 RT_NOREF(pDevIns, iReg);
6308 STAM_COUNTER_INC(&pThis->StatWrConfig);
6309 /// @todo side effects?
6310 pThis->config = val;
6311 return VINF_SUCCESS;
6312}
6313
6314
6315
6316/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
6317/* xHCI Port Register access routines */
6318/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
6319
6320
6321
6322/**
6323 * Read the PORTSC register.
6324 */
6325static VBOXSTRICTRC HcPortStatusCtrl_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iPort, uint32_t *pu32Value)
6326{
6327 PXHCIHUBPORT p = &pThis->aPorts[iPort];
6328 RT_NOREF(pDevIns);
6329 STAM_COUNTER_INC(&pThis->StatRdPortStatusCtrl);
6330
6331 Assert(!(pThis->hcc_params & XHCI_HCC_PPC));
6332
6333 if (p->portsc & XHCI_PORT_PR)
6334 {
6335/// @todo Probably not needed?
6336#ifdef IN_RING3
6337 Log2(("HcPortStatusCtrl_r(): port %u: Impatient guest!\n", IDX_TO_ID(iPort)));
6338 RTThreadYield();
6339#else
6340 Log2(("HcPortStatusCtrl_r: yield -> VINF_IOM_R3_MMIO_READ\n"));
6341 return VINF_IOM_R3_MMIO_READ;
6342#endif
6343 }
6344
6345 /* The WPR bit is always read as zero. */
6346 *pu32Value = p->portsc & ~XHCI_PORT_WPR;
6347 return VINF_SUCCESS;
6348}
6349
6350/**
6351 * Write the PORTSC register.
6352 */
6353static VBOXSTRICTRC HcPortStatusCtrl_w(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iPort, uint32_t val)
6354{
6355 PXHCIHUBPORT p = &pThis->aPorts[iPort];
6356#ifdef IN_RING3
6357 PXHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PXHCICC);
6358#endif
6359 STAM_COUNTER_INC(&pThis->StatWrPortStatusCtrl);
6360
6361 /* If no register change results, we're done. */
6362 if ( p->portsc == val
6363 && !(val & XHCI_PORT_CHANGE_MASK))
6364 return VINF_SUCCESS;
6365
6366 /* If port state is not changing (status bits are being cleared etc.), we can do it in any context.
6367 * This case occurs when the R/W control bits are not changing and the W1C bits are not being set.
6368 */
6369 if ( (p->portsc & XHCI_PORT_CTL_RW_MASK) == (val & XHCI_PORT_CTL_RW_MASK)
6370 && !(val & XHCI_PORT_CTL_W1_MASK))
6371 {
6372 Log(("HcPortStatusCtrl_w port %u (status only): old=%x new=%x\n", IDX_TO_ID(iPort), p->portsc, val));
6373
6374 if (val & XHCI_PORT_RESERVED)
6375 Log(("Reserved bits set %x!\n", val & XHCI_PORT_RESERVED));
6376
6377 /* A write to clear any of the change notification bits. */
6378 if (val & XHCI_PORT_CHANGE_MASK)
6379 p->portsc &= ~(val & XHCI_PORT_CHANGE_MASK);
6380
6381 /* Update the wake mask. */
6382 p->portsc &= ~XHCI_PORT_WAKE_MASK;
6383 p->portsc |= val & XHCI_PORT_WAKE_MASK;
6384
6385 /* There may still be differences between 'portsc' and 'val' in
6386 * the R/O bits; that does not count as a register change and is fine.
6387 * The RW1x control bits are not considered either since those only matter
6388 * if set in 'val'. Since the LWS bit was not set, the PLS bits should not
6389 * be compared. The port change bits may differ as well since the guest
6390 * could be clearing only some or none of them.
6391 */
6392 AssertMsg(!(val & XHCI_PORT_CTL_W1_MASK), ("val=%X\n", val));
6393 AssertMsg(!(val & XHCI_PORT_LWS), ("val=%X\n", val));
6394 AssertMsg((val & ~(XHCI_PORT_RO_MASK|XHCI_PORT_CTL_W1_MASK|XHCI_PORT_PLS_MASK|XHCI_PORT_CHANGE_MASK)) == (p->portsc & ~(XHCI_PORT_RO_MASK|XHCI_PORT_CTL_W1_MASK|XHCI_PORT_PLS_MASK|XHCI_PORT_CHANGE_MASK)), ("val=%X vs. portsc=%X\n", val, p->portsc));
6395 return VINF_SUCCESS;
6396 }
6397
6398 /* Actual USB port state changes need to be done in R3. */
6399#ifdef IN_RING3
6400 Log(("HcPortStatusCtrl_w port %u: old=%x new=%x\n", IDX_TO_ID(iPort), p->portsc, val));
6401 Assert(!(pThis->hcc_params & XHCI_HCC_PPC));
6402 Assert(p->portsc & XHCI_PORT_PP);
6403
6404 if (val & XHCI_PORT_RESERVED)
6405 Log(("Reserved bits set %x!\n", val & XHCI_PORT_RESERVED));
6406
6407 /* A write to clear any of the change notification bits. */
6408 if (val & XHCI_PORT_CHANGE_MASK)
6409 p->portsc &= ~(val & XHCI_PORT_CHANGE_MASK);
6410
6411 /* Writing the Port Enable/Disable bit as 1 disables a port; it cannot be
6412 * enabled that way. Writing the bit as zero does does nothing.
6413 */
6414 if ((val & XHCI_PORT_PED) && (p->portsc & XHCI_PORT_PED))
6415 {
6416 p->portsc &= ~XHCI_PORT_PED;
6417 Log(("HcPortStatusCtrl_w(): port %u: DISABLE\n", IDX_TO_ID(iPort)));
6418 }
6419
6420 if (!(val & XHCI_PORT_PP) && (p->portsc & XHCI_PORT_PP))
6421 {
6422 p->portsc &= ~XHCI_PORT_PP;
6423 Log(("HcPortStatusCtrl_w(): port %u: POWER OFF\n", IDX_TO_ID(iPort)));
6424 }
6425
6426 /* Warm Port Reset - USB3 only; see 4.19.5.1. */
6427 if ((val & XHCI_PORT_WPR) && IS_USB3_PORT_IDX_SHR(pThis, iPort))
6428 {
6429 Log(("HcPortStatusCtrl_w(): port %u: WARM RESET\n", IDX_TO_ID(iPort)));
6430 if (xhciR3RhPortSetIfConnected(pThis, iPort, XHCI_PORT_PR | XHCI_PORT_WPR))
6431 {
6432 PXHCIROOTHUBR3 pRh = GET_PORT_PRH(pThisCC, iPort);
6433
6434 VUSBIRhDevReset(pRh->pIRhConn, GET_VUSB_PORT_FROM_XHCI_PORT(pRh, iPort), false /* don't reset on linux */, NULL /* sync */, NULL, PDMDevHlpGetVM(pDevIns));
6435 xhciR3PortResetDone(pDevIns, iPort);
6436 }
6437 }
6438
6439 if (val & XHCI_PORT_PR)
6440 {
6441 Log(("HcPortStatusCtrl_w(): port %u: RESET\n", IDX_TO_ID(iPort)));
6442 if (xhciR3RhPortSetIfConnected(pThis, iPort, XHCI_PORT_PR))
6443 {
6444 PXHCIROOTHUBR3 pRh = GET_PORT_PRH(pThisCC, iPort);
6445
6446 VUSBIRhDevReset(pRh->pIRhConn, GET_VUSB_PORT_FROM_XHCI_PORT(pRh, iPort), false /* don't reset on linux */, NULL /* sync */, NULL, PDMDevHlpGetVM(pDevIns));
6447 xhciR3PortResetDone(pDevIns, iPort);
6448 }
6449 else if (p->portsc & XHCI_PORT_PR)
6450 {
6451 /* the guest is getting impatient. */
6452 Log2(("HcPortStatusCtrl_w(): port %u: Impatient guest!\n", IDX_TO_ID(iPort)));
6453 RTThreadYield();
6454 }
6455 }
6456
6457 /// @todo Do some sanity checking on the new link state?
6458 /* Update the link state if requested. */
6459 if (val & XHCI_PORT_LWS)
6460 {
6461 unsigned old_pls;
6462 unsigned new_pls;
6463
6464 old_pls = (p->portsc & XHCI_PORT_PLS_MASK) >> XHCI_PORT_PLS_SHIFT;
6465 new_pls = (val & XHCI_PORT_PLS_MASK) >> XHCI_PORT_PLS_SHIFT;
6466
6467 p->portsc &= ~XHCI_PORT_PLS_MASK;
6468 p->portsc |= new_pls << XHCI_PORT_PLS_SHIFT;
6469 Log2(("HcPortStatusCtrl_w(): port %u: Updating link state from %u to %u\n", IDX_TO_ID(iPort), old_pls, new_pls));
6470 /* U3->U0 (USB3) and Resume->U0 transitions set the PLC flag. See 4.15.2.2 */
6471 if (new_pls == XHCI_PLS_U0)
6472 if (old_pls == XHCI_PLS_U3 || old_pls == XHCI_PLS_RESUME)
6473 {
6474 p->portsc |= XHCI_PORT_PLC;
6475 xhciR3GenPortChgEvent(pDevIns, pThis, IDX_TO_ID(iPort));
6476 }
6477 }
6478
6479 /// @todo which other bits can we safely ignore?
6480
6481 /* Update the wake mask. */
6482 p->portsc &= ~XHCI_PORT_WAKE_MASK;
6483 p->portsc |= val & XHCI_PORT_WAKE_MASK;
6484
6485 return VINF_SUCCESS;
6486#else /* !IN_RING3 */
6487 RT_NOREF(pDevIns);
6488 return VINF_IOM_R3_MMIO_WRITE;
6489#endif /* !IN_RING3 */
6490}
6491
6492
6493/**
6494 * Read the PORTPMSC register.
6495 */
6496static VBOXSTRICTRC HcPortPowerMgmt_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iPort, uint32_t *pu32Value)
6497{
6498 PXHCIHUBPORT p = &pThis->aPorts[iPort];
6499 RT_NOREF(pDevIns);
6500 STAM_COUNTER_INC(&pThis->StatRdPortPowerMgmt);
6501
6502 *pu32Value = p->portpm;
6503 return VINF_SUCCESS;
6504}
6505
6506
6507/**
6508 * Write the PORTPMSC register.
6509 */
6510static VBOXSTRICTRC HcPortPowerMgmt_w(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iPort, uint32_t val)
6511{
6512 PXHCIHUBPORT p = &pThis->aPorts[iPort];
6513 RT_NOREF(pDevIns);
6514 STAM_COUNTER_INC(&pThis->StatWrPortPowerMgmt);
6515
6516 /// @todo anything to do here?
6517 p->portpm = val;
6518 return VINF_SUCCESS;
6519}
6520
6521
6522/**
6523 * Read the PORTLI register.
6524 */
6525static VBOXSTRICTRC HcPortLinkInfo_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iPort, uint32_t *pu32Value)
6526{
6527 PXHCIHUBPORT p = &pThis->aPorts[iPort];
6528 RT_NOREF(pDevIns);
6529 STAM_COUNTER_INC(&pThis->StatRdPortLinkInfo);
6530
6531 /* The link information is R/O; we probably can't get it at all. If we
6532 * do maintain it for USB3 ports, we also have to reset it (5.4.10).
6533 */
6534 *pu32Value = p->portli;
6535 return VINF_SUCCESS;
6536}
6537
6538/**
6539 * Read the reserved register. Linux likes to do this.
6540 */
6541static VBOXSTRICTRC HcPortRsvd_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iPort, uint32_t *pu32Value)
6542{
6543 RT_NOREF(pDevIns, pThis, iPort);
6544 STAM_COUNTER_INC(&pThis->StatRdPortRsvd);
6545 *pu32Value = 0;
6546 return VINF_SUCCESS;
6547}
6548
6549
6550
6551/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
6552/* xHCI Interrupter Register access routines */
6553/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
6554
6555
6556
6557/**
6558 * Read the IMAN register.
6559 */
6560static VBOXSTRICTRC HcIntrMgmt_r(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t *pu32Value)
6561{
6562 RT_NOREF(pDevIns, pThis);
6563 STAM_COUNTER_INC(&pThis->StatRdIntrMgmt);
6564
6565 *pu32Value = ip->iman;
6566 return VINF_SUCCESS;
6567}
6568
6569/**
6570 * Write the IMAN register.
6571 */
6572static VBOXSTRICTRC HcIntrMgmt_w(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t val)
6573{
6574 uint32_t uNew = val & XHCI_IMAN_VALID_MASK;
6575 STAM_COUNTER_INC(&pThis->StatWrIntrMgmt);
6576
6577 if (val & ~XHCI_IMAN_VALID_MASK)
6578 Log(("Reserved bits set %x!\n", val & ~XHCI_IMAN_VALID_MASK));
6579
6580 /* If the Interrupt Pending (IP) bit is set, writing one clears it.
6581 * Note that when MSIs are enabled, the bit auto-clears almost immediately.
6582 */
6583 if (val & ip->iman & XHCI_IMAN_IP)
6584 {
6585 Log2(("clearing interrupt on interrupter %u\n", ip->index));
6586 PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW);
6587 STAM_COUNTER_INC(&pThis->StatIntrsCleared);
6588 uNew &= ~XHCI_IMAN_IP;
6589 }
6590 else
6591 {
6592 /* Preserve the current IP bit. */
6593 uNew = (uNew & ~XHCI_IMAN_IP) | (ip->iman & XHCI_IMAN_IP);
6594 }
6595
6596 /* Trigger an interrupt if the IP bit is set and IE transitions from 0 to 1. */
6597 if ( (uNew & XHCI_IMAN_IE)
6598 && !(ip->iman & XHCI_IMAN_IE)
6599 && (ip->iman & XHCI_IMAN_IP)
6600 && (pThis->cmd & XHCI_CMD_INTE))
6601 PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_HIGH);
6602
6603 ip->iman = uNew;
6604 return VINF_SUCCESS;
6605}
6606
6607/**
6608 * Read the IMOD register.
6609 */
6610static VBOXSTRICTRC HcIntrMod_r(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t *pu32Value)
6611{
6612 RT_NOREF(pDevIns, pThis);
6613 STAM_COUNTER_INC(&pThis->StatRdIntrMod);
6614
6615 *pu32Value = ip->imod;
6616 return VINF_SUCCESS;
6617}
6618
6619/**
6620 * Write the IMOD register.
6621 */
6622static VBOXSTRICTRC HcIntrMod_w(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t val)
6623{
6624 RT_NOREF(pDevIns, pThis);
6625 STAM_COUNTER_INC(&pThis->StatWrIntrMod);
6626
6627 /// @todo Does writing a zero to IMODC/IMODI potentially trigger
6628 /// an interrupt?
6629 ip->imod = val;
6630 return VINF_SUCCESS;
6631}
6632
6633/**
6634 * Read the ERSTSZ register.
6635 */
6636static VBOXSTRICTRC HcEvtRSTblSize_r(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t *pu32Value)
6637{
6638 RT_NOREF(pDevIns, pThis);
6639 STAM_COUNTER_INC(&pThis->StatRdEvtRstblSize);
6640
6641 *pu32Value = ip->erstsz;
6642 return VINF_SUCCESS;
6643}
6644
6645/**
6646 * Write the ERSTSZ register.
6647 */
6648static VBOXSTRICTRC HcEvtRSTblSize_w(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t val)
6649{
6650 RT_NOREF(pDevIns, pThis);
6651 STAM_COUNTER_INC(&pThis->StatWrEvtRstblSize);
6652
6653 if (val & ~XHCI_ERSTSZ_MASK)
6654 Log(("Reserved bits set %x!\n", val & ~XHCI_ERSTSZ_MASK));
6655 if (val > XHCI_ERSTMAX)
6656 Log(("ERSTSZ (%u) > ERSTMAX (%u)!\n", val, XHCI_ERSTMAX));
6657
6658 /* Enforce the maximum size. */
6659 ip->erstsz = RT_MIN(val, XHCI_ERSTMAX);
6660
6661 if (!ip->index && !ip->erstsz) /* Windows 8 does this temporarily. Thanks guys... */
6662 Log(("ERSTSZ is zero for primary interrupter: undefined behavior!\n"));
6663
6664 return VINF_SUCCESS;
6665}
6666
6667/**
6668 * Read the reserved register. Linux likes to do this.
6669 */
6670static VBOXSTRICTRC HcEvtRsvd_r(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t *pu32Value)
6671{
6672 RT_NOREF(pDevIns, pThis, ip);
6673 STAM_COUNTER_INC(&pThis->StatRdEvtRsvd);
6674 *pu32Value = 0;
6675 return VINF_SUCCESS;
6676}
6677
6678/**
6679 * Read the low dword of the ERSTBA register.
6680 */
6681static VBOXSTRICTRC HcEvtRSTblBaseLo_r(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t *pu32Value)
6682{
6683 RT_NOREF(pDevIns, pThis);
6684 STAM_COUNTER_INC(&pThis->StatRdEvtRsTblBaseLo);
6685
6686 *pu32Value = (uint32_t)ip->erstba;
6687 return VINF_SUCCESS;
6688}
6689
6690
6691/**
6692 * Write the low dword of the ERSTBA register.
6693 */
6694static VBOXSTRICTRC HcEvtRSTblBaseLo_w(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t val)
6695{
6696 STAM_COUNTER_INC(&pThis->StatWrEvtRsTblBaseLo);
6697
6698 if (val & ~pThis->erst_addr_mask)
6699 Log(("Reserved bits set %x!\n", val & ~pThis->erst_addr_mask));
6700
6701 /* NB: A dword write to the low half clears the high half. */
6702 ip->erstba = val & pThis->erst_addr_mask;
6703
6704 /* Initialize the internal event ring state. */
6705 ip->evtr_pcs = 1;
6706 ip->erst_idx = 0;
6707 ip->ipe = false;
6708
6709 /* Fetch the first ERST entry now. Not later! That "sets the Event Ring
6710 * State Machine:EREP Advancement to the Start state"
6711 */
6712 xhciFetchErstEntry(pDevIns, pThis, ip);
6713
6714 return VINF_SUCCESS;
6715}
6716
6717/**
6718 * Read the high dword of the ERSTBA register.
6719 */
6720static VBOXSTRICTRC HcEvtRSTblBaseHi_r(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t *pu32Value)
6721{
6722 RT_NOREF(pDevIns, pThis);
6723 STAM_COUNTER_INC(&pThis->StatRdEvtRsTblBaseHi);
6724
6725 *pu32Value = (uint32_t)(ip->erstba >> 32);
6726 return VINF_SUCCESS;
6727}
6728
6729/**
6730 * Write the high dword of the ERSTBA register.
6731 */
6732static VBOXSTRICTRC HcEvtRSTblBaseHi_w(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t val)
6733{
6734 STAM_COUNTER_INC(&pThis->StatWrEvtRsTblBaseHi);
6735
6736 /* Update the high dword while preserving the low one. */
6737 ip->erstba = ((uint64_t)val << 32) | (uint32_t)ip->erstba;
6738
6739 /* We shouldn't be doing this when AC64 is set. But High Sierra
6740 * ignores that because it "knows" the xHC handles 64-bit addressing,
6741 * so we're going to assume that OSes are not going to write junk into
6742 * ERSTBAH when they don't see AC64 set.
6743 */
6744 xhciFetchErstEntry(pDevIns, pThis, ip);
6745
6746 return VINF_SUCCESS;
6747}
6748
6749
6750/**
6751 * Read the low dword of the ERDP register.
6752 */
6753static VBOXSTRICTRC HcEvtRingDeqPtrLo_r(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t *pu32Value)
6754{
6755 RT_NOREF(pThis);
6756 STAM_COUNTER_INC(&pThis->StatRdEvtRingDeqPtrLo);
6757
6758 /* Lock to avoid incomplete update being seen. */
6759 int rc = PDMDevHlpCritSectEnter(pDevIns, &ip->lock, VINF_IOM_R3_MMIO_READ);
6760 if (rc != VINF_SUCCESS)
6761 return rc;
6762
6763 *pu32Value = (uint32_t)ip->erdp;
6764
6765 PDMDevHlpCritSectLeave(pDevIns, &ip->lock);
6766
6767 return VINF_SUCCESS;
6768}
6769
6770/**
6771 * Write the low dword of the ERDP register.
6772 */
6773static VBOXSTRICTRC HcEvtRingDeqPtrLo_w(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t val)
6774{
6775 uint64_t old_erdp;
6776 uint64_t new_erdp;
6777 STAM_COUNTER_INC(&pThis->StatWrEvtRingDeqPtrLo);
6778
6779 /* NB: A dword write to the low half clears the high half.
6780 * The high dword should be ignored when AC64=0, but High Sierra
6781 * does not care what we report. Therefore a write to the low dword
6782 * handles all the control bits and a write to the high dword still
6783 * updates the ERDP address. On a 64-bit host, there must be a
6784 * back-to-back low dword + high dword access. We are going to boldly
6785 * assume that the guest will not place the event ring across the 4G
6786 * boundary (i.e. storing the bottom part in the firmware ROM).
6787 */
6788 int rc = PDMDevHlpCritSectEnter(pDevIns, &ip->lock, VINF_IOM_R3_MMIO_WRITE);
6789 if (rc != VINF_SUCCESS)
6790 return rc;
6791
6792 old_erdp = ip->erdp & XHCI_ERDP_ADDR_MASK; /* Remember old ERDP address. */
6793 new_erdp = ip->erdp & XHCI_ERDP_EHB; /* Preserve EHB */
6794
6795 /* If the Event Handler Busy (EHB) bit is set, writing a one clears it. */
6796 if (val & ip->erdp & XHCI_ERDP_EHB)
6797 {
6798 Log2(("clearing EHB on interrupter %p\n", ip));
6799 new_erdp &= ~XHCI_ERDP_EHB;
6800 }
6801 /// @todo Check if this might inadvertently set EHB!
6802
6803 new_erdp |= val & ~XHCI_ERDP_EHB;
6804 ip->erdp = new_erdp;
6805
6806 /* Check if the ERDP changed. See workaround below. */
6807 if (old_erdp != (new_erdp & XHCI_ERDP_ADDR_MASK))
6808 ip->erdp_rewrites = 0;
6809 else
6810 ++ip->erdp_rewrites;
6811
6812 LogFlowFunc(("ERDP: %RGp, EREP: %RGp\n", (RTGCPHYS)(ip->erdp & XHCI_ERDP_ADDR_MASK), (RTGCPHYS)ip->erep));
6813
6814 if ((ip->erdp & XHCI_ERDP_ADDR_MASK) == ip->erep)
6815 {
6816 Log2(("Event Ring empty, clearing IPE\n"));
6817 ip->ipe = false;
6818 }
6819 else if (ip->ipe && (val & XHCI_ERDP_EHB))
6820 {
6821 /* EHB is being cleared but the ring isn't empty and IPE is still set. */
6822 if (RT_UNLIKELY(old_erdp == (new_erdp & XHCI_ERDP_ADDR_MASK) && ip->erdp_rewrites > 2))
6823 {
6824 /* If guest does not advance the ERDP, do not trigger an interrupt
6825 * again. Workaround for buggy xHCI initialization in Linux 4.6 which
6826 * enables interrupts before setting up internal driver state. That
6827 * leads to the guest IRQ handler not actually handling events and
6828 * infinitely re-triggering interrupts. However, only do this if the
6829 * guest has already written the same ERDP value a few times. The Intel
6830 * xHCI driver always writes the same ERDP twice and we must still
6831 * re-trigger interrupts in that case.
6832 * See @bugref{8546}.
6833 */
6834 Log2(("Event Ring not empty, ERDP not advanced, not re-triggering interrupt!\n"));
6835 ip->ipe = false;
6836 }
6837 else
6838 {
6839 Log2(("Event Ring not empty, re-triggering interrupt\n"));
6840 xhciSetIntr(pDevIns, pThis, ip);
6841 }
6842 }
6843
6844 PDMDevHlpCritSectLeave(pDevIns, &ip->lock);
6845
6846 return VINF_SUCCESS;
6847}
6848
6849/**
6850 * Read the high dword of the ERDP register.
6851 */
6852static VBOXSTRICTRC HcEvtRingDeqPtrHi_r(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t *pu32Value)
6853{
6854 RT_NOREF(pDevIns, pThis);
6855 STAM_COUNTER_INC(&pThis->StatRdEvtRingDeqPtrHi);
6856
6857 *pu32Value = (uint32_t)(ip->erdp >> 32);
6858 return VINF_SUCCESS;
6859}
6860
6861/**
6862 * Write the high dword of the ERDP register.
6863 */
6864static VBOXSTRICTRC HcEvtRingDeqPtrHi_w(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR ip, uint32_t val)
6865{
6866 RT_NOREF(pThis);
6867 STAM_COUNTER_INC(&pThis->StatWrEvtRingDeqPtrHi);
6868
6869 /* See HcEvtRingDeqPtrLo_w for semantics. */
6870 int rc = PDMDevHlpCritSectEnter(pDevIns, &ip->lock, VINF_IOM_R3_MMIO_WRITE);
6871 if (rc != VINF_SUCCESS)
6872 return rc;
6873
6874 /* Update the high dword while preserving the low one. */
6875 ip->erdp = ((uint64_t)val << 32) | (uint32_t)ip->erdp;
6876
6877 PDMDevHlpCritSectLeave(pDevIns, &ip->lock);
6878
6879 return VINF_SUCCESS;
6880}
6881
6882
6883/**
6884 * xHCI register access routines.
6885 */
6886typedef struct
6887{
6888 const char *pszName;
6889 VBOXSTRICTRC (*pfnRead )(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t *pu32Value);
6890 VBOXSTRICTRC (*pfnWrite)(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t iReg, uint32_t u32Value);
6891} XHCIREGACC;
6892
6893/**
6894 * xHCI interrupter register access routines.
6895 */
6896typedef struct
6897{
6898 const char *pszName;
6899 VBOXSTRICTRC (*pfnIntrRead )(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR pIntr, uint32_t *pu32Value);
6900 VBOXSTRICTRC (*pfnIntrWrite)(PPDMDEVINS pDevIns, PXHCI pThis, PXHCIINTRPTR pIntr, uint32_t u32Value);
6901} XHCIINTRREGACC;
6902
6903/**
6904 * Operational registers descriptor table.
6905 */
6906static const XHCIREGACC g_aOpRegs[] =
6907{
6908 {"USBCMD" , HcUsbcmd_r, HcUsbcmd_w },
6909 {"USBSTS", HcUsbsts_r, HcUsbsts_w },
6910 {"PAGESIZE", HcPagesize_r, NULL },
6911 {"Unused", NULL, NULL },
6912 {"Unused", NULL, NULL },
6913 {"DNCTRL", HcDevNotifyCtrl_r, HcDevNotifyCtrl_w },
6914 {"CRCRL", HcCmdRingCtlLo_r, HcCmdRingCtlLo_w },
6915 {"CRCRH", HcCmdRingCtlHi_r, HcCmdRingCtlHi_w },
6916 {"Unused", NULL, NULL },
6917 {"Unused", NULL, NULL },
6918 {"Unused", NULL, NULL },
6919 {"Unused", NULL, NULL },
6920 {"DCBAAPL", HcDevCtxBAAPLo_r, HcDevCtxBAAPLo_w },
6921 {"DCBAAPH", HcDevCtxBAAPHi_r, HcDevCtxBAAPHi_w },
6922 {"CONFIG", HcConfig_r, HcConfig_w }
6923};
6924
6925
6926/**
6927 * Port registers descriptor table (for a single port). The number of ports
6928 * and their associated registers depends on the NDP value.
6929 */
6930static const XHCIREGACC g_aPortRegs[] =
6931{
6932 /*
6933 */
6934 {"PORTSC", HcPortStatusCtrl_r, HcPortStatusCtrl_w },
6935 {"PORTPMSC", HcPortPowerMgmt_r, HcPortPowerMgmt_w },
6936 {"PORTLI", HcPortLinkInfo_r, NULL },
6937 {"Reserved", HcPortRsvd_r, NULL }
6938};
6939AssertCompile(RT_ELEMENTS(g_aPortRegs) * sizeof(uint32_t) == 0x10);
6940
6941
6942/**
6943 * Interrupter runtime registers descriptor table (for a single interrupter).
6944 * The number of interrupters depends on the XHCI_NINTR value.
6945 */
6946static const XHCIINTRREGACC g_aIntrRegs[] =
6947{
6948 {"IMAN", HcIntrMgmt_r, HcIntrMgmt_w },
6949 {"IMOD", HcIntrMod_r, HcIntrMod_w },
6950 {"ERSTSZ", HcEvtRSTblSize_r, HcEvtRSTblSize_w },
6951 {"Reserved", HcEvtRsvd_r, NULL },
6952 {"ERSTBAL", HcEvtRSTblBaseLo_r, HcEvtRSTblBaseLo_w },
6953 {"ERSTBAH", HcEvtRSTblBaseHi_r, HcEvtRSTblBaseHi_w },
6954 {"ERDPL", HcEvtRingDeqPtrLo_r, HcEvtRingDeqPtrLo_w },
6955 {"ERDPH", HcEvtRingDeqPtrHi_r, HcEvtRingDeqPtrHi_w }
6956};
6957AssertCompile(RT_ELEMENTS(g_aIntrRegs) * sizeof(uint32_t) == 0x20);
6958
6959
6960/**
6961 * Read the MFINDEX register.
6962 */
6963static int HcMfIndex_r(PPDMDEVINS pDevIns, PXHCI pThis, uint32_t *pu32Value)
6964{
6965 uint64_t uNanoTime;
6966 uint64_t uMfTime;
6967 STAM_COUNTER_INC(&pThis->StatRdMfIndex);
6968
6969 /* MFINDEX increments once per micro-frame, i.e. 8 times per millisecond
6970 * or every 125us. The resolution is only 14 bits, meaning that MFINDEX
6971 * wraps around after it reaches 0x3FFF (16383) or every 2048 milliseconds.
6972 */
6973 /// @todo MFINDEX should only be running when R/S is set. May not matter.
6974 uNanoTime = PDMDevHlpTimerGet(pDevIns, pThis->hWrapTimer);
6975 uMfTime = uNanoTime / 125000;
6976
6977 *pu32Value = uMfTime & 0x3FFF;
6978 Log2(("MFINDEX read: %u\n", *pu32Value));
6979 return VINF_SUCCESS;
6980}
6981
6982/**
6983 * @callback_method_impl{FNIOMMMIONEWREAD, Read a MMIO register.}
6984 *
6985 * @note We only accept 32-bit writes that are 32-bit aligned.
6986 */
6987static DECLCALLBACK(VBOXSTRICTRC) xhciMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb)
6988{
6989 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
6990 const uint32_t offReg = (uint32_t)off;
6991 uint32_t * const pu32 = (uint32_t *)pv;
6992 uint32_t iReg;
6993 RT_NOREF(pvUser);
6994
6995 Log2(("xhciRead %RGp (offset %04X) size=%d\n", off, offReg, cb));
6996
6997 if (offReg < XHCI_CAPS_REG_SIZE)
6998 {
6999 switch (offReg)
7000 {
7001 case 0x0: /* CAPLENGTH + HCIVERSION */
7002 *pu32 = (pThis->hci_version << 16) | pThis->cap_length;
7003 break;
7004
7005 case 0x4: /* HCSPARAMS1 (structural) */
7006 Log2(("HCSPARAMS1 read\n"));
7007 *pu32 = pThis->hcs_params1;
7008 break;
7009
7010 case 0x8: /* HCSPARAMS2 (structural) */
7011 Log2(("HCSPARAMS2 read\n"));
7012 *pu32 = pThis->hcs_params2;
7013 break;
7014
7015 case 0xC: /* HCSPARAMS3 (structural) */
7016 Log2(("HCSPARAMS3 read\n"));
7017 *pu32 = pThis->hcs_params3;
7018 break;
7019
7020 case 0x10: /* HCCPARAMS1 (caps) */
7021 Log2(("HCCPARAMS1 read\n"));
7022 *pu32 = pThis->hcc_params;
7023 break;
7024
7025 case 0x14: /* DBOFF (doorbell offset) */
7026 Log2(("DBOFF read\n"));
7027 *pu32 = pThis->dbell_off;
7028 break;
7029
7030 case 0x18: /* RTSOFF (run-time register offset) */
7031 Log2(("RTSOFF read\n"));
7032 *pu32 = pThis->rts_off;
7033 break;
7034
7035 case 0x1C: /* HCCPARAMS2 (caps) */
7036 Log2(("HCCPARAMS2 read\n"));
7037 *pu32 = 0; /* xHCI 1.1 only */
7038 break;
7039
7040 default:
7041 Log(("xHCI: Trying to read unknown capability register %u!\n", offReg));
7042 STAM_COUNTER_INC(&pThis->StatRdUnknown);
7043 return VINF_IOM_MMIO_UNUSED_FF;
7044 }
7045 STAM_COUNTER_INC(&pThis->StatRdCaps);
7046 Log2(("xhciRead %RGp size=%d -> val=%x\n", off, cb, *pu32));
7047 return VINF_SUCCESS;
7048 }
7049
7050 /*
7051 * Validate the access (in case of IOM bugs or incorrect MMIO registration).
7052 */
7053 AssertMsgReturn(cb == sizeof(uint32_t), ("IOM bug? %RGp LB %d\n", off, cb),
7054 VINF_IOM_MMIO_UNUSED_FF /* No idea what really would happen... */);
7055 /** r=bird: If you don't have an idea what would happen for non-dword reads,
7056 * then the flags passed to IOM when creating the MMIO region are doubtful, right? */
7057 AssertMsgReturn(!(off & 0x3), ("IOM bug? %RGp LB %d\n", off, cb), VINF_IOM_MMIO_UNUSED_FF);
7058
7059 /*
7060 * Validate the register and call the read operator.
7061 */
7062 VBOXSTRICTRC rcStrict = VINF_IOM_MMIO_UNUSED_FF;
7063 if (offReg >= XHCI_DOORBELL_OFFSET)
7064 {
7065 /* The doorbell registers are effectively write-only and return 0 when read. */
7066 iReg = (offReg - XHCI_DOORBELL_OFFSET) >> 2;
7067 if (iReg < XHCI_NDS)
7068 {
7069 STAM_COUNTER_INC(&pThis->StatRdDoorBell);
7070 *pu32 = 0;
7071 rcStrict = VINF_SUCCESS;
7072 Log2(("xhciRead: DBellReg (DB %u) %RGp size=%d -> val=%x (rc=%d)\n", iReg, off, cb, *pu32, VBOXSTRICTRC_VAL(rcStrict)));
7073 }
7074 }
7075 else if (offReg >= XHCI_RTREG_OFFSET)
7076 {
7077 /* Run-time registers. */
7078 Assert(offReg < XHCI_DOORBELL_OFFSET);
7079 /* The MFINDEX register would be interrupter -1... */
7080 if (offReg < XHCI_RTREG_OFFSET + RT_ELEMENTS(g_aIntrRegs) * sizeof(uint32_t))
7081 {
7082 if (offReg == XHCI_RTREG_OFFSET)
7083 rcStrict = HcMfIndex_r(pDevIns, pThis, pu32);
7084 else
7085 {
7086 /* The silly Linux xHCI driver reads the reserved registers. */
7087 STAM_COUNTER_INC(&pThis->StatRdUnknown);
7088 *pu32 = 0;
7089 rcStrict = VINF_SUCCESS;
7090 }
7091 }
7092 else
7093 {
7094 Assert((offReg - XHCI_RTREG_OFFSET) / (RT_ELEMENTS(g_aIntrRegs) * sizeof(uint32_t)) > 0);
7095 const uint32_t iIntr = (offReg - XHCI_RTREG_OFFSET) / (RT_ELEMENTS(g_aIntrRegs) * sizeof(uint32_t)) - 1;
7096
7097 if (iIntr < XHCI_NINTR)
7098 {
7099 iReg = (offReg >> 2) & (RT_ELEMENTS(g_aIntrRegs) - 1);
7100 const XHCIINTRREGACC *pReg = &g_aIntrRegs[iReg];
7101 if (pReg->pfnIntrRead)
7102 {
7103 PXHCIINTRPTR pIntr = &pThis->aInterrupters[iIntr];
7104 rcStrict = pReg->pfnIntrRead(pDevIns, pThis, pIntr, pu32);
7105 Log2(("xhciRead: IntrReg (intr %u): %RGp (%s) size=%d -> val=%x (rc=%d)\n", iIntr, off, pReg->pszName, cb, *pu32, VBOXSTRICTRC_VAL(rcStrict)));
7106 }
7107 }
7108 }
7109 }
7110 else if (offReg >= XHCI_XECP_OFFSET)
7111 {
7112 /* Extended Capability registers. */
7113 Assert(offReg < XHCI_RTREG_OFFSET);
7114 uint32_t offXcp = offReg - XHCI_XECP_OFFSET;
7115
7116 if (offXcp + cb <= RT_MIN(pThis->cbExtCap, sizeof(pThis->abExtCap))) /* can't trust cbExtCap in ring-0. */
7117 {
7118 *pu32 = *(uint32_t *)&pThis->abExtCap[offXcp];
7119 rcStrict = VINF_SUCCESS;
7120 }
7121 Log2(("xhciRead: ExtCapReg %RGp size=%d -> val=%x (rc=%d)\n", off, cb, *pu32, VBOXSTRICTRC_VAL(rcStrict)));
7122 }
7123 else
7124 {
7125 /* Operational registers (incl. port registers). */
7126 Assert(offReg < XHCI_XECP_OFFSET);
7127 iReg = (offReg - XHCI_CAPS_REG_SIZE) >> 2;
7128 if (iReg < RT_ELEMENTS(g_aOpRegs))
7129 {
7130 const XHCIREGACC *pReg = &g_aOpRegs[iReg];
7131 if (pReg->pfnRead)
7132 {
7133 rcStrict = pReg->pfnRead(pDevIns, pThis, iReg, pu32);
7134 Log2(("xhciRead: OpReg %RGp (%s) size=%d -> val=%x (rc=%d)\n", off, pReg->pszName, cb, *pu32, VBOXSTRICTRC_VAL(rcStrict)));
7135 }
7136 }
7137 else if (iReg >= (XHCI_PORT_REG_OFFSET >> 2))
7138 {
7139 iReg -= (XHCI_PORT_REG_OFFSET >> 2);
7140 const uint32_t iPort = iReg / RT_ELEMENTS(g_aPortRegs);
7141 if (iPort < XHCI_NDP_CFG(pThis))
7142 {
7143 iReg = (offReg >> 2) & (RT_ELEMENTS(g_aPortRegs) - 1);
7144 Assert(iReg < RT_ELEMENTS(g_aPortRegs));
7145 const XHCIREGACC *pReg = &g_aPortRegs[iReg];
7146 if (pReg->pfnRead)
7147 {
7148 rcStrict = pReg->pfnRead(pDevIns, pThis, iPort, pu32);
7149 Log2(("xhciRead: PortReg (port %u): %RGp (%s) size=%d -> val=%x (rc=%d)\n", IDX_TO_ID(iPort), off, pReg->pszName, cb, *pu32, VBOXSTRICTRC_VAL(rcStrict)));
7150 }
7151 }
7152 }
7153 }
7154
7155 if (rcStrict != VINF_IOM_MMIO_UNUSED_FF)
7156 { /* likely */ }
7157 else
7158 {
7159 STAM_COUNTER_INC(&pThis->StatRdUnknown);
7160 Log(("xHCI: Trying to read unimplemented register at offset %04X!\n", offReg));
7161 }
7162
7163 return rcStrict;
7164}
7165
7166
7167/**
7168 * @callback_method_impl{FNIOMMMIONEWWRITE, Write to a MMIO register.}
7169 *
7170 * @note We only accept 32-bit writes that are 32-bit aligned.
7171 */
7172static DECLCALLBACK(VBOXSTRICTRC) xhciMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
7173{
7174 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
7175 const uint32_t offReg = (uint32_t)off;
7176 uint32_t * const pu32 = (uint32_t *)pv;
7177 uint32_t iReg;
7178 RT_NOREF(pvUser);
7179
7180 Log2(("xhciWrite %RGp (offset %04X) %x size=%d\n", off, offReg, *(uint32_t *)pv, cb));
7181
7182 if (offReg < XHCI_CAPS_REG_SIZE)
7183 {
7184 /* These are read-only */
7185 Log(("xHCI: Trying to write to register %u!\n", offReg));
7186 STAM_COUNTER_INC(&pThis->StatWrUnknown);
7187 return VINF_SUCCESS;
7188 }
7189
7190 /*
7191 * Validate the access (in case of IOM bug or incorrect MMIO registration).
7192 */
7193 AssertMsgReturn(cb == sizeof(uint32_t), ("IOM bug? %RGp LB %d\n", off, cb), VINF_SUCCESS);
7194 AssertMsgReturn(!(off & 0x3), ("IOM bug? %RGp LB %d\n", off, cb), VINF_SUCCESS);
7195
7196 /*
7197 * Validate the register and call the write operator.
7198 */
7199 VBOXSTRICTRC rcStrict = VINF_IOM_MMIO_UNUSED_FF;
7200 if (offReg >= XHCI_DOORBELL_OFFSET)
7201 {
7202 /* Let's spring into action... as long as the xHC is running. */
7203 iReg = (offReg - XHCI_DOORBELL_OFFSET) >> 2;
7204 if ((pThis->cmd & XHCI_CMD_RS) && iReg < XHCI_NDS)
7205 {
7206 if (iReg == 0)
7207 {
7208 /* DB0 aka Command Ring. */
7209 STAM_COUNTER_INC(&pThis->StatWrDoorBell0);
7210 if (*pu32 == 0)
7211 {
7212 /* Set the Command Ring state to Running if not already set. */
7213 if (!(pThis->crcr & XHCI_CRCR_CRR))
7214 {
7215 Log(("Command ring entered Running state\n"));
7216 ASMAtomicOrU64(&pThis->crcr, XHCI_CRCR_CRR);
7217 }
7218 xhciKickWorker(pDevIns, pThis, XHCI_JOB_PROCESS_CMDRING, 0);
7219 }
7220 else
7221 Log2(("Ignoring DB0 write with value %X!\n", *pu32));
7222 }
7223 else
7224 {
7225 /* Device context doorbell. Do basic parameter checking to avoid
7226 * waking up the worker thread needlessly.
7227 */
7228 STAM_COUNTER_INC(&pThis->StatWrDoorBellN);
7229 uint8_t uDBTarget = *pu32 & XHCI_DB_TGT_MASK;
7230 Assert(uDBTarget < 32); /// @todo Report an error? Or just ignore?
7231 if (uDBTarget < 32)
7232 {
7233 Log2(("Ring bell for slot %u, DCI %u\n", iReg, uDBTarget));
7234 ASMAtomicOrU32(&pThis->aBellsRung[ID_TO_IDX(iReg)], 1 << uDBTarget);
7235 xhciKickWorker(pDevIns, pThis, XHCI_JOB_DOORBELL, *pu32);
7236 }
7237 else
7238 Log2(("Ignoring DB%u write with bad target %u!\n", iReg, uDBTarget));
7239 }
7240 rcStrict = VINF_SUCCESS;
7241 Log2(("xhciWrite: DBellReg (DB %u) %RGp size=%d <- val=%x (rc=%d)\n", iReg, off, cb, *(uint32_t *)pv, VBOXSTRICTRC_VAL(rcStrict)));
7242 }
7243 }
7244 else if (offReg >= XHCI_RTREG_OFFSET)
7245 {
7246 /* Run-time registers. */
7247 Assert(offReg < XHCI_DOORBELL_OFFSET);
7248 /* NB: The MFINDEX register is R/O. */
7249 if (offReg >= XHCI_RTREG_OFFSET + (RT_ELEMENTS(g_aIntrRegs) * sizeof(uint32_t)))
7250 {
7251 Assert((offReg - XHCI_RTREG_OFFSET) / (RT_ELEMENTS(g_aIntrRegs) * sizeof(uint32_t)) > 0);
7252 const uint32_t iIntr = (offReg - XHCI_RTREG_OFFSET) / (RT_ELEMENTS(g_aIntrRegs) * sizeof(uint32_t)) - 1;
7253
7254 if (iIntr < XHCI_NINTR)
7255 {
7256 iReg = (offReg >> 2) & (RT_ELEMENTS(g_aIntrRegs) - 1);
7257 const XHCIINTRREGACC *pReg = &g_aIntrRegs[iReg];
7258 if (pReg->pfnIntrWrite)
7259 {
7260 PXHCIINTRPTR pIntr = &pThis->aInterrupters[iIntr];
7261 rcStrict = pReg->pfnIntrWrite(pDevIns, pThis, pIntr, *pu32);
7262 Log2(("xhciWrite: IntrReg (intr %u): %RGp (%s) size=%d <- val=%x (rc=%d)\n", iIntr, off, pReg->pszName, cb, *pu32, VBOXSTRICTRC_VAL(rcStrict)));
7263 }
7264 }
7265 }
7266 }
7267 else
7268 {
7269 /* Operational registers (incl. port registers). */
7270 Assert(offReg < XHCI_RTREG_OFFSET);
7271 iReg = (offReg - pThis->cap_length) >> 2;
7272 if (iReg < RT_ELEMENTS(g_aOpRegs))
7273 {
7274 const XHCIREGACC *pReg = &g_aOpRegs[iReg];
7275 if (pReg->pfnWrite)
7276 {
7277 rcStrict = pReg->pfnWrite(pDevIns, pThis, iReg, *(uint32_t *)pv);
7278 Log2(("xhciWrite: OpReg %RGp (%s) size=%d <- val=%x (rc=%d)\n", off, pReg->pszName, cb, *(uint32_t *)pv, VBOXSTRICTRC_VAL(rcStrict)));
7279 }
7280 }
7281 else if (iReg >= (XHCI_PORT_REG_OFFSET >> 2))
7282 {
7283 iReg -= (XHCI_PORT_REG_OFFSET >> 2);
7284 const uint32_t iPort = iReg / RT_ELEMENTS(g_aPortRegs);
7285 if (iPort < XHCI_NDP_CFG(pThis))
7286 {
7287 iReg = (offReg >> 2) & (RT_ELEMENTS(g_aPortRegs) - 1);
7288 Assert(iReg < RT_ELEMENTS(g_aPortRegs));
7289 const XHCIREGACC *pReg = &g_aPortRegs[iReg];
7290 if (pReg->pfnWrite)
7291 {
7292 rcStrict = pReg->pfnWrite(pDevIns, pThis, iPort, *pu32);
7293 Log2(("xhciWrite: PortReg (port %u): %RGp (%s) size=%d <- val=%x (rc=%d)\n", IDX_TO_ID(iPort), off, pReg->pszName, cb, *pu32, VBOXSTRICTRC_VAL(rcStrict)));
7294 }
7295 }
7296 }
7297 }
7298
7299 if (rcStrict != VINF_IOM_MMIO_UNUSED_FF)
7300 { /* likely */ }
7301 else
7302 {
7303 /* Ignore writes to unimplemented or read-only registers. */
7304 STAM_COUNTER_INC(&pThis->StatWrUnknown);
7305 Log(("xHCI: Trying to write unimplemented or R/O register at offset %04X!\n", offReg));
7306 rcStrict = VINF_SUCCESS;
7307 }
7308
7309 return rcStrict;
7310}
7311
7312
7313#ifdef IN_RING3
7314
7315/**
7316 * @callback_method_impl{FNTMTIMERDEV,
7317 * Provides periodic MFINDEX wrap events. See 4.14.2.}
7318 */
7319static DECLCALLBACK(void) xhciR3WrapTimer(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, void *pvUser)
7320{
7321 PXHCI pThis = (PXHCI)pvUser;
7322 XHCI_EVENT_TRB ed;
7323 LogFlow(("xhciR3WrapTimer:\n"));
7324 RT_NOREF(hTimer);
7325
7326 /*
7327 * Post the MFINDEX Wrap event and rearm the timer. Only called
7328 * when the EWE bit is set in command register.
7329 */
7330 RT_ZERO(ed);
7331 ed.mwe.cc = XHCI_TCC_SUCCESS;
7332 ed.mwe.type = XHCI_TRB_MFIDX_WRAP;
7333 xhciR3WriteEvent(pDevIns, pThis, &ed, XHCI_PRIMARY_INTERRUPTER, false);
7334
7335 xhciSetWrapTimer(pDevIns, pThis);
7336}
7337
7338
7339/**
7340 * @callback_method_impl{FNSSMDEVSAVEEXEC}
7341 */
7342static DECLCALLBACK(int) xhciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
7343{
7344 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
7345 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
7346 uint32_t iPort;
7347 uint32_t iSlot;
7348 uint32_t iIntr;
7349
7350 LogFlow(("xhciR3SaveExec: \n"));
7351
7352 /* Save HC operational registers. */
7353 pHlp->pfnSSMPutU32(pSSM, pThis->cmd);
7354 pHlp->pfnSSMPutU32(pSSM, pThis->status);
7355 pHlp->pfnSSMPutU32(pSSM, pThis->dnctrl);
7356 pHlp->pfnSSMPutU64(pSSM, pThis->crcr);
7357 pHlp->pfnSSMPutU64(pSSM, pThis->dcbaap);
7358 pHlp->pfnSSMPutU32(pSSM, pThis->config);
7359
7360 /* Save HC non-register state. */
7361 pHlp->pfnSSMPutU64(pSSM, pThis->cmdr_dqp);
7362 pHlp->pfnSSMPutBool(pSSM, pThis->cmdr_ccs);
7363
7364 /* Save per-slot state. */
7365 pHlp->pfnSSMPutU32(pSSM, XHCI_NDS);
7366 for (iSlot = 0; iSlot < XHCI_NDS; ++iSlot)
7367 {
7368 pHlp->pfnSSMPutU8 (pSSM, pThis->aSlotState[iSlot]);
7369 pHlp->pfnSSMPutU32(pSSM, pThis->aBellsRung[iSlot]);
7370 }
7371
7372 /* Save root hub (port) state. */
7373 pHlp->pfnSSMPutU32(pSSM, XHCI_NDP_CFG(pThis));
7374 for (iPort = 0; iPort < XHCI_NDP_CFG(pThis); ++iPort)
7375 {
7376 pHlp->pfnSSMPutU32(pSSM, pThis->aPorts[iPort].portsc);
7377 pHlp->pfnSSMPutU32(pSSM, pThis->aPorts[iPort].portpm);
7378 }
7379
7380 /* Save interrupter state. */
7381 pHlp->pfnSSMPutU32(pSSM, XHCI_NINTR);
7382 for (iIntr = 0; iIntr < XHCI_NINTR; ++iIntr)
7383 {
7384 pHlp->pfnSSMPutU32(pSSM, pThis->aInterrupters[iIntr].iman);
7385 pHlp->pfnSSMPutU32(pSSM, pThis->aInterrupters[iIntr].imod);
7386 pHlp->pfnSSMPutU32(pSSM, pThis->aInterrupters[iIntr].erstsz);
7387 pHlp->pfnSSMPutU64(pSSM, pThis->aInterrupters[iIntr].erstba);
7388 pHlp->pfnSSMPutU64(pSSM, pThis->aInterrupters[iIntr].erdp);
7389 pHlp->pfnSSMPutU64(pSSM, pThis->aInterrupters[iIntr].erep);
7390 pHlp->pfnSSMPutU16(pSSM, pThis->aInterrupters[iIntr].erst_idx);
7391 pHlp->pfnSSMPutU16(pSSM, pThis->aInterrupters[iIntr].trb_count);
7392 pHlp->pfnSSMPutBool(pSSM, pThis->aInterrupters[iIntr].evtr_pcs);
7393 pHlp->pfnSSMPutBool(pSSM, pThis->aInterrupters[iIntr].ipe);
7394 }
7395
7396 /* Terminator marker. */
7397 pHlp->pfnSSMPutU32(pSSM, UINT32_MAX);
7398
7399 /* If not continuing after save, force HC into non-running state to avoid trouble later. */
7400 if (pHlp->pfnSSMHandleGetAfter(pSSM) != SSMAFTER_CONTINUE)
7401 pThis->cmd &= ~XHCI_CMD_RS;
7402
7403 return VINF_SUCCESS;
7404}
7405
7406
7407/**
7408 * @callback_method_impl{FNSSMDEVLOADEXEC}
7409 */
7410static DECLCALLBACK(int) xhciR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
7411{
7412 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
7413 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
7414 int rc;
7415 uint32_t cPorts;
7416 uint32_t iPort;
7417 uint32_t cSlots;
7418 uint32_t iSlot;
7419 uint32_t cIntrs;
7420 uint32_t iIntr;
7421 uint64_t u64Dummy;
7422 uint32_t u32Dummy;
7423 uint16_t u16Dummy;
7424 uint8_t u8Dummy;
7425 bool fDummy;
7426
7427 LogFlow(("xhciR3LoadExec:\n"));
7428
7429 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
7430 if (uVersion != XHCI_SAVED_STATE_VERSION)
7431 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
7432
7433 /* Load HC operational registers. */
7434 pHlp->pfnSSMGetU32(pSSM, &pThis->cmd);
7435 pHlp->pfnSSMGetU32(pSSM, &pThis->status);
7436 pHlp->pfnSSMGetU32(pSSM, &pThis->dnctrl);
7437 pHlp->pfnSSMGetU64(pSSM, &pThis->crcr);
7438 pHlp->pfnSSMGetU64(pSSM, &pThis->dcbaap);
7439 pHlp->pfnSSMGetU32(pSSM, &pThis->config);
7440
7441 /* Load HC non-register state. */
7442 pHlp->pfnSSMGetU64(pSSM, &pThis->cmdr_dqp);
7443 pHlp->pfnSSMGetBool(pSSM, &pThis->cmdr_ccs);
7444
7445 /* Load per-slot state. */
7446 rc = pHlp->pfnSSMGetU32(pSSM, &cSlots);
7447 AssertRCReturn(rc, rc);
7448 if (cSlots > 256) /* Sanity check. */
7449 return VERR_SSM_INVALID_STATE;
7450 for (iSlot = 0; iSlot < cSlots; ++iSlot)
7451 {
7452 /* Load only as many slots as we have; discard any extras. */
7453 if (iSlot < XHCI_NDS)
7454 {
7455 pHlp->pfnSSMGetU8 (pSSM, &pThis->aSlotState[iSlot]);
7456 pHlp->pfnSSMGetU32(pSSM, &pThis->aBellsRung[iSlot]);
7457 }
7458 else
7459 {
7460 pHlp->pfnSSMGetU8 (pSSM, &u8Dummy);
7461 pHlp->pfnSSMGetU32(pSSM, &u32Dummy);
7462 }
7463 }
7464
7465 /* Load root hub (port) state. */
7466 rc = pHlp->pfnSSMGetU32(pSSM, &cPorts);
7467 AssertRCReturn(rc, rc);
7468 if (cPorts > 256) /* Sanity check. */
7469 return VERR_SSM_INVALID_STATE;
7470
7471 for (iPort = 0; iPort < cPorts; ++iPort)
7472 {
7473 /* Load only as many ports as we have; discard any extras. */
7474 if (iPort < XHCI_NDP_CFG(pThis))
7475 {
7476 pHlp->pfnSSMGetU32(pSSM, &pThis->aPorts[iPort].portsc);
7477 pHlp->pfnSSMGetU32(pSSM, &pThis->aPorts[iPort].portpm);
7478 }
7479 else
7480 {
7481 pHlp->pfnSSMGetU32(pSSM, &u32Dummy);
7482 pHlp->pfnSSMGetU32(pSSM, &u32Dummy);
7483 }
7484 }
7485
7486 /* Load interrupter state. */
7487 rc = pHlp->pfnSSMGetU32(pSSM, &cIntrs);
7488 AssertRCReturn(rc, rc);
7489 if (cIntrs > 256) /* Sanity check. */
7490 return VERR_SSM_INVALID_STATE;
7491 for (iIntr = 0; iIntr < cIntrs; ++iIntr)
7492 {
7493 /* Load only as many interrupters as we have; discard any extras. */
7494 if (iIntr < XHCI_NINTR)
7495 {
7496 pHlp->pfnSSMGetU32(pSSM, &pThis->aInterrupters[iIntr].iman);
7497 pHlp->pfnSSMGetU32(pSSM, &pThis->aInterrupters[iIntr].imod);
7498 pHlp->pfnSSMGetU32(pSSM, &pThis->aInterrupters[iIntr].erstsz);
7499 pHlp->pfnSSMGetU64(pSSM, &pThis->aInterrupters[iIntr].erstba);
7500 pHlp->pfnSSMGetU64(pSSM, &pThis->aInterrupters[iIntr].erdp);
7501 pHlp->pfnSSMGetU64(pSSM, &pThis->aInterrupters[iIntr].erep);
7502 pHlp->pfnSSMGetU16(pSSM, &pThis->aInterrupters[iIntr].erst_idx);
7503 pHlp->pfnSSMGetU16(pSSM, &pThis->aInterrupters[iIntr].trb_count);
7504 pHlp->pfnSSMGetBool(pSSM, &pThis->aInterrupters[iIntr].evtr_pcs);
7505 pHlp->pfnSSMGetBool(pSSM, &pThis->aInterrupters[iIntr].ipe);
7506 }
7507 else
7508 {
7509 pHlp->pfnSSMGetU32(pSSM, &u32Dummy);
7510 pHlp->pfnSSMGetU32(pSSM, &u32Dummy);
7511 pHlp->pfnSSMGetU32(pSSM, &u32Dummy);
7512 pHlp->pfnSSMGetU64(pSSM, &u64Dummy);
7513 pHlp->pfnSSMGetU64(pSSM, &u64Dummy);
7514 pHlp->pfnSSMGetU64(pSSM, &u64Dummy);
7515 pHlp->pfnSSMGetU16(pSSM, &u16Dummy);
7516 pHlp->pfnSSMGetU16(pSSM, &u16Dummy);
7517 pHlp->pfnSSMGetBool(pSSM, &fDummy);
7518 pHlp->pfnSSMGetBool(pSSM, &fDummy);
7519 }
7520 }
7521
7522 /* Terminator marker. */
7523 rc = pHlp->pfnSSMGetU32(pSSM, &u32Dummy);
7524 AssertRCReturn(rc, rc);
7525 AssertReturn(u32Dummy == UINT32_MAX, VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
7526
7527 return rc;
7528}
7529
7530
7531/* -=-=-=-=- DBGF -=-=-=-=- */
7532
7533/**
7534 * @callback_method_impl{FNDBGFHANDLERDEV, Dumps xHCI state.}
7535 */
7536static DECLCALLBACK(void) xhciR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
7537{
7538 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
7539 RTGCPHYS GPAddr;
7540 bool fVerbose = false;
7541 unsigned i, j;
7542 uint64_t u64Val;
7543
7544 /* Parse arguments. */
7545 if (pszArgs)
7546 fVerbose = strstr(pszArgs, "verbose") != NULL;
7547
7548#ifdef XHCI_ERROR_INJECTION
7549 if (pszArgs && strstr(pszArgs, "dropintrhw"))
7550 {
7551 pHlp->pfnPrintf(pHlp, "Dropping the next interrupt (external)!\n");
7552 pThis->fDropIntrHw = true;
7553 return;
7554 }
7555
7556 if (pszArgs && strstr(pszArgs, "dropintrint"))
7557 {
7558 pHlp->pfnPrintf(pHlp, "Dropping the next interrupt (internal)!\n");
7559 pThis->fDropIntrIpe = true;
7560 return;
7561 }
7562
7563 if (pszArgs && strstr(pszArgs, "dropurb"))
7564 {
7565 pHlp->pfnPrintf(pHlp, "Dropping the next URB!\n");
7566 pThis->fDropUrb = true;
7567 return;
7568 }
7569
7570 if (pszArgs && strstr(pszArgs, "genintrhw"))
7571 {
7572 pHlp->pfnPrintf(pHlp, "Generating hardware interrupt (external)...\n");
7573 int iIntr = 0;
7574 PXHCIINTRPTR pIntr = &pThis->aInterrupters[iIntr & XHCI_INTR_MASK];
7575 xhciSetIntr(pDevIns, pThis, pIntr);
7576 return;
7577 }
7578
7579 if (pszArgs && strstr(pszArgs, "genintrint"))
7580 {
7581 pHlp->pfnPrintf(pHlp, "Generating hardware interrupt (internal)...\n");
7582 int iIntr = 0;
7583 PXHCIINTRPTR pIntr = &pThis->aInterrupters[iIntr & XHCI_INTR_MASK];
7584 xhciR3SetIntrPending(pDevIns, pThis, pIntr);
7585 return;
7586 }
7587
7588 if (pszArgs && strstr(pszArgs, "genintrhw"))
7589 {
7590 pHlp->pfnPrintf(pHlp, "Generating hardware interrupt (external)...\n");
7591 int iIntr = 0;
7592 PXHCIINTRPTR pIntr = &pThis->aInterrupters[iIntr & XHCI_INTR_MASK];
7593 xhciSetIntr(pDevIns, pThis, pIntr);
7594 return;
7595 }
7596
7597 if (pszArgs && strstr(pszArgs, "genintrint"))
7598 {
7599 pHlp->pfnPrintf(pHlp, "Generating hardware interrupt (internal)...\n");
7600 int iIntr = 0;
7601 PXHCIINTRPTR pIntr = &pThis->aInterrupters[iIntr & XHCI_INTR_MASK];
7602 xhciR3SetIntrPending(pDevIns, pThis, pIntr);
7603 return;
7604 }
7605
7606 if (pszArgs && strstr(pszArgs, "genportchgevt"))
7607 {
7608 pHlp->pfnPrintf(pHlp, "Generating port change event...\n");
7609 int iPort = 0;
7610 xhciR3GenPortChgEvent(pDevIns, pThis, IDX_TO_ID(iPort));
7611 return;
7612 }
7613
7614 if (pszArgs && strstr(pszArgs, "genmfiwrapevt"))
7615 {
7616 pHlp->pfnPrintf(pHlp, "Generating MF Index wrap event...\n");
7617 XHCI_EVENT_TRB ed;
7618 RT_ZERO(ed);
7619 ed.mwe.cc = XHCI_TCC_SUCCESS;
7620 ed.mwe.type = XHCI_TRB_MFIDX_WRAP;
7621 xhciR3WriteEvent(pDevIns, pThis, &ed, XHCI_PRIMARY_INTERRUPTER, false);
7622 return;
7623 }
7624
7625 if (pszArgs && strstr(pszArgs, "gendoorbell"))
7626 {
7627 pHlp->pfnPrintf(pHlp, "Generating doorbell ring..\n");
7628 xhciKickWorker(pDevIns, pThis, XHCI_JOB_DOORBELL, 0);
7629 return;
7630 }
7631#endif
7632
7633 /* Show basic information. */
7634 pHlp->pfnPrintf(pHlp,
7635 "%s#%d: PCI MMIO=%RGp IRQ=%u MSI=%s R0=%RTbool RC=%RTbool\n",
7636 pDevIns->pReg->szName,
7637 pDevIns->iInstance,
7638 PDMDevHlpMmioGetMappingAddress(pDevIns, pThis->hMmio),
7639 PCIDevGetInterruptLine(pDevIns->apPciDevs[0]),
7640#ifdef VBOX_WITH_MSI_DEVICES
7641 xhciIsMSIEnabled(pDevIns->apPciDevs[0]) ? "on" : "off",
7642#else
7643 "none",
7644#endif
7645 pDevIns->fR0Enabled, pDevIns->fRCEnabled);
7646
7647 /* Command register. */
7648 pHlp->pfnPrintf(pHlp, "USBCMD: %X:", pThis->cmd);
7649 if (pThis->cmd & XHCI_CMD_EU3S) pHlp->pfnPrintf(pHlp, " EU3S" );
7650 if (pThis->cmd & XHCI_CMD_EWE) pHlp->pfnPrintf(pHlp, " EWE" );
7651 if (pThis->cmd & XHCI_CMD_CRS) pHlp->pfnPrintf(pHlp, " CRS" );
7652 if (pThis->cmd & XHCI_CMD_CSS) pHlp->pfnPrintf(pHlp, " CSS" );
7653 if (pThis->cmd & XHCI_CMD_LCRST) pHlp->pfnPrintf(pHlp, " LCRST" );
7654 if (pThis->cmd & XHCI_CMD_HSEE) pHlp->pfnPrintf(pHlp, " HSEE" );
7655 if (pThis->cmd & XHCI_CMD_INTE) pHlp->pfnPrintf(pHlp, " INTE" );
7656 if (pThis->cmd & XHCI_CMD_HCRST) pHlp->pfnPrintf(pHlp, " HCRST" );
7657 if (pThis->cmd & XHCI_CMD_RS) pHlp->pfnPrintf(pHlp, " RS" );
7658 pHlp->pfnPrintf(pHlp, "\n");
7659
7660 /* Status register. */
7661 pHlp->pfnPrintf(pHlp, "USBSTS: %X:", pThis->status);
7662 if (pThis->status & XHCI_STATUS_HCH) pHlp->pfnPrintf(pHlp, " HCH" );
7663 if (pThis->status & XHCI_STATUS_HSE) pHlp->pfnPrintf(pHlp, " HSE" );
7664 if (pThis->status & XHCI_STATUS_EINT) pHlp->pfnPrintf(pHlp, " EINT" );
7665 if (pThis->status & XHCI_STATUS_PCD) pHlp->pfnPrintf(pHlp, " PCD" );
7666 if (pThis->status & XHCI_STATUS_SSS) pHlp->pfnPrintf(pHlp, " SSS" );
7667 if (pThis->status & XHCI_STATUS_RSS) pHlp->pfnPrintf(pHlp, " RSS" );
7668 if (pThis->status & XHCI_STATUS_SRE) pHlp->pfnPrintf(pHlp, " SRE" );
7669 if (pThis->status & XHCI_STATUS_CNR) pHlp->pfnPrintf(pHlp, " CNR" );
7670 if (pThis->status & XHCI_STATUS_HCE) pHlp->pfnPrintf(pHlp, " HCE" );
7671 pHlp->pfnPrintf(pHlp, "\n");
7672
7673 /* Device Notification Control and Configure registers. */
7674 pHlp->pfnPrintf(pHlp, "DNCTRL: %X CONFIG: %X (%u slots)\n", pThis->dnctrl, pThis->config, pThis->config);
7675
7676 /* Device Context Base Address Array. */
7677 GPAddr = pThis->dcbaap & XHCI_DCBAA_ADDR_MASK;
7678 pHlp->pfnPrintf(pHlp, "DCBAA ptr: %RGp\n", GPAddr);
7679 /* The DCBAA must be valid in 'run' state. */
7680 if (fVerbose && (pThis->cmd & XHCI_CMD_RS))
7681 {
7682 PDMDevHlpPCIPhysRead(pDevIns, GPAddr, &u64Val, sizeof(u64Val));
7683 pHlp->pfnPrintf(pHlp, " Scratchpad buffer: %RX64\n", u64Val);
7684 }
7685
7686 /* Command Ring Control Register. */
7687 pHlp->pfnPrintf(pHlp, "CRCR: %X:", pThis->crcr & ~XHCI_CRCR_ADDR_MASK);
7688 if (pThis->crcr & XHCI_CRCR_RCS) pHlp->pfnPrintf(pHlp, " RCS");
7689 if (pThis->crcr & XHCI_CRCR_CS) pHlp->pfnPrintf(pHlp, " CS" );
7690 if (pThis->crcr & XHCI_CRCR_CA) pHlp->pfnPrintf(pHlp, " CA" );
7691 if (pThis->crcr & XHCI_CRCR_CRR) pHlp->pfnPrintf(pHlp, " CRR");
7692 pHlp->pfnPrintf(pHlp, "\n");
7693 GPAddr = pThis->crcr & XHCI_CRCR_ADDR_MASK;
7694 pHlp->pfnPrintf(pHlp, "CRCR ptr : %RGp\n", GPAddr);
7695
7696 /* Interrupters. */
7697 if (fVerbose)
7698 {
7699 for (i = 0; i < RT_ELEMENTS(pThis->aInterrupters); ++i)
7700 {
7701 if (pThis->aInterrupters[i].erstsz)
7702 {
7703 XHCIINTRPTR *ir = &pThis->aInterrupters[i];
7704
7705 pHlp->pfnPrintf(pHlp, "Interrupter %d (IPE=%u)\n", i, ir->ipe);
7706
7707 /* The Interrupt Management Register. */
7708 pHlp->pfnPrintf(pHlp, " IMAN : %X:", ir->iman);
7709 if (ir->iman & XHCI_IMAN_IP) pHlp->pfnPrintf(pHlp, " IP");
7710 if (ir->iman & XHCI_IMAN_IE) pHlp->pfnPrintf(pHlp, " IE");
7711 pHlp->pfnPrintf(pHlp, "\n");
7712
7713 /* The Interrupt Moderation Register. */
7714 pHlp->pfnPrintf(pHlp, " IMOD : %X:", ir->imod);
7715 pHlp->pfnPrintf(pHlp, " IMODI=%u", ir->imod & XHCI_IMOD_IMODI_MASK);
7716 pHlp->pfnPrintf(pHlp, " IMODC=%u", (ir->imod & XHCI_IMOD_IMODC_MASK) >> XHCI_IMOD_IMODC_SHIFT);
7717 pHlp->pfnPrintf(pHlp, "\n");
7718
7719 pHlp->pfnPrintf(pHlp, " ERSTSZ: %X\n", ir->erstsz);
7720 pHlp->pfnPrintf(pHlp, " ERSTBA: %RGp\n", (RTGCPHYS)ir->erstba);
7721
7722 pHlp->pfnPrintf(pHlp, " ERDP : %RGp:", (RTGCPHYS)ir->erdp);
7723 pHlp->pfnPrintf(pHlp, " EHB=%u", !!(ir->erdp & XHCI_ERDP_EHB));
7724 pHlp->pfnPrintf(pHlp, " DESI=%u", ir->erdp & XHCI_ERDP_DESI_MASK);
7725 pHlp->pfnPrintf(pHlp, " ptr=%RGp", ir->erdp & XHCI_ERDP_ADDR_MASK);
7726 pHlp->pfnPrintf(pHlp, "\n");
7727
7728 pHlp->pfnPrintf(pHlp, " EREP : %RGp", ir->erep);
7729 pHlp->pfnPrintf(pHlp, " Free TRBs in seg=%u", ir->trb_count);
7730 pHlp->pfnPrintf(pHlp, "\n");
7731 }
7732 }
7733 }
7734
7735 /* Port control/status. */
7736 for (i = 0; i < XHCI_NDP_CFG(pThis); ++i)
7737 {
7738 PXHCIHUBPORT p = &pThis->aPorts[i];
7739
7740 pHlp->pfnPrintf(pHlp, "Port %02u (USB%c): ", IDX_TO_ID(i), IS_USB3_PORT_IDX_SHR(pThis, i) ? '3' : '2');
7741
7742 /* Port Status register. */
7743 pHlp->pfnPrintf(pHlp, "PORTSC: %8X:", p->portsc);
7744 if (p->portsc & XHCI_PORT_CCS) pHlp->pfnPrintf(pHlp, " CCS" );
7745 if (p->portsc & XHCI_PORT_PED) pHlp->pfnPrintf(pHlp, " PED" );
7746 if (p->portsc & XHCI_PORT_OCA) pHlp->pfnPrintf(pHlp, " OCA" );
7747 if (p->portsc & XHCI_PORT_PR ) pHlp->pfnPrintf(pHlp, " PR" );
7748 pHlp->pfnPrintf(pHlp, " PLS=%u", (p->portsc & XHCI_PORT_PLS_MASK) >> XHCI_PORT_PLS_SHIFT);
7749 if (p->portsc & XHCI_PORT_PP ) pHlp->pfnPrintf(pHlp, " PP" );
7750 pHlp->pfnPrintf(pHlp, " SPD=%u", (p->portsc & XHCI_PORT_SPD_MASK) >> XHCI_PORT_SPD_SHIFT);
7751 if (p->portsc & XHCI_PORT_LWS) pHlp->pfnPrintf(pHlp, " LWS" );
7752 if (p->portsc & XHCI_PORT_CSC) pHlp->pfnPrintf(pHlp, " CSC" );
7753 if (p->portsc & XHCI_PORT_PEC) pHlp->pfnPrintf(pHlp, " PEC" );
7754 if (p->portsc & XHCI_PORT_WRC) pHlp->pfnPrintf(pHlp, " WRC" );
7755 if (p->portsc & XHCI_PORT_OCC) pHlp->pfnPrintf(pHlp, " OCC" );
7756 if (p->portsc & XHCI_PORT_PRC) pHlp->pfnPrintf(pHlp, " PRC" );
7757 if (p->portsc & XHCI_PORT_PLC) pHlp->pfnPrintf(pHlp, " PLC" );
7758 if (p->portsc & XHCI_PORT_CEC) pHlp->pfnPrintf(pHlp, " CEC" );
7759 if (p->portsc & XHCI_PORT_CAS) pHlp->pfnPrintf(pHlp, " CAS" );
7760 if (p->portsc & XHCI_PORT_WCE) pHlp->pfnPrintf(pHlp, " WCE" );
7761 if (p->portsc & XHCI_PORT_WDE) pHlp->pfnPrintf(pHlp, " WDE" );
7762 if (p->portsc & XHCI_PORT_WOE) pHlp->pfnPrintf(pHlp, " WOE" );
7763 if (p->portsc & XHCI_PORT_DR ) pHlp->pfnPrintf(pHlp, " DR" );
7764 if (p->portsc & XHCI_PORT_WPR) pHlp->pfnPrintf(pHlp, " WPR" );
7765 pHlp->pfnPrintf(pHlp, "\n");
7766 }
7767
7768 /* Device contexts. */
7769 if (fVerbose && (pThis->cmd & XHCI_CMD_RS))
7770 {
7771 for (i = 0; i < XHCI_NDS; ++i)
7772 {
7773 if (pThis->aSlotState[i] > XHCI_DEVSLOT_EMPTY)
7774 {
7775 RTGCPHYS GCPhysSlot;
7776 XHCI_DEV_CTX ctxDevice;
7777 XHCI_SLOT_CTX ctxSlot;
7778 const char *pcszDesc;
7779 uint8_t uSlotID = IDX_TO_ID(i);
7780
7781 /* Find the slot address/ */
7782 GCPhysSlot = xhciR3FetchDevCtxAddr(pDevIns, pThis, uSlotID);
7783 pHlp->pfnPrintf(pHlp, "Slot %d (device context @ %RGp)\n", uSlotID, GCPhysSlot);
7784 if (!GCPhysSlot)
7785 {
7786 pHlp->pfnPrintf(pHlp, "Bad context address, skipping!\n");
7787 continue;
7788 }
7789
7790 /* Just read in the whole lot and sort in which contexts are valid later. */
7791 PDMDevHlpPCIPhysRead(pDevIns, GCPhysSlot, &ctxDevice, sizeof(ctxDevice));
7792
7793 ctxSlot = ctxDevice.entry[0].sc;
7794 pcszDesc = ctxSlot.slot_state < RT_ELEMENTS(g_apszSltStates) ? g_apszSltStates[ctxSlot.slot_state] : "BAD!!!";
7795 pHlp->pfnPrintf(pHlp, " Speed:%u Entries:%u RhPort:%u", ctxSlot.speed, ctxSlot.ctx_ent, ctxSlot.rh_port);
7796 pHlp->pfnPrintf(pHlp, " Address:%u State:%s \n", ctxSlot.dev_addr, pcszDesc);
7797 pHlp->pfnPrintf(pHlp, " Doorbells:%08X\n", pThis->aBellsRung[ID_TO_IDX(uSlotID)]);
7798
7799 /* Endpoint contexts. */
7800 for (j = 1; j <= ctxSlot.ctx_ent; ++j)
7801 {
7802 XHCI_EP_CTX ctxEP = ctxDevice.entry[j].ep;
7803
7804 /* Skip disabled endpoints -- they may be unused and do not
7805 * contain valid data in any case.
7806 */
7807 if (ctxEP.ep_state == XHCI_EPST_DISABLED)
7808 continue;
7809
7810 pcszDesc = ctxEP.ep_state < RT_ELEMENTS(g_apszEpStates) ? g_apszEpStates[ctxEP.ep_state] : "BAD!!!";
7811 pHlp->pfnPrintf(pHlp, " Endpoint DCI %u State:%s", j, pcszDesc);
7812 pcszDesc = ctxEP.ep_type < RT_ELEMENTS(g_apszEpTypes) ? g_apszEpTypes[ctxEP.ep_type] : "BAD!!!";
7813 pHlp->pfnPrintf(pHlp, " Type:%s\n",pcszDesc);
7814
7815 pHlp->pfnPrintf(pHlp, " Mult:%u MaxPStreams:%u LSA:%u Interval:%u\n",
7816 ctxEP.mult, ctxEP.maxps, ctxEP.lsa, ctxEP.interval);
7817 pHlp->pfnPrintf(pHlp, " CErr:%u HID:%u MaxPS:%u MaxBS:%u",
7818 ctxEP.c_err, ctxEP.hid, ctxEP.max_pkt_sz, ctxEP.max_brs_sz);
7819 pHlp->pfnPrintf(pHlp, " AvgTRBLen:%u MaxESIT:%u",
7820 ctxEP.avg_trb_len, ctxEP.max_esit);
7821 pHlp->pfnPrintf(pHlp, " LastFrm:%u IFC:%u LastCC:%u\n",
7822 ctxEP.last_frm, ctxEP.ifc, ctxEP.last_cc);
7823 pHlp->pfnPrintf(pHlp, " TRDP:%RGp DCS:%u\n", (RTGCPHYS)(ctxEP.trdp & XHCI_TRDP_ADDR_MASK),
7824 ctxEP.trdp & XHCI_TRDP_DCS_MASK);
7825 pHlp->pfnPrintf(pHlp, " TREP:%RGp DCS:%u\n", (RTGCPHYS)(ctxEP.trep & XHCI_TRDP_ADDR_MASK),
7826 ctxEP.trep & XHCI_TRDP_DCS_MASK);
7827 }
7828 }
7829 }
7830 }
7831}
7832
7833
7834/**
7835 * @interface_method_impl{PDMDEVREG,pfnReset}
7836 */
7837static DECLCALLBACK(void) xhciR3Reset(PPDMDEVINS pDevIns)
7838{
7839 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
7840 PXHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PXHCICC);
7841 LogFlow(("xhciR3Reset:\n"));
7842
7843 /*
7844 * There is no distinction between cold boot, warm reboot and software reboots,
7845 * all of these are treated as cold boots. We are also doing the initialization
7846 * job of a BIOS or SMM driver.
7847 *
7848 * Important: Don't confuse UsbReset with hardware reset. Hardware reset is
7849 * just one way of getting into the UsbReset state.
7850 */
7851
7852 /* Set the HC Halted bit now to prevent completion callbacks from running
7853 *(there is really no point when resetting).
7854 */
7855 ASMAtomicOrU32(&pThis->status, XHCI_STATUS_HCH);
7856
7857 xhciR3BusStop(pDevIns, pThis, pThisCC);
7858 xhciR3DoReset(pThis, pThisCC, XHCI_USB_RESET, true /* reset devices */);
7859}
7860
7861
7862/**
7863 * @interface_method_impl{PDMDEVREG,pfnDestruct}
7864 */
7865static DECLCALLBACK(int) xhciR3Destruct(PPDMDEVINS pDevIns)
7866{
7867 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
7868 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
7869 PXHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PXHCICC);
7870 LogFlow(("xhciR3Destruct:\n"));
7871
7872 /*
7873 * Destroy interrupter locks.
7874 */
7875 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aInterrupters); ++i)
7876 {
7877 if (PDMDevHlpCritSectIsInitialized(pDevIns, &pThis->aInterrupters[i].lock))
7878 PDMDevHlpCritSectDelete(pDevIns, &pThis->aInterrupters[i].lock);
7879 }
7880
7881 /*
7882 * Clean up the worker thread and associated machinery.
7883 */
7884 if (pThis->hEvtProcess != NIL_SUPSEMEVENT)
7885 {
7886 PDMDevHlpSUPSemEventClose(pDevIns, pThis->hEvtProcess);
7887 pThis->hEvtProcess = NIL_SUPSEMEVENT;
7888 }
7889 if (RTCritSectIsInitialized(&pThisCC->CritSectThrd))
7890 RTCritSectDelete(&pThisCC->CritSectThrd);
7891
7892 return VINF_SUCCESS;
7893}
7894
7895
7896/**
7897 * Worker for xhciR3Construct that registers a LUN (USB root hub).
7898 */
7899static int xhciR3RegisterHub(PPDMDEVINS pDevIns, PXHCIROOTHUBR3 pRh, int iLun, const char *pszDesc)
7900{
7901 int rc = PDMDevHlpDriverAttach(pDevIns, iLun, &pRh->IBase, &pRh->pIBase, pszDesc);
7902 AssertMsgRCReturn(rc, ("Configuration error: Failed to attach root hub driver to LUN #%d! (%Rrc)\n", iLun, rc), rc);
7903
7904 pRh->pIRhConn = PDMIBASE_QUERY_INTERFACE(pRh->pIBase, VUSBIROOTHUBCONNECTOR);
7905 AssertMsgReturn(pRh->pIRhConn,
7906 ("Configuration error: The driver doesn't provide the VUSBIROOTHUBCONNECTOR interface!\n"),
7907 VERR_PDM_MISSING_INTERFACE);
7908
7909 /* Set URB parameters. */
7910 rc = VUSBIRhSetUrbParams(pRh->pIRhConn, sizeof(VUSBURBHCIINT), 0);
7911 if (RT_FAILURE(rc))
7912 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("OHCI: Failed to set URB parameters"));
7913
7914 return rc;
7915}
7916
7917/**
7918 * @interface_method_impl{PDMDEVREG,pfnConstruct,XHCI
7919 * constructor}
7920 */
7921static DECLCALLBACK(int) xhciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
7922{
7923 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
7924 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
7925 PXHCICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PXHCICC);
7926 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
7927 uint32_t cUsb2Ports;
7928 uint32_t cUsb3Ports;
7929 int rc;
7930 LogFlow(("xhciR3Construct:\n"));
7931 RT_NOREF(iInstance);
7932
7933 /*
7934 * Initialize data so the destructor runs smoothly.
7935 */
7936 pThis->hEvtProcess = NIL_SUPSEMEVENT;
7937
7938 /*
7939 * Validate and read configuration.
7940 */
7941 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "USB2Ports|USB3Ports|ChipType", "");
7942
7943 /* Number of USB2 ports option. */
7944 rc = pHlp->pfnCFGMQueryU32Def(pCfg, "USB2Ports", &cUsb2Ports, XHCI_NDP_20_DEFAULT);
7945 if (RT_FAILURE(rc))
7946 return PDMDEV_SET_ERROR(pDevIns, rc,
7947 N_("xHCI configuration error: failed to read USB2Ports as integer"));
7948
7949 if (cUsb2Ports == 0 || cUsb2Ports > XHCI_NDP_MAX)
7950 return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
7951 N_("xHCI configuration error: USB2Ports must be in range [%u,%u]"),
7952 1, XHCI_NDP_MAX);
7953
7954 /* Number of USB3 ports option. */
7955 rc = pHlp->pfnCFGMQueryU32Def(pCfg, "USB3Ports", &cUsb3Ports, XHCI_NDP_30_DEFAULT);
7956 if (RT_FAILURE(rc))
7957 return PDMDEV_SET_ERROR(pDevIns, rc,
7958 N_("xHCI configuration error: failed to read USB3Ports as integer"));
7959
7960 if (cUsb3Ports == 0 || cUsb3Ports > XHCI_NDP_MAX)
7961 return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
7962 N_("xHCI configuration error: USB3Ports must be in range [%u,%u]"),
7963 1, XHCI_NDP_MAX);
7964
7965 /* Check that the total number of ports is within limits.*/
7966 if (cUsb2Ports + cUsb3Ports > XHCI_NDP_MAX)
7967 return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
7968 N_("xHCI configuration error: USB2Ports + USB3Ports must be in range [%u,%u]"),
7969 1, XHCI_NDP_MAX);
7970
7971 /* Determine the model. */
7972 char szChipType[16];
7973 rc = pHlp->pfnCFGMQueryStringDef(pCfg, "ChipType", &szChipType[0], sizeof(szChipType), "PantherPoint");
7974 if (RT_FAILURE(rc))
7975 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
7976 N_("xHCI configuration error: Querying \"ChipType\" as string failed"));
7977
7978 /*
7979 * The default model is Panther Point (8086:1E31), Intel's first and most widely
7980 * supported xHCI implementation. For debugging, the Lynx Point (8086:8C31) model
7981 * can be selected. These two models work with the 7 Series and 8 Series Intel xHCI
7982 * drivers for Windows 7, respectively. There is no functional difference.
7983 * For Windows XP support, it's also possible to present a Renesas uPD720201 xHC;
7984 * this is an evolution of the original NEC xHCI chip.
7985 */
7986 bool fChipLynxPoint = false;
7987 bool fChipRenesas = false;
7988 if (!strcmp(szChipType, "PantherPoint"))
7989 fChipLynxPoint = false;
7990 else if (!strcmp(szChipType, "LynxPoint"))
7991 fChipLynxPoint = true;
7992 else if (!strcmp(szChipType, "uPD720201"))
7993 fChipRenesas = true;
7994 else
7995 return PDMDevHlpVMSetError(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, RT_SRC_POS,
7996 N_("xHCI configuration error: The \"ChipType\" value \"%s\" is unsupported"), szChipType);
7997
7998 LogFunc(("cUsb2Ports=%u cUsb3Ports=%u szChipType=%s (%d,%d) fR0Enabled=%d fRCEnabled=%d\n", cUsb2Ports, cUsb3Ports,
7999 szChipType, fChipLynxPoint, fChipRenesas, pDevIns->fR0Enabled, pDevIns->fRCEnabled));
8000
8001 /* Set up interrupter locks. */
8002 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aInterrupters); ++i)
8003 {
8004 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->aInterrupters[i].lock, RT_SRC_POS, "xHCIIntr#%u", i);
8005 if (RT_FAILURE(rc))
8006 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
8007 N_("xHCI: Failed to create critical section for interrupter %u"), i);
8008 pThis->aInterrupters[i].index = i; /* Stash away index, mostly for logging/debugging. */
8009 }
8010
8011
8012 /*
8013 * Init instance data.
8014 */
8015 pThisCC->pDevIns = pDevIns;
8016
8017 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
8018 if (fChipRenesas)
8019 {
8020 pThis->erst_addr_mask = NEC_ERST_ADDR_MASK;
8021 PCIDevSetVendorId(pPciDev, 0x1912);
8022 PCIDevSetDeviceId(pPciDev, 0x0014);
8023 PCIDevSetByte(pPciDev, VBOX_PCI_REVISION_ID, 0x02);
8024 }
8025 else
8026 {
8027 pThis->erst_addr_mask = XHCI_ERST_ADDR_MASK;
8028 PCIDevSetVendorId(pPciDev, 0x8086);
8029 if (fChipLynxPoint)
8030 PCIDevSetDeviceId(pPciDev, 0x8C31); /* Lynx Point / 8 Series */
8031 else
8032 PCIDevSetDeviceId(pPciDev, 0x1E31); /* Panther Point / 7 Series */
8033 }
8034
8035 PCIDevSetClassProg(pPciDev, 0x30); /* xHCI */
8036 PCIDevSetClassSub(pPciDev, 0x03); /* USB 3.0 */
8037 PCIDevSetClassBase(pPciDev, 0x0C);
8038 PCIDevSetInterruptPin(pPciDev, 0x01);
8039#ifdef VBOX_WITH_MSI_DEVICES
8040 PCIDevSetStatus(pPciDev, VBOX_PCI_STATUS_CAP_LIST);
8041 PCIDevSetCapabilityList(pPciDev, 0x80);
8042#endif
8043 PDMPciDevSetByte(pPciDev, 0x60, 0x20); /* serial bus release number register; 0x20 = USB 2.0 */
8044 /** @todo USBLEGSUP & USBLEGCTLSTS? Legacy interface for the BIOS (0xEECP+0 & 0xEECP+4) */
8045
8046 pThis->cTotalPorts = (uint8_t)(cUsb2Ports + cUsb3Ports);
8047
8048 /* Set up the USB2 root hub interface. */
8049 pThis->cUsb2Ports = (uint8_t)cUsb2Ports;
8050 pThisCC->RootHub2.pXhciR3 = pThisCC;
8051 pThisCC->RootHub2.cPortsImpl = cUsb2Ports;
8052 pThisCC->RootHub2.uPortBase = 0;
8053 pThisCC->RootHub2.IBase.pfnQueryInterface = xhciR3RhQueryInterface;
8054 pThisCC->RootHub2.IRhPort.pfnGetAvailablePorts = xhciR3RhGetAvailablePorts;
8055 pThisCC->RootHub2.IRhPort.pfnGetUSBVersions = xhciR3RhGetUSBVersions2;
8056 pThisCC->RootHub2.IRhPort.pfnAttach = xhciR3RhAttach;
8057 pThisCC->RootHub2.IRhPort.pfnDetach = xhciR3RhDetach;
8058 pThisCC->RootHub2.IRhPort.pfnReset = xhciR3RhReset;
8059 pThisCC->RootHub2.IRhPort.pfnXferCompletion = xhciR3RhXferCompletion;
8060 pThisCC->RootHub2.IRhPort.pfnXferError = xhciR3RhXferError;
8061
8062 /* Now the USB3 root hub interface. */
8063 pThis->cUsb3Ports = (uint8_t)cUsb3Ports;
8064 pThisCC->RootHub3.pXhciR3 = pThisCC;
8065 pThisCC->RootHub3.cPortsImpl = cUsb3Ports;
8066 pThisCC->RootHub3.uPortBase = XHCI_NDP_USB2(pThisCC);
8067 pThisCC->RootHub3.IBase.pfnQueryInterface = xhciR3RhQueryInterface;
8068 pThisCC->RootHub3.IRhPort.pfnGetAvailablePorts = xhciR3RhGetAvailablePorts;
8069 pThisCC->RootHub3.IRhPort.pfnGetUSBVersions = xhciR3RhGetUSBVersions3;
8070 pThisCC->RootHub3.IRhPort.pfnAttach = xhciR3RhAttach;
8071 pThisCC->RootHub3.IRhPort.pfnDetach = xhciR3RhDetach;
8072 pThisCC->RootHub3.IRhPort.pfnReset = xhciR3RhReset;
8073 pThisCC->RootHub3.IRhPort.pfnXferCompletion = xhciR3RhXferCompletion;
8074 pThisCC->RootHub3.IRhPort.pfnXferError = xhciR3RhXferError;
8075
8076 /* USB LED */
8077 pThisCC->RootHub2.Led.u32Magic = PDMLED_MAGIC;
8078 pThisCC->RootHub3.Led.u32Magic = PDMLED_MAGIC;
8079 pThisCC->IBase.pfnQueryInterface = xhciR3QueryStatusInterface;
8080 pThisCC->ILeds.pfnQueryStatusLed = xhciR3QueryStatusLed;
8081
8082 /* Initialize the capability registers */
8083 pThis->cap_length = XHCI_CAPS_REG_SIZE;
8084 pThis->hci_version = 0x100; /* Version 1.0 */
8085 pThis->hcs_params1 = (XHCI_NDP_CFG(pThis) << 24) | (XHCI_NINTR << 8) | XHCI_NDS;
8086 pThis->hcs_params2 = (XHCI_ERSTMAX_LOG2 << 4) | XHCI_IST;
8087 pThis->hcs_params3 = (4 << 16) | 1; /* Matches Intel 7 Series xHCI. */
8088 /* Note: The Intel 7 Series xHCI does not have port power control (XHCI_HCC_PPC). */
8089 pThis->hcc_params = ((XHCI_XECP_OFFSET >> 2) << XHCI_HCC_XECP_SHIFT); /// @todo other fields
8090 pThis->dbell_off = XHCI_DOORBELL_OFFSET;
8091 pThis->rts_off = XHCI_RTREG_OFFSET;
8092
8093 /*
8094 * Set up extended capabilities.
8095 */
8096 rc = xhciR3BuildExtCaps(pThis, pThisCC);
8097 AssertRCReturn(rc, rc);
8098
8099 /*
8100 * Register PCI device and I/O region.
8101 */
8102 rc = PDMDevHlpPCIRegister(pDevIns, pPciDev);
8103 AssertRCReturn(rc, rc);
8104
8105#ifdef VBOX_WITH_MSI_DEVICES
8106 PDMMSIREG MsiReg;
8107 RT_ZERO(MsiReg);
8108 MsiReg.cMsiVectors = 1;
8109 MsiReg.iMsiCapOffset = XHCI_PCI_MSI_CAP_OFS;
8110 MsiReg.iMsiNextOffset = 0x00;
8111 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg);
8112 if (RT_FAILURE (rc))
8113 {
8114 PCIDevSetCapabilityList(pPciDev, 0x0);
8115 /* That's OK, we can work without MSI */
8116 }
8117#endif
8118
8119 rc = PDMDevHlpPCIIORegionCreateMmio(pDevIns, 0, XHCI_MMIO_SIZE, PCI_ADDRESS_SPACE_MEM,
8120 xhciMmioWrite, xhciMmioRead, NULL,
8121 IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_DWORD_ZEROED
8122 /*| IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_WRITE*/,
8123 "USB xHCI", &pThis->hMmio);
8124 AssertRCReturn(rc, rc);
8125
8126 /*
8127 * Register the saved state data unit.
8128 */
8129 rc = PDMDevHlpSSMRegisterEx(pDevIns, XHCI_SAVED_STATE_VERSION, sizeof(*pThis), NULL,
8130 NULL, NULL, NULL,
8131 NULL, xhciR3SaveExec, NULL,
8132 NULL, xhciR3LoadExec, NULL);
8133 AssertRCReturn(rc, rc);
8134
8135 /*
8136 * Attach to the VBox USB RootHub Driver on LUN #0 (USB3 root hub).
8137 * NB: USB3 must come first so that emulated devices which support both USB2
8138 * and USB3 are attached to the USB3 hub.
8139 */
8140 rc = xhciR3RegisterHub(pDevIns, &pThisCC->RootHub3, 0, "RootHubUSB3");
8141 AssertRCReturn(rc, rc);
8142
8143 /*
8144 * Attach to the VBox USB RootHub Driver on LUN #1 (USB2 root hub).
8145 */
8146 rc = xhciR3RegisterHub(pDevIns, &pThisCC->RootHub2, 1, "RootHubUSB2");
8147 AssertRCReturn(rc, rc);
8148
8149 /*
8150 * Attach the status LED (optional).
8151 */
8152 PPDMIBASE pBase;
8153 rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pThisCC->IBase, &pBase, "Status Port");
8154 if (RT_SUCCESS(rc))
8155 pThisCC->pLedsConnector = PDMIBASE_QUERY_INTERFACE(pBase, PDMILEDCONNECTORS);
8156 else if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
8157 {
8158 AssertMsgFailed(("xHCI: Failed to attach to status driver. rc=%Rrc\n", rc));
8159 return PDMDEV_SET_ERROR(pDevIns, rc, N_("xHCI cannot attach to status driver"));
8160 }
8161
8162 /*
8163 * Create the MFINDEX wrap event timer.
8164 */
8165 rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL, xhciR3WrapTimer, pThis,
8166 TMTIMER_FLAGS_NO_CRIT_SECT | TMTIMER_FLAGS_RING0, "xHCI MFINDEX Wrap", &pThis->hWrapTimer);
8167 AssertRCReturn(rc, rc);
8168
8169 /*
8170 * Set up the worker thread.
8171 */
8172 rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->hEvtProcess);
8173 AssertLogRelRCReturn(rc, rc);
8174
8175 rc = RTCritSectInit(&pThisCC->CritSectThrd);
8176 AssertLogRelRCReturn(rc, rc);
8177
8178 rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->pWorkerThread, pThis, xhciR3WorkerLoop, xhciR3WorkerWakeUp,
8179 0, RTTHREADTYPE_IO, "xHCI");
8180 AssertLogRelRCReturn(rc, rc);
8181
8182 /*
8183 * Do a hardware reset.
8184 */
8185 xhciR3DoReset(pThis, pThisCC, XHCI_USB_RESET, false /* don't reset devices */);
8186
8187# ifdef VBOX_WITH_STATISTICS
8188 /*
8189 * Register statistics.
8190 */
8191 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatErrorIsocUrbs, STAMTYPE_COUNTER, "IsocUrbsErr", STAMUNIT_OCCURENCES, "Isoch URBs completed w/error.");
8192 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatErrorIsocPkts, STAMTYPE_COUNTER, "IsocPktsErr", STAMUNIT_OCCURENCES, "Isoch packets completed w/error.");
8193 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatEventsWritten, STAMTYPE_COUNTER, "EventsWritten", STAMUNIT_OCCURENCES, "Event TRBs delivered.");
8194 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatEventsDropped, STAMTYPE_COUNTER, "EventsDropped", STAMUNIT_OCCURENCES, "Event TRBs dropped (HC stopped).");
8195 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIntrsPending, STAMTYPE_COUNTER, "IntrsPending", STAMUNIT_OCCURENCES, "Requests to set the IP bit.");
8196 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIntrsSet, STAMTYPE_COUNTER, "IntrsSet", STAMUNIT_OCCURENCES, "Actual interrupts delivered.");
8197 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIntrsNotSet, STAMTYPE_COUNTER, "IntrsNotSet", STAMUNIT_OCCURENCES, "Interrupts not delivered/disabled.");
8198 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatIntrsCleared, STAMTYPE_COUNTER, "IntrsCleared", STAMUNIT_OCCURENCES, "Interrupts cleared by guest.");
8199 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTRBsPerCtlUrb, STAMTYPE_COUNTER, "UrbTrbsCtl", STAMUNIT_COUNT, "TRBs per one control URB.");
8200 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTRBsPerDtaUrb, STAMTYPE_COUNTER, "UrbTrbsDta", STAMUNIT_COUNT, "TRBs per one data (bulk/intr) URB.");
8201 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatTRBsPerIsoUrb, STAMTYPE_COUNTER, "UrbTrbsIso", STAMUNIT_COUNT, "TRBs per one isochronous URB.");
8202 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatUrbSizeCtrl, STAMTYPE_COUNTER, "UrbSizeCtl", STAMUNIT_COUNT, "Size of a control URB in bytes.");
8203 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatUrbSizeData, STAMTYPE_COUNTER, "UrbSizeDta", STAMUNIT_COUNT, "Size of a data (bulk/intr) URB in bytes.");
8204 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatUrbSizeIsoc, STAMTYPE_COUNTER, "UrbSizeIso", STAMUNIT_COUNT, "Size of an isochronous URB in bytes.");
8205
8206 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdCaps, STAMTYPE_COUNTER, "Regs/RdCaps", STAMUNIT_COUNT, "");
8207 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdCmdRingCtlHi, STAMTYPE_COUNTER, "Regs/RdCmdRingCtlHi", STAMUNIT_COUNT, "");
8208 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdCmdRingCtlLo, STAMTYPE_COUNTER, "Regs/RdCmdRingCtlLo", STAMUNIT_COUNT, "");
8209 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdConfig, STAMTYPE_COUNTER, "Regs/RdConfig", STAMUNIT_COUNT, "");
8210 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdDevCtxBaapHi, STAMTYPE_COUNTER, "Regs/RdDevCtxBaapHi", STAMUNIT_COUNT, "");
8211 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdDevCtxBaapLo, STAMTYPE_COUNTER, "Regs/RdDevCtxBaapLo", STAMUNIT_COUNT, "");
8212 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdDevNotifyCtrl, STAMTYPE_COUNTER, "Regs/RdDevNotifyCtrl", STAMUNIT_COUNT, "");
8213 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdDoorBell, STAMTYPE_COUNTER, "Regs/RdDoorBell", STAMUNIT_COUNT, "");
8214 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdEvtRingDeqPtrHi, STAMTYPE_COUNTER, "Regs/RdEvtRingDeqPtrHi", STAMUNIT_COUNT, "");
8215 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdEvtRingDeqPtrLo, STAMTYPE_COUNTER, "Regs/RdEvtRingDeqPtrLo", STAMUNIT_COUNT, "");
8216 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdEvtRsTblBaseHi, STAMTYPE_COUNTER, "Regs/RdEvtRsTblBaseHi", STAMUNIT_COUNT, "");
8217 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdEvtRsTblBaseLo, STAMTYPE_COUNTER, "Regs/RdEvtRsTblBaseLo", STAMUNIT_COUNT, "");
8218 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdEvtRstblSize, STAMTYPE_COUNTER, "Regs/RdEvtRstblSize", STAMUNIT_COUNT, "");
8219 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdEvtRsvd, STAMTYPE_COUNTER, "Regs/RdEvtRsvd", STAMUNIT_COUNT, "");
8220 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdIntrMgmt, STAMTYPE_COUNTER, "Regs/RdIntrMgmt", STAMUNIT_COUNT, "");
8221 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdIntrMod, STAMTYPE_COUNTER, "Regs/RdIntrMod", STAMUNIT_COUNT, "");
8222 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdMfIndex, STAMTYPE_COUNTER, "Regs/RdMfIndex", STAMUNIT_COUNT, "");
8223 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdPageSize, STAMTYPE_COUNTER, "Regs/RdPageSize", STAMUNIT_COUNT, "");
8224 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdPortLinkInfo, STAMTYPE_COUNTER, "Regs/RdPortLinkInfo", STAMUNIT_COUNT, "");
8225 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdPortPowerMgmt, STAMTYPE_COUNTER, "Regs/RdPortPowerMgmt", STAMUNIT_COUNT, "");
8226 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdPortRsvd, STAMTYPE_COUNTER, "Regs/RdPortRsvd", STAMUNIT_COUNT, "");
8227 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdPortStatusCtrl, STAMTYPE_COUNTER, "Regs/RdPortStatusCtrl", STAMUNIT_COUNT, "");
8228 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdUsbCmd, STAMTYPE_COUNTER, "Regs/RdUsbCmd", STAMUNIT_COUNT, "");
8229 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdUsbSts, STAMTYPE_COUNTER, "Regs/RdUsbSts", STAMUNIT_COUNT, "");
8230 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatRdUnknown, STAMTYPE_COUNTER, "Regs/RdUnknown", STAMUNIT_COUNT, "");
8231
8232 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrCmdRingCtlHi, STAMTYPE_COUNTER, "Regs/WrCmdRingCtlHi", STAMUNIT_COUNT, "");
8233 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrCmdRingCtlLo, STAMTYPE_COUNTER, "Regs/WrCmdRingCtlLo", STAMUNIT_COUNT, "");
8234 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrConfig, STAMTYPE_COUNTER, "Regs/WrConfig", STAMUNIT_COUNT, "");
8235 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrDevCtxBaapHi, STAMTYPE_COUNTER, "Regs/WrDevCtxBaapHi", STAMUNIT_COUNT, "");
8236 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrDevCtxBaapLo, STAMTYPE_COUNTER, "Regs/WrDevCtxBaapLo", STAMUNIT_COUNT, "");
8237 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrDevNotifyCtrl, STAMTYPE_COUNTER, "Regs/WrDevNotifyCtrl", STAMUNIT_COUNT, "");
8238 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrDoorBell0, STAMTYPE_COUNTER, "Regs/WrDoorBell0", STAMUNIT_COUNT, "");
8239 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrDoorBellN, STAMTYPE_COUNTER, "Regs/WrDoorBellN", STAMUNIT_COUNT, "");
8240 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrEvtRingDeqPtrHi, STAMTYPE_COUNTER, "Regs/WrEvtRingDeqPtrHi", STAMUNIT_COUNT, "");
8241 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrEvtRingDeqPtrLo, STAMTYPE_COUNTER, "Regs/WrEvtRingDeqPtrLo", STAMUNIT_COUNT, "");
8242 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrEvtRsTblBaseHi, STAMTYPE_COUNTER, "Regs/WrEvtRsTblBaseHi", STAMUNIT_COUNT, "");
8243 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrEvtRsTblBaseLo, STAMTYPE_COUNTER, "Regs/WrEvtRsTblBaseLo", STAMUNIT_COUNT, "");
8244 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrEvtRstblSize, STAMTYPE_COUNTER, "Regs/WrEvtRstblSize", STAMUNIT_COUNT, "");
8245 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrIntrMgmt, STAMTYPE_COUNTER, "Regs/WrIntrMgmt", STAMUNIT_COUNT, "");
8246 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrIntrMod, STAMTYPE_COUNTER, "Regs/WrIntrMod", STAMUNIT_COUNT, "");
8247 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrPortPowerMgmt, STAMTYPE_COUNTER, "Regs/WrPortPowerMgmt", STAMUNIT_COUNT, "");
8248 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrPortStatusCtrl, STAMTYPE_COUNTER, "Regs/WrPortStatusCtrl", STAMUNIT_COUNT, "");
8249 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrUsbCmd, STAMTYPE_COUNTER, "Regs/WrUsbCmd", STAMUNIT_COUNT, "");
8250 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrUsbSts, STAMTYPE_COUNTER, "Regs/WrUsbSts", STAMUNIT_COUNT, "");
8251 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatWrUnknown, STAMTYPE_COUNTER, "Regs/WrUnknown", STAMUNIT_COUNT, "");
8252# endif /* VBOX_WITH_STATISTICS */
8253
8254 /*
8255 * Register debugger info callbacks.
8256 */
8257 PDMDevHlpDBGFInfoRegister(pDevIns, "xhci", "xHCI registers.", xhciR3Info);
8258
8259 return VINF_SUCCESS;
8260}
8261
8262#else /* !IN_RING3 */
8263
8264/**
8265 * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
8266 */
8267static DECLCALLBACK(int) xhciRZConstruct(PPDMDEVINS pDevIns)
8268{
8269 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
8270 PXHCI pThis = PDMDEVINS_2_DATA(pDevIns, PXHCI);
8271
8272 int rc = PDMDevHlpMmioSetUpContext(pDevIns, pThis->hMmio, xhciMmioWrite, xhciMmioRead, NULL /*pvUser*/);
8273 AssertRCReturn(rc, rc);
8274
8275 return VINF_SUCCESS;
8276}
8277
8278#endif /* !IN_RING3 */
8279
8280/* Without this, g_DeviceXHCI won't be visible outside this module! */
8281extern "C" const PDMDEVREG g_DeviceXHCI;
8282
8283const PDMDEVREG g_DeviceXHCI =
8284{
8285 /* .u32version = */ PDM_DEVREG_VERSION,
8286 /* .uReserved0 = */ 0,
8287 /* .szName = */ "usb-xhci",
8288 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE,
8289 /* .fClass = */ PDM_DEVREG_CLASS_BUS_USB,
8290 /* .cMaxInstances = */ ~0U,
8291 /* .uSharedVersion = */ 42,
8292 /* .cbInstanceShared = */ sizeof(XHCI),
8293 /* .cbInstanceCC = */ sizeof(XHCICC),
8294 /* .cbInstanceRC = */ sizeof(XHCIRC),
8295 /* .cMaxPciDevices = */ 1,
8296 /* .cMaxMsixVectors = */ 0,
8297 /* .pszDescription = */ "xHCI USB controller.\n",
8298#if defined(IN_RING3)
8299# ifdef VBOX_IN_EXTPACK
8300 /* .pszRCMod = */ "VBoxEhciRC.rc",
8301 /* .pszR0Mod = */ "VBoxEhciR0.r0",
8302# else
8303 /* .pszRCMod = */ "VBoxDDRC.rc",
8304 /* .pszR0Mod = */ "VBoxDDR0.r0",
8305# endif
8306 /* .pfnConstruct = */ xhciR3Construct,
8307 /* .pfnDestruct = */ xhciR3Destruct,
8308 /* .pfnRelocate = */ NULL,
8309 /* .pfnMemSetup = */ NULL,
8310 /* .pfnPowerOn = */ NULL,
8311 /* .pfnReset = */ xhciR3Reset,
8312 /* .pfnSuspend = */ NULL,
8313 /* .pfnResume = */ NULL,
8314 /* .pfnAttach = */ NULL,
8315 /* .pfnDetach = */ NULL,
8316 /* .pfnQueryInterface = */ NULL,
8317 /* .pfnInitComplete = */ NULL,
8318 /* .pfnPowerOff = */ NULL,
8319 /* .pfnSoftReset = */ NULL,
8320 /* .pfnReserved0 = */ NULL,
8321 /* .pfnReserved1 = */ NULL,
8322 /* .pfnReserved2 = */ NULL,
8323 /* .pfnReserved3 = */ NULL,
8324 /* .pfnReserved4 = */ NULL,
8325 /* .pfnReserved5 = */ NULL,
8326 /* .pfnReserved6 = */ NULL,
8327 /* .pfnReserved7 = */ NULL,
8328#elif defined(IN_RING0)
8329 /* .pfnEarlyConstruct = */ NULL,
8330 /* .pfnConstruct = */ xhciRZConstruct,
8331 /* .pfnDestruct = */ NULL,
8332 /* .pfnFinalDestruct = */ NULL,
8333 /* .pfnRequest = */ NULL,
8334 /* .pfnReserved0 = */ NULL,
8335 /* .pfnReserved1 = */ NULL,
8336 /* .pfnReserved2 = */ NULL,
8337 /* .pfnReserved3 = */ NULL,
8338 /* .pfnReserved4 = */ NULL,
8339 /* .pfnReserved5 = */ NULL,
8340 /* .pfnReserved6 = */ NULL,
8341 /* .pfnReserved7 = */ NULL,
8342#elif defined(IN_RC)
8343 /* .pfnConstruct = */ xhciRZConstruct,
8344 /* .pfnReserved0 = */ NULL,
8345 /* .pfnReserved1 = */ NULL,
8346 /* .pfnReserved2 = */ NULL,
8347 /* .pfnReserved3 = */ NULL,
8348 /* .pfnReserved4 = */ NULL,
8349 /* .pfnReserved5 = */ NULL,
8350 /* .pfnReserved6 = */ NULL,
8351 /* .pfnReserved7 = */ NULL,
8352#else
8353# error "Not in IN_RING3, IN_RING0 or IN_RC!"
8354#endif
8355 /* .u32VersionEnd = */ PDM_DEVREG_VERSION
8356};
8357
8358#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use