hcd-xhci.c 108.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * 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/>.
 */
P
Peter Maydell 已提交
21
#include "qemu/osdep.h"
G
Gerd Hoffmann 已提交
22
#include "hw/hw.h"
23
#include "qemu/timer.h"
24
#include "qemu/queue.h"
G
Gerd Hoffmann 已提交
25
#include "hw/usb.h"
26 27 28
#include "hw/pci/pci.h"
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
G
Gerd Hoffmann 已提交
29
#include "trace.h"
30
#include "qapi/error.h"
31

G
Gerd Hoffmann 已提交
32 33
#include "hcd-xhci.h"

34 35 36 37 38 39 40 41
//#define DEBUG_XHCI
//#define DEBUG_DATA

#ifdef DEBUG_XHCI
#define DPRINTF(...) fprintf(stderr, __VA_ARGS__)
#else
#define DPRINTF(...) do {} while (0)
#endif
G
Gerd Hoffmann 已提交
42 43
#define FIXME(_msg) do { fprintf(stderr, "FIXME %s:%d %s\n", \
                                 __func__, __LINE__, _msg); abort(); } while (0)
44

L
Ladi Prosek 已提交
45
#define TRB_LINK_LIMIT  32
G
Gerd Hoffmann 已提交
46 47
#define COMMAND_LIMIT   256
#define TRANSFER_LIMIT  256
48

49 50
#define LEN_CAP         0x40
#define LEN_OPER        (0x400 + 0x10 * MAXPORTS)
G
Gerd Hoffmann 已提交
51
#define LEN_RUNTIME     ((MAXINTRS + 1) * 0x20)
52 53
#define LEN_DOORBELL    ((MAXSLOTS + 1) * 0x20)

G
Gerd Hoffmann 已提交
54 55 56
#define OFF_OPER        LEN_CAP
#define OFF_RUNTIME     0x1000
#define OFF_DOORBELL    0x2000
G
Gerd Hoffmann 已提交
57 58
#define OFF_MSIX_TABLE  0x3000
#define OFF_MSIX_PBA    0x3800
59
/* must be power of 2 */
G
Gerd Hoffmann 已提交
60
#define LEN_REGS        0x4000
61

G
Gerd Hoffmann 已提交
62 63 64 65 66 67
#if (OFF_OPER + LEN_OPER) > OFF_RUNTIME
#error Increase OFF_RUNTIME
#endif
#if (OFF_RUNTIME + LEN_RUNTIME) > OFF_DOORBELL
#error Increase OFF_DOORBELL
#endif
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
#if (OFF_DOORBELL + LEN_DOORBELL) > LEN_REGS
# error Increase LEN_REGS
#endif

/* bit definitions */
#define USBCMD_RS       (1<<0)
#define USBCMD_HCRST    (1<<1)
#define USBCMD_INTE     (1<<2)
#define USBCMD_HSEE     (1<<3)
#define USBCMD_LHCRST   (1<<7)
#define USBCMD_CSS      (1<<8)
#define USBCMD_CRS      (1<<9)
#define USBCMD_EWE      (1<<10)
#define USBCMD_EU3S     (1<<11)

#define USBSTS_HCH      (1<<0)
#define USBSTS_HSE      (1<<2)
#define USBSTS_EINT     (1<<3)
#define USBSTS_PCD      (1<<4)
#define USBSTS_SSS      (1<<8)
#define USBSTS_RSS      (1<<9)
#define USBSTS_SRE      (1<<10)
#define USBSTS_CNR      (1<<11)
#define USBSTS_HCE      (1<<12)


#define PORTSC_CCS          (1<<0)
#define PORTSC_PED          (1<<1)
#define PORTSC_OCA          (1<<3)
#define PORTSC_PR           (1<<4)
#define PORTSC_PLS_SHIFT        5
#define PORTSC_PLS_MASK     0xf
#define PORTSC_PP           (1<<9)
#define PORTSC_SPEED_SHIFT      10
#define PORTSC_SPEED_MASK   0xf
#define PORTSC_SPEED_FULL   (1<<10)
#define PORTSC_SPEED_LOW    (2<<10)
#define PORTSC_SPEED_HIGH   (3<<10)
#define PORTSC_SPEED_SUPER  (4<<10)
#define PORTSC_PIC_SHIFT        14
#define PORTSC_PIC_MASK     0x3
#define PORTSC_LWS          (1<<16)
#define PORTSC_CSC          (1<<17)
#define PORTSC_PEC          (1<<18)
#define PORTSC_WRC          (1<<19)
#define PORTSC_OCC          (1<<20)
#define PORTSC_PRC          (1<<21)
#define PORTSC_PLC          (1<<22)
#define PORTSC_CEC          (1<<23)
#define PORTSC_CAS          (1<<24)
#define PORTSC_WCE          (1<<25)
#define PORTSC_WDE          (1<<26)
#define PORTSC_WOE          (1<<27)
#define PORTSC_DR           (1<<30)
#define PORTSC_WPR          (1<<31)

#define CRCR_RCS        (1<<0)
#define CRCR_CS         (1<<1)
#define CRCR_CA         (1<<2)
#define CRCR_CRR        (1<<3)

#define IMAN_IP         (1<<0)
#define IMAN_IE         (1<<1)

#define ERDP_EHB        (1<<3)

#define TRB_SIZE 16
typedef struct XHCITRB {
    uint64_t parameter;
    uint32_t status;
    uint32_t control;
139
    dma_addr_t addr;
140 141 142
    bool ccs;
} XHCITRB;

143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
enum {
    PLS_U0              =  0,
    PLS_U1              =  1,
    PLS_U2              =  2,
    PLS_U3              =  3,
    PLS_DISABLED        =  4,
    PLS_RX_DETECT       =  5,
    PLS_INACTIVE        =  6,
    PLS_POLLING         =  7,
    PLS_RECOVERY        =  8,
    PLS_HOT_RESET       =  9,
    PLS_COMPILANCE_MODE = 10,
    PLS_TEST_MODE       = 11,
    PLS_RESUME          = 15,
};
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194

#define CR_LINK TR_LINK

#define TRB_C               (1<<0)
#define TRB_TYPE_SHIFT          10
#define TRB_TYPE_MASK       0x3f
#define TRB_TYPE(t)         (((t).control >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK)

#define TRB_EV_ED           (1<<2)

#define TRB_TR_ENT          (1<<1)
#define TRB_TR_ISP          (1<<2)
#define TRB_TR_NS           (1<<3)
#define TRB_TR_CH           (1<<4)
#define TRB_TR_IOC          (1<<5)
#define TRB_TR_IDT          (1<<6)
#define TRB_TR_TBC_SHIFT        7
#define TRB_TR_TBC_MASK     0x3
#define TRB_TR_BEI          (1<<9)
#define TRB_TR_TLBPC_SHIFT      16
#define TRB_TR_TLBPC_MASK   0xf
#define TRB_TR_FRAMEID_SHIFT    20
#define TRB_TR_FRAMEID_MASK 0x7ff
#define TRB_TR_SIA          (1<<31)

#define TRB_TR_DIR          (1<<16)

#define TRB_CR_SLOTID_SHIFT     24
#define TRB_CR_SLOTID_MASK  0xff
#define TRB_CR_EPID_SHIFT       16
#define TRB_CR_EPID_MASK    0x1f

#define TRB_CR_BSR          (1<<9)
#define TRB_CR_DC           (1<<9)

#define TRB_LK_TC           (1<<1)

G
Gerd Hoffmann 已提交
195 196 197 198
#define TRB_INTR_SHIFT          22
#define TRB_INTR_MASK       0x3ff
#define TRB_INTR(t)         (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK)

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
#define EP_TYPE_MASK        0x7
#define EP_TYPE_SHIFT           3

#define EP_STATE_MASK       0x7
#define EP_DISABLED         (0<<0)
#define EP_RUNNING          (1<<0)
#define EP_HALTED           (2<<0)
#define EP_STOPPED          (3<<0)
#define EP_ERROR            (4<<0)

#define SLOT_STATE_MASK     0x1f
#define SLOT_STATE_SHIFT        27
#define SLOT_STATE(s)       (((s)>>SLOT_STATE_SHIFT)&SLOT_STATE_MASK)
#define SLOT_ENABLED        0
#define SLOT_DEFAULT        1
#define SLOT_ADDRESSED      2
#define SLOT_CONFIGURED     3

#define SLOT_CONTEXT_ENTRIES_MASK 0x1f
#define SLOT_CONTEXT_ENTRIES_SHIFT 27

220 221 222 223 224 225 226 227 228 229
#define get_field(data, field)                  \
    (((data) >> field##_SHIFT) & field##_MASK)

#define set_field(data, newval, field) do {                     \
        uint32_t val = *data;                                   \
        val &= ~(field##_MASK << field##_SHIFT);                \
        val |= ((newval) & field##_MASK) << field##_SHIFT;      \
        *data = val;                                            \
    } while (0)

230 231 232 233 234 235 236 237 238 239 240 241
typedef enum EPType {
    ET_INVALID = 0,
    ET_ISO_OUT,
    ET_BULK_OUT,
    ET_INTR_OUT,
    ET_CONTROL,
    ET_ISO_IN,
    ET_BULK_IN,
    ET_INTR_IN,
} EPType;

typedef struct XHCITransfer {
242
    XHCIEPContext *epctx;
243
    USBPacket packet;
G
Gerd Hoffmann 已提交
244
    QEMUSGList sgl;
G
Gerd Hoffmann 已提交
245 246
    bool running_async;
    bool running_retry;
247
    bool complete;
248
    bool int_req;
249
    unsigned int iso_pkts;
G
Gerd Hoffmann 已提交
250
    unsigned int streamid;
251 252
    bool in_xfer;
    bool iso_xfer;
253
    bool timed_xfer;
254 255 256 257 258 259 260 261 262

    unsigned int trb_count;
    XHCITRB *trbs;

    TRBCCode status;

    unsigned int pkts;
    unsigned int pktsize;
    unsigned int cur_pkt;
G
Gerd Hoffmann 已提交
263 264

    uint64_t mfindex_kick;
265 266

    QTAILQ_ENTRY(XHCITransfer) next;
267 268
} XHCITransfer;

G
Gerd Hoffmann 已提交
269 270 271 272 273 274 275
struct XHCIStreamContext {
    dma_addr_t pctx;
    unsigned int sct;
    XHCIRing ring;
};

struct XHCIEPContext {
G
Gerd Hoffmann 已提交
276 277 278 279
    XHCIState *xhci;
    unsigned int slotid;
    unsigned int epid;

280
    XHCIRing ring;
281 282
    uint32_t xfer_count;
    QTAILQ_HEAD(, XHCITransfer) transfers;
G
Gerd Hoffmann 已提交
283
    XHCITransfer *retry;
284
    EPType type;
285
    dma_addr_t pctx;
286 287
    unsigned int max_psize;
    uint32_t state;
288
    uint32_t kick_active;
G
Gerd Hoffmann 已提交
289

G
Gerd Hoffmann 已提交
290 291 292 293 294 295
    /* streams */
    unsigned int max_pstreams;
    bool         lsa;
    unsigned int nr_pstreams;
    XHCIStreamContext *pstreams;

G
Gerd Hoffmann 已提交
296 297 298 299
    /* iso xfer scheduling */
    unsigned int interval;
    int64_t mfindex_last;
    QEMUTimer *kick_timer;
G
Gerd Hoffmann 已提交
300
};
301 302 303 304 305 306 307 308

typedef struct XHCIEvRingSeg {
    uint32_t addr_low;
    uint32_t addr_high;
    uint32_t size;
    uint32_t rsvd;
} XHCIEvRingSeg;

G
Gerd Hoffmann 已提交
309
static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
G
Gerd Hoffmann 已提交
310
                         unsigned int epid, unsigned int streamid);
G
Gerd Hoffmann 已提交
311
static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid);
312 313
static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid,
                                unsigned int epid);
314
static void xhci_xfer_report(XHCITransfer *xfer);
G
Gerd Hoffmann 已提交
315 316
static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v);
static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v);
317
static USBEndpoint *xhci_epid_to_usbep(XHCIEPContext *epctx);
G
Gerd Hoffmann 已提交
318

319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
static const char *TRBType_names[] = {
    [TRB_RESERVED]                     = "TRB_RESERVED",
    [TR_NORMAL]                        = "TR_NORMAL",
    [TR_SETUP]                         = "TR_SETUP",
    [TR_DATA]                          = "TR_DATA",
    [TR_STATUS]                        = "TR_STATUS",
    [TR_ISOCH]                         = "TR_ISOCH",
    [TR_LINK]                          = "TR_LINK",
    [TR_EVDATA]                        = "TR_EVDATA",
    [TR_NOOP]                          = "TR_NOOP",
    [CR_ENABLE_SLOT]                   = "CR_ENABLE_SLOT",
    [CR_DISABLE_SLOT]                  = "CR_DISABLE_SLOT",
    [CR_ADDRESS_DEVICE]                = "CR_ADDRESS_DEVICE",
    [CR_CONFIGURE_ENDPOINT]            = "CR_CONFIGURE_ENDPOINT",
    [CR_EVALUATE_CONTEXT]              = "CR_EVALUATE_CONTEXT",
    [CR_RESET_ENDPOINT]                = "CR_RESET_ENDPOINT",
    [CR_STOP_ENDPOINT]                 = "CR_STOP_ENDPOINT",
    [CR_SET_TR_DEQUEUE]                = "CR_SET_TR_DEQUEUE",
    [CR_RESET_DEVICE]                  = "CR_RESET_DEVICE",
    [CR_FORCE_EVENT]                   = "CR_FORCE_EVENT",
    [CR_NEGOTIATE_BW]                  = "CR_NEGOTIATE_BW",
    [CR_SET_LATENCY_TOLERANCE]         = "CR_SET_LATENCY_TOLERANCE",
    [CR_GET_PORT_BANDWIDTH]            = "CR_GET_PORT_BANDWIDTH",
    [CR_FORCE_HEADER]                  = "CR_FORCE_HEADER",
    [CR_NOOP]                          = "CR_NOOP",
    [ER_TRANSFER]                      = "ER_TRANSFER",
    [ER_COMMAND_COMPLETE]              = "ER_COMMAND_COMPLETE",
    [ER_PORT_STATUS_CHANGE]            = "ER_PORT_STATUS_CHANGE",
    [ER_BANDWIDTH_REQUEST]             = "ER_BANDWIDTH_REQUEST",
    [ER_DOORBELL]                      = "ER_DOORBELL",
    [ER_HOST_CONTROLLER]               = "ER_HOST_CONTROLLER",
    [ER_DEVICE_NOTIFICATION]           = "ER_DEVICE_NOTIFICATION",
    [ER_MFINDEX_WRAP]                  = "ER_MFINDEX_WRAP",
    [CR_VENDOR_NEC_FIRMWARE_REVISION]  = "CR_VENDOR_NEC_FIRMWARE_REVISION",
    [CR_VENDOR_NEC_CHALLENGE_RESPONSE] = "CR_VENDOR_NEC_CHALLENGE_RESPONSE",
};

356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
static const char *TRBCCode_names[] = {
    [CC_INVALID]                       = "CC_INVALID",
    [CC_SUCCESS]                       = "CC_SUCCESS",
    [CC_DATA_BUFFER_ERROR]             = "CC_DATA_BUFFER_ERROR",
    [CC_BABBLE_DETECTED]               = "CC_BABBLE_DETECTED",
    [CC_USB_TRANSACTION_ERROR]         = "CC_USB_TRANSACTION_ERROR",
    [CC_TRB_ERROR]                     = "CC_TRB_ERROR",
    [CC_STALL_ERROR]                   = "CC_STALL_ERROR",
    [CC_RESOURCE_ERROR]                = "CC_RESOURCE_ERROR",
    [CC_BANDWIDTH_ERROR]               = "CC_BANDWIDTH_ERROR",
    [CC_NO_SLOTS_ERROR]                = "CC_NO_SLOTS_ERROR",
    [CC_INVALID_STREAM_TYPE_ERROR]     = "CC_INVALID_STREAM_TYPE_ERROR",
    [CC_SLOT_NOT_ENABLED_ERROR]        = "CC_SLOT_NOT_ENABLED_ERROR",
    [CC_EP_NOT_ENABLED_ERROR]          = "CC_EP_NOT_ENABLED_ERROR",
    [CC_SHORT_PACKET]                  = "CC_SHORT_PACKET",
    [CC_RING_UNDERRUN]                 = "CC_RING_UNDERRUN",
    [CC_RING_OVERRUN]                  = "CC_RING_OVERRUN",
    [CC_VF_ER_FULL]                    = "CC_VF_ER_FULL",
    [CC_PARAMETER_ERROR]               = "CC_PARAMETER_ERROR",
    [CC_BANDWIDTH_OVERRUN]             = "CC_BANDWIDTH_OVERRUN",
    [CC_CONTEXT_STATE_ERROR]           = "CC_CONTEXT_STATE_ERROR",
    [CC_NO_PING_RESPONSE_ERROR]        = "CC_NO_PING_RESPONSE_ERROR",
    [CC_EVENT_RING_FULL_ERROR]         = "CC_EVENT_RING_FULL_ERROR",
    [CC_INCOMPATIBLE_DEVICE_ERROR]     = "CC_INCOMPATIBLE_DEVICE_ERROR",
    [CC_MISSED_SERVICE_ERROR]          = "CC_MISSED_SERVICE_ERROR",
    [CC_COMMAND_RING_STOPPED]          = "CC_COMMAND_RING_STOPPED",
    [CC_COMMAND_ABORTED]               = "CC_COMMAND_ABORTED",
    [CC_STOPPED]                       = "CC_STOPPED",
    [CC_STOPPED_LENGTH_INVALID]        = "CC_STOPPED_LENGTH_INVALID",
    [CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR]
    = "CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR",
    [CC_ISOCH_BUFFER_OVERRUN]          = "CC_ISOCH_BUFFER_OVERRUN",
    [CC_EVENT_LOST_ERROR]              = "CC_EVENT_LOST_ERROR",
    [CC_UNDEFINED_ERROR]               = "CC_UNDEFINED_ERROR",
    [CC_INVALID_STREAM_ID_ERROR]       = "CC_INVALID_STREAM_ID_ERROR",
    [CC_SECONDARY_BANDWIDTH_ERROR]     = "CC_SECONDARY_BANDWIDTH_ERROR",
    [CC_SPLIT_TRANSACTION_ERROR]       = "CC_SPLIT_TRANSACTION_ERROR",
};

395 396 397 398 399 400 401 402
static const char *ep_state_names[] = {
    [EP_DISABLED] = "disabled",
    [EP_RUNNING]  = "running",
    [EP_HALTED]   = "halted",
    [EP_STOPPED]  = "stopped",
    [EP_ERROR]    = "error",
};

403 404 405 406 407 408 409 410 411 412 413 414 415 416
static const char *lookup_name(uint32_t index, const char **list, uint32_t llen)
{
    if (index >= llen || list[index] == NULL) {
        return "???";
    }
    return list[index];
}

static const char *trb_name(XHCITRB *trb)
{
    return lookup_name(TRB_TYPE(*trb), TRBType_names,
                       ARRAY_SIZE(TRBType_names));
}

417 418 419 420 421 422
static const char *event_name(XHCIEvent *event)
{
    return lookup_name(event->ccode, TRBCCode_names,
                       ARRAY_SIZE(TRBCCode_names));
}

423 424 425 426 427 428
static const char *ep_state_name(uint32_t state)
{
    return lookup_name(state, ep_state_names,
                       ARRAY_SIZE(ep_state_names));
}

G
Gerd Hoffmann 已提交
429 430 431 432 433
static bool xhci_get_flag(XHCIState *xhci, enum xhci_flags bit)
{
    return xhci->flags & (1 << bit);
}

G
Gerd Hoffmann 已提交
434 435 436 437 438
static void xhci_set_flag(XHCIState *xhci, enum xhci_flags bit)
{
    xhci->flags |= (1 << bit);
}

