Commit 82ea61c6 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/kraxel/tags/pull-usb-8' into staging



qtest: improve ehci/uhci test
usb: misc fixes, mostly for usb3/xhci

# gpg: Signature made Mon 02 Jun 2014 15:40:34 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-usb-8:
  xhci: order superspeed ports first
  xhci: make port reset trace point more verbose
  usb: add usb_pick_speed
  usb-host: add HAVE_STREAMS define
  usb-host: allow attaching usb3 devices to ehci
  usb: improve ehci/uhci test
  usb: move ehci register defines to header file
  usb: add uhci port status reserved bit
  usb: move uhci register defines to header file
  qtest: fix qpci_config_writel

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 1673e89e 7bafd888
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -28,6 +28,26 @@
#include "qemu/iov.h"
#include "trace.h"

void usb_pick_speed(USBPort *port)
{
    static const int speeds[] = {
        USB_SPEED_SUPER,
        USB_SPEED_HIGH,
        USB_SPEED_FULL,
        USB_SPEED_LOW,
    };
    USBDevice *udev = port->dev;
    int i;

    for (i = 0; i < ARRAY_SIZE(speeds); i++) {
        if ((udev->speedmask & (1 << speeds[i])) &&
            (port->speedmask & (1 << speeds[i]))) {
            udev->speed = speeds[i];
            return;
        }
    }
}

void usb_attach(USBPort *port)
{
    USBDevice *dev = port->dev;
@@ -35,6 +55,7 @@ void usb_attach(USBPort *port)
    assert(dev != NULL);
    assert(dev->attached);
    assert(dev->state == USB_STATE_NOTATTACHED);
    usb_pick_speed(port);
    port->ops->attach(port);
    dev->state = USB_STATE_ATTACHED;
    usb_device_handle_attach(dev);
+0 −12
Original line number Diff line number Diff line
@@ -518,18 +518,6 @@ void usb_desc_init(USBDevice *dev)

void usb_desc_attach(USBDevice *dev)
{
    const USBDesc *desc = usb_device_get_usb_desc(dev);

    assert(desc != NULL);
    if (desc->super && (dev->port->speedmask & USB_SPEED_MASK_SUPER)) {
        dev->speed = USB_SPEED_SUPER;
    } else if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
        dev->speed = USB_SPEED_HIGH;
    } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) {
        dev->speed = USB_SPEED_FULL;
    } else {
        return;
    }
    usb_desc_setdefaults(dev);
}

+1 −78
Original line number Diff line number Diff line
@@ -27,87 +27,10 @@
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#include "hw/usb/ehci-regs.h"
#include "hw/usb/hcd-ehci.h"
#include "trace.h"

/* Capability Registers Base Address - section 2.2 */
#define CAPLENGTH        0x0000  /* 1-byte, 0x0001 reserved */
#define HCIVERSION       0x0002  /* 2-bytes, i/f version # */
#define HCSPARAMS        0x0004  /* 4-bytes, structural params */
#define HCCPARAMS        0x0008  /* 4-bytes, capability params */
#define EECP             HCCPARAMS + 1
#define HCSPPORTROUTE1   0x000c
#define HCSPPORTROUTE2   0x0010

#define USBCMD           0x0000
#define USBCMD_RUNSTOP   (1 << 0)      // run / Stop
#define USBCMD_HCRESET   (1 << 1)      // HC Reset
#define USBCMD_FLS       (3 << 2)      // Frame List Size
#define USBCMD_FLS_SH    2             // Frame List Size Shift
#define USBCMD_PSE       (1 << 4)      // Periodic Schedule Enable
#define USBCMD_ASE       (1 << 5)      // Asynch Schedule Enable
#define USBCMD_IAAD      (1 << 6)      // Int Asynch Advance Doorbell
#define USBCMD_LHCR      (1 << 7)      // Light Host Controller Reset
#define USBCMD_ASPMC     (3 << 8)      // Async Sched Park Mode Count
#define USBCMD_ASPME     (1 << 11)     // Async Sched Park Mode Enable
#define USBCMD_ITC       (0x7f << 16)  // Int Threshold Control
#define USBCMD_ITC_SH    16            // Int Threshold Control Shift

