Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 1 | /* |
| 2 | * USB xHCI controller emulation |
| 3 | * |
| 4 | * Copyright (c) 2011 Securiforest |
| 5 | * Date: 2011-05-11 ; Author: Hector Martin <hector@marcansoft.com> |
| 6 | * Based on usb-ohci.c, emulates Renesas NEC USB 3.0 |
| 7 | * |
| 8 | * This library is free software; you can redistribute it and/or |
| 9 | * modify it under the terms of the GNU Lesser General Public |
| 10 | * License as published by the Free Software Foundation; either |
Chetan Pant | bee4197 | 2020-10-23 12:23:32 +0000 | [diff] [blame] | 11 | * version 2.1 of the License, or (at your option) any later version. |
Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 12 | * |
| 13 | * This library is distributed in the hope that it will be useful, |
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 16 | * Lesser General Public License for more details. |
| 17 | * |
| 18 | * You should have received a copy of the GNU Lesser General Public |
| 19 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
| 20 | */ |
| 21 | |
Markus Armbruster | f91005e | 2019-06-04 20:16:18 +0200 | [diff] [blame] | 22 | #ifndef HW_USB_HCD_XHCI_H |
| 23 | #define HW_USB_HCD_XHCI_H |
Eduardo Habkost | db1015e | 2020-09-03 16:43:22 -0400 | [diff] [blame] | 24 | #include "qom/object.h" |
Markus Armbruster | f91005e | 2019-06-04 20:16:18 +0200 | [diff] [blame] | 25 | |
Sai Pavan Boddu | 755fba11 | 2020-09-24 19:50:51 +0530 | [diff] [blame] | 26 | #include "hw/usb.h" |
Gerd Hoffmann | 848db52 | 2020-10-20 09:48:36 +0200 | [diff] [blame] | 27 | #include "hw/usb/xhci.h" |
Sai Pavan Boddu | 8ddab8d | 2020-09-24 19:50:52 +0530 | [diff] [blame] | 28 | #include "sysemu/dma.h" |
Sai Pavan Boddu | 755fba11 | 2020-09-24 19:50:51 +0530 | [diff] [blame] | 29 | |
Eduardo Habkost | 8063396 | 2020-09-16 14:25:19 -0400 | [diff] [blame] | 30 | OBJECT_DECLARE_SIMPLE_TYPE(XHCIState, XHCI) |
Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 31 | |
Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 32 | /* Very pessimistic, let's hope it's enough for all cases */ |
Gerd Hoffmann | 848db52 | 2020-10-20 09:48:36 +0200 | [diff] [blame] | 33 | #define EV_QUEUE (((3 * 24) + 16) * XHCI_MAXSLOTS) |
Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 34 | |
Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 35 | typedef struct XHCIStreamContext XHCIStreamContext; |
| 36 | typedef struct XHCIEPContext XHCIEPContext; |
| 37 | |
| 38 | enum xhci_flags { |
| 39 | XHCI_FLAG_SS_FIRST = 1, |
| 40 | XHCI_FLAG_FORCE_PCIE_ENDCAP, |
| 41 | XHCI_FLAG_ENABLE_STREAMS, |
| 42 | }; |
| 43 | |
| 44 | typedef enum TRBType { |
| 45 | TRB_RESERVED = 0, |
| 46 | TR_NORMAL, |
| 47 | TR_SETUP, |
| 48 | TR_DATA, |
| 49 | TR_STATUS, |
| 50 | TR_ISOCH, |
| 51 | TR_LINK, |
| 52 | TR_EVDATA, |
| 53 | TR_NOOP, |
| 54 | CR_ENABLE_SLOT, |
| 55 | CR_DISABLE_SLOT, |
| 56 | CR_ADDRESS_DEVICE, |
| 57 | CR_CONFIGURE_ENDPOINT, |
| 58 | CR_EVALUATE_CONTEXT, |
| 59 | CR_RESET_ENDPOINT, |
| 60 | CR_STOP_ENDPOINT, |
| 61 | CR_SET_TR_DEQUEUE, |
| 62 | CR_RESET_DEVICE, |
| 63 | CR_FORCE_EVENT, |
| 64 | CR_NEGOTIATE_BW, |
| 65 | CR_SET_LATENCY_TOLERANCE, |
| 66 | CR_GET_PORT_BANDWIDTH, |
| 67 | CR_FORCE_HEADER, |
| 68 | CR_NOOP, |
| 69 | ER_TRANSFER = 32, |
| 70 | ER_COMMAND_COMPLETE, |
| 71 | ER_PORT_STATUS_CHANGE, |
| 72 | ER_BANDWIDTH_REQUEST, |
| 73 | ER_DOORBELL, |
| 74 | ER_HOST_CONTROLLER, |
| 75 | ER_DEVICE_NOTIFICATION, |
| 76 | ER_MFINDEX_WRAP, |
| 77 | /* vendor specific bits */ |
| 78 | CR_VENDOR_NEC_FIRMWARE_REVISION = 49, |
| 79 | CR_VENDOR_NEC_CHALLENGE_RESPONSE = 50, |
| 80 | } TRBType; |
| 81 | |
| 82 | typedef enum TRBCCode { |
| 83 | CC_INVALID = 0, |
| 84 | CC_SUCCESS, |
| 85 | CC_DATA_BUFFER_ERROR, |
| 86 | CC_BABBLE_DETECTED, |
| 87 | CC_USB_TRANSACTION_ERROR, |
| 88 | CC_TRB_ERROR, |
| 89 | CC_STALL_ERROR, |
| 90 | CC_RESOURCE_ERROR, |
| 91 | CC_BANDWIDTH_ERROR, |
| 92 | CC_NO_SLOTS_ERROR, |
| 93 | CC_INVALID_STREAM_TYPE_ERROR, |
| 94 | CC_SLOT_NOT_ENABLED_ERROR, |
| 95 | CC_EP_NOT_ENABLED_ERROR, |
| 96 | CC_SHORT_PACKET, |
| 97 | CC_RING_UNDERRUN, |
| 98 | CC_RING_OVERRUN, |
| 99 | CC_VF_ER_FULL, |
| 100 | CC_PARAMETER_ERROR, |
| 101 | CC_BANDWIDTH_OVERRUN, |
| 102 | CC_CONTEXT_STATE_ERROR, |
| 103 | CC_NO_PING_RESPONSE_ERROR, |
| 104 | CC_EVENT_RING_FULL_ERROR, |
| 105 | CC_INCOMPATIBLE_DEVICE_ERROR, |
| 106 | CC_MISSED_SERVICE_ERROR, |
| 107 | CC_COMMAND_RING_STOPPED, |
| 108 | CC_COMMAND_ABORTED, |
| 109 | CC_STOPPED, |
| 110 | CC_STOPPED_LENGTH_INVALID, |
| 111 | CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29, |
| 112 | CC_ISOCH_BUFFER_OVERRUN = 31, |
| 113 | CC_EVENT_LOST_ERROR, |
| 114 | CC_UNDEFINED_ERROR, |
| 115 | CC_INVALID_STREAM_ID_ERROR, |
| 116 | CC_SECONDARY_BANDWIDTH_ERROR, |
| 117 | CC_SPLIT_TRANSACTION_ERROR |
| 118 | } TRBCCode; |
| 119 | |
| 120 | typedef struct XHCIRing { |
| 121 | dma_addr_t dequeue; |
| 122 | bool ccs; |
| 123 | } XHCIRing; |
| 124 | |
| 125 | typedef struct XHCIPort { |
| 126 | XHCIState *xhci; |
| 127 | uint32_t portsc; |
| 128 | uint32_t portnr; |
| 129 | USBPort *uport; |
| 130 | uint32_t speedmask; |
Philippe Mathieu-Daudé | 96b66e5 | 2021-01-18 19:11:15 +0100 | [diff] [blame] | 131 | char name[20]; |
Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 132 | MemoryRegion mem; |
| 133 | } XHCIPort; |
| 134 | |
| 135 | typedef struct XHCISlot { |
| 136 | bool enabled; |
| 137 | bool addressed; |
Yuri Benditovich | b4329d1 | 2019-01-28 20:05:09 +0000 | [diff] [blame] | 138 | uint16_t intr; |
Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 139 | dma_addr_t ctx; |
| 140 | USBPort *uport; |
| 141 | XHCIEPContext *eps[31]; |
| 142 | } XHCISlot; |
| 143 | |
| 144 | typedef struct XHCIEvent { |
| 145 | TRBType type; |
| 146 | TRBCCode ccode; |
| 147 | uint64_t ptr; |
| 148 | uint32_t length; |
| 149 | uint32_t flags; |
| 150 | uint8_t slotid; |
| 151 | uint8_t epid; |
| 152 | } XHCIEvent; |
| 153 | |
| 154 | typedef struct XHCIInterrupter { |
| 155 | uint32_t iman; |
| 156 | uint32_t imod; |
| 157 | uint32_t erstsz; |
| 158 | uint32_t erstba_low; |
| 159 | uint32_t erstba_high; |
| 160 | uint32_t erdp_low; |
| 161 | uint32_t erdp_high; |
| 162 | |
| 163 | bool msix_used, er_pcs; |
| 164 | |
| 165 | dma_addr_t er_start; |
| 166 | uint32_t er_size; |
| 167 | unsigned int er_ep_idx; |
| 168 | |
| 169 | /* kept for live migration compat only */ |
| 170 | bool er_full_unused; |
| 171 | XHCIEvent ev_buffer[EV_QUEUE]; |
| 172 | unsigned int ev_buffer_put; |
| 173 | unsigned int ev_buffer_get; |
| 174 | |
| 175 | } XHCIInterrupter; |
| 176 | |
Sai Pavan Boddu | 8ddab8d | 2020-09-24 19:50:52 +0530 | [diff] [blame] | 177 | typedef struct XHCIState { |
| 178 | DeviceState parent; |
Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 179 | |
| 180 | USBBus bus; |
| 181 | MemoryRegion mem; |
Sai Pavan Boddu | f00ff13 | 2020-09-24 19:50:53 +0530 | [diff] [blame] | 182 | MemoryRegion *dma_mr; |
Sai Pavan Boddu | a531707 | 2020-09-24 19:50:50 +0530 | [diff] [blame] | 183 | AddressSpace *as; |
Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 184 | MemoryRegion mem_cap; |
| 185 | MemoryRegion mem_oper; |
| 186 | MemoryRegion mem_runtime; |
| 187 | MemoryRegion mem_doorbell; |
| 188 | |
| 189 | /* properties */ |
| 190 | uint32_t numports_2; |
| 191 | uint32_t numports_3; |
| 192 | uint32_t numintrs; |
| 193 | uint32_t numslots; |
| 194 | uint32_t flags; |
| 195 | uint32_t max_pstreams_mask; |
Sai Pavan Boddu | 8ddab8d | 2020-09-24 19:50:52 +0530 | [diff] [blame] | 196 | void (*intr_update)(XHCIState *s, int n, bool enable); |
Ruimei Yan | fc967aa | 2021-05-21 10:42:24 +0800 | [diff] [blame] | 197 | bool (*intr_raise)(XHCIState *s, int n, bool level); |
Sai Pavan Boddu | 8ddab8d | 2020-09-24 19:50:52 +0530 | [diff] [blame] | 198 | DeviceState *hostOpaque; |
Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 199 | |
| 200 | /* Operational Registers */ |
| 201 | uint32_t usbcmd; |
| 202 | uint32_t usbsts; |
| 203 | uint32_t dnctrl; |
| 204 | uint32_t crcr_low; |
| 205 | uint32_t crcr_high; |
| 206 | uint32_t dcbaap_low; |
| 207 | uint32_t dcbaap_high; |
| 208 | uint32_t config; |
| 209 | |
Gerd Hoffmann | 848db52 | 2020-10-20 09:48:36 +0200 | [diff] [blame] | 210 | USBPort uports[MAX_CONST(XHCI_MAXPORTS_2, XHCI_MAXPORTS_3)]; |
| 211 | XHCIPort ports[XHCI_MAXPORTS]; |
| 212 | XHCISlot slots[XHCI_MAXSLOTS]; |
Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 213 | uint32_t numports; |
| 214 | |
| 215 | /* Runtime Registers */ |
| 216 | int64_t mfindex_start; |
| 217 | QEMUTimer *mfwrap_timer; |
Gerd Hoffmann | 848db52 | 2020-10-20 09:48:36 +0200 | [diff] [blame] | 218 | XHCIInterrupter intr[XHCI_MAXINTRS]; |
Gerd Hoffmann | 0bbb2f3 | 2017-05-17 12:33:12 +0200 | [diff] [blame] | 219 | |
| 220 | XHCIRing cmd_ring; |
| 221 | |
| 222 | bool nec_quirks; |
Sai Pavan Boddu | 8ddab8d | 2020-09-24 19:50:52 +0530 | [diff] [blame] | 223 | } XHCIState; |
Markus Armbruster | f91005e | 2019-06-04 20:16:18 +0200 | [diff] [blame] | 224 | |
Sai Pavan Boddu | 8ddab8d | 2020-09-24 19:50:52 +0530 | [diff] [blame] | 225 | extern const VMStateDescription vmstate_xhci; |
Sai Pavan Boddu | 755fba11 | 2020-09-24 19:50:51 +0530 | [diff] [blame] | 226 | bool xhci_get_flag(XHCIState *xhci, enum xhci_flags bit); |
| 227 | void xhci_set_flag(XHCIState *xhci, enum xhci_flags bit); |
Markus Armbruster | f91005e | 2019-06-04 20:16:18 +0200 | [diff] [blame] | 228 | #endif |