G
Gerd Hoffmann 已提交
439 440
static uint64_t xhci_mfindex_get(XHCIState *xhci)
{
441
    int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
G
Gerd Hoffmann 已提交
442 443 444 445 446 447 448 449 450 451
    return (now - xhci->mfindex_start) / 125000;
}

static void xhci_mfwrap_update(XHCIState *xhci)
{
    const uint32_t bits = USBCMD_RS | USBCMD_EWE;
    uint32_t mfindex, left;
    int64_t now;

    if ((xhci->usbcmd & bits) == bits) {
452
        now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
G
Gerd Hoffmann 已提交
453 454
        mfindex = ((now - xhci->mfindex_start) / 125000) & 0x3fff;
        left = 0x4000 - mfindex;
455
        timer_mod(xhci->mfwrap_timer, now + left * 125000);
G
Gerd Hoffmann 已提交
456
    } else {
457
        timer_del(xhci->mfwrap_timer);
G
Gerd Hoffmann 已提交
458 459 460 461 462 463 464 465
    }
}

static void xhci_mfwrap_timer(void *opaque)
{
    XHCIState *xhci = opaque;
    XHCIEvent wrap = { ER_MFINDEX_WRAP, CC_SUCCESS };

G
Gerd Hoffmann 已提交
466
    xhci_event(xhci, &wrap, 0);
G
Gerd Hoffmann 已提交
467 468
    xhci_mfwrap_update(xhci);
}
469

470
static inline dma_addr_t xhci_addr64(uint32_t low, uint32_t high)
471
{
472 473 474 475 476
    if (sizeof(dma_addr_t) == 4) {
        return low;
    } else {
        return low | (((dma_addr_t)high << 16) << 16);
    }
477 478
}

479
static inline dma_addr_t xhci_mask64(uint64_t addr)
480
{
481 482 483 484 485
    if (sizeof(dma_addr_t) == 4) {
        return addr & 0xffffffff;
    } else {
        return addr;
    }
486 487
}

D
David Gibson 已提交
488 489 490 491 492 493 494
static inline void xhci_dma_read_u32s(XHCIState *xhci, dma_addr_t addr,
                                      uint32_t *buf, size_t len)
{
    int i;

    assert((len % sizeof(uint32_t)) == 0);

495
    pci_dma_read(PCI_DEVICE(xhci), addr, buf, len);
D
David Gibson 已提交
496 497 498 499 500 501 502 503 504 505

    for (i = 0; i < (len / sizeof(uint32_t)); i++) {
        buf[i] = le32_to_cpu(buf[i]);
    }
}

static inline void xhci_dma_write_u32s(XHCIState *xhci, dma_addr_t addr,
                                       uint32_t *buf, size_t len)
{
    int i;
506 507
    uint32_t tmp[5];
    uint32_t n = len / sizeof(uint32_t);
D
David Gibson 已提交
508 509

    assert((len % sizeof(uint32_t)) == 0);
510
    assert(n <= ARRAY_SIZE(tmp));
D
David Gibson 已提交
511

512
    for (i = 0; i < n; i++) {
D
David Gibson 已提交
513 514
        tmp[i] = cpu_to_le32(buf[i]);
    }
515
    pci_dma_write(PCI_DEVICE(xhci), addr, tmp, len);
D
David Gibson 已提交
516 517
}

G
Gerd Hoffmann 已提交
518 519 520 521 522 523 524 525 526 527 528
static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport)
{
    int index;

    if (!uport->dev) {
        return NULL;
    }
    switch (uport->dev->speed) {
    case USB_SPEED_LOW:
    case USB_SPEED_FULL:
    case USB_SPEED_HIGH:
529 530 531 532 533
        if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
            index = uport->index + xhci->numports_3;
        } else {
            index = uport->index;
        }
G
Gerd Hoffmann 已提交
534 535
        break;
    case USB_SPEED_SUPER:
536 537 538 539 540
        if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
            index = uport->index;
        } else {
            index = uport->index + xhci->numports_2;
        }
G
Gerd Hoffmann 已提交
541 542 543 544 545 546 547
        break;
    default:
        return NULL;
    }
    return &xhci->ports[index];
}

G
Gerd Hoffmann 已提交
548
static void xhci_intx_update(XHCIState *xhci)
549
{
550
    PCIDevice *pci_dev = PCI_DEVICE(xhci);
551 552
    int level = 0;

553 554
    if (msix_enabled(pci_dev) ||
        msi_enabled(pci_dev)) {
G
Gerd Hoffmann 已提交
555 556 557
        return;
    }

G
Gerd Hoffmann 已提交
558 559
    if (xhci->intr[0].iman & IMAN_IP &&
        xhci->intr[0].iman & IMAN_IE &&
L
Lai Jiangshan 已提交
560
        xhci->usbcmd & USBCMD_INTE) {
561 562 563
        level = 1;
    }

G
Gerd Hoffmann 已提交
564
    trace_usb_xhci_irq_intx(level);
565
    pci_set_irq(pci_dev, level);
G
Gerd Hoffmann 已提交
566 567
}

G
Gerd Hoffmann 已提交
568
static void xhci_msix_update(XHCIState *xhci, int v)
G
Gerd Hoffmann 已提交
569
{
570
    PCIDevice *pci_dev = PCI_DEVICE(xhci);
G
Gerd Hoffmann 已提交
571 572
    bool enabled;

573
    if (!msix_enabled(pci_dev)) {
G
Gerd Hoffmann 已提交
574 575 576
        return;
    }

G
Gerd Hoffmann 已提交
577 578
    enabled = xhci->intr[v].iman & IMAN_IE;
    if (enabled == xhci->intr[v].msix_used) {
G
Gerd Hoffmann 已提交
579 580 581 582
        return;
    }

    if (enabled) {
G
Gerd Hoffmann 已提交
583
        trace_usb_xhci_irq_msix_use(v);
584
        msix_vector_use(pci_dev, v);
G
Gerd Hoffmann 已提交
585
        xhci->intr[v].msix_used = true;
G
Gerd Hoffmann 已提交
586
    } else {
G
Gerd Hoffmann 已提交
587
        trace_usb_xhci_irq_msix_unuse(v);
588
        msix_vector_unuse(pci_dev, v);
G
Gerd Hoffmann 已提交
589
        xhci->intr[v].msix_used = false;
G
Gerd Hoffmann 已提交
590 591 592
    }
}

G
Gerd Hoffmann 已提交
593
static void xhci_intr_raise(XHCIState *xhci, int v)
G
Gerd Hoffmann 已提交
594
{
595
    PCIDevice *pci_dev = PCI_DEVICE(xhci);
596
    bool pending = (xhci->intr[v].erdp_low & ERDP_EHB);
597

G
Gerd Hoffmann 已提交
598 599
    xhci->intr[v].erdp_low |= ERDP_EHB;
    xhci->intr[v].iman |= IMAN_IP;
600 601
    xhci->usbsts |= USBSTS_EINT;

602 603 604
    if (pending) {
        return;
    }
G
Gerd Hoffmann 已提交
605
    if (!(xhci->intr[v].iman & IMAN_IE)) {
G
Gerd Hoffmann 已提交
606 607 608 609 610 611 612
        return;
    }

    if (!(xhci->usbcmd & USBCMD_INTE)) {
        return;
    }

613
    if (msix_enabled(pci_dev)) {
G
Gerd Hoffmann 已提交
614
        trace_usb_xhci_irq_msix(v);
615
        msix_notify(pci_dev, v);
G
Gerd Hoffmann 已提交
616 617 618
        return;
    }

619
    if (msi_enabled(pci_dev)) {
G
Gerd Hoffmann 已提交
620
        trace_usb_xhci_irq_msi(v);
621
        msi_notify(pci_dev, v);
G
Gerd Hoffmann 已提交
622
        return;
623
    }
G
Gerd Hoffmann 已提交
624

G
Gerd Hoffmann 已提交
625 626
    if (v == 0) {
        trace_usb_xhci_irq_intx(1);
627
        pci_irq_assert(pci_dev);
G
Gerd Hoffmann 已提交
628
    }
629 630 631 632
}

static inline int xhci_running(XHCIState *xhci)
{
633
    return !(xhci->usbsts & USBSTS_HCH);
634 635 636 637 638
}

static void xhci_die(XHCIState *xhci)
{
    xhci->usbsts |= USBSTS_HCE;
639
    DPRINTF("xhci: asserted controller error\n");
640 641
}

G
Gerd Hoffmann 已提交
642
static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v)
643
{
644
    PCIDevice *pci_dev = PCI_DEVICE(xhci);
G
Gerd Hoffmann 已提交
645
    XHCIInterrupter *intr = &xhci->intr[v];
646
    XHCITRB ev_trb;
647
    dma_addr_t addr;
648 649 650 651 652

    ev_trb.parameter = cpu_to_le64(event->ptr);
    ev_trb.status = cpu_to_le32(event->length | (event->ccode << 24));
    ev_trb.control = (event->slotid << 24) | (event->epid << 16) |
                     event->flags | (event->type << TRB_TYPE_SHIFT);
G
Gerd Hoffmann 已提交
653
    if (intr->er_pcs) {
654 655 656 657
        ev_trb.control |= TRB_C;
    }
    ev_trb.control = cpu_to_le32(ev_trb.control);

G
Gerd Hoffmann 已提交
658
    trace_usb_xhci_queue_event(v, intr->er_ep_idx, trb_name(&ev_trb),
659 660
                               event_name(event), ev_trb.parameter,
                               ev_trb.status, ev_trb.control);
661

G
Gerd Hoffmann 已提交
662
    addr = intr->er_start + TRB_SIZE*intr->er_ep_idx;
663
    pci_dma_write(pci_dev, addr, &ev_trb, TRB_SIZE);
664

G
Gerd Hoffmann 已提交
665 666 667 668
    intr->er_ep_idx++;
    if (intr->er_ep_idx >= intr->er_size) {
        intr->er_ep_idx = 0;
        intr->er_pcs = !intr->er_pcs;
669 670 671
    }
}

G
Gerd Hoffmann 已提交
672
static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v)
673
{
G
Gerd Hoffmann 已提交
674
    XHCIInterrupter *intr;
675
    dma_addr_t erdp;
676 677
    unsigned int dp_idx;

678 679
    if (v >= xhci->numintrs) {
        DPRINTF("intr nr out of range (%d >= %d)\n", v, xhci->numintrs);
G
Gerd Hoffmann 已提交
680 681 682 683
        return;
    }
    intr = &xhci->intr[v];

G
Gerd Hoffmann 已提交
684 685 686
    erdp = xhci_addr64(intr->erdp_low, intr->erdp_high);
    if (erdp < intr->er_start ||
        erdp >= (intr->er_start + TRB_SIZE*intr->er_size)) {
687 688
        DPRINTF("xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp);
        DPRINTF("xhci: ER[%d] at "DMA_ADDR_FMT" len %d\n",
G
Gerd Hoffmann 已提交
689
                v, intr->er_start, intr->er_size);
690 691 692 693
        xhci_die(xhci);
        return;
    }

G
Gerd Hoffmann 已提交
694 695
    dp_idx = (erdp - intr->er_start) / TRB_SIZE;
    assert(dp_idx < intr->er_size);
696

697 698
    if ((intr->er_ep_idx + 2) % intr->er_size == dp_idx) {
        DPRINTF("xhci: ER %d full, send ring full error\n", v);
699
        XHCIEvent full = {ER_HOST_CONTROLLER, CC_EVENT_RING_FULL_ERROR};
700 701 702
        xhci_write_event(xhci, &full, v);
    } else if ((intr->er_ep_idx + 1) % intr->er_size == dp_idx) {
        DPRINTF("xhci: ER %d full, drop event\n", v);
703
    } else {
G
Gerd Hoffmann 已提交
704
        xhci_write_event(xhci, event, v);
705 706
    }

G
Gerd Hoffmann 已提交
707
    xhci_intr_raise(xhci, v);
708 709 710
}

static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring,
711
                           dma_addr_t base)
712 713 714 715 716 717
{
    ring->dequeue = base;
    ring->ccs = 1;
}

static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
718
                               dma_addr_t *addr)
719
{
720
    PCIDevice *pci_dev = PCI_DEVICE(xhci);
721
    uint32_t link_cnt = 0;
722

723 724
    while (1) {
        TRBType type;
725
        pci_dma_read(pci_dev, ring->dequeue, trb, TRB_SIZE);
726 727 728 729 730 731
        trb->addr = ring->dequeue;
        trb->ccs = ring->ccs;
        le64_to_cpus(&trb->parameter);
        le32_to_cpus(&trb->status);
        le32_to_cpus(&trb->control);

G
Gerd Hoffmann 已提交
732 733
        trace_usb_xhci_fetch_trb(ring->dequeue, trb_name(trb),
                                 trb->parameter, trb->status, trb->control);
734 735 736 737 738 739 740 741 742 743 744 745 746 747

        if ((trb->control & TRB_C) != ring->ccs) {
            return 0;
        }

        type = TRB_TYPE(*trb);

        if (type != TR_LINK) {
            if (addr) {
                *addr = ring->dequeue;
            }
            ring->dequeue += TRB_SIZE;
            return type;
        } else {
748
            if (++link_cnt > TRB_LINK_LIMIT) {
G
Gerd Hoffmann 已提交
749
                trace_usb_xhci_enforced_limit("trb-link");
750 751
                return 0;
            }
752 753 754 755 756 757 758 759 760 761
            ring->dequeue = xhci_mask64(trb->parameter);
            if (trb->control & TRB_LK_TC) {
                ring->ccs = !ring->ccs;
            }
        }
    }
}

static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
{
762
    PCIDevice *pci_dev = PCI_DEVICE(xhci);
763 764
    XHCITRB trb;
    int length = 0;
765
    dma_addr_t dequeue = ring->dequeue;
766 767 768
    bool ccs = ring->ccs;
    /* hack to bundle together the two/three TDs that make a setup transfer */
    bool control_td_set = 0;
769
    uint32_t link_cnt = 0;
770 771 772

    while (1) {
        TRBType type;
773
        pci_dma_read(pci_dev, dequeue, &trb, TRB_SIZE);
774 775 776 777 778 779 780 781 782 783 784
        le64_to_cpus(&trb.parameter);
        le32_to_cpus(&trb.status);
        le32_to_cpus(&trb.control);

        if ((trb.control & TRB_C) != ccs) {
            return -length;
        }

        type = TRB_TYPE(trb);

        if (type == TR_LINK) {
785 786 787
            if (++link_cnt > TRB_LINK_LIMIT) {
                return -length;
            }
788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
            dequeue = xhci_mask64(trb.parameter);
            if (trb.control & TRB_LK_TC) {
                ccs = !ccs;
            }
            continue;
        }

        length += 1;
        dequeue += TRB_SIZE;

        if (type == TR_SETUP) {
            control_td_set = 1;
        } else if (type == TR_STATUS) {
            control_td_set = 0;
        }

        if (!control_td_set && !(trb.control & TRB_TR_CH)) {
            return length;
        }
    }
}

G
Gerd Hoffmann 已提交
810
static void xhci_er_reset(XHCIState *xhci, int v)
811
{
G
Gerd Hoffmann 已提交
812
    XHCIInterrupter *intr = &xhci->intr[v];
813
    XHCIEvRingSeg seg;
814
    dma_addr_t erstba = xhci_addr64(intr->erstba_low, intr->erstba_high);
815

816
    if (intr->erstsz == 0 || erstba == 0) {
G
Gerd Hoffmann 已提交
817 818 819 820 821
        /* disabled */
        intr->er_start = 0;
        intr->er_size = 0;
        return;
    }
822
    /* cache the (sole) event ring segment location */
G
Gerd Hoffmann 已提交
823
    if (intr->erstsz != 1) {
824
        DPRINTF("xhci: invalid value for ERSTSZ: %d\n", intr->erstsz);
825 826 827
        xhci_die(xhci);
        return;
    }
828
    pci_dma_read(PCI_DEVICE(xhci), erstba, &seg, sizeof(seg));
829 830 831 832
    le32_to_cpus(&seg.addr_low);
    le32_to_cpus(&seg.addr_high);
    le32_to_cpus(&seg.size);
    if (seg.size < 16 || seg.size > 4096) {
833
        DPRINTF("xhci: invalid value for segment size: %d\n", seg.size);
834 835 836
        xhci_die(xhci);
        return;
    }
G
Gerd Hoffmann 已提交
837 838
    intr->er_start = xhci_addr64(seg.addr_low, seg.addr_high);
    intr->er_size = seg.size;
839

G
Gerd Hoffmann 已提交
840 841
    intr->er_ep_idx = 0;
    intr->er_pcs = 1;
842

G
Gerd Hoffmann 已提交
843 844
    DPRINTF("xhci: event ring[%d]:" DMA_ADDR_FMT " [%d]\n",
            v, intr->er_start, intr->er_size);
845 846 847 848
}

static void xhci_run(XHCIState *xhci)
{
G
Gerd Hoffmann 已提交
849
    trace_usb_xhci_run();
850
    xhci->usbsts &= ~USBSTS_HCH;
851
    xhci->mfindex_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
852 853 854 855
}

static void xhci_stop(XHCIState *xhci)
{
G
Gerd Hoffmann 已提交
856
    trace_usb_xhci_stop();
857 858 859 860
    xhci->usbsts |= USBSTS_HCH;
    xhci->crcr_low &= ~CRCR_CRR;
}

G
Gerd Hoffmann 已提交
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886
static XHCIStreamContext *xhci_alloc_stream_contexts(unsigned count,
                                                     dma_addr_t base)
{
    XHCIStreamContext *stctx;
    unsigned int i;

    stctx = g_new0(XHCIStreamContext, count);
    for (i = 0; i < count; i++) {
        stctx[i].pctx = base + i * 16;
        stctx[i].sct = -1;
    }
    return stctx;
}

static void xhci_reset_streams(XHCIEPContext *epctx)
{
    unsigned int i;

    for (i = 0; i < epctx->nr_pstreams; i++) {
        epctx->pstreams[i].sct = -1;
    }
}

static void xhci_alloc_streams(XHCIEPContext *epctx, dma_addr_t base)
{
    assert(epctx->pstreams == NULL);
887
    epctx->nr_pstreams = 2 << epctx->max_pstreams;
G
Gerd Hoffmann 已提交
888 889 890 891 892 893 894 895 896 897 898 899
    epctx->pstreams = xhci_alloc_stream_contexts(epctx->nr_pstreams, base);
}

static void xhci_free_streams(XHCIEPContext *epctx)
{
    assert(epctx->pstreams != NULL);

    g_free(epctx->pstreams);
    epctx->pstreams = NULL;
    epctx->nr_pstreams = 0;
}

900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
static int xhci_epmask_to_eps_with_streams(XHCIState *xhci,
                                           unsigned int slotid,
                                           uint32_t epmask,
                                           XHCIEPContext **epctxs,
                                           USBEndpoint **eps)
{
    XHCISlot *slot;
    XHCIEPContext *epctx;
    USBEndpoint *ep;
    int i, j;

    assert(slotid >= 1 && slotid <= xhci->numslots);

    slot = &xhci->slots[slotid - 1];

    for (i = 2, j = 0; i <= 31; i++) {
G
Gerd Hoffmann 已提交
916
        if (!(epmask & (1u << i))) {
917 918 919 920
            continue;
        }

        epctx = slot->eps[i - 1];
921
        ep = xhci_epid_to_usbep(epctx);
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997
        if (!epctx || !epctx->nr_pstreams || !ep) {
            continue;
        }

        if (epctxs) {
            epctxs[j] = epctx;
        }
        eps[j++] = ep;
    }
    return j;
}

static void xhci_free_device_streams(XHCIState *xhci, unsigned int slotid,
                                     uint32_t epmask)
{
    USBEndpoint *eps[30];
    int nr_eps;

    nr_eps = xhci_epmask_to_eps_with_streams(xhci, slotid, epmask, NULL, eps);
    if (nr_eps) {
        usb_device_free_streams(eps[0]->dev, eps, nr_eps);
    }
}