#define USBSTS           0x0004
#define USBSTS_RO_MASK   0x0000003f
#define USBSTS_INT       (1 << 0)      // USB Interrupt
#define USBSTS_ERRINT    (1 << 1)      // Error Interrupt
#define USBSTS_PCD       (1 << 2)      // Port Change Detect
#define USBSTS_FLR       (1 << 3)      // Frame List Rollover
#define USBSTS_HSE       (1 << 4)      // Host System Error
#define USBSTS_IAA       (1 << 5)      // Interrupt on Async Advance
#define USBSTS_HALT      (1 << 12)     // HC Halted
#define USBSTS_REC       (1 << 13)     // Reclamation
#define USBSTS_PSS       (1 << 14)     // Periodic Schedule Status
#define USBSTS_ASS       (1 << 15)     // Asynchronous Schedule Status

/*
 *  Interrupt enable bits correspond to the interrupt active bits in USBSTS
 *  so no need to redefine here.
 */
#define USBINTR              0x0008
#define USBINTR_MASK         0x0000003f

#define FRINDEX              0x000c
#define CTRLDSSEGMENT        0x0010
#define PERIODICLISTBASE     0x0014
#define ASYNCLISTADDR        0x0018
#define ASYNCLISTADDR_MASK   0xffffffe0

#define CONFIGFLAG           0x0040

/*
 * Bits that are reserved or are read-only are masked out of values
 * written to us by software
 */
#define PORTSC_RO_MASK       0x007001c0
#define PORTSC_RWC_MASK      0x0000002a
#define PORTSC_WKOC_E        (1 << 22)    // Wake on Over Current Enable
#define PORTSC_WKDS_E        (1 << 21)    // Wake on Disconnect Enable
#define PORTSC_WKCN_E        (1 << 20)    // Wake on Connect Enable
#define PORTSC_PTC           (15 << 16)   // Port Test Control
#define PORTSC_PTC_SH        16           // Port Test Control shift
#define PORTSC_PIC           (3 << 14)    // Port Indicator Control
#define PORTSC_PIC_SH        14           // Port Indicator Control Shift
#define PORTSC_POWNER        (1 << 13)    // Port Owner
#define PORTSC_PPOWER        (1 << 12)    // Port Power
#define PORTSC_LINESTAT      (3 << 10)    // Port Line Status
#define PORTSC_LINESTAT_SH   10           // Port Line Status Shift
#define PORTSC_PRESET        (1 << 8)     // Port Reset
#define PORTSC_SUSPEND       (1 << 7)     // Port Suspend
#define PORTSC_FPRES         (1 << 6)     // Force Port Resume
#define PORTSC_OCC           (1 << 5)     // Over Current Change
#define PORTSC_OCA           (1 << 4)     // Over Current Active
#define PORTSC_PEDC          (1 << 3)     // Port Enable/Disable Change
#define PORTSC_PED           (1 << 2)     // Port Enable/Disable
#define PORTSC_CSC           (1 << 1)     // Connect Status Change
#define PORTSC_CONNECT       (1 << 0)     // Current Connect Status

#define FRAME_TIMER_FREQ 1000
#define FRAME_TIMER_NS   (1000000000 / FRAME_TIMER_FREQ)
#define UFRAME_TIMER_NS  (FRAME_TIMER_NS / 8)
+1 −35
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
 */
#include "hw/hw.h"
#include "hw/usb.h"
#include "hw/usb/uhci-regs.h"
#include "hw/pci/pci.h"
#include "qemu/timer.h"
#include "qemu/iov.h"
@@ -37,41 +38,6 @@
//#define DEBUG
//#define DEBUG_DUMP_DATA

#define UHCI_CMD_FGR      (1 << 4)
#define UHCI_CMD_EGSM     (1 << 3)
#define UHCI_CMD_GRESET   (1 << 2)
#define UHCI_CMD_HCRESET  (1 << 1)
#define UHCI_CMD_RS       (1 << 0)

#define UHCI_STS_HCHALTED (1 << 5)
#define UHCI_STS_HCPERR   (1 << 4)
#define UHCI_STS_HSERR    (1 << 3)
#define UHCI_STS_RD       (1 << 2)
#define UHCI_STS_USBERR   (1 << 1)
#define UHCI_STS_USBINT   (1 << 0)

#define TD_CTRL_SPD     (1 << 29)
#define TD_CTRL_ERROR_SHIFT  27
#define TD_CTRL_IOS     (1 << 25)
#define TD_CTRL_IOC     (1 << 24)
#define TD_CTRL_ACTIVE  (1 << 23)
#define TD_CTRL_STALL   (1 << 22)
#define TD_CTRL_BABBLE  (1 << 20)
#define TD_CTRL_NAK     (1 << 19)
#define TD_CTRL_TIMEOUT (1 << 18)

