/* * USB xHCI controller emulation * * Copyright (c) 2011 Securiforest * Date: 2011-05-11 ; Author: Hector Martin * 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 . */ #ifndef HW_USB_HCD_XHCI_H #define HW_USB_HCD_XHCI_H #include "qom/object.h" #include "hw/usb.h" #include "sysemu/dma.h" #define TYPE_XHCI "base-xhci" #define TYPE_NEC_XHCI "nec-usb-xhci" #define TYPE_QEMU_XHCI "qemu-xhci" OBJECT_DECLARE_SIMPLE_TYPE(XHCIState, 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 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; uint16_t intr; 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; typedef struct XHCIState { DeviceState parent; USBBus bus; MemoryRegion mem; MemoryRegion *dma_mr; AddressSpace *as; 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; void (*intr_update)(XHCIState *s, int n, bool enable); void (*intr_raise)(XHCIState *s, int n, bool level); DeviceState *hostOpaque; /* 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_CONST(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; } XHCIState; extern const VMStateDescription vmstate_xhci; bool xhci_get_flag(XHCIState *xhci, enum xhci_flags bit); void xhci_set_flag(XHCIState *xhci, enum xhci_flags bit); #endif