static TRBCCode xhci_alloc_device_streams(XHCIState *xhci, unsigned int slotid,
                                          uint32_t epmask)
{
    XHCIEPContext *epctxs[30];
    USBEndpoint *eps[30];
    int i, r, nr_eps, req_nr_streams, dev_max_streams;

    nr_eps = xhci_epmask_to_eps_with_streams(xhci, slotid, epmask, epctxs,
                                             eps);
    if (nr_eps == 0) {
        return CC_SUCCESS;
    }

    req_nr_streams = epctxs[0]->nr_pstreams;
    dev_max_streams = eps[0]->max_streams;

    for (i = 1; i < nr_eps; i++) {
        /*
         * HdG: I don't expect these to ever trigger, but if they do we need
         * to come up with another solution, ie group identical endpoints
         * together and make an usb_device_alloc_streams call per group.
         */
        if (epctxs[i]->nr_pstreams != req_nr_streams) {
            FIXME("guest streams config not identical for all eps");
            return CC_RESOURCE_ERROR;
        }
        if (eps[i]->max_streams != dev_max_streams) {
            FIXME("device streams config not identical for all eps");
            return CC_RESOURCE_ERROR;
        }
    }

    /*
     * max-streams in both the device descriptor and in the controller is a
     * power of 2. But stream id 0 is reserved, so if a device can do up to 4
     * streams the guest will ask for 5 rounded up to the next power of 2 which
     * becomes 8. For emulated devices usb_device_alloc_streams is a nop.
     *
     * For redirected devices however this is an issue, as there we must ask
     * the real xhci controller to alloc streams, and the host driver for the
     * real xhci controller will likely disallow allocating more streams then
     * the device can handle.
     *
     * So we limit the requested nr_streams to the maximum number the device
     * can handle.
     */
    if (req_nr_streams > dev_max_streams) {
        req_nr_streams = dev_max_streams;
    }

    r = usb_device_alloc_streams(eps[0]->dev, eps, nr_eps, req_nr_streams);
    if (r != 0) {
998
        DPRINTF("xhci: alloc streams failed\n");
999 1000 1001 1002 1003 1004
        return CC_RESOURCE_ERROR;
    }

    return CC_SUCCESS;
}

G
Gerd Hoffmann 已提交
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037
static XHCIStreamContext *xhci_find_stream(XHCIEPContext *epctx,
                                           unsigned int streamid,
                                           uint32_t *cc_error)
{
    XHCIStreamContext *sctx;
    dma_addr_t base;
    uint32_t ctx[2], sct;

    assert(streamid != 0);
    if (epctx->lsa) {
        if (streamid >= epctx->nr_pstreams) {
            *cc_error = CC_INVALID_STREAM_ID_ERROR;
            return NULL;
        }
        sctx = epctx->pstreams + streamid;
    } else {
        FIXME("secondary streams not implemented yet");
    }

    if (sctx->sct == -1) {
        xhci_dma_read_u32s(epctx->xhci, sctx->pctx, ctx, sizeof(ctx));
        sct = (ctx[0] >> 1) & 0x07;
        if (epctx->lsa && sct != 1) {
            *cc_error = CC_INVALID_STREAM_TYPE_ERROR;
            return NULL;
        }
        sctx->sct = sct;
        base = xhci_addr64(ctx[0] & ~0xf, ctx[1]);
        xhci_ring_init(epctx->xhci, &sctx->ring, base);
    }
    return sctx;
}

1038
static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
G
Gerd Hoffmann 已提交
1039
                              XHCIStreamContext *sctx, uint32_t state)
1040
{
1041
    XHCIRing *ring = NULL;
1042
    uint32_t ctx[5];
G
Gerd Hoffmann 已提交
1043
    uint32_t ctx2[2];
1044

D
David Gibson 已提交
1045
    xhci_dma_read_u32s(xhci, epctx->pctx, ctx, sizeof(ctx));
1046 1047
    ctx[0] &= ~EP_STATE_MASK;
    ctx[0] |= state;
G
Gerd Hoffmann 已提交
1048 1049 1050 1051

    /* update ring dequeue ptr */
    if (epctx->nr_pstreams) {
        if (sctx != NULL) {
1052
            ring = &sctx->ring;
G
Gerd Hoffmann 已提交
1053 1054 1055 1056 1057 1058 1059
            xhci_dma_read_u32s(xhci, sctx->pctx, ctx2, sizeof(ctx2));
            ctx2[0] &= 0xe;
            ctx2[0] |= sctx->ring.dequeue | sctx->ring.ccs;
            ctx2[1] = (sctx->ring.dequeue >> 16) >> 16;
            xhci_dma_write_u32s(xhci, sctx->pctx, ctx2, sizeof(ctx2));
        }
    } else {
1060 1061 1062 1063 1064 1065
        ring = &epctx->ring;
    }
    if (ring) {
        ctx[2] = ring->dequeue | ring->ccs;
        ctx[3] = (ring->dequeue >> 16) >> 16;

G
Gerd Hoffmann 已提交
1066 1067 1068 1069
        DPRINTF("xhci: set epctx: " DMA_ADDR_FMT " state=%d dequeue=%08x%08x\n",
                epctx->pctx, state, ctx[3], ctx[2]);
    }

D
David Gibson 已提交
1070
    xhci_dma_write_u32s(xhci, epctx->pctx, ctx, sizeof(ctx));
1071 1072 1073 1074 1075
    if (epctx->state != state) {
        trace_usb_xhci_ep_state(epctx->slotid, epctx->epid,
                                ep_state_name(epctx->state),
                                ep_state_name(state));
    }
1076 1077 1078
    epctx->state = state;
}

G
Gerd Hoffmann 已提交
1079 1080 1081
static void xhci_ep_kick_timer(void *opaque)
{
    XHCIEPContext *epctx = opaque;
G
Gerd Hoffmann 已提交
1082
    xhci_kick_epctx(epctx, 0);
G
Gerd Hoffmann 已提交
1083 1084
}

G
Gerd Hoffmann 已提交
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
static XHCIEPContext *xhci_alloc_epctx(XHCIState *xhci,
                                       unsigned int slotid,
                                       unsigned int epid)
{
    XHCIEPContext *epctx;

    epctx = g_new0(XHCIEPContext, 1);
    epctx->xhci = xhci;
    epctx->slotid = slotid;
    epctx->epid = epid;

1096
    QTAILQ_INIT(&epctx->transfers);
1097
    epctx->kick_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_ep_kick_timer, epctx);
G
Gerd Hoffmann 已提交
1098 1099 1100 1101

    return epctx;
}

G
Gerd Hoffmann 已提交
1102 1103
static void xhci_init_epctx(XHCIEPContext *epctx,
                            dma_addr_t pctx, uint32_t *ctx)
1104
{
1105
    dma_addr_t dequeue;
1106 1107 1108 1109 1110 1111 1112

    dequeue = xhci_addr64(ctx[2] & ~0xf, ctx[3]);

    epctx->type = (ctx[1] >> EP_TYPE_SHIFT) & EP_TYPE_MASK;
    epctx->pctx = pctx;
    epctx->max_psize = ctx[1]>>16;
    epctx->max_psize *= 1+((ctx[1]>>8)&0xff);
1113
    epctx->max_pstreams = (ctx[0] >> 10) & epctx->xhci->max_pstreams_mask;
G
Gerd Hoffmann 已提交
1114 1115 1116 1117
    epctx->lsa = (ctx[0] >> 15) & 1;
    if (epctx->max_pstreams) {
        xhci_alloc_streams(epctx, dequeue);
    } else {
G
Gerd Hoffmann 已提交
1118
        xhci_ring_init(epctx->xhci, &epctx->ring, dequeue);
G
Gerd Hoffmann 已提交
1119 1120
        epctx->ring.ccs = ctx[2] & 1;
    }
1121

1122
    epctx->interval = 1 << ((ctx[0] >> 16) & 0xff);
G
Gerd Hoffmann 已提交
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
}

static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
                               unsigned int epid, dma_addr_t pctx,
                               uint32_t *ctx)
{
    XHCISlot *slot;
    XHCIEPContext *epctx;

    trace_usb_xhci_ep_enable(slotid, epid);
    assert(slotid >= 1 && slotid <= xhci->numslots);
    assert(epid >= 1 && epid <= 31);

    slot = &xhci->slots[slotid-1];
    if (slot->eps[epid-1]) {
        xhci_disable_ep(xhci, slotid, epid);
    }

    epctx = xhci_alloc_epctx(xhci, slotid, epid);
    slot->eps[epid-1] = epctx;
    xhci_init_epctx(epctx, pctx, ctx);

G
Gonglei 已提交
1145 1146 1147
    DPRINTF("xhci: endpoint %d.%d type is %d, max transaction (burst) "
            "size is %d\n", epid/2, epid%2, epctx->type, epctx->max_psize);

G
Gerd Hoffmann 已提交
1148 1149
    epctx->mfindex_last = 0;

1150 1151 1152 1153 1154 1155 1156
    epctx->state = EP_RUNNING;
    ctx[0] &= ~EP_STATE_MASK;
    ctx[0] |= EP_RUNNING;

    return CC_SUCCESS;
}

1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
static XHCITransfer *xhci_ep_alloc_xfer(XHCIEPContext *epctx,
                                        uint32_t length)
{
    uint32_t limit = epctx->nr_pstreams + 16;
    XHCITransfer *xfer;

    if (epctx->xfer_count >= limit) {
        return NULL;
    }

    xfer = g_new0(XHCITransfer, 1);
    xfer->epctx = epctx;
    xfer->trbs = g_new(XHCITRB, length);
    xfer->trb_count = length;
    usb_packet_init(&xfer->packet);

    QTAILQ_INSERT_TAIL(&epctx->transfers, xfer, next);
    epctx->xfer_count++;

    return xfer;
}

static void xhci_ep_free_xfer(XHCITransfer *xfer)
{
    QTAILQ_REMOVE(&xfer->epctx->transfers, xfer, next);
    xfer->epctx->xfer_count--;

    usb_packet_cleanup(&xfer->packet);
    g_free(xfer->trbs);
    g_free(xfer);
}

1189
static int xhci_ep_nuke_one_xfer(XHCITransfer *t, TRBCCode report)
1190 1191 1192
{
    int killed = 0;

1193 1194 1195 1196 1197
    if (report && (t->running_async || t->running_retry)) {
        t->status = report;
        xhci_xfer_report(t);
    }

1198 1199 1200 1201 1202 1203
    if (t->running_async) {
        usb_cancel_packet(&t->packet);
        t->running_async = 0;
        killed = 1;
    }
    if (t->running_retry) {
G
Gerd Hoffmann 已提交
1204 1205 1206
        if (t->epctx) {
            t->epctx->retry = NULL;
            timer_del(t->epctx->kick_timer);
1207 1208
        }
        t->running_retry = 0;
1209
        killed = 1;
1210
    }
1211
    g_free(t->trbs);
1212 1213

    t->trbs = NULL;
1214
    t->trb_count = 0;
1215 1216 1217 1218

    return killed;
}

1219
static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
1220
                               unsigned int epid, TRBCCode report)
1221 1222 1223
{
    XHCISlot *slot;
    XHCIEPContext *epctx;
1224 1225
    XHCITransfer *xfer;
    int killed = 0;
1226
    USBEndpoint *ep = NULL;
1227
    assert(slotid >= 1 && slotid <= xhci->numslots);
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
    assert(epid >= 1 && epid <= 31);

    DPRINTF("xhci_ep_nuke_xfers(%d, %d)\n", slotid, epid);

    slot = &xhci->slots[slotid-1];

    if (!slot->eps[epid-1]) {
        return 0;
    }

    epctx = slot->eps[epid-1];

1240 1241 1242 1243 1244 1245
    for (;;) {
        xfer = QTAILQ_FIRST(&epctx->transfers);
        if (xfer == NULL) {
            break;
        }
        killed += xhci_ep_nuke_one_xfer(xfer, report);
1246 1247 1248
        if (killed) {
            report = 0; /* Only report once */
        }
1249
        xhci_ep_free_xfer(xfer);
1250
    }
1251

1252
    ep = xhci_epid_to_usbep(epctx);
1253 1254 1255
    if (ep) {
        usb_device_ep_stopped(ep->dev, ep);
    }
1256 1257 1258 1259 1260 1261 1262 1263 1264
    return killed;
}

static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid,
                               unsigned int epid)
{
    XHCISlot *slot;
    XHCIEPContext *epctx;

G
Gerd Hoffmann 已提交
1265
    trace_usb_xhci_ep_disable(slotid, epid);
1266
    assert(slotid >= 1 && slotid <= xhci->numslots);
1267 1268 1269 1270 1271 1272 1273 1274 1275
    assert(epid >= 1 && epid <= 31);

    slot = &xhci->slots[slotid-1];

    if (!slot->eps[epid-1]) {
        DPRINTF("xhci: slot %d ep %d already disabled\n", slotid, epid);
        return CC_SUCCESS;
    }

1276
    xhci_ep_nuke_xfers(xhci, slotid, epid, 0);
1277 1278 1279

    epctx = slot->eps[epid-1];

G
Gerd Hoffmann 已提交
1280 1281 1282 1283
    if (epctx->nr_pstreams) {
        xhci_free_streams(epctx);
    }

R
Roman Kagan 已提交
1284 1285 1286 1287
    /* only touch guest RAM if we're not resetting the HC */
    if (xhci->dcbaap_low || xhci->dcbaap_high) {
        xhci_set_ep_state(xhci, epctx, NULL, EP_DISABLED);
    }
1288

1289
    timer_free(epctx->kick_timer);
1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
    g_free(epctx);
    slot->eps[epid-1] = NULL;

    return CC_SUCCESS;
}

static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned int slotid,
                             unsigned int epid)
{
    XHCISlot *slot;
    XHCIEPContext *epctx;

G
Gerd Hoffmann 已提交
1302
    trace_usb_xhci_ep_stop(slotid, epid);
1303
    assert(slotid >= 1 && slotid <= xhci->numslots);
1304 1305

    if (epid < 1 || epid > 31) {
1306
        DPRINTF("xhci: bad ep %d\n", epid);
1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
        return CC_TRB_ERROR;
    }

    slot = &xhci->slots[slotid-1];

    if (!slot->eps[epid-1]) {
        DPRINTF("xhci: slot %d ep %d not enabled\n", slotid, epid);
        return CC_EP_NOT_ENABLED_ERROR;
    }

1317
    if (xhci_ep_nuke_xfers(xhci, slotid, epid, CC_STOPPED) > 0) {
1318
        DPRINTF("xhci: FIXME: endpoint stopped w/ xfers running, "
1319 1320 1321 1322 1323
                "data might be lost\n");
    }

    epctx = slot->eps[epid-1];

G
Gerd Hoffmann 已提交
1324 1325 1326 1327 1328
    xhci_set_ep_state(xhci, epctx, NULL, EP_STOPPED);

    if (epctx->nr_pstreams) {
        xhci_reset_streams(epctx);
    }
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338

    return CC_SUCCESS;
}

static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
                              unsigned int epid)
{
    XHCISlot *slot;
    XHCIEPContext *epctx;

G
Gerd Hoffmann 已提交
1339
    trace_usb_xhci_ep_reset(slotid, epid);
1340
    assert(slotid >= 1 && slotid <= xhci->numslots);
1341 1342

    if (epid < 1 || epid > 31) {
1343
        DPRINTF("xhci: bad ep %d\n", epid);
1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356
        return CC_TRB_ERROR;
    }

    slot = &xhci->slots[slotid-1];

    if (!slot->eps[epid-1]) {
        DPRINTF("xhci: slot %d ep %d not enabled\n", slotid, epid);
        return CC_EP_NOT_ENABLED_ERROR;
    }

    epctx = slot->eps[epid-1];

    if (epctx->state != EP_HALTED) {
1357
        DPRINTF("xhci: reset EP while EP %d not halted (%d)\n",
1358 1359 1360 1361
                epid, epctx->state);
        return CC_CONTEXT_STATE_ERROR;
    }

1362
    if (xhci_ep_nuke_xfers(xhci, slotid, epid, 0) > 0) {
1363
        DPRINTF("xhci: FIXME: endpoint reset w/ xfers running, "
1364 1365 1366
                "data might be lost\n");
    }

G
Gerd Hoffmann 已提交
1367
    if (!xhci->slots[slotid-1].uport ||
1368 1369
        !xhci->slots[slotid-1].uport->dev ||
        !xhci->slots[slotid-1].uport->dev->attached) {
1370 1371 1372
        return CC_USB_TRANSACTION_ERROR;
    }

G
Gerd Hoffmann 已提交
1373 1374 1375 1376 1377
    xhci_set_ep_state(xhci, epctx, NULL, EP_STOPPED);

    if (epctx->nr_pstreams) {
        xhci_reset_streams(epctx);
    }
1378 1379 1380 1381 1382

    return CC_SUCCESS;
}

static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid,
G
Gerd Hoffmann 已提交
1383 1384
                                    unsigned int epid, unsigned int streamid,
                                    uint64_t pdequeue)
1385 1386 1387
{
    XHCISlot *slot;
    XHCIEPContext *epctx;
G
Gerd Hoffmann 已提交
1388
    XHCIStreamContext *sctx;
1389
    dma_addr_t dequeue;
1390

1391
    assert(slotid >= 1 && slotid <= xhci->numslots);
1392 1393

    if (epid < 1 || epid > 31) {
1394
        DPRINTF("xhci: bad ep %d\n", epid);
1395 1396 1397
        return CC_TRB_ERROR;
    }

G
Gerd Hoffmann 已提交
1398
    trace_usb_xhci_ep_set_dequeue(slotid, epid, streamid, pdequeue);
1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410
    dequeue = xhci_mask64(pdequeue);

    slot = &xhci->slots[slotid-1];

    if (!slot->eps[epid-1]) {
        DPRINTF("xhci: slot %d ep %d not enabled\n", slotid, epid);
        return CC_EP_NOT_ENABLED_ERROR;
    }

    epctx = slot->eps[epid-1];

    if (epctx->state != EP_STOPPED) {
1411
        DPRINTF("xhci: set EP dequeue pointer while EP %d not stopped\n", epid);
1412 1413 1414
        return CC_CONTEXT_STATE_ERROR;
    }

G
Gerd Hoffmann 已提交
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
    if (epctx->nr_pstreams) {
        uint32_t err;
        sctx = xhci_find_stream(epctx, streamid, &err);
        if (sctx == NULL) {
            return err;
        }
        xhci_ring_init(xhci, &sctx->ring, dequeue & ~0xf);
        sctx->ring.ccs = dequeue & 1;
    } else {
        sctx = NULL;
        xhci_ring_init(xhci, &epctx->ring, dequeue & ~0xF);
        epctx->ring.ccs = dequeue & 1;
    }
1428

G
Gerd Hoffmann 已提交
1429
    xhci_set_ep_state(xhci, epctx, sctx, EP_STOPPED);
1430 1431 1432 1433

    return CC_SUCCESS;
}

1434
static int xhci_xfer_create_sgl(XHCITransfer *xfer, int in_xfer)
1435
{
G
Gerd Hoffmann 已提交
1436
    XHCIState *xhci = xfer->epctx->xhci;
G
Gerd Hoffmann 已提交
1437
    int i;
1438

1439
    xfer->int_req = false;
1440
    pci_dma_sglist_init(&xfer->sgl, PCI_DEVICE(xhci), xfer->trb_count);
1441 1442
    for (i = 0; i < xfer->trb_count; i++) {
        XHCITRB *trb = &xfer->trbs[i];
1443
        dma_addr_t addr;
1444 1445
        unsigned int chunk = 0;

1446 1447 1448 1449
        if (trb->control & TRB_TR_IOC) {
            xfer->int_req = true;
        }

1450 1451 1452
        switch (TRB_TYPE(*trb)) {
        case TR_DATA:
            if ((!(trb->control & TRB_TR_DIR)) != (!in_xfer)) {
1453
                DPRINTF("xhci: data direction mismatch for TR_DATA\n");
G
Gerd Hoffmann 已提交
1454
                goto err;
1455 1456 1457 1458 1459
            }
            /* fallthrough */
        case TR_NORMAL:
        case TR_ISOCH:
            addr = xhci_mask64(trb->parameter);
G
Gerd Hoffmann 已提交
1460 1461 1462
            chunk = trb->status & 0x1ffff;
            if (trb->control & TRB_TR_IDT) {
                if (chunk > 8 || in_xfer) {
1463
                    DPRINTF("xhci: invalid immediate data TRB\n");
G
Gerd Hoffmann 已提交
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494
                    goto err;
                }
                qemu_sglist_add(&xfer->sgl, trb->addr, chunk);
            } else {
                qemu_sglist_add(&xfer->sgl, addr, chunk);
            }
            break;
        }
    }

    return 0;

err:
    qemu_sglist_destroy(&xfer->sgl);
    xhci_die(xhci);
    return -1;
}

