| /* |
| * USB xHCI controller emulation |
| * |
| * Copyright (c) 2011 Securiforest |
| * Date: 2011-05-11 ; Author: Hector Martin <hector@marcansoft.com> |
| * Based on usb-ohci.c, emulates Renesas NEC USB 3.0 |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #define TYPE_XHCI "base-xhci" |
| #define TYPE_NEC_XHCI "nec-usb-xhci" |
| #define TYPE_QEMU_XHCI "qemu-xhci" |
| |
| #define XHCI(obj) \ |
| OBJECT_CHECK(XHCIState, (obj), TYPE_XHCI) |
| |
| #define MAXPORTS_2 15 |
| #define MAXPORTS_3 15 |
| |
| #define MAXPORTS (MAXPORTS_2 + MAXPORTS_3) |
| #define MAXSLOTS 64 |
| #define MAXINTRS 16 |
| |
| /* Very pessimistic, let's hope it's enough for all cases */ |
| #define EV_QUEUE (((3 * 24) + 16) * MAXSLOTS) |
| |
| typedef struct XHCIState XHCIState; |
| typedef struct XHCIStreamContext XHCIStreamContext; |
| typedef struct XHCIEPContext XHCIEPContext; |
| |
| enum xhci_flags { |
| XHCI_FLAG_SS_FIRST = 1, |
| XHCI_FLAG_FORCE_PCIE_ENDCAP, |
| XHCI_FLAG_ENABLE_STREAMS, |
| }; |
| |
| typedef enum TRBType { |
| TRB_RESERVED = 0, |
| TR_NORMAL, |
| TR_SETUP, |
| TR_DATA, |
| TR_STATUS, |
| TR_ISOCH, |
| TR_LINK, |
| TR_EVDATA, |
| TR_NOOP, |
| CR_ENABLE_SLOT, |
| CR_DISABLE_SLOT, |
| CR_ADDRESS_DEVICE, |
| CR_CONFIGURE_ENDPOINT, |
| CR_EVALUATE_CONTEXT, |
| CR_RESET_ENDPOINT, |
| CR_STOP_ENDPOINT, |
| CR_SET_TR_DEQUEUE, |
| CR_RESET_DEVICE, |
| CR_FORCE_EVENT, |
| CR_NEGOTIATE_BW, |
| CR_SET_LATENCY_TOLERANCE, |
| CR_GET_PORT_BANDWIDTH, |
| CR_FORCE_HEADER, |
| CR_NOOP, |
| ER_TRANSFER = 32, |
| ER_COMMAND_COMPLETE, |
| ER_PORT_STATUS_CHANGE, |
| ER_BANDWIDTH_REQUEST, |
| ER_DOORBELL, |
| ER_HOST_CONTROLLER, |
| ER_DEVICE_NOTIFICATION, |
| ER_MFINDEX_WRAP, |
| /* vendor specific bits */ |
| CR_VENDOR_NEC_FIRMWARE_REVISION = 49, |
| CR_VENDOR_NEC_CHALLENGE_RESPONSE = 50, |
| } TRBType; |
| |
| typedef enum TRBCCode { |
| CC_INVALID = 0, |
| CC_SUCCESS, |
| CC_DATA_BUFFER_ERROR, |
| CC_BABBLE_DETECTED, |
| CC_USB_TRANSACTION_ERROR, |
| CC_TRB_ERROR, |
| CC_STALL_ERROR, |
| CC_RESOURCE_ERROR, |
| CC_BANDWIDTH_ERROR, |
| CC_NO_SLOTS_ERROR, |
| CC_INVALID_STREAM_TYPE_ERROR, |
| CC_SLOT_NOT_ENABLED_ERROR, |
| CC_EP_NOT_ENABLED_ERROR, |
| CC_SHORT_PACKET, |
| CC_RING_UNDERRUN, |
| CC_RING_OVERRUN, |
| CC_VF_ER_FULL, |
| CC_PARAMETER_ERROR, |
| CC_BANDWIDTH_OVERRUN, |
| CC_CONTEXT_STATE_ERROR, |
| CC_NO_PING_RESPONSE_ERROR, |
| CC_EVENT_RING_FULL_ERROR, |
| CC_INCOMPATIBLE_DEVICE_ERROR, |
| CC_MISSED_SERVICE_ERROR, |
| CC_COMMAND_RING_STOPPED, |
| CC_COMMAND_ABORTED, |
| CC_STOPPED, |
| CC_STOPPED_LENGTH_INVALID, |
| CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29, |
| CC_ISOCH_BUFFER_OVERRUN = 31, |
| CC_EVENT_LOST_ERROR, |
| CC_UNDEFINED_ERROR, |
| CC_INVALID_STREAM_ID_ERROR, |
| CC_SECONDARY_BANDWIDTH_ERROR, |
| CC_SPLIT_TRANSACTION_ERROR |
| } TRBCCode; |
| |
| typedef struct XHCIRing { |
| dma_addr_t dequeue; |
| bool ccs; |
| } XHCIRing; |
| |
| typedef struct XHCIPort { |
| XHCIState *xhci; |
| uint32_t portsc; |
| uint32_t portnr; |
| USBPort *uport; |
| uint32_t speedmask; |
| char name[16]; |
| MemoryRegion mem; |
| } XHCIPort; |
| |
| typedef struct XHCISlot { |
| bool enabled; |
| bool addressed; |
| dma_addr_t ctx; |
| USBPort *uport; |
| XHCIEPContext *eps[31]; |
| } XHCISlot; |
| |
| typedef struct XHCIEvent { |
| TRBType type; |
| TRBCCode ccode; |
| uint64_t ptr; |
| uint32_t length; |
| uint32_t flags; |
| uint8_t slotid; |
| uint8_t epid; |
| } XHCIEvent; |
| |
| typedef struct XHCIInterrupter { |
| uint32_t iman; |
| uint32_t imod; |
| uint32_t erstsz; |
| uint32_t erstba_low; |
| uint32_t erstba_high; |
| uint32_t erdp_low; |
| uint32_t erdp_high; |
| |
| bool msix_used, er_pcs; |
| |
| dma_addr_t er_start; |
| uint32_t er_size; |
| unsigned int er_ep_idx; |
| |
| /* kept for live migration compat only */ |
| bool er_full_unused; |
| XHCIEvent ev_buffer[EV_QUEUE]; |
| unsigned int ev_buffer_put; |
| unsigned int ev_buffer_get; |
| |
| } XHCIInterrupter; |
| |
| struct XHCIState { |
| /*< private >*/ |
| PCIDevice parent_obj; |
| /*< public >*/ |
| |
| USBBus bus; |
| MemoryRegion mem; |
| MemoryRegion mem_cap; |
| MemoryRegion mem_oper; |
| MemoryRegion mem_runtime; |
| MemoryRegion mem_doorbell; |
| |
| /* properties */ |
| uint32_t numports_2; |
| uint32_t numports_3; |
| uint32_t numintrs; |
| uint32_t numslots; |
| uint32_t flags; |
| uint32_t max_pstreams_mask; |
| OnOffAuto msi; |
| OnOffAuto msix; |
| |
| /* Operational Registers */ |
| uint32_t usbcmd; |
| uint32_t usbsts; |
| uint32_t dnctrl; |
| uint32_t crcr_low; |
| uint32_t crcr_high; |
| uint32_t dcbaap_low; |
| uint32_t dcbaap_high; |
| uint32_t config; |
| |
| USBPort uports[MAX(MAXPORTS_2, MAXPORTS_3)]; |
| XHCIPort ports[MAXPORTS]; |
| XHCISlot slots[MAXSLOTS]; |
| uint32_t numports; |
| |
| /* Runtime Registers */ |
| int64_t mfindex_start; |
| QEMUTimer *mfwrap_timer; |
| XHCIInterrupter intr[MAXINTRS]; |
| |
| XHCIRing cmd_ring; |
| |
| bool nec_quirks; |
| }; |