#define UHCI_PORT_SUSPEND (1 << 12)
#define UHCI_PORT_RESET (1 << 9)
#define UHCI_PORT_LSDA  (1 << 8)
#define UHCI_PORT_RD    (1 << 6)
#define UHCI_PORT_ENC   (1 << 3)
#define UHCI_PORT_EN    (1 << 2)
#define UHCI_PORT_CSC   (1 << 1)
#define UHCI_PORT_CCS   (1 << 0)

#define UHCI_PORT_READ_ONLY    (0x1bb)
#define UHCI_PORT_WRITE_CLEAR  (UHCI_PORT_CSC | UHCI_PORT_ENC)

#define FRAME_TIMER_FREQ 1000

#define FRAME_MAX_LOOPS  256
+38 −9
Original line number Diff line number Diff line
@@ -498,6 +498,7 @@ typedef struct XHCIEvRingSeg {
enum xhci_flags {
    XHCI_FLAG_USE_MSI = 1,
    XHCI_FLAG_USE_MSI_X,
    XHCI_FLAG_SS_FIRST,
};

static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
@@ -714,10 +715,18 @@ static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport)
    case USB_SPEED_LOW:
    case USB_SPEED_FULL:
    case USB_SPEED_HIGH:
        if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
            index = uport->index + xhci->numports_3;
        } else {
            index = uport->index;
        }
        break;
    case USB_SPEED_SUPER:
        if (xhci_get_flag(xhci, XHCI_FLAG_SS_FIRST)) {
            index = uport->index;
        } else {
            index = uport->index + xhci->numports_2;
        }
        break;
    default:
        return NULL;
@@ -2856,7 +2865,7 @@ static void xhci_port_update(XHCIPort *port, int is_detach)

static void xhci_port_reset(XHCIPort *port, bool warm_reset)
{
    trace_usb_xhci_port_reset(port->portnr);
    trace_usb_xhci_port_reset(port->portnr, warm_reset);

    if (!xhci_port_have_device(port)) {
        return;
@@ -2972,7 +2981,11 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size)
        ret = 0x20425355; /* "USB " */
        break;
    case 0x28: /* Supported Protocol:08 */
        ret = 0x00000001 | (xhci->numports_2<<8);
        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;
        }
        break;
    case 0x2c: /* Supported Protocol:0c */
        ret = 0x00000000; /* reserved */
@@ -2984,7 +2997,11 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size)
        ret = 0x20425355; /* "USB " */
        break;
    case 0x38: /* Supported Protocol:08 */
        ret = 0x00000000 | (xhci->numports_2+1) | (xhci->numports_3<<8);
        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);
        }
        break;
    case 0x3c: /* Supported Protocol:0c */
        ret = 0x00000000; /* reserved */
@@ -3517,8 +3534,13 @@ static void usb_xhci_init(XHCIState *xhci)
    for (i = 0; i < usbports; i++) {
        speedmask = 0;
        if (i < xhci->numports_2) {
            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;
            }
            port->uport = &xhci->uports[i];
            port->speedmask =
                USB_SPEED_MASK_LOW  |
@@ -3528,8 +3550,13 @@ static void usb_xhci_init(XHCIState *xhci)
            speedmask |= port->speedmask;
        }
        if (i < xhci->numports_3) {
            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;
            }
            port->uport = &xhci->uports[i];
            port->speedmask = USB_SPEED_MASK_SUPER;
            snprintf(port->name, sizeof(port->name), "usb3 port #%d", i+1);
@@ -3788,6 +3815,8 @@ static const VMStateDescription vmstate_xhci = {
static Property xhci_properties[] = {
    DEFINE_PROP_BIT("msi",      XHCIState, flags, XHCI_FLAG_USE_MSI, true),
    DEFINE_PROP_BIT("msix",     XHCIState, flags, XHCI_FLAG_USE_MSI_X, true),
    DEFINE_PROP_BIT("superspeed-ports-first",
                    XHCIState, flags, XHCI_FLAG_SS_FIRST, true),
    DEFINE_PROP_UINT32("intrs", XHCIState, numintrs, MAXINTRS),
    DEFINE_PROP_UINT32("slots", XHCIState, numslots, MAXSLOTS),
    DEFINE_PROP_UINT32("p2",    XHCIState, numports_2, 4),
Loading