static void xhci_xfer_unmap(XHCITransfer *xfer)
{
    usb_packet_unmap(&xfer->packet, &xfer->sgl);
    qemu_sglist_destroy(&xfer->sgl);
}

static void xhci_xfer_report(XHCITransfer *xfer)
{
    uint32_t edtla = 0;
    unsigned int left;
    bool reported = 0;
    bool shortpkt = 0;
    XHCIEvent event = {ER_TRANSFER, CC_SUCCESS};
G
Gerd Hoffmann 已提交
1495
    XHCIState *xhci = xfer->epctx->xhci;
G
Gerd Hoffmann 已提交
1496 1497
    int i;

1498
    left = xfer->packet.actual_length;
G
Gerd Hoffmann 已提交
1499 1500 1501 1502 1503 1504

    for (i = 0; i < xfer->trb_count; i++) {
        XHCITRB *trb = &xfer->trbs[i];
        unsigned int chunk = 0;

        switch (TRB_TYPE(*trb)) {
1505 1506 1507 1508 1509 1510
        case TR_SETUP:
            chunk = trb->status & 0x1ffff;
            if (chunk > 8) {
                chunk = 8;
            }
            break;
G
Gerd Hoffmann 已提交
1511 1512 1513
        case TR_DATA:
        case TR_NORMAL:
        case TR_ISOCH:
1514 1515 1516
            chunk = trb->status & 0x1ffff;
            if (chunk > left) {
                chunk = left;
G
Gerd Hoffmann 已提交
1517 1518
                if (xfer->status == CC_SUCCESS) {
                    shortpkt = 1;
1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529
                }
            }
            left -= chunk;
            edtla += chunk;
            break;
        case TR_STATUS:
            reported = 0;
            shortpkt = 0;
            break;
        }

1530 1531 1532
        if (!reported && ((trb->control & TRB_TR_IOC) ||
                          (shortpkt && (trb->control & TRB_TR_ISP)) ||
                          (xfer->status != CC_SUCCESS && left == 0))) {
1533 1534
            event.slotid = xfer->epctx->slotid;
            event.epid = xfer->epctx->epid;
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549
            event.length = (trb->status & 0x1ffff) - chunk;
            event.flags = 0;
            event.ptr = trb->addr;
            if (xfer->status == CC_SUCCESS) {
                event.ccode = shortpkt ? CC_SHORT_PACKET : CC_SUCCESS;
            } else {
                event.ccode = xfer->status;
            }
            if (TRB_TYPE(*trb) == TR_EVDATA) {
                event.ptr = trb->parameter;
                event.flags |= TRB_EV_ED;
                event.length = edtla & 0xffffff;
                DPRINTF("xhci_xfer_data: EDTLA=%d\n", event.length);
                edtla = 0;
            }
G
Gerd Hoffmann 已提交
1550
            xhci_event(xhci, &event, TRB_INTR(*trb));
1551
            reported = 1;
G
Gerd Hoffmann 已提交
1552 1553 1554
            if (xfer->status != CC_SUCCESS) {
                return;
            }
1555
        }
G
Gerd Hoffmann 已提交
1556 1557 1558 1559 1560 1561 1562 1563

        switch (TRB_TYPE(*trb)) {
        case TR_SETUP:
            reported = 0;
            shortpkt = 0;
            break;
        }

1564 1565 1566 1567 1568
    }
}

static void xhci_stall_ep(XHCITransfer *xfer)
{
G
Gerd Hoffmann 已提交
1569 1570
    XHCIEPContext *epctx = xfer->epctx;
    XHCIState *xhci = epctx->xhci;
G
Gerd Hoffmann 已提交
1571 1572
    uint32_t err;
    XHCIStreamContext *sctx;
1573

1574 1575 1576 1577 1578
    if (epctx->type == ET_ISO_IN || epctx->type == ET_ISO_OUT) {
        /* never halt isoch endpoints, 4.10.2 */
        return;
    }

G
Gerd Hoffmann 已提交
1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
    if (epctx->nr_pstreams) {
        sctx = xhci_find_stream(epctx, xfer->streamid, &err);
        if (sctx == NULL) {
            return;
        }
        sctx->ring.dequeue = xfer->trbs[0].addr;
        sctx->ring.ccs = xfer->trbs[0].ccs;
        xhci_set_ep_state(xhci, epctx, sctx, EP_HALTED);
    } else {
        epctx->ring.dequeue = xfer->trbs[0].addr;
        epctx->ring.ccs = xfer->trbs[0].ccs;
        xhci_set_ep_state(xhci, epctx, NULL, EP_HALTED);
    }
1592 1593
}

1594 1595
static int xhci_setup_packet(XHCITransfer *xfer)
{
1596 1597 1598 1599
    USBEndpoint *ep;
    int dir;

    dir = xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT;
1600 1601 1602 1603

    if (xfer->packet.ep) {
        ep = xfer->packet.ep;
    } else {
1604
        ep = xhci_epid_to_usbep(xfer->epctx);
1605
        if (!ep) {
1606
            DPRINTF("xhci: slot %d has no device\n",
L
Ladi Prosek 已提交
1607
                    xfer->epctx->slotid);
1608 1609 1610 1611
            return -1;
        }
    }

1612
    xhci_xfer_create_sgl(xfer, dir == USB_TOKEN_IN); /* Also sets int_req */
G
Gerd Hoffmann 已提交
1613
    usb_packet_setup(&xfer->packet, dir, ep, xfer->streamid,
G
Gerd Hoffmann 已提交
1614
                     xfer->trbs[0].addr, false, xfer->int_req);
1615
    usb_packet_map(&xfer->packet, &xfer->sgl);
1616
    DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n",
1617
            xfer->packet.pid, ep->dev->addr, ep->nr);
1618 1619 1620
    return 0;
}

1621
static int xhci_try_complete_packet(XHCITransfer *xfer)
1622
{
1623
    if (xfer->packet.status == USB_RET_ASYNC) {
G
Gerd Hoffmann 已提交
1624
        trace_usb_xhci_xfer_async(xfer);
G
Gerd Hoffmann 已提交
1625 1626 1627 1628
        xfer->running_async = 1;
        xfer->running_retry = 0;
        xfer->complete = 0;
        return 0;
1629
    } else if (xfer->packet.status == USB_RET_NAK) {
G
Gerd Hoffmann 已提交
1630
        trace_usb_xhci_xfer_nak(xfer);
G
Gerd Hoffmann 已提交
1631 1632
        xfer->running_async = 0;
        xfer->running_retry = 1;
1633 1634 1635
        xfer->complete = 0;
        return 0;
    } else {
G
Gerd Hoffmann 已提交
1636 1637
        xfer->running_async = 0;
        xfer->running_retry = 0;
1638
        xfer->complete = 1;
G
Gerd Hoffmann 已提交
1639
        xhci_xfer_unmap(xfer);
1640 1641
    }

1642 1643
    if (xfer->packet.status == USB_RET_SUCCESS) {
        trace_usb_xhci_xfer_success(xfer, xfer->packet.actual_length);
G
Gerd Hoffmann 已提交
1644 1645
        xfer->status = CC_SUCCESS;
        xhci_xfer_report(xfer);
1646 1647 1648 1649
        return 0;
    }

    /* error */
1650 1651
    trace_usb_xhci_xfer_error(xfer, xfer->packet.status);
    switch (xfer->packet.status) {
1652
    case USB_RET_NODEV:
G
Gerd Hoffmann 已提交
1653
    case USB_RET_IOERROR:
1654
        xfer->status = CC_USB_TRANSACTION_ERROR;
G
Gerd Hoffmann 已提交
1655
        xhci_xfer_report(xfer);
1656 1657 1658 1659
        xhci_stall_ep(xfer);
        break;
    case USB_RET_STALL:
        xfer->status = CC_STALL_ERROR;
G
Gerd Hoffmann 已提交
1660
        xhci_xfer_report(xfer);
1661 1662
        xhci_stall_ep(xfer);
        break;
G
Gerd Hoffmann 已提交
1663 1664 1665 1666 1667
    case USB_RET_BABBLE:
        xfer->status = CC_BABBLE_DETECTED;
        xhci_xfer_report(xfer);
        xhci_stall_ep(xfer);
        break;
1668
    default:
1669
        DPRINTF("%s: FIXME: status = %d\n", __func__,
1670
                xfer->packet.status);
G
Gerd Hoffmann 已提交
1671
        FIXME("unhandled USB_RET_*");
1672 1673 1674 1675 1676 1677 1678
    }
    return 0;
}

static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
{
    XHCITRB *trb_setup, *trb_status;
G
Gerd Hoffmann 已提交
1679
    uint8_t bmRequestType;
1680 1681 1682 1683

    trb_setup = &xfer->trbs[0];
    trb_status = &xfer->trbs[xfer->trb_count-1];

1684 1685
    trace_usb_xhci_xfer_start(xfer, xfer->epctx->slotid,
                              xfer->epctx->epid, xfer->streamid);
G
Gerd Hoffmann 已提交
1686

1687 1688 1689 1690 1691 1692 1693
    /* at most one Event Data TRB allowed after STATUS */
    if (TRB_TYPE(*trb_status) == TR_EVDATA && xfer->trb_count > 2) {
        trb_status--;
    }

    /* do some sanity checks */
    if (TRB_TYPE(*trb_setup) != TR_SETUP) {
1694
        DPRINTF("xhci: ep0 first TD not SETUP: %d\n",
1695 1696 1697 1698
                TRB_TYPE(*trb_setup));
        return -1;
    }
    if (TRB_TYPE(*trb_status) != TR_STATUS) {
1699
        DPRINTF("xhci: ep0 last TD not STATUS: %d\n",
1700 1701 1702 1703
                TRB_TYPE(*trb_status));
        return -1;
    }
    if (!(trb_setup->control & TRB_TR_IDT)) {
1704
        DPRINTF("xhci: Setup TRB doesn't have IDT set\n");
1705 1706 1707
        return -1;
    }
    if ((trb_setup->status & 0x1ffff) != 8) {
1708
        DPRINTF("xhci: Setup TRB has bad length (%d)\n",
1709 1710 1711 1712 1713 1714 1715 1716
                (trb_setup->status & 0x1ffff));
        return -1;
    }

    bmRequestType = trb_setup->parameter;

    xfer->in_xfer = bmRequestType & USB_DIR_IN;
    xfer->iso_xfer = false;
1717
    xfer->timed_xfer = false;
1718

1719 1720 1721
    if (xhci_setup_packet(xfer) < 0) {
        return -1;
    }
G
Gerd Hoffmann 已提交
1722 1723
    xfer->packet.parameter = trb_setup->parameter;

1724
    usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
1725
    xhci_try_complete_packet(xfer);
1726 1727 1728
    return 0;
}

1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739
static void xhci_calc_intr_kick(XHCIState *xhci, XHCITransfer *xfer,
                                XHCIEPContext *epctx, uint64_t mfindex)
{
    uint64_t asap = ((mfindex + epctx->interval - 1) &
                     ~(epctx->interval-1));
    uint64_t kick = epctx->mfindex_last + epctx->interval;

    assert(epctx->interval != 0);
    xfer->mfindex_kick = MAX(asap, kick);
}

G
Gerd Hoffmann 已提交
1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752
static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
                               XHCIEPContext *epctx, uint64_t mfindex)
{
    if (xfer->trbs[0].control & TRB_TR_SIA) {
        uint64_t asap = ((mfindex + epctx->interval - 1) &
                         ~(epctx->interval-1));
        if (asap >= epctx->mfindex_last &&
            asap <= epctx->mfindex_last + epctx->interval * 4) {
            xfer->mfindex_kick = epctx->mfindex_last + epctx->interval;
        } else {
            xfer->mfindex_kick = asap;
        }
    } else {
G
Gerd Hoffmann 已提交
1753 1754
        xfer->mfindex_kick = ((xfer->trbs[0].control >> TRB_TR_FRAMEID_SHIFT)
                              & TRB_TR_FRAMEID_MASK) << 3;
G
Gerd Hoffmann 已提交
1755
        xfer->mfindex_kick |= mfindex & ~0x3fff;
G
Gerd Hoffmann 已提交
1756
        if (xfer->mfindex_kick + 0x100 < mfindex) {
G
Gerd Hoffmann 已提交
1757 1758 1759 1760 1761
            xfer->mfindex_kick += 0x4000;
        }
    }
}

1762 1763
static void xhci_check_intr_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
                                     XHCIEPContext *epctx, uint64_t mfindex)
G
Gerd Hoffmann 已提交
1764 1765
{
    if (xfer->mfindex_kick > mfindex) {
1766
        timer_mod(epctx->kick_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
G
Gerd Hoffmann 已提交
1767 1768 1769 1770
                       (xfer->mfindex_kick - mfindex) * 125000);
        xfer->running_retry = 1;
    } else {
        epctx->mfindex_last = xfer->mfindex_kick;
1771
        timer_del(epctx->kick_timer);
G
Gerd Hoffmann 已提交
1772 1773 1774 1775 1776
        xfer->running_retry = 0;
    }
}


1777 1778
static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
{
G
Gerd Hoffmann 已提交
1779
    uint64_t mfindex;
1780

L
Ladi Prosek 已提交
1781
    DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", epctx->slotid, epctx->epid);
1782 1783 1784 1785 1786 1787

    xfer->in_xfer = epctx->type>>2;

    switch(epctx->type) {
    case ET_INTR_OUT:
    case ET_INTR_IN:
1788 1789 1790 1791 1792 1793 1794 1795 1796 1797
        xfer->pkts = 0;
        xfer->iso_xfer = false;
        xfer->timed_xfer = true;
        mfindex = xhci_mfindex_get(xhci);
        xhci_calc_intr_kick(xhci, xfer, epctx, mfindex);
        xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex);
        if (xfer->running_retry) {
            return -1;
        }
        break;
1798 1799
    case ET_BULK_OUT:
    case ET_BULK_IN:
G
Gerd Hoffmann 已提交
1800 1801
        xfer->pkts = 0;
        xfer->iso_xfer = false;
1802
        xfer->timed_xfer = false;
1803 1804 1805
        break;
    case ET_ISO_OUT:
    case ET_ISO_IN:
G
Gerd Hoffmann 已提交
1806 1807
        xfer->pkts = 1;
        xfer->iso_xfer = true;
1808
        xfer->timed_xfer = true;
G
Gerd Hoffmann 已提交
1809 1810
        mfindex = xhci_mfindex_get(xhci);
        xhci_calc_iso_kick(xhci, xfer, epctx, mfindex);
1811
        xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex);
G
Gerd Hoffmann 已提交
1812 1813 1814
        if (xfer->running_retry) {
            return -1;
        }
1815 1816
        break;
    default:
1817
        trace_usb_xhci_unimplemented("endpoint type", epctx->type);
1818 1819 1820
        return -1;
    }

1821 1822 1823
    if (xhci_setup_packet(xfer) < 0) {
        return -1;
    }
1824
    usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
1825
    xhci_try_complete_packet(xfer);
1826 1827 1828 1829 1830
    return 0;
}

static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
{
1831 1832
    trace_usb_xhci_xfer_start(xfer, xfer->epctx->slotid,
                              xfer->epctx->epid, xfer->streamid);
1833
    return xhci_submit(xhci, xfer, epctx);
1834 1835
}

G
Gerd Hoffmann 已提交
1836 1837
static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
                         unsigned int epid, unsigned int streamid)
1838 1839 1840
{
    XHCIEPContext *epctx;

1841
    assert(slotid >= 1 && slotid <= xhci->numslots);
1842 1843 1844
    assert(epid >= 1 && epid <= 31);

    if (!xhci->slots[slotid-1].enabled) {
1845
        DPRINTF("xhci: xhci_kick_ep for disabled slot %d\n", slotid);
1846 1847 1848 1849
        return;
    }
    epctx = xhci->slots[slotid-1].eps[epid-1];
    if (!epctx) {
1850
        DPRINTF("xhci: xhci_kick_ep for disabled endpoint %d,%d\n",
1851 1852 1853 1854
                epid, slotid);
        return;
    }

1855 1856 1857
    if (epctx->kick_active) {
        return;
    }
G
Gerd Hoffmann 已提交
1858 1859 1860 1861 1862 1863
    xhci_kick_epctx(epctx, streamid);
}

static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
{
    XHCIState *xhci = epctx->xhci;
1864
    XHCIStreamContext *stctx = NULL;
G
Gerd Hoffmann 已提交
1865 1866 1867 1868
    XHCITransfer *xfer;
    XHCIRing *ring;
    USBEndpoint *ep = NULL;
    uint64_t mfindex;
G
Gerd Hoffmann 已提交
1869
    unsigned int count = 0;
G
Gerd Hoffmann 已提交
1870 1871 1872 1873
    int length;
    int i;

    trace_usb_xhci_ep_kick(epctx->slotid, epctx->epid, streamid);
1874
    assert(!epctx->kick_active);
G
Gerd Hoffmann 已提交
1875

1876 1877
    /* If the device has been detached, but the guest has not noticed this
       yet the 2 above checks will succeed, but we must NOT continue */
G
Gerd Hoffmann 已提交
1878 1879 1880
    if (!xhci->slots[epctx->slotid - 1].uport ||
        !xhci->slots[epctx->slotid - 1].uport->dev ||
        !xhci->slots[epctx->slotid - 1].uport->dev->attached) {
1881 1882 1883
        return;
    }

G
Gerd Hoffmann 已提交
1884 1885 1886
    if (epctx->retry) {
        XHCITransfer *xfer = epctx->retry;

G
Gerd Hoffmann 已提交
1887
        trace_usb_xhci_xfer_retry(xfer);
G
Gerd Hoffmann 已提交
1888
        assert(xfer->running_retry);
1889 1890
        if (xfer->timed_xfer) {
            /* time to kick the transfer? */
G
Gerd Hoffmann 已提交
1891
            mfindex = xhci_mfindex_get(xhci);
1892
            xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex);
G
Gerd Hoffmann 已提交
1893 1894 1895
            if (xfer->running_retry) {
                return;
            }
1896 1897 1898 1899 1900
            xfer->timed_xfer = 0;
            xfer->running_retry = 1;
        }
        if (xfer->iso_xfer) {
            /* retry iso transfer */
G
Gerd Hoffmann 已提交
1901 1902 1903
            if (xhci_setup_packet(xfer) < 0) {
                return;
            }
1904 1905
            usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
            assert(xfer->packet.status != USB_RET_NAK);
1906
            xhci_try_complete_packet(xfer);
G
Gerd Hoffmann 已提交
1907 1908 1909 1910 1911
        } else {
            /* retry nak'ed transfer */
            if (xhci_setup_packet(xfer) < 0) {
                return;
            }
1912 1913
            usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
            if (xfer->packet.status == USB_RET_NAK) {
G
Gerd Hoffmann 已提交
1914 1915
                return;
            }
1916
            xhci_try_complete_packet(xfer);
G
Gerd Hoffmann 已提交
1917 1918
        }
        assert(!xfer->running_retry);
1919
        if (xfer->complete) {
1920 1921
            /* update ring dequeue ptr */
            xhci_set_ep_state(xhci, epctx, stctx, epctx->state);
1922 1923
            xhci_ep_free_xfer(epctx->retry);
        }
G
Gerd Hoffmann 已提交
1924 1925 1926
        epctx->retry = NULL;
    }

1927 1928 1929 1930 1931
    if (epctx->state == EP_HALTED) {
        DPRINTF("xhci: ep halted, not running schedule\n");
        return;
    }

G
Gerd Hoffmann 已提交
1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945

    if (epctx->nr_pstreams) {
        uint32_t err;
        stctx = xhci_find_stream(epctx, streamid, &err);
        if (stctx == NULL) {
            return;
        }
        ring = &stctx->ring;
        xhci_set_ep_state(xhci, epctx, stctx, EP_RUNNING);
    } else {
        ring = &epctx->ring;
        streamid = 0;
        xhci_set_ep_state(xhci, epctx, NULL, EP_RUNNING);
    }
1946
    assert(ring->dequeue != 0);
1947

1948
    epctx->kick_active++;
1949
    while (1) {
G
Gerd Hoffmann 已提交
1950
        length = xhci_ring_chain_length(xhci, ring);
1951
        if (length <= 0) {
1952 1953 1954 1955 1956 1957 1958 1959 1960 1961
            if (epctx->type == ET_ISO_OUT || epctx->type == ET_ISO_IN) {
                /* 4.10.3.1 */
                XHCIEvent ev = { ER_TRANSFER };
                ev.ccode  = epctx->type == ET_ISO_IN ?
                    CC_RING_OVERRUN : CC_RING_UNDERRUN;
                ev.slotid = epctx->slotid;
                ev.epid   = epctx->epid;
                ev.ptr    = epctx->ring.dequeue;
                xhci_event(xhci, &ev, xhci->slots[epctx->slotid-1].intr);
            }
1962 1963
            break;
        }
1964 1965 1966
        xfer = xhci_ep_alloc_xfer(epctx, length);
        if (xfer == NULL) {
            break;
1967 1968 1969
        }

        for (i = 0; i < length; i++) {
1970 1971
            TRBType type;
            type = xhci_ring_fetch(xhci, ring, &xfer->trbs[i], NULL);
1972 1973 1974 1975 1976 1977
            if (!type) {
                xhci_die(xhci);
                xhci_ep_free_xfer(xfer);
                epctx->kick_active--;
                return;
            }
1978
        }
G
Gerd Hoffmann 已提交
1979
        xfer->streamid = streamid;
1980

G
Gerd Hoffmann 已提交
1981
        if (epctx->epid == 1) {
1982
            xhci_fire_ctl_transfer(xhci, xfer);
1983
        } else {
1984 1985 1986
            xhci_fire_transfer(xhci, xfer, epctx);
        }
        if (xfer->complete) {
1987 1988
            /* update ring dequeue ptr */
            xhci_set_ep_state(xhci, epctx, stctx, epctx->state);
1989 1990
            xhci_ep_free_xfer(xfer);
            xfer = NULL;
1991 1992
        }

G
Gerd Hoffmann 已提交
1993 1994 1995
        if (epctx->state == EP_HALTED) {
            break;
        }
1996
        if (xfer != NULL && xfer->running_retry) {
G
Gerd Hoffmann 已提交
1997 1998 1999 2000
            DPRINTF("xhci: xfer nacked, stopping schedule\n");
            epctx->retry = xfer;
            break;
        }
G
Gerd Hoffmann 已提交
2001 2002 2003 2004
        if (count++ > TRANSFER_LIMIT) {
            trace_usb_xhci_enforced_limit("transfers");
            break;
        }
2005
    }
2006
    epctx->kick_active--;
2007

2008
    ep = xhci_epid_to_usbep(epctx);
2009 2010 2011
    if (ep) {
        usb_device_flush_ep_queue(ep->dev, ep);
    }
2012 2013 2014 2015
}

static TRBCCode xhci_enable_slot(XHCIState *xhci, unsigned int slotid)
{
G
Gerd Hoffmann 已提交
2016
    trace_usb_xhci_slot_enable(slotid);
2017
    assert(slotid >= 1 && slotid <= xhci->numslots);
2018
    xhci->slots[slotid-1].enabled = 1;
2019
    xhci->slots[slotid-1].uport = NULL;
2020 2021 2022 2023 2024 2025 2026 2027 2028
    memset(xhci->slots[slotid-1].eps, 0, sizeof(XHCIEPContext*)*31);

    return CC_SUCCESS;
}

static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid)
{
    int i;

G
Gerd Hoffmann 已提交
2029
    trace_usb_xhci_slot_disable(slotid);
2030
    assert(slotid >= 1 && slotid <= xhci->numslots);
2031 2032 2033 2034 2035 2036 2037 2038

    for (i = 1; i <= 31; i++) {
        if (xhci->slots[slotid-1].eps[i-1]) {
            xhci_disable_ep(xhci, slotid, i);
        }
    }

    xhci->slots[slotid-1].enabled = 0;
G
Gerd Hoffmann 已提交
2039
    xhci->slots[slotid-1].addressed = 0;
2040
    xhci->slots[slotid-1].uport = NULL;
2041
    xhci->slots[slotid-1].intr = 0;
2042 2043 2044
    return CC_SUCCESS;
}

2045 2046 2047 2048 2049 2050 2051
static USBPort *xhci_lookup_uport(XHCIState *xhci, uint32_t *slot_ctx)
{
    USBPort *uport;
    char path[32];
    int i, pos, port;

    port = (slot_ctx[1]>>16) & 0xFF;
2052 2053 2054
    if (port < 1 || port > xhci->numports) {
        return NULL;
    }
2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072
    port = xhci->ports[port-1].uport->index+1;
    pos = snprintf(path, sizeof(path), "%d", port);
    for (i = 0; i < 5; i++) {
        port = (slot_ctx[0] >> 4*i) & 0x0f;
        if (!port) {
            break;
        }
        pos += snprintf(path + pos, sizeof(path) - pos, ".%d", port);
    }

    QTAILQ_FOREACH(uport, &xhci->bus.used, next) {
        if (strcmp(uport->path, path) == 0) {
            return uport;
        }
    }
    return NULL;
}

2073 2074 2075 2076
static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
                                  uint64_t pictx, bool bsr)
{
    XHCISlot *slot;
2077
    USBPort *uport;
2078
    USBDevice *dev;
2079
    dma_addr_t ictx, octx, dcbaap;
2080 2081 2082 2083 2084 2085 2086
    uint64_t poctx;
    uint32_t ictl_ctx[2];
    uint32_t slot_ctx[4];
    uint32_t ep0_ctx[5];
    int i;
    TRBCCode res;

2087
    assert(slotid >= 1 && slotid <= xhci->numslots);
2088 2089

    dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
2090
    poctx = ldq_le_pci_dma(PCI_DEVICE(xhci), dcbaap + 8 * slotid);
2091
    ictx = xhci_mask64(pictx);
D
David Gibson 已提交
2092
    octx = xhci_mask64(poctx);
2093

2094 2095
    DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx);
    DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
2096

D
David Gibson 已提交
2097
    xhci_dma_read_u32s(xhci, ictx, ictl_ctx, sizeof(ictl_ctx));
2098 2099

    if (ictl_ctx[0] != 0x0 || ictl_ctx[1] != 0x3) {
2100
        DPRINTF("xhci: invalid input context control %08x %08x\n",
2101 2102 2103 2104
                ictl_ctx[0], ictl_ctx[1]);
        return CC_TRB_ERROR;
    }

D
David Gibson 已提交
2105 2106
    xhci_dma_read_u32s(xhci, ictx+32, slot_ctx, sizeof(slot_ctx));
    xhci_dma_read_u32s(xhci, ictx+64, ep0_ctx, sizeof(ep0_ctx));
2107 2108 2109 2110 2111 2112 2113

    DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
            slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);

    DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n",
            ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);

2114 2115
    uport = xhci_lookup_uport(xhci, slot_ctx);
    if (uport == NULL) {
2116
        DPRINTF("xhci: port not found\n");
2117
        return CC_TRB_ERROR;
2118
    }
2119
    trace_usb_xhci_slot_address(slotid, uport->path);
2120 2121

    dev = uport->dev;
2122
    if (!dev || !dev->attached) {
2123
        DPRINTF("xhci: port %s not connected\n", uport->path);
2124 2125 2126
        return CC_USB_TRANSACTION_ERROR;
    }

2127
    for (i = 0; i < xhci->numslots; i++) {
2128 2129 2130
        if (i == slotid-1) {
            continue;
        }
2131
        if (xhci->slots[i].uport == uport) {
2132
            DPRINTF("xhci: port %s already assigned to slot %d\n",
2133
                    uport->path, i+1);
2134 2135 2136 2137 2138
            return CC_TRB_ERROR;
        }
    }

    slot = &xhci->slots[slotid-1];
2139
    slot->uport = uport;
2140
    slot->ctx = octx;
2141
    slot->intr = get_field(slot_ctx[2], TRB_INTR);
2142

2143 2144
    /* Make sure device is in USB_STATE_DEFAULT state */
    usb_device_reset(dev);
2145 2146 2147
    if (bsr) {
        slot_ctx[3] = SLOT_DEFAULT << SLOT_STATE_SHIFT;
    } else {
2148
        USBPacket p;
G
Gerd Hoffmann 已提交
2149 2150
        uint8_t buf[1];

2151
        slot_ctx[3] = (SLOT_ADDRESSED << SLOT_STATE_SHIFT) | slotid;
G
Gerd Hoffmann 已提交
2152 2153
        memset(&p, 0, sizeof(p));
        usb_packet_addbuf(&p, buf, sizeof(buf));
2154
        usb_packet_setup(&p, USB_TOKEN_OUT,
G
Gerd Hoffmann 已提交
2155
                         usb_ep_get(dev, USB_TOKEN_OUT, 0), 0,
2156 2157
                         0, false, false);
        usb_device_handle_control(dev, &p,
2158
                                  DeviceOutRequest | USB_REQ_SET_ADDRESS,
2159
                                  slotid, 0, 0, NULL);
2160
        assert(p.status != USB_RET_ASYNC);
2161 2162 2163 2164 2165 2166 2167 2168 2169
    }

    res = xhci_enable_ep(xhci, slotid, 1, octx+32, ep0_ctx);

    DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
            slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
    DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
            ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);

D
David Gibson 已提交
2170 2171
    xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
    xhci_dma_write_u32s(xhci, octx+32, ep0_ctx, sizeof(ep0_ctx));
2172

G
Gerd Hoffmann 已提交
2173
    xhci->slots[slotid-1].addressed = 1;
2174 2175 2176 2177 2178 2179 2180
    return res;
}


static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
                                  uint64_t pictx, bool dc)
{
2181
    dma_addr_t ictx, octx;
2182 2183 2184 2185 2186 2187 2188
    uint32_t ictl_ctx[2];
    uint32_t slot_ctx[4];
    uint32_t islot_ctx[4];
    uint32_t ep_ctx[5];
    int i;
    TRBCCode res;

G
Gerd Hoffmann 已提交
2189
    trace_usb_xhci_slot_configure(slotid);
2190
    assert(slotid >= 1 && slotid <= xhci->numslots);
2191 2192 2193 2194

    ictx = xhci_mask64(pictx);
    octx = xhci->slots[slotid-1].ctx;

2195 2196
    DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx);
    DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
2197 2198 2199 2200 2201 2202 2203 2204

    if (dc) {
        for (i = 2; i <= 31; i++) {
            if (xhci->slots[slotid-1].eps[i-1]) {
                xhci_disable_ep(xhci, slotid, i);
            }
        }

D
David Gibson 已提交
2205
        xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
2206 2207 2208 2209
        slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
        slot_ctx[3] |= SLOT_ADDRESSED << SLOT_STATE_SHIFT;
        DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
                slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
D
David Gibson 已提交
2210
        xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
2211 2212 2213 2214

        return CC_SUCCESS;
    }

D
David Gibson 已提交
2215
    xhci_dma_read_u32s(xhci, ictx, ictl_ctx, sizeof(ictl_ctx));
2216 2217

    if ((ictl_ctx[0] & 0x3) != 0x0 || (ictl_ctx[1] & 0x3) != 0x1) {
2218
        DPRINTF("xhci: invalid input context control %08x %08x\n",
2219 2220 2221 2222
                ictl_ctx[0], ictl_ctx[1]);
        return CC_TRB_ERROR;
    }

D
David Gibson 已提交
2223 2224
    xhci_dma_read_u32s(xhci, ictx+32, islot_ctx, sizeof(islot_ctx));
    xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
2225 2226

    if (SLOT_STATE(slot_ctx[3]) < SLOT_ADDRESSED) {
2227
        DPRINTF("xhci: invalid slot state %08x\n", slot_ctx[3]);
2228 2229 2230
        return CC_CONTEXT_STATE_ERROR;
    }

2231 2232
    xhci_free_device_streams(xhci, slotid, ictl_ctx[0] | ictl_ctx[1]);

2233 2234 2235 2236 2237
    for (i = 2; i <= 31; i++) {
        if (ictl_ctx[0] & (1<<i)) {
            xhci_disable_ep(xhci, slotid, i);
        }
        if (ictl_ctx[1] & (1<<i)) {
D
David Gibson 已提交
2238
            xhci_dma_read_u32s(xhci, ictx+32+(32*i), ep_ctx, sizeof(ep_ctx));
2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249
            DPRINTF("xhci: input ep%d.%d context: %08x %08x %08x %08x %08x\n",
                    i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
                    ep_ctx[3], ep_ctx[4]);
            xhci_disable_ep(xhci, slotid, i);
            res = xhci_enable_ep(xhci, slotid, i, octx+(32*i), ep_ctx);
            if (res != CC_SUCCESS) {
                return res;
            }
            DPRINTF("xhci: output ep%d.%d context: %08x %08x %08x %08x %08x\n",
                    i/2, i%2, ep_ctx[0], ep_ctx[1], ep_ctx[2],
                    ep_ctx[3], ep_ctx[4]);
D
David Gibson 已提交
2250
            xhci_dma_write_u32s(xhci, octx+(32*i), ep_ctx, sizeof(ep_ctx));
2251 2252 2253
        }
    }

2254 2255 2256
    res = xhci_alloc_device_streams(xhci, slotid, ictl_ctx[1]);
    if (res != CC_SUCCESS) {
        for (i = 2; i <= 31; i++) {
G
Gerd Hoffmann 已提交
2257
            if (ictl_ctx[1] & (1u << i)) {
2258 2259 2260 2261 2262 2263
                xhci_disable_ep(xhci, slotid, i);
            }
        }
        return res;
    }

2264 2265 2266 2267 2268 2269 2270 2271
    slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
    slot_ctx[3] |= SLOT_CONFIGURED << SLOT_STATE_SHIFT;
    slot_ctx[0] &= ~(SLOT_CONTEXT_ENTRIES_MASK << SLOT_CONTEXT_ENTRIES_SHIFT);
    slot_ctx[0] |= islot_ctx[0] & (SLOT_CONTEXT_ENTRIES_MASK <<
                                   SLOT_CONTEXT_ENTRIES_SHIFT);
    DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
            slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);

D
David Gibson 已提交
2272
    xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
2273 2274 2275 2276 2277 2278 2279 2280

    return CC_SUCCESS;
}


static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
                                   uint64_t pictx)
{
2281
    dma_addr_t ictx, octx;
2282 2283 2284 2285 2286 2287
    uint32_t ictl_ctx[2];
    uint32_t iep0_ctx[5];
    uint32_t ep0_ctx[5];
    uint32_t islot_ctx[4];
    uint32_t slot_ctx[4];

G
Gerd Hoffmann 已提交
2288
    trace_usb_xhci_slot_evaluate(slotid);
2289
    assert(slotid >= 1 && slotid <= xhci->numslots);
2290 2291 2292 2293

    ictx = xhci_mask64(pictx);
    octx = xhci->slots[slotid-1].ctx;

2294 2295
    DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx);
    DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
2296

D
David Gibson 已提交
2297
    xhci_dma_read_u32s(xhci, ictx, ictl_ctx, sizeof(ictl_ctx));
2298 2299

    if (ictl_ctx[0] != 0x0 || ictl_ctx[1] & ~0x3) {
2300
        DPRINTF("xhci: invalid input context control %08x %08x\n",
2301 2302 2303 2304 2305
                ictl_ctx[0], ictl_ctx[1]);
        return CC_TRB_ERROR;
    }

    if (ictl_ctx[1] & 0x1) {
D
David Gibson 已提交
2306
        xhci_dma_read_u32s(xhci, ictx+32, islot_ctx, sizeof(islot_ctx));
2307 2308 2309 2310

        DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n",
                islot_ctx[0], islot_ctx[1], islot_ctx[2], islot_ctx[3]);

D
David Gibson 已提交
2311
        xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
2312 2313 2314

        slot_ctx[1] &= ~0xFFFF; /* max exit latency */
        slot_ctx[1] |= islot_ctx[1] & 0xFFFF;
2315 2316 2317
        /* update interrupter target field */
        xhci->slots[slotid-1].intr = get_field(islot_ctx[2], TRB_INTR);
        set_field(&slot_ctx[2], xhci->slots[slotid-1].intr, TRB_INTR);
2318 2319 2320 2321

        DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
                slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);

D
David Gibson 已提交
2322
        xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
2323 2324 2325
    }

    if (ictl_ctx[1] & 0x2) {
D
David Gibson 已提交
2326
        xhci_dma_read_u32s(xhci, ictx+64, iep0_ctx, sizeof(iep0_ctx));
2327 2328 2329 2330 2331

        DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n",
                iep0_ctx[0], iep0_ctx[1], iep0_ctx[2],
                iep0_ctx[3], iep0_ctx[4]);

D
David Gibson 已提交
2332
        xhci_dma_read_u32s(xhci, octx+32, ep0_ctx, sizeof(ep0_ctx));
2333 2334 2335 2336 2337 2338 2339

        ep0_ctx[1] &= ~0xFFFF0000; /* max packet size*/
        ep0_ctx[1] |= iep0_ctx[1] & 0xFFFF0000;

        DPRINTF("xhci: output ep0 context: %08x %08x %08x %08x %08x\n",
                ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);

D
David Gibson 已提交
2340
        xhci_dma_write_u32s(xhci, octx+32, ep0_ctx, sizeof(ep0_ctx));
2341 2342 2343 2344 2345 2346 2347 2348
    }

    return CC_SUCCESS;
}

static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid)
{
    uint32_t slot_ctx[4];
2349
    dma_addr_t octx;
2350 2351
    int i;

G
Gerd Hoffmann 已提交
2352
    trace_usb_xhci_slot_reset(slotid);
2353
    assert(slotid >= 1 && slotid <= xhci->numslots);
2354 2355 2356

    octx = xhci->slots[slotid-1].ctx;

2357
    DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx);
2358 2359 2360 2361 2362 2363 2364

    for (i = 2; i <= 31; i++) {
        if (xhci->slots[slotid-1].eps[i-1]) {
            xhci_disable_ep(xhci, slotid, i);
        }
    }

D
David Gibson 已提交
2365
    xhci_dma_read_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
2366 2367 2368 2369
    slot_ctx[3] &= ~(SLOT_STATE_MASK << SLOT_STATE_SHIFT);
    slot_ctx[3] |= SLOT_DEFAULT << SLOT_STATE_SHIFT;
    DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
            slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
D
David Gibson 已提交
2370
    xhci_dma_write_u32s(xhci, octx, slot_ctx, sizeof(slot_ctx));
2371 2372 2373 2374 2375 2376 2377 2378

    return CC_SUCCESS;
}

static unsigned int xhci_get_slot(XHCIState *xhci, XHCIEvent *event, XHCITRB *trb)
{
    unsigned int slotid;
    slotid = (trb->control >> TRB_CR_SLOTID_SHIFT) & TRB_CR_SLOTID_MASK;
2379
    if (slotid < 1 || slotid > xhci->numslots) {
2380
        DPRINTF("xhci: bad slot id %d\n", slotid);
2381 2382 2383
        event->ccode = CC_TRB_ERROR;
        return 0;
    } else if (!xhci->slots[slotid-1].enabled) {
2384
        DPRINTF("xhci: slot id %d not enabled\n", slotid);
2385 2386 2387 2388 2389 2390
        event->ccode = CC_SLOT_NOT_ENABLED_ERROR;
        return 0;
    }
    return slotid;
}

2391 2392 2393
/* cleanup slot state on usb device detach */
static void xhci_detach_slot(XHCIState *xhci, USBPort *uport)
{
G
Gerd Hoffmann 已提交
2394
    int slot, ep;
2395 2396 2397 2398 2399 2400 2401 2402 2403 2404

    for (slot = 0; slot < xhci->numslots; slot++) {
        if (xhci->slots[slot].uport == uport) {
            break;
        }
    }
    if (slot == xhci->numslots) {
        return;
    }

G
Gerd Hoffmann 已提交
2405 2406
    for (ep = 0; ep < 31; ep++) {
        if (xhci->slots[slot].eps[ep]) {
2407
            xhci_ep_nuke_xfers(xhci, slot + 1, ep + 1, 0);
G
Gerd Hoffmann 已提交
2408 2409
        }
    }
2410 2411 2412
    xhci->slots[slot].uport = NULL;
}

2413 2414
static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
{
2415
    dma_addr_t ctx;
G
Gerd Hoffmann 已提交
2416
    uint8_t bw_ctx[xhci->numports+1];
2417 2418 2419 2420 2421

    DPRINTF("xhci_get_port_bandwidth()\n");

    ctx = xhci_mask64(pctx);

2422
    DPRINTF("xhci: bandwidth context at "DMA_ADDR_FMT"\n", ctx);
2423 2424 2425

    /* TODO: actually implement real values here */
    bw_ctx[0] = 0;
G
Gerd Hoffmann 已提交
2426
    memset(&bw_ctx[1], 80, xhci->numports); /* 80% */
2427
    pci_dma_write(PCI_DEVICE(xhci), ctx, bw_ctx, sizeof(bw_ctx));
2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452

    return CC_SUCCESS;
}

static uint32_t rotl(uint32_t v, unsigned count)
{
    count &= 31;
    return (v << count) | (v >> (32 - count));
}


static uint32_t xhci_nec_challenge(uint32_t hi, uint32_t lo)
{
    uint32_t val;
    val = rotl(lo - 0x49434878, 32 - ((hi>>8) & 0x1F));
    val += rotl(lo + 0x49434878, hi & 0x1F);
    val -= rotl(hi ^ 0x49434878, (lo >> 16) & 0x1F);
    return ~val;
}

static void xhci_process_commands(XHCIState *xhci)
{
    XHCITRB trb;
    TRBType type;
    XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS};
2453
    dma_addr_t addr;
G
Gerd Hoffmann 已提交
2454
    unsigned int i, slotid = 0, count = 0;
2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467

    DPRINTF("xhci_process_commands()\n");
    if (!xhci_running(xhci)) {
        DPRINTF("xhci_process_commands() called while xHC stopped or paused\n");
        return;
    }

    xhci->crcr_low |= CRCR_CRR;

    while ((type = xhci_ring_fetch(xhci, &xhci->cmd_ring, &trb, &addr))) {
        event.ptr = addr;
        switch (type) {
        case CR_ENABLE_SLOT:
2468
            for (i = 0; i < xhci->numslots; i++) {
2469 2470 2471 2472
                if (!xhci->slots[i].enabled) {
                    break;
                }
            }
2473
            if (i >= xhci->numslots) {
2474
                DPRINTF("xhci: no device slots available\n");
2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527
                event.ccode = CC_NO_SLOTS_ERROR;
            } else {
                slotid = i+1;
                event.ccode = xhci_enable_slot(xhci, slotid);
            }
            break;
        case CR_DISABLE_SLOT:
            slotid = xhci_get_slot(xhci, &event, &trb);
            if (slotid) {
                event.ccode = xhci_disable_slot(xhci, slotid);
            }
            break;
        case CR_ADDRESS_DEVICE:
            slotid = xhci_get_slot(xhci, &event, &trb);
            if (slotid) {
                event.ccode = xhci_address_slot(xhci, slotid, trb.parameter,
                                                trb.control & TRB_CR_BSR);
            }
            break;
        case CR_CONFIGURE_ENDPOINT:
            slotid = xhci_get_slot(xhci, &event, &trb);
            if (slotid) {
                event.ccode = xhci_configure_slot(xhci, slotid, trb.parameter,
                                                  trb.control & TRB_CR_DC);
            }
            break;
        case CR_EVALUATE_CONTEXT:
            slotid = xhci_get_slot(xhci, &event, &trb);
            if (slotid) {
                event.ccode = xhci_evaluate_slot(xhci, slotid, trb.parameter);
            }
            break;
        case CR_STOP_ENDPOINT:
            slotid = xhci_get_slot(xhci, &event, &trb);
            if (slotid) {
                unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT)
                    & TRB_CR_EPID_MASK;
                event.ccode = xhci_stop_ep(xhci, slotid, epid);
            }
            break;
        case CR_RESET_ENDPOINT:
            slotid = xhci_get_slot(xhci, &event, &trb);
            if (slotid) {
                unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT)
                    & TRB_CR_EPID_MASK;
                event.ccode = xhci_reset_ep(xhci, slotid, epid);
            }
            break;
        case CR_SET_TR_DEQUEUE:
            slotid = xhci_get_slot(xhci, &event, &trb);
            if (slotid) {
                unsigned int epid = (trb.control >> TRB_CR_EPID_SHIFT)
                    & TRB_CR_EPID_MASK;
G
Gerd Hoffmann 已提交
2528 2529 2530
                unsigned int streamid = (trb.status >> 16) & 0xffff;
                event.ccode = xhci_set_ep_dequeue(xhci, slotid,
                                                  epid, streamid,
2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543
                                                  trb.parameter);
            }
            break;
        case CR_RESET_DEVICE:
            slotid = xhci_get_slot(xhci, &event, &trb);
            if (slotid) {
                event.ccode = xhci_reset_slot(xhci, slotid);
            }
            break;
        case CR_GET_PORT_BANDWIDTH:
            event.ccode = xhci_get_port_bandwidth(xhci, trb.parameter);
            break;
        case CR_VENDOR_NEC_FIRMWARE_REVISION:
2544 2545 2546 2547 2548 2549
            if (xhci->nec_quirks) {
                event.type = 48; /* NEC reply */
                event.length = 0x3025;
            } else {
                event.ccode = CC_TRB_ERROR;
            }
2550 2551
            break;
        case CR_VENDOR_NEC_CHALLENGE_RESPONSE:
2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563
            if (xhci->nec_quirks) {
                uint32_t chi = trb.parameter >> 32;
                uint32_t clo = trb.parameter;
                uint32_t val = xhci_nec_challenge(chi, clo);
                event.length = val & 0xFFFF;
                event.epid = val >> 16;
                slotid = val >> 24;
                event.type = 48; /* NEC reply */
            } else {
                event.ccode = CC_TRB_ERROR;
            }
            break;
2564
        default:
2565
            trace_usb_xhci_unimplemented("command", type);
2566 2567 2568 2569
            event.ccode = CC_TRB_ERROR;
            break;
        }
        event.slotid = slotid;
G
Gerd Hoffmann 已提交
2570
        xhci_event(xhci, &event, 0);
G
Gerd Hoffmann 已提交
2571 2572 2573 2574 2575

        if (count++ > COMMAND_LIMIT) {
            trace_usb_xhci_enforced_limit("commands");
            return;
        }
2576 2577 2578
    }
}

G
Gerd Hoffmann 已提交
2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589
static bool xhci_port_have_device(XHCIPort *port)
{
    if (!port->uport->dev || !port->uport->dev->attached) {
        return false; /* no device present */
    }
    if (!((1 << port->uport->dev->speed) & port->speedmask)) {
        return false; /* speed mismatch */
    }
    return true;
}

G
Gerd Hoffmann 已提交
2590 2591 2592 2593 2594 2595 2596 2597
static void xhci_port_notify(XHCIPort *port, uint32_t bits)
{
    XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS,
                     port->portnr << 24 };

    if ((port->portsc & bits) == bits) {
        return;
    }
G
Gerd Hoffmann 已提交
2598
    trace_usb_xhci_port_notify(port->portnr, bits);
G
Gerd Hoffmann 已提交
2599 2600 2601 2602 2603 2604 2605
    port->portsc |= bits;
    if (!xhci_running(port->xhci)) {
        return;
    }
    xhci_event(port->xhci, &ev, 0);
}

2606
static void xhci_port_update(XHCIPort *port, int is_detach)
2607
{
2608 2609
    uint32_t pls = PLS_RX_DETECT;

2610
    assert(port);
2611
    port->portsc = PORTSC_PP;
G
Gerd Hoffmann 已提交
2612
    if (!is_detach && xhci_port_have_device(port)) {
2613
        port->portsc |= PORTSC_CCS;
G
Gerd Hoffmann 已提交
2614
        switch (port->uport->dev->speed) {
2615 2616
        case USB_SPEED_LOW:
            port->portsc |= PORTSC_SPEED_LOW;
2617
            pls = PLS_POLLING;
2618 2619 2620
            break;
        case USB_SPEED_FULL:
            port->portsc |= PORTSC_SPEED_FULL;
2621
            pls = PLS_POLLING;
2622 2623 2624
            break;
        case USB_SPEED_HIGH:
            port->portsc |= PORTSC_SPEED_HIGH;
2625
            pls = PLS_POLLING;
2626
            break;
G
Gerd Hoffmann 已提交
2627 2628
        case USB_SPEED_SUPER:
            port->portsc |= PORTSC_SPEED_SUPER;
2629 2630
            port->portsc |= PORTSC_PED;
            pls = PLS_U0;
G
Gerd Hoffmann 已提交
2631
            break;
2632 2633
        }
    }
2634
    set_field(&port->portsc, pls, PORTSC_PLS);
G
Gerd Hoffmann 已提交
2635
    trace_usb_xhci_port_link(port->portnr, pls);
G
Gerd Hoffmann 已提交
2636
    xhci_port_notify(port, PORTSC_CSC);
2637 2638
}

G
Gerd Hoffmann 已提交
2639
static void xhci_port_reset(XHCIPort *port, bool warm_reset)
G
Gerd Hoffmann 已提交
2640
{
2641
    trace_usb_xhci_port_reset(port->portnr, warm_reset);
G
Gerd Hoffmann 已提交
2642

2643 2644 2645 2646
    if (!xhci_port_have_device(port)) {
        return;
    }

G
Gerd Hoffmann 已提交
2647
    usb_device_reset(port->uport->dev);
2648 2649

    switch (port->uport->dev->speed) {
G
Gerd Hoffmann 已提交
2650 2651 2652 2653 2654
    case USB_SPEED_SUPER:
        if (warm_reset) {
            port->portsc |= PORTSC_WRC;
        }
        /* fall through */
2655 2656 2657 2658
    case USB_SPEED_LOW:
    case USB_SPEED_FULL:
    case USB_SPEED_HIGH:
        set_field(&port->portsc, PLS_U0, PORTSC_PLS);
G
Gerd Hoffmann 已提交
2659
        trace_usb_xhci_port_link(port->portnr, PLS_U0);
2660 2661 2662 2663 2664 2665
        port->portsc |= PORTSC_PED;
        break;
    }

    port->portsc &= ~PORTSC_PR;
    xhci_port_notify(port, PORTSC_PRC);
G
Gerd Hoffmann 已提交
2666 2667
}

J
Jan Kiszka 已提交
2668
static void xhci_reset(DeviceState *dev)
2669
{
2670
    XHCIState *xhci = XHCI(dev);
2671 2672
    int i;

G
Gerd Hoffmann 已提交
2673
    trace_usb_xhci_reset();
2674
    if (!(xhci->usbsts & USBSTS_HCH)) {
2675
        DPRINTF("xhci: reset while running!\n");
2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686
    }

    xhci->usbcmd = 0;
    xhci->usbsts = USBSTS_HCH;
    xhci->dnctrl = 0;
    xhci->crcr_low = 0;
    xhci->crcr_high = 0;
    xhci->dcbaap_low = 0;
    xhci->dcbaap_high = 0;
    xhci->config = 0;

2687
    for (i = 0; i < xhci->numslots; i++) {
2688 2689 2690
        xhci_disable_slot(xhci, i+1);
    }

G
Gerd Hoffmann 已提交
2691
    for (i = 0; i < xhci->numports; i++) {
2692
        xhci_port_update(xhci->ports + i, 0);
2693 2694
    }

2695
    for (i = 0; i < xhci->numintrs; i++) {
G
Gerd Hoffmann 已提交
2696 2697 2698 2699 2700 2701 2702 2703
        xhci->intr[i].iman = 0;
        xhci->intr[i].imod = 0;
        xhci->intr[i].erstsz = 0;
        xhci->intr[i].erstba_low = 0;
        xhci->intr[i].erstba_high = 0;
        xhci->intr[i].erdp_low = 0;
        xhci->intr[i].erdp_high = 0;
        xhci->intr[i].msix_used = 0;
2704

G
Gerd Hoffmann 已提交
2705 2706 2707 2708 2709
        xhci->intr[i].er_ep_idx = 0;
        xhci->intr[i].er_pcs = 1;
        xhci->intr[i].ev_buffer_put = 0;
        xhci->intr[i].ev_buffer_get = 0;
    }
G
Gerd Hoffmann 已提交
2710

2711
    xhci->mfindex_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
G
Gerd Hoffmann 已提交
2712
    xhci_mfwrap_update(xhci);
2713 2714
}

A
Avi Kivity 已提交
2715
static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size)
2716
{
2717
    XHCIState *xhci = ptr;
G
Gerd Hoffmann 已提交
2718
    uint32_t ret;
2719 2720 2721

    switch (reg) {
    case 0x00: /* HCIVERSION, CAPLENGTH */
G
Gerd Hoffmann 已提交
2722 2723
        ret = 0x01000000 | LEN_CAP;
        break;
2724
    case 0x04: /* HCSPARAMS 1 */
G
Gerd Hoffmann 已提交
2725
        ret = ((xhci->numports_2+xhci->numports_3)<<24)
2726
            | (xhci->numintrs<<8) | xhci->numslots;
G
Gerd Hoffmann 已提交
2727
        break;
2728
    case 0x08: /* HCSPARAMS 2 */
G
Gerd Hoffmann 已提交
2729 2730
        ret = 0x0000000f;
        break;
2731
    case 0x0c: /* HCSPARAMS 3 */
G
Gerd Hoffmann 已提交
2732 2733
        ret = 0x00000000;
        break;
2734
    case 0x10: /* HCCPARAMS */
G
Gerd Hoffmann 已提交
2735
        if (sizeof(dma_addr_t) == 4) {
2736
            ret = 0x00080000 | (xhci->max_pstreams_mask << 12);
G
Gerd Hoffmann 已提交
2737
        } else {
2738
            ret = 0x00080001 | (xhci->max_pstreams_mask << 12);
G
Gerd Hoffmann 已提交
2739 2740
        }
        break;
2741
    case 0x14: /* DBOFF */
G
Gerd Hoffmann 已提交
2742 2743
        ret = OFF_DOORBELL;
        break;
2744
    case 0x18: /* RTSOFF */
G
Gerd Hoffmann 已提交
2745 2746
        ret = OFF_RUNTIME;
        break;
2747 2748 2749

    /* extended capabilities */
    case 0x20: /* Supported Protocol:00 */
G
Gerd Hoffmann 已提交
2750 2751
        ret = 0x02000402; /* USB 2.0 */
        break;
2752
    case 0x24: /* Supported Protocol:04 */
G
Gerd Hoffmann 已提交
2753
        ret = 0x20425355; /* "USB " */
G
Gerd Hoffmann 已提交
2754
        break;
2755
    case 0x28: /* Supported Protocol:08 */
2756 2757 2758 2759 2760
        if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
            ret = (xhci->numports_2<<8) | (xhci->numports_3+1);
        } else {
            ret = (xhci->numports_2<<8) | 1;
        }
G
Gerd Hoffmann 已提交
2761
        break;
2762
    case 0x2c: /* Supported Protocol:0c */
G
Gerd Hoffmann 已提交
2763 2764
        ret = 0x00000000; /* reserved */
        break;
2765
    case 0x30: /* Supported Protocol:00 */
G
Gerd Hoffmann 已提交
2766 2767
        ret = 0x03000002; /* USB 3.0 */
        break;
2768
    case 0x34: /* Supported Protocol:04 */
G
Gerd Hoffmann 已提交
2769
        ret = 0x20425355; /* "USB " */
G
Gerd Hoffmann 已提交
2770
        break;
2771
    case 0x38: /* Supported Protocol:08 */
2772 2773 2774 2775 2776
        if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
            ret = (xhci->numports_3<<8) | 1;
        } else {
            ret = (xhci->numports_3<<8) | (xhci->numports_2+1);
        }
G
Gerd Hoffmann 已提交
2777
        break;
2778
    case 0x3c: /* Supported Protocol:0c */
G
Gerd Hoffmann 已提交
2779 2780
        ret = 0x00000000; /* reserved */
        break;
2781
    default:
2782
        trace_usb_xhci_unimplemented("cap read", reg);
G
Gerd Hoffmann 已提交
2783
        ret = 0;
2784
    }
G
Gerd Hoffmann 已提交
2785 2786 2787

    trace_usb_xhci_cap_read(reg, ret);
    return ret;
2788 2789
}

A
Avi Kivity 已提交
2790
static uint64_t xhci_port_read(void *ptr, hwaddr reg, unsigned size)
2791
{
2792
    XHCIPort *port = ptr;
G
Gerd Hoffmann 已提交
2793 2794
    uint32_t ret;

2795
    switch (reg) {
2796
    case 0x00: /* PORTSC */
2797
        ret = port->portsc;
G
Gerd Hoffmann 已提交
2798
        break;
2799 2800
    case 0x04: /* PORTPMSC */
    case 0x08: /* PORTLI */
G
Gerd Hoffmann 已提交
2801 2802
        ret = 0;
        break;
2803 2804
    case 0x0c: /* reserved */
    default:
2805
        trace_usb_xhci_unimplemented("port read", reg);
G
Gerd Hoffmann 已提交
2806
        ret = 0;
2807
    }
G
Gerd Hoffmann 已提交
2808

2809
    trace_usb_xhci_port_read(port->portnr, reg, ret);
G
Gerd Hoffmann 已提交
2810
    return ret;
2811 2812
}

A
Avi Kivity 已提交
2813
static void xhci_port_write(void *ptr, hwaddr reg,
2814
                            uint64_t val, unsigned size)
2815
{
2816
    XHCIPort *port = ptr;
G
Gerd Hoffmann 已提交
2817
    uint32_t portsc, notify;
2818

2819
    trace_usb_xhci_port_write(port->portnr, reg, val);
G
Gerd Hoffmann 已提交
2820

2821
    switch (reg) {
2822
    case 0x00: /* PORTSC */
G
Gerd Hoffmann 已提交
2823
        /* write-1-to-start bits */
G
Gerd Hoffmann 已提交
2824 2825 2826 2827
        if (val & PORTSC_WPR) {
            xhci_port_reset(port, true);
            break;
        }
G
Gerd Hoffmann 已提交
2828
        if (val & PORTSC_PR) {
G
Gerd Hoffmann 已提交
2829
            xhci_port_reset(port, false);
G
Gerd Hoffmann 已提交
2830 2831 2832
            break;
        }

2833
        portsc = port->portsc;
G
Gerd Hoffmann 已提交
2834
        notify = 0;
2835 2836 2837 2838 2839
        /* write-1-to-clear bits*/
        portsc &= ~(val & (PORTSC_CSC|PORTSC_PEC|PORTSC_WRC|PORTSC_OCC|
                           PORTSC_PRC|PORTSC_PLC|PORTSC_CEC));
        if (val & PORTSC_LWS) {
            /* overwrite PLS only when LWS=1 */
G
Gerd Hoffmann 已提交
2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859
            uint32_t old_pls = get_field(port->portsc, PORTSC_PLS);
            uint32_t new_pls = get_field(val, PORTSC_PLS);
            switch (new_pls) {
            case PLS_U0:
                if (old_pls != PLS_U0) {
                    set_field(&portsc, new_pls, PORTSC_PLS);
                    trace_usb_xhci_port_link(port->portnr, new_pls);
                    notify = PORTSC_PLC;
                }
                break;
            case PLS_U3:
                if (old_pls < PLS_U3) {
                    set_field(&portsc, new_pls, PORTSC_PLS);
                    trace_usb_xhci_port_link(port->portnr, new_pls);
                }
                break;
            case PLS_RESUME:
                /* windows does this for some reason, don't spam stderr */
                break;
            default:
2860
                DPRINTF("%s: ignore pls write (old %d, new %d)\n",
G
Gerd Hoffmann 已提交
2861 2862 2863
                        __func__, old_pls, new_pls);
                break;
            }
2864 2865 2866 2867
        }
        /* read/write bits */
        portsc &= ~(PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE);
        portsc |= (val & (PORTSC_PP|PORTSC_WCE|PORTSC_WDE|PORTSC_WOE));
G
Gerd Hoffmann 已提交
2868
        port->portsc = portsc;
G
Gerd Hoffmann 已提交
2869 2870
        if (notify) {
            xhci_port_notify(port, notify);
2871 2872 2873 2874 2875
        }
        break;
    case 0x04: /* PORTPMSC */
    case 0x08: /* PORTLI */
    default:
2876
        trace_usb_xhci_unimplemented("port write", reg);
2877 2878 2879
    }
}

A
Avi Kivity 已提交
2880
static uint64_t xhci_oper_read(void *ptr, hwaddr reg, unsigned size)
2881
{
2882
    XHCIState *xhci = ptr;
G
Gerd Hoffmann 已提交
2883
    uint32_t ret;
2884 2885 2886

    switch (reg) {
    case 0x00: /* USBCMD */
G
Gerd Hoffmann 已提交
2887 2888
        ret = xhci->usbcmd;
        break;
2889
    case 0x04: /* USBSTS */
G
Gerd Hoffmann 已提交
2890 2891
        ret = xhci->usbsts;
        break;
2892
    case 0x08: /* PAGESIZE */
G
Gerd Hoffmann 已提交
2893 2894
        ret = 1; /* 4KiB */
        break;
2895
    case 0x14: /* DNCTRL */
G
Gerd Hoffmann 已提交
2896 2897
        ret = xhci->dnctrl;
        break;
2898
    case 0x18: /* CRCR low */
G
Gerd Hoffmann 已提交
2899 2900
        ret = xhci->crcr_low & ~0xe;
        break;
2901
    case 0x1c: /* CRCR high */
G
Gerd Hoffmann 已提交
2902 2903
        ret = xhci->crcr_high;
        break;
2904
    case 0x30: /* DCBAAP low */
G
Gerd Hoffmann 已提交
2905 2906
        ret = xhci->dcbaap_low;
        break;
2907
    case 0x34: /* DCBAAP high */
G
Gerd Hoffmann 已提交
2908 2909
        ret = xhci->dcbaap_high;
        break;
2910
    case 0x38: /* CONFIG */
G
Gerd Hoffmann 已提交
2911 2912
        ret = xhci->config;
        break;
2913
    default:
2914
        trace_usb_xhci_unimplemented("oper read", reg);
G
Gerd Hoffmann 已提交
2915
        ret = 0;
2916
    }
G
Gerd Hoffmann 已提交
2917 2918 2919

    trace_usb_xhci_oper_read(reg, ret);
    return ret;
2920 2921
}

A
Avi Kivity 已提交
2922
static void xhci_oper_write(void *ptr, hwaddr reg,
2923
                            uint64_t val, unsigned size)
2924
{
2925
    XHCIState *xhci = ptr;
2926
    DeviceState *d = DEVICE(ptr);
2927

G
Gerd Hoffmann 已提交
2928 2929
    trace_usb_xhci_oper_write(reg, val);

2930 2931 2932 2933 2934 2935 2936
    switch (reg) {
    case 0x00: /* USBCMD */
        if ((val & USBCMD_RS) && !(xhci->usbcmd & USBCMD_RS)) {
            xhci_run(xhci);
        } else if (!(val & USBCMD_RS) && (xhci->usbcmd & USBCMD_RS)) {
            xhci_stop(xhci);
        }
2937 2938 2939 2940 2941 2942 2943 2944
        if (val & USBCMD_CSS) {
            /* save state */
            xhci->usbsts &= ~USBSTS_SRE;
        }
        if (val & USBCMD_CRS) {
            /* restore state */
            xhci->usbsts |= USBSTS_SRE;
        }
2945
        xhci->usbcmd = val & 0xc0f;
G
Gerd Hoffmann 已提交
2946
        xhci_mfwrap_update(xhci);
2947
        if (val & USBCMD_HCRST) {
2948
            xhci_reset(d);
2949
        }
G
Gerd Hoffmann 已提交
2950
        xhci_intx_update(xhci);
2951 2952 2953 2954 2955
        break;

    case 0x04: /* USBSTS */
        /* these bits are write-1-to-clear */
        xhci->usbsts &= ~(val & (USBSTS_HSE|USBSTS_EINT|USBSTS_PCD|USBSTS_SRE));
G
Gerd Hoffmann 已提交
2956
        xhci_intx_update(xhci);
2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969
        break;

    case 0x14: /* DNCTRL */
        xhci->dnctrl = val & 0xffff;
        break;
    case 0x18: /* CRCR low */
        xhci->crcr_low = (val & 0xffffffcf) | (xhci->crcr_low & CRCR_CRR);
        break;
    case 0x1c: /* CRCR high */
        xhci->crcr_high = val;
        if (xhci->crcr_low & (CRCR_CA|CRCR_CS) && (xhci->crcr_low & CRCR_CRR)) {
            XHCIEvent event = {ER_COMMAND_COMPLETE, CC_COMMAND_RING_STOPPED};
            xhci->crcr_low &= ~CRCR_CRR;
G
Gerd Hoffmann 已提交
2970
            xhci_event(xhci, &event, 0);
2971 2972
            DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low);
        } else {
2973
            dma_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val);
2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987
            xhci_ring_init(xhci, &xhci->cmd_ring, base);
        }
        xhci->crcr_low &= ~(CRCR_CA | CRCR_CS);
        break;
    case 0x30: /* DCBAAP low */
        xhci->dcbaap_low = val & 0xffffffc0;
        break;
    case 0x34: /* DCBAAP high */
        xhci->dcbaap_high = val;
        break;
    case 0x38: /* CONFIG */
        xhci->config = val & 0xff;
        break;
    default:
2988
        trace_usb_xhci_unimplemented("oper write", reg);
2989 2990 2991
    }
}

A
Avi Kivity 已提交
2992
static uint64_t xhci_runtime_read(void *ptr, hwaddr reg,
2993
                                  unsigned size)
2994
{
2995
    XHCIState *xhci = ptr;
2996
    uint32_t ret = 0;
2997

2998 2999 3000 3001 3002 3003
    if (reg < 0x20) {
        switch (reg) {
        case 0x00: /* MFINDEX */
            ret = xhci_mfindex_get(xhci) & 0x3fff;
            break;
        default:
3004
            trace_usb_xhci_unimplemented("runtime read", reg);
3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032
            break;
        }
    } else {
        int v = (reg - 0x20) / 0x20;
        XHCIInterrupter *intr = &xhci->intr[v];
        switch (reg & 0x1f) {
        case 0x00: /* IMAN */
            ret = intr->iman;
            break;
        case 0x04: /* IMOD */
            ret = intr->imod;
            break;
        case 0x08: /* ERSTSZ */
            ret = intr->erstsz;
            break;
        case 0x10: /* ERSTBA low */
            ret = intr->erstba_low;
            break;
        case 0x14: /* ERSTBA high */
            ret = intr->erstba_high;
            break;
        case 0x18: /* ERDP low */
            ret = intr->erdp_low;
            break;
        case 0x1c: /* ERDP high */
            ret = intr->erdp_high;
            break;
        }
3033
    }
G
Gerd Hoffmann 已提交
3034 3035 3036

    trace_usb_xhci_runtime_read(reg, ret);
    return ret;
3037 3038
}

A
Avi Kivity 已提交
3039
static void xhci_runtime_write(void *ptr, hwaddr reg,
3040
                               uint64_t val, unsigned size)
3041
{
3042
    XHCIState *xhci = ptr;
3043 3044
    int v = (reg - 0x20) / 0x20;
    XHCIInterrupter *intr = &xhci->intr[v];
3045
    trace_usb_xhci_runtime_write(reg, val);
3046

3047
    if (reg < 0x20) {
3048
        trace_usb_xhci_unimplemented("runtime write", reg);
3049 3050 3051 3052 3053
        return;
    }

    switch (reg & 0x1f) {
    case 0x00: /* IMAN */
3054
        if (val & IMAN_IP) {
G
Gerd Hoffmann 已提交
3055
            intr->iman &= ~IMAN_IP;
3056
        }
G
Gerd Hoffmann 已提交
3057 3058
        intr->iman &= ~IMAN_IE;
        intr->iman |= val & IMAN_IE;
3059 3060 3061 3062
        if (v == 0) {
            xhci_intx_update(xhci);
        }
        xhci_msix_update(xhci, v);
3063
        break;
3064
    case 0x04: /* IMOD */
G
Gerd Hoffmann 已提交
3065
        intr->imod = val;
3066
        break;
3067
    case 0x08: /* ERSTSZ */
G
Gerd Hoffmann 已提交
3068
        intr->erstsz = val & 0xffff;
3069
        break;
3070
    case 0x10: /* ERSTBA low */
3071 3072 3073 3074 3075 3076
        if (xhci->nec_quirks) {
            /* NEC driver bug: it doesn't align this to 64 bytes */
            intr->erstba_low = val & 0xfffffff0;
        } else {
            intr->erstba_low = val & 0xffffffc0;
        }
3077
        break;
3078
    case 0x14: /* ERSTBA high */
G
Gerd Hoffmann 已提交
3079
        intr->erstba_high = val;
3080
        xhci_er_reset(xhci, v);
3081
        break;
3082
    case 0x18: /* ERDP low */
3083
        if (val & ERDP_EHB) {
G
Gerd Hoffmann 已提交
3084
            intr->erdp_low &= ~ERDP_EHB;
3085
        }
G
Gerd Hoffmann 已提交
3086
        intr->erdp_low = (val & ~ERDP_EHB) | (intr->erdp_low & ERDP_EHB);
3087 3088 3089 3090 3091 3092 3093 3094 3095
        if (val & ERDP_EHB) {
            dma_addr_t erdp = xhci_addr64(intr->erdp_low, intr->erdp_high);
            unsigned int dp_idx = (erdp - intr->er_start) / TRB_SIZE;
            if (erdp >= intr->er_start &&
                erdp < (intr->er_start + TRB_SIZE * intr->er_size) &&
                dp_idx != intr->er_ep_idx) {
                xhci_intr_raise(xhci, v);
            }
        }
3096
        break;
3097
    case 0x1c: /* ERDP high */
G
Gerd Hoffmann 已提交
3098
        intr->erdp_high = val;
3099 3100
        break;
    default:
3101
        trace_usb_xhci_unimplemented("oper write", reg);
3102 3103 3104
    }
}

A
Avi Kivity 已提交
3105
static uint64_t xhci_doorbell_read(void *ptr, hwaddr reg,
3106
                                   unsigned size)
3107 3108
{
    /* doorbells always read as 0 */
G
Gerd Hoffmann 已提交
3109
    trace_usb_xhci_doorbell_read(reg, 0);
3110 3111 3112
    return 0;
}

A
Avi Kivity 已提交
3113
static void xhci_doorbell_write(void *ptr, hwaddr reg,
3114
                                uint64_t val, unsigned size)
3115
{
3116
    XHCIState *xhci = ptr;
G
Gerd Hoffmann 已提交
3117
    unsigned int epid, streamid;
3118

G
Gerd Hoffmann 已提交
3119
    trace_usb_xhci_doorbell_write(reg, val);
3120 3121

    if (!xhci_running(xhci)) {
3122
        DPRINTF("xhci: wrote doorbell while xHC stopped or paused\n");
3123 3124 3125 3126 3127 3128 3129 3130 3131
        return;
    }

    reg >>= 2;

    if (reg == 0) {
        if (val == 0) {
            xhci_process_commands(xhci);
        } else {
3132
            DPRINTF("xhci: bad doorbell 0 write: 0x%x\n",
3133
                    (uint32_t)val);
3134 3135
        }
    } else {
G
Gerd Hoffmann 已提交
3136 3137
        epid = val & 0xff;
        streamid = (val >> 16) & 0xffff;
3138
        if (reg > xhci->numslots) {
3139
            DPRINTF("xhci: bad doorbell %d\n", (int)reg);
G
Gerd Hoffmann 已提交
3140
        } else if (epid > 31) {
3141
            DPRINTF("xhci: bad doorbell %d write: 0x%x\n",
3142
                    (int)reg, (uint32_t)val);
3143
        } else {
G
Gerd Hoffmann 已提交
3144
            xhci_kick_ep(xhci, reg, epid, streamid);
3145 3146 3147 3148
        }
    }
}

G
Gerd Hoffmann 已提交
3149 3150 3151 3152 3153 3154
static void xhci_cap_write(void *opaque, hwaddr addr, uint64_t val,
                           unsigned width)
{
    /* nothing */
}

3155 3156
static const MemoryRegionOps xhci_cap_ops = {
    .read = xhci_cap_read,
G
Gerd Hoffmann 已提交
3157
    .write = xhci_cap_write,
3158
    .valid.min_access_size = 1,
3159
    .valid.max_access_size = 4,
3160 3161
    .impl.min_access_size = 4,
    .impl.max_access_size = 4,
3162 3163
    .endianness = DEVICE_LITTLE_ENDIAN,
};
3164

3165 3166 3167 3168 3169 3170 3171
static const MemoryRegionOps xhci_oper_ops = {
    .read = xhci_oper_read,
    .write = xhci_oper_write,
    .valid.min_access_size = 4,
    .valid.max_access_size = 4,
    .endianness = DEVICE_LITTLE_ENDIAN,
};
3172

3173 3174 3175 3176 3177 3178 3179 3180
static const MemoryRegionOps xhci_port_ops = {
    .read = xhci_port_read,
    .write = xhci_port_write,
    .valid.min_access_size = 4,
    .valid.max_access_size = 4,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

3181 3182 3183 3184 3185 3186 3187
static const MemoryRegionOps xhci_runtime_ops = {
    .read = xhci_runtime_read,
    .write = xhci_runtime_write,
    .valid.min_access_size = 4,
    .valid.max_access_size = 4,
    .endianness = DEVICE_LITTLE_ENDIAN,
};
3188

3189 3190 3191
static const MemoryRegionOps xhci_doorbell_ops = {
    .read = xhci_doorbell_read,
    .write = xhci_doorbell_write,
3192 3193 3194 3195 3196 3197 3198 3199
    .valid.min_access_size = 4,
    .valid.max_access_size = 4,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static void xhci_attach(USBPort *usbport)
{
    XHCIState *xhci = usbport->opaque;
G
Gerd Hoffmann 已提交
3200
    XHCIPort *port = xhci_lookup_port(xhci, usbport);
3201

3202
    xhci_port_update(port, 0);
3203 3204 3205 3206 3207
}

static void xhci_detach(USBPort *usbport)
{
    XHCIState *xhci = usbport->opaque;
G
Gerd Hoffmann 已提交
3208
    XHCIPort *port = xhci_lookup_port(xhci, usbport);
3209

3210
    xhci_detach_slot(xhci, usbport);
3211
    xhci_port_update(port, 1);
3212 3213
}

G
Gerd Hoffmann 已提交
3214 3215 3216
static void xhci_wakeup(USBPort *usbport)
{
    XHCIState *xhci = usbport->opaque;
G
Gerd Hoffmann 已提交
3217
    XHCIPort *port = xhci_lookup_port(xhci, usbport);
G
Gerd Hoffmann 已提交
3218

3219
    assert(port);
3220
    if (get_field(port->portsc, PORTSC_PLS) != PLS_U3) {
G
Gerd Hoffmann 已提交
3221 3222
        return;
    }
3223
    set_field(&port->portsc, PLS_RESUME, PORTSC_PLS);
G
Gerd Hoffmann 已提交
3224
    xhci_port_notify(port, PORTSC_PLC);
G
Gerd Hoffmann 已提交
3225 3226
}

3227 3228 3229 3230
static void xhci_complete(USBPort *port, USBPacket *packet)
{
    XHCITransfer *xfer = container_of(packet, XHCITransfer, packet);

3231
    if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
3232
        xhci_ep_nuke_one_xfer(xfer, 0);
3233 3234
        return;
    }
3235
    xhci_try_complete_packet(xfer);
G
Gerd Hoffmann 已提交
3236
    xhci_kick_epctx(xfer->epctx, xfer->streamid);
3237 3238 3239
    if (xfer->complete) {
        xhci_ep_free_xfer(xfer);
    }
3240 3241
}

3242
static void xhci_child_detach(USBPort *uport, USBDevice *child)
3243
{
3244 3245 3246
    USBBus *bus = usb_bus_from_device(child);
    XHCIState *xhci = container_of(bus, XHCIState, bus);

G
Gerd Hoffmann 已提交
3247
    xhci_detach_slot(xhci, child->port);
3248 3249
}

3250
static USBPortOps xhci_uport_ops = {
3251 3252
    .attach   = xhci_attach,
    .detach   = xhci_detach,
G
Gerd Hoffmann 已提交
3253
    .wakeup   = xhci_wakeup,
3254 3255 3256 3257
    .complete = xhci_complete,
    .child_detach = xhci_child_detach,
};

G
Gerd Hoffmann 已提交
3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269
static int xhci_find_epid(USBEndpoint *ep)
{
    if (ep->nr == 0) {
        return 1;
    }
    if (ep->pid == USB_TOKEN_IN) {
        return ep->nr * 2 + 1;
    } else {
        return ep->nr * 2;
    }
}

3270
static USBEndpoint *xhci_epid_to_usbep(XHCIEPContext *epctx)
3271
{
3272 3273
    USBPort *uport;
    uint32_t token;
3274

3275
    if (!epctx) {
3276 3277
        return NULL;
    }
3278
    uport = epctx->xhci->slots[epctx->slotid - 1].uport;
3279
    if (!uport || !uport->dev) {
3280 3281
        return NULL;
    }
3282
    token = (epctx->epid & 1) ? USB_TOKEN_IN : USB_TOKEN_OUT;
3283
    return usb_ep_get(uport->dev, token, epctx->epid >> 1);
3284 3285
}

G
Gerd Hoffmann 已提交
3286 3287
static void xhci_wakeup_endpoint(USBBus *bus, USBEndpoint *ep,
                                 unsigned int stream)
G
Gerd Hoffmann 已提交
3288 3289 3290 3291 3292
{
    XHCIState *xhci = container_of(bus, XHCIState, bus);
    int slotid;

    DPRINTF("%s\n", __func__);
3293
    slotid = ep->dev->addr;
G
Gerd Hoffmann 已提交
3294 3295 3296 3297
    if (slotid == 0 || !xhci->slots[slotid-1].enabled) {
        DPRINTF("%s: oops, no slot for dev %d\n", __func__, ep->dev->addr);
        return;
    }
G
Gerd Hoffmann 已提交
3298
    xhci_kick_ep(xhci, slotid, xhci_find_epid(ep), stream);
G
Gerd Hoffmann 已提交
3299 3300
}

3301
static USBBusOps xhci_bus_ops = {
G
Gerd Hoffmann 已提交
3302
    .wakeup_endpoint = xhci_wakeup_endpoint,
3303 3304
};

3305
static void usb_xhci_init(XHCIState *xhci)
3306
{
3307
    DeviceState *dev = DEVICE(xhci);
G
Gerd Hoffmann 已提交
3308 3309
    XHCIPort *port;
    int i, usbports, speedmask;
3310 3311 3312

    xhci->usbsts = USBSTS_HCH;

G
Gerd Hoffmann 已提交
3313 3314 3315 3316 3317 3318 3319 3320 3321
    if (xhci->numports_2 > MAXPORTS_2) {
        xhci->numports_2 = MAXPORTS_2;
    }
    if (xhci->numports_3 > MAXPORTS_3) {
        xhci->numports_3 = MAXPORTS_3;
    }
    usbports = MAX(xhci->numports_2, xhci->numports_3);
    xhci->numports = xhci->numports_2 + xhci->numports_3;

3322
    usb_bus_new(&xhci->bus, sizeof(xhci->bus), &xhci_bus_ops, dev);
3323

G
Gerd Hoffmann 已提交
3324 3325 3326
    for (i = 0; i < usbports; i++) {
        speedmask = 0;
        if (i < xhci->numports_2) {
3327 3328 3329 3330 3331 3332 3333
            if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
                port = &xhci->ports[i + xhci->numports_3];
                port->portnr = i + 1 + xhci->numports_3;
            } else {
                port = &xhci->ports[i];
                port->portnr = i + 1;
            }
G
Gerd Hoffmann 已提交
3334 3335 3336 3337 3338
            port->uport = &xhci->uports[i];
            port->speedmask =
                USB_SPEED_MASK_LOW  |
                USB_SPEED_MASK_FULL |
                USB_SPEED_MASK_HIGH;
3339
            snprintf(port->name, sizeof(port->name), "usb2 port #%d", i+1);
G
Gerd Hoffmann 已提交
3340 3341 3342
            speedmask |= port->speedmask;
        }
        if (i < xhci->numports_3) {
3343 3344 3345 3346 3347 3348 3349
            if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
                port = &xhci->ports[i];
                port->portnr = i + 1;
            } else {
                port = &xhci->ports[i + xhci->numports_2];
                port->portnr = i + 1 + xhci->numports_2;
            }
G
Gerd Hoffmann 已提交
3350 3351
            port->uport = &xhci->uports[i];
            port->speedmask = USB_SPEED_MASK_SUPER;
3352
            snprintf(port->name, sizeof(port->name), "usb3 port #%d", i+1);
G
Gerd Hoffmann 已提交
3353 3354 3355
            speedmask |= port->speedmask;
        }
        usb_register_port(&xhci->bus, &xhci->uports[i], xhci, i,
3356
                          &xhci_uport_ops, speedmask);
3357 3358 3359
    }
}

3360
static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
3361
{
3362
    int i, ret;
3363
    Error *err = NULL;
3364

3365
    XHCIState *xhci = XHCI(dev);
3366

3367 3368 3369 3370
    dev->config[PCI_CLASS_PROG] = 0x30;    /* xHCI */
    dev->config[PCI_INTERRUPT_PIN] = 0x01; /* interrupt pin 1 */
    dev->config[PCI_CACHE_LINE_SIZE] = 0x10;
    dev->config[0x60] = 0x30; /* release number */
3371

3372 3373 3374
    if (strcmp(object_get_typename(OBJECT(dev)), TYPE_NEC_XHCI) == 0) {
        xhci->nec_quirks = true;
    }
3375 3376 3377
    if (xhci->numintrs > MAXINTRS) {
        xhci->numintrs = MAXINTRS;
    }
G
Gerd Hoffmann 已提交
3378 3379 3380
    while (xhci->numintrs & (xhci->numintrs - 1)) {   /* ! power of 2 */
        xhci->numintrs++;
    }
3381 3382 3383 3384 3385 3386 3387 3388 3389
    if (xhci->numintrs < 1) {
        xhci->numintrs = 1;
    }
    if (xhci->numslots > MAXSLOTS) {
        xhci->numslots = MAXSLOTS;
    }
    if (xhci->numslots < 1) {
        xhci->numslots = 1;
    }
3390 3391 3392 3393 3394
    if (xhci_get_flag(xhci, XHCI_FLAG_ENABLE_STREAMS)) {
        xhci->max_pstreams_mask = 7; /* == 256 primary streams */
    } else {
        xhci->max_pstreams_mask = 0;
    }
3395

3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413
    if (xhci->msi != ON_OFF_AUTO_OFF) {
        ret = msi_init(dev, 0x70, xhci->numintrs, true, false, &err);
        /* Any error other than -ENOTSUP(board's MSI support is broken)
         * is a programming error */
        assert(!ret || ret == -ENOTSUP);
        if (ret && xhci->msi == ON_OFF_AUTO_ON) {
            /* Can't satisfy user's explicit msi=on request, fail */
            error_append_hint(&err, "You have to use msi=auto (default) or "
                    "msi=off with this machine type.\n");
            error_propagate(errp, err);
            return;
        }
        assert(!err || xhci->msi == ON_OFF_AUTO_AUTO);
        /* With msi=auto, we fall back to MSI off silently */
        error_free(err);
    }

    usb_xhci_init(xhci);
3414
    xhci->mfwrap_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_mfwrap_timer, xhci);
G
Gerd Hoffmann 已提交
3415

3416 3417
    memory_region_init(&xhci->mem, OBJECT(xhci), "xhci", LEN_REGS);
    memory_region_init_io(&xhci->mem_cap, OBJECT(xhci), &xhci_cap_ops, xhci,
3418
                          "capabilities", LEN_CAP);
3419
    memory_region_init_io(&xhci->mem_oper, OBJECT(xhci), &xhci_oper_ops, xhci,
3420
                          "operational", 0x400);
3421
    memory_region_init_io(&xhci->mem_runtime, OBJECT(xhci), &xhci_runtime_ops, xhci,
3422
                          "runtime", LEN_RUNTIME);
3423
    memory_region_init_io(&xhci->mem_doorbell, OBJECT(xhci), &xhci_doorbell_ops, xhci,
3424 3425 3426 3427 3428 3429 3430
                          "doorbell", LEN_DOORBELL);

    memory_region_add_subregion(&xhci->mem, 0,            &xhci->mem_cap);
    memory_region_add_subregion(&xhci->mem, OFF_OPER,     &xhci->mem_oper);
    memory_region_add_subregion(&xhci->mem, OFF_RUNTIME,  &xhci->mem_runtime);
    memory_region_add_subregion(&xhci->mem, OFF_DOORBELL, &xhci->mem_doorbell);

3431 3432 3433 3434
    for (i = 0; i < xhci->numports; i++) {
        XHCIPort *port = &xhci->ports[i];
        uint32_t offset = OFF_OPER + 0x400 + 0x10 * i;
        port->xhci = xhci;
3435
        memory_region_init_io(&port->mem, OBJECT(xhci), &xhci_port_ops, port,
3436 3437 3438 3439
                              port->name, 0x10);
        memory_region_add_subregion(&xhci->mem, offset, &port->mem);
    }

3440
    pci_register_bar(dev, 0,
3441 3442 3443
                     PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64,
                     &xhci->mem);

3444
    if (pci_bus_is_express(pci_get_bus(dev)) ||
3445
        xhci_get_flag(xhci, XHCI_FLAG_FORCE_PCIE_ENDCAP)) {
3446
        ret = pcie_endpoint_cap_init(dev, 0xa0);
M
Mao Zhongyi 已提交
3447
        assert(ret > 0);
3448
    }
3449

3450
    if (xhci->msix != ON_OFF_AUTO_OFF) {
3451
        /* TODO check for errors, and should fail when msix=on */
3452
        msix_init(dev, xhci->numintrs,
G
Gerd Hoffmann 已提交
3453 3454
                  &xhci->mem, 0, OFF_MSIX_TABLE,
                  &xhci->mem, 0, OFF_MSIX_PBA,
3455
                  0x90, NULL);
G
Gerd Hoffmann 已提交
3456
    }
3457 3458
}

G
Gonglei 已提交
3459 3460 3461 3462 3463
static void usb_xhci_exit(PCIDevice *dev)
{
    int i;
    XHCIState *xhci = XHCI(dev);

G
Gonglei 已提交
3464 3465
    trace_usb_xhci_exit();

G
Gonglei 已提交
3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488
    for (i = 0; i < xhci->numslots; i++) {
        xhci_disable_slot(xhci, i + 1);
    }

    if (xhci->mfwrap_timer) {
        timer_del(xhci->mfwrap_timer);
        timer_free(xhci->mfwrap_timer);
        xhci->mfwrap_timer = NULL;
    }

    memory_region_del_subregion(&xhci->mem, &xhci->mem_cap);
    memory_region_del_subregion(&xhci->mem, &xhci->mem_oper);
    memory_region_del_subregion(&xhci->mem, &xhci->mem_runtime);
    memory_region_del_subregion(&xhci->mem, &xhci->mem_doorbell);

    for (i = 0; i < xhci->numports; i++) {
        XHCIPort *port = &xhci->ports[i];
        memory_region_del_subregion(&xhci->mem, &port->mem);
    }

    /* destroy msix memory region */
    if (dev->msix_table && dev->msix_pba
        && dev->msix_entry_used) {
3489
        msix_uninit(dev, &xhci->mem, &xhci->mem);
G
Gonglei 已提交
3490 3491 3492 3493 3494
    }

    usb_bus_release(&xhci->bus);
}

G
Gerd Hoffmann 已提交
3495 3496 3497
static int usb_xhci_post_load(void *opaque, int version_id)
{
    XHCIState *xhci = opaque;
3498
    PCIDevice *pci_dev = PCI_DEVICE(xhci);
G
Gerd Hoffmann 已提交
3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513
    XHCISlot *slot;
    XHCIEPContext *epctx;
    dma_addr_t dcbaap, pctx;
    uint32_t slot_ctx[4];
    uint32_t ep_ctx[5];
    int slotid, epid, state, intr;

    dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);

    for (slotid = 1; slotid <= xhci->numslots; slotid++) {
        slot = &xhci->slots[slotid-1];
        if (!slot->addressed) {
            continue;
        }
        slot->ctx =
3514
            xhci_mask64(ldq_le_pci_dma(pci_dev, dcbaap + 8 * slotid));
G
Gerd Hoffmann 已提交
3515 3516
        xhci_dma_read_u32s(xhci, slot->ctx, slot_ctx, sizeof(slot_ctx));
        slot->uport = xhci_lookup_uport(xhci, slot_ctx);
3517 3518 3519 3520 3521 3522
        if (!slot->uport) {
            /* should not happen, but may trigger on guest bugs */
            slot->enabled = 0;
            slot->addressed = 0;
            continue;
        }
G
Gerd Hoffmann 已提交
3523 3524
        assert(slot->uport && slot->uport->dev);

3525
        for (epid = 1; epid <= 31; epid++) {
G
Gerd Hoffmann 已提交
3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537
            pctx = slot->ctx + 32 * epid;
            xhci_dma_read_u32s(xhci, pctx, ep_ctx, sizeof(ep_ctx));
            state = ep_ctx[0] & EP_STATE_MASK;
            if (state == EP_DISABLED) {
                continue;
            }
            epctx = xhci_alloc_epctx(xhci, slotid, epid);
            slot->eps[epid-1] = epctx;
            xhci_init_epctx(epctx, pctx, ep_ctx);
            epctx->state = state;
            if (state == EP_RUNNING) {
                /* kick endpoint after vmload is finished */
3538
                timer_mod(epctx->kick_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
G
Gerd Hoffmann 已提交
3539 3540 3541 3542 3543 3544
            }
        }
    }

    for (intr = 0; intr < xhci->numintrs; intr++) {
        if (xhci->intr[intr].msix_used) {
3545
            msix_vector_use(pci_dev, intr);
G
Gerd Hoffmann 已提交
3546
        } else {
3547
            msix_vector_unuse(pci_dev, intr);
G
Gerd Hoffmann 已提交
3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593
        }
    }

    return 0;
}

static const VMStateDescription vmstate_xhci_ring = {
    .name = "xhci-ring",
    .version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT64(dequeue, XHCIRing),
        VMSTATE_BOOL(ccs, XHCIRing),
        VMSTATE_END_OF_LIST()
    }
};

static const VMStateDescription vmstate_xhci_port = {
    .name = "xhci-port",
    .version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32(portsc, XHCIPort),
        VMSTATE_END_OF_LIST()
    }
};

static const VMStateDescription vmstate_xhci_slot = {
    .name = "xhci-slot",
    .version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_BOOL(enabled,   XHCISlot),
        VMSTATE_BOOL(addressed, XHCISlot),
        VMSTATE_END_OF_LIST()
    }
};

static const VMStateDescription vmstate_xhci_event = {
    .name = "xhci-event",
    .version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32(type,   XHCIEvent),
        VMSTATE_UINT32(ccode,  XHCIEvent),
        VMSTATE_UINT64(ptr,    XHCIEvent),
        VMSTATE_UINT32(length, XHCIEvent),
        VMSTATE_UINT32(flags,  XHCIEvent),
        VMSTATE_UINT8(slotid,  XHCIEvent),
        VMSTATE_UINT8(epid,    XHCIEvent),
3594
        VMSTATE_END_OF_LIST()
G
Gerd Hoffmann 已提交
3595 3596 3597 3598 3599
    }
};

static bool xhci_er_full(void *opaque, int version_id)
{
3600
    return false;
G
Gerd Hoffmann 已提交
3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623
}

static const VMStateDescription vmstate_xhci_intr = {
    .name = "xhci-intr",
    .version_id = 1,
    .fields = (VMStateField[]) {
        /* registers */
        VMSTATE_UINT32(iman,          XHCIInterrupter),
        VMSTATE_UINT32(imod,          XHCIInterrupter),
        VMSTATE_UINT32(erstsz,        XHCIInterrupter),
        VMSTATE_UINT32(erstba_low,    XHCIInterrupter),
        VMSTATE_UINT32(erstba_high,   XHCIInterrupter),
        VMSTATE_UINT32(erdp_low,      XHCIInterrupter),
        VMSTATE_UINT32(erdp_high,     XHCIInterrupter),

        /* state */
        VMSTATE_BOOL(msix_used,       XHCIInterrupter),
        VMSTATE_BOOL(er_pcs,          XHCIInterrupter),
        VMSTATE_UINT64(er_start,      XHCIInterrupter),
        VMSTATE_UINT32(er_size,       XHCIInterrupter),
        VMSTATE_UINT32(er_ep_idx,     XHCIInterrupter),

        /* event queue (used if ring is full) */
3624
        VMSTATE_BOOL(er_full_unused,  XHCIInterrupter),
G
Gerd Hoffmann 已提交
3625 3626 3627 3628 3629 3630 3631 3632 3633 3634
        VMSTATE_UINT32_TEST(ev_buffer_put, XHCIInterrupter, xhci_er_full),
        VMSTATE_UINT32_TEST(ev_buffer_get, XHCIInterrupter, xhci_er_full),
        VMSTATE_STRUCT_ARRAY_TEST(ev_buffer, XHCIInterrupter, EV_QUEUE,
                                  xhci_er_full, 1,
                                  vmstate_xhci_event, XHCIEvent),

        VMSTATE_END_OF_LIST()
    }
};

3635 3636
static const VMStateDescription vmstate_xhci = {
    .name = "xhci",
G
Gerd Hoffmann 已提交
3637 3638 3639
    .version_id = 1,
    .post_load = usb_xhci_post_load,
    .fields = (VMStateField[]) {
3640
        VMSTATE_PCI_DEVICE(parent_obj, XHCIState),
3641
        VMSTATE_MSIX(parent_obj, XHCIState),
G
Gerd Hoffmann 已提交
3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661

        VMSTATE_STRUCT_VARRAY_UINT32(ports, XHCIState, numports, 1,
                                     vmstate_xhci_port, XHCIPort),
        VMSTATE_STRUCT_VARRAY_UINT32(slots, XHCIState, numslots, 1,
                                     vmstate_xhci_slot, XHCISlot),
        VMSTATE_STRUCT_VARRAY_UINT32(intr, XHCIState, numintrs, 1,
                                     vmstate_xhci_intr, XHCIInterrupter),

        /* Operational Registers */
        VMSTATE_UINT32(usbcmd,        XHCIState),
        VMSTATE_UINT32(usbsts,        XHCIState),
        VMSTATE_UINT32(dnctrl,        XHCIState),
        VMSTATE_UINT32(crcr_low,      XHCIState),
        VMSTATE_UINT32(crcr_high,     XHCIState),
        VMSTATE_UINT32(dcbaap_low,    XHCIState),
        VMSTATE_UINT32(dcbaap_high,   XHCIState),
        VMSTATE_UINT32(config,        XHCIState),

        /* Runtime Registers & state */
        VMSTATE_INT64(mfindex_start,  XHCIState),
3662
        VMSTATE_TIMER_PTR(mfwrap_timer,   XHCIState),
G
Gerd Hoffmann 已提交
3663 3664 3665 3666
        VMSTATE_STRUCT(cmd_ring, XHCIState, 1, vmstate_xhci_ring, XHCIRing),

        VMSTATE_END_OF_LIST()
    }
3667 3668
};

G
Gerd Hoffmann 已提交
3669 3670 3671
static Property xhci_properties[] = {
    DEFINE_PROP_BIT("streams", XHCIState, flags,
                    XHCI_FLAG_ENABLE_STREAMS, true),
3672 3673
    DEFINE_PROP_UINT32("p2",    XHCIState, numports_2, 4),
    DEFINE_PROP_UINT32("p3",    XHCIState, numports_3, 4),
3674 3675 3676
    DEFINE_PROP_END_OF_LIST(),
};

3677 3678 3679 3680 3681 3682 3683
static void xhci_instance_init(Object *obj)
{
    /* QEMU_PCI_CAP_EXPRESS initialization does not depend on QEMU command
     * line, therefore, no need to wait to realize like other devices */
    PCI_DEVICE(obj)->cap_present |= QEMU_PCI_CAP_EXPRESS;
}

3684 3685 3686
static void xhci_class_init(ObjectClass *klass, void *data)
{
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
3687
    DeviceClass *dc = DEVICE_CLASS(klass);
3688

3689 3690
    dc->vmsd    = &vmstate_xhci;
    dc->props   = xhci_properties;
J
Jan Kiszka 已提交
3691
    dc->reset   = xhci_reset;
3692
    set_bit(DEVICE_CATEGORY_USB, dc->categories);
3693
    k->realize      = usb_xhci_realize;
G
Gonglei 已提交
3694
    k->exit         = usb_xhci_exit;
3695 3696 3697
    k->class_id     = PCI_CLASS_SERIAL_USB;
}

3698
static const TypeInfo xhci_info = {
3699
    .name          = TYPE_XHCI,
3700 3701 3702
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(XHCIState),
    .class_init    = xhci_class_init,
3703
    .instance_init = xhci_instance_init,
G
Gerd Hoffmann 已提交
3704
    .abstract      = true,
3705 3706 3707 3708 3709
    .interfaces = (InterfaceInfo[]) {
        { INTERFACE_PCIE_DEVICE },
        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
        { }
    },
G
Gerd Hoffmann 已提交
3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720
};

static void qemu_xhci_class_init(ObjectClass *klass, void *data)
{
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->vendor_id    = PCI_VENDOR_ID_REDHAT;
    k->device_id    = PCI_DEVICE_ID_REDHAT_XHCI;
    k->revision     = 0x01;
}

G
Gerd Hoffmann 已提交
3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731
static void qemu_xhci_instance_init(Object *obj)
{
    XHCIState *xhci = XHCI(obj);

    xhci->msi      = ON_OFF_AUTO_OFF;
    xhci->msix     = ON_OFF_AUTO_AUTO;
    xhci->numintrs = MAXINTRS;
    xhci->numslots = MAXSLOTS;
    xhci_set_flag(xhci, XHCI_FLAG_SS_FIRST);
}

G
Gerd Hoffmann 已提交
3732 3733 3734 3735
static const TypeInfo qemu_xhci_info = {
    .name          = TYPE_QEMU_XHCI,
    .parent        = TYPE_XHCI,
    .class_init    = qemu_xhci_class_init,
G
Gerd Hoffmann 已提交
3736
    .instance_init = qemu_xhci_instance_init,
3737 3738
};

A
Andreas Färber 已提交
3739
static void xhci_register_types(void)
3740
{
3741
    type_register_static(&xhci_info);
G
Gerd Hoffmann 已提交
3742
    type_register_static(&qemu_xhci_info);
3743
}
A
Andreas Färber 已提交
3744 3745

type_init(xhci_register_types)