diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/e1000.c | 167 | ||||
-rw-r--r-- | hw/e1000_hw.h | 12 | ||||
-rw-r--r-- | hw/eepro100.c | 28 | ||||
-rw-r--r-- | hw/usb/core.c | 1 | ||||
-rw-r--r-- | hw/usb/desc.c | 32 | ||||
-rw-r--r-- | hw/usb/desc.h | 1 | ||||
-rw-r--r-- | hw/usb/dev-audio.c | 1 | ||||
-rw-r--r-- | hw/usb/dev-bluetooth.c | 1 | ||||
-rw-r--r-- | hw/usb/dev-hub.c | 1 | ||||
-rw-r--r-- | hw/usb/dev-network.c | 1 | ||||
-rw-r--r-- | hw/usb/dev-serial.c | 1 | ||||
-rw-r--r-- | hw/usb/dev-smartcard-reader.c | 1 | ||||
-rw-r--r-- | hw/usb/dev-storage.c | 6 | ||||
-rw-r--r-- | hw/usb/dev-wacom.c | 1 | ||||
-rw-r--r-- | hw/usb/hcd-ehci.c | 23 | ||||
-rw-r--r-- | hw/usb/hcd-uhci.c | 1 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 192 | ||||
-rw-r--r-- | hw/usb/host-linux.c | 12 | ||||
-rw-r--r-- | hw/usb/redirect.c | 9 | ||||
-rw-r--r-- | hw/virtio-serial-bus.c | 57 | ||||
-rw-r--r-- | hw/virtio.c | 11 |
21 files changed, 372 insertions, 187 deletions
diff --git a/hw/e1000.c b/hw/e1000.c index 9c764624f9..4573f1301e 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -42,7 +42,7 @@ enum { DEBUG_GENERAL, DEBUG_IO, DEBUG_MMIO, DEBUG_INTERRUPT, DEBUG_RX, DEBUG_TX, DEBUG_MDIC, DEBUG_EEPROM, DEBUG_UNKNOWN, DEBUG_TXSUM, DEBUG_TXERR, DEBUG_RXERR, - DEBUG_RXFILTER, DEBUG_NOTYET, + DEBUG_RXFILTER, DEBUG_PHY, DEBUG_NOTYET, }; #define DBGBIT(x) (1<<DEBUG_##x) static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL); @@ -125,6 +125,8 @@ typedef struct E1000State_st { uint16_t reading; uint32_t old_eecd; } eecd_state; + + QEMUTimer *autoneg_timer; } E1000State; #define defreg(x) x = (E1000_##x>>2) @@ -142,6 +144,48 @@ enum { defreg(VET), }; +static void +e1000_link_down(E1000State *s) +{ + s->mac_reg[STATUS] &= ~E1000_STATUS_LU; + s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS; +} + +static void +e1000_link_up(E1000State *s) +{ + s->mac_reg[STATUS] |= E1000_STATUS_LU; + s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS; +} + +static void +set_phy_ctrl(E1000State *s, int index, uint16_t val) +{ + if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) { + s->nic->nc.link_down = true; + e1000_link_down(s); + s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE; + DBGOUT(PHY, "Start link auto negotiation\n"); + qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500); + } +} + +static void +e1000_autoneg_timer(void *opaque) +{ + E1000State *s = opaque; + s->nic->nc.link_down = false; + e1000_link_up(s); + s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE; + DBGOUT(PHY, "Auto negotiation is completed\n"); +} + +static void (*phyreg_writeops[])(E1000State *, int, uint16_t) = { + [PHY_CTRL] = set_phy_ctrl, +}; + +enum { NPHYWRITEOPS = ARRAY_SIZE(phyreg_writeops) }; + enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W }; static const char phy_regcap[0x20] = { [PHY_STATUS] = PHY_R, [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW, @@ -152,11 +196,37 @@ static const char phy_regcap[0x20] = { [PHY_ID2] = PHY_R, [M88E1000_PHY_SPEC_STATUS] = PHY_R }; +static const uint16_t phy_reg_init[] = { + [PHY_CTRL] = 0x1140, + [PHY_STATUS] = 0x794d, /* link initially up with not completed autoneg */ + [PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT, + [PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360, + [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1, + [PHY_LP_ABILITY] = 0x1e0, [PHY_1000T_STATUS] = 0x3c00, + [M88E1000_PHY_SPEC_STATUS] = 0xac00, +}; + +static const uint32_t mac_reg_init[] = { + [PBA] = 0x00100030, + [LEDCTL] = 0x602, + [CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 | + E1000_CTRL_SPD_1000 | E1000_CTRL_SLU, + [STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE | + E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK | + E1000_STATUS_SPEED_1000 | E1000_STATUS_FD | + E1000_STATUS_LU, + [MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN | + E1000_MANC_ARP_EN | E1000_MANC_0298_EN | + E1000_MANC_RMCP_EN, +}; + static void set_interrupt_cause(E1000State *s, int index, uint32_t val) { - if (val) + if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) { + /* Only for 8257x */ val |= E1000_ICR_INT_ASSERTED; + } s->mac_reg[ICR] = val; s->mac_reg[ICS] = val; qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0); @@ -193,6 +263,23 @@ rxbufsize(uint32_t v) return 2048; } +static void e1000_reset(void *opaque) +{ + E1000State *d = opaque; + + qemu_del_timer(d->autoneg_timer); + memset(d->phy_reg, 0, sizeof d->phy_reg); + memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init); + memset(d->mac_reg, 0, sizeof d->mac_reg); + memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init); + d->rxbuf_min_shift = 1; + memset(&d->tx, 0, sizeof d->tx); + + if (d->nic->nc.link_down) { + e1000_link_down(d); + } +} + static void set_ctrl(E1000State *s, int index, uint32_t val) { @@ -230,11 +317,18 @@ set_mdic(E1000State *s, int index, uint32_t val) if (!(phy_regcap[addr] & PHY_W)) { DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr); val |= E1000_MDIC_ERROR; - } else + } else { + if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) { + phyreg_writeops[addr](s, index, data); + } s->phy_reg[addr] = data; + } } s->mac_reg[MDIC] = val | E1000_MDIC_READY; - set_ics(s, 0, E1000_ICR_MDAC); + + if (val & E1000_MDIC_INT_EN) { + set_ics(s, 0, E1000_ICR_MDAC); + } } static uint32_t @@ -349,6 +443,16 @@ fcs_len(E1000State *s) } static void +e1000_send_packet(E1000State *s, const uint8_t *buf, int size) +{ + if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) { + s->nic->nc.info->receive(&s->nic->nc, buf, size); + } else { + qemu_send_packet(&s->nic->nc, buf, size); + } +} + +static void xmit_seg(E1000State *s) { uint16_t len, *sp; @@ -397,9 +501,9 @@ xmit_seg(E1000State *s) memmove(tp->vlan, tp->data, 4); memmove(tp->data, tp->data + 4, 8); memcpy(tp->data + 8, tp->vlan_header, 4); - qemu_send_packet(&s->nic->nc, tp->vlan, tp->size + 4); + e1000_send_packet(s, tp->vlan, tp->size + 4); } else - qemu_send_packet(&s->nic->nc, tp->data, tp->size); + e1000_send_packet(s, tp->data, tp->size); s->mac_reg[TPT]++; s->mac_reg[GPTC]++; n = s->mac_reg[TOTL]; @@ -622,11 +726,9 @@ e1000_set_link_status(VLANClientState *nc) uint32_t old_status = s->mac_reg[STATUS]; if (nc->link_down) { - s->mac_reg[STATUS] &= ~E1000_STATUS_LU; - s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS; + e1000_link_down(s); } else { - s->mac_reg[STATUS] |= E1000_STATUS_LU; - s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS; + e1000_link_up(s); } if (s->mac_reg[STATUS] != old_status) @@ -901,6 +1003,7 @@ static void (*macreg_writeops[])(E1000State *, int, uint32_t) = { [MTA ... MTA+127] = &mac_writereg, [VFTA ... VFTA+127] = &mac_writereg, }; + enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) }; static void @@ -1061,29 +1164,6 @@ static const uint16_t e1000_eeprom_template[64] = { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, }; -static const uint16_t phy_reg_init[] = { - [PHY_CTRL] = 0x1140, [PHY_STATUS] = 0x796d, // link initially up - [PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT, - [PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360, - [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1, - [PHY_LP_ABILITY] = 0x1e0, [PHY_1000T_STATUS] = 0x3c00, - [M88E1000_PHY_SPEC_STATUS] = 0xac00, -}; - -static const uint32_t mac_reg_init[] = { - [PBA] = 0x00100030, - [LEDCTL] = 0x602, - [CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 | - E1000_CTRL_SPD_1000 | E1000_CTRL_SLU, - [STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE | - E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK | - E1000_STATUS_SPEED_1000 | E1000_STATUS_FD | - E1000_STATUS_LU, - [MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN | - E1000_MANC_ARP_EN | E1000_MANC_0298_EN | - E1000_MANC_RMCP_EN, -}; - /* PCI interface */ static void @@ -1117,29 +1197,14 @@ pci_e1000_uninit(PCIDevice *dev) { E1000State *d = DO_UPCAST(E1000State, dev, dev); + qemu_del_timer(d->autoneg_timer); + qemu_free_timer(d->autoneg_timer); memory_region_destroy(&d->mmio); memory_region_destroy(&d->io); qemu_del_vlan_client(&d->nic->nc); return 0; } -static void e1000_reset(void *opaque) -{ - E1000State *d = opaque; - - memset(d->phy_reg, 0, sizeof d->phy_reg); - memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init); - memset(d->mac_reg, 0, sizeof d->mac_reg); - memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init); - d->rxbuf_min_shift = 1; - memset(&d->tx, 0, sizeof d->tx); - - if (d->nic->nc.link_down) { - d->mac_reg[STATUS] &= ~E1000_STATUS_LU; - d->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS; - } -} - static NetClientInfo net_e1000_info = { .type = NET_CLIENT_TYPE_NIC, .size = sizeof(NICState), @@ -1188,6 +1253,8 @@ static int pci_e1000_init(PCIDevice *pci_dev) add_boot_device_path(d->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0"); + d->autoneg_timer = qemu_new_timer_ms(vm_clock, e1000_autoneg_timer, d); + return 0; } diff --git a/hw/e1000_hw.h b/hw/e1000_hw.h index 9e29af8c82..c9cb79e64d 100644 --- a/hw/e1000_hw.h +++ b/hw/e1000_hw.h @@ -349,6 +349,18 @@ #define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */ #define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */ +/* PHY Control Register */ +#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ +#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ +#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ +#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ +#define MII_CR_POWER_DOWN 0x0800 /* Power down */ +#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ +#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ +#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ + /* PHY Status Register */ #define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ #define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ diff --git a/hw/eepro100.c b/hw/eepro100.c index 02e6f7ef31..6279ae36ec 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -322,8 +322,32 @@ static const uint16_t eepro100_mdi_mask[] = { 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, }; +#define POLYNOMIAL 0x04c11db6 + static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s); +/* From FreeBSD (locally modified). */ +static unsigned e100_compute_mcast_idx(const uint8_t *ep) +{ + uint32_t crc; + int carry, i, j; + uint8_t b; + + crc = 0xffffffff; + for (i = 0; i < 6; i++) { + b = *ep++; + for (j = 0; j < 8; j++) { + carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); + crc <<= 1; + b >>= 1; + if (carry) { + crc = ((crc ^ POLYNOMIAL) | carry); + } + } + } + return (crc & BITS(7, 2)) >> 2; +} + /* Read a 16 bit control/status (CSR) register. */ static uint16_t e100_read_reg2(EEPRO100State *s, E100RegisterOffset addr) { @@ -823,7 +847,7 @@ static void set_multicast_list(EEPRO100State *s) uint8_t multicast_addr[6]; pci_dma_read(&s->dev, s->cb_address + 10 + i, multicast_addr, 6); TRACE(OTHER, logout("multicast entry %s\n", nic_dump(multicast_addr, 6))); - unsigned mcast_idx = compute_mcast_idx(multicast_addr); + unsigned mcast_idx = e100_compute_mcast_idx(multicast_addr); assert(mcast_idx < 64); s->mult[mcast_idx >> 3] |= (1 << (mcast_idx & 7)); } @@ -1650,7 +1674,7 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size if (s->configuration[21] & BIT(3)) { /* Multicast all bit is set, receive all multicast frames. */ } else { - unsigned mcast_idx = compute_mcast_idx(buf); + unsigned mcast_idx = e100_compute_mcast_idx(buf); assert(mcast_idx < 64); if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) { /* Multicast frame is allowed in hash table. */ diff --git a/hw/usb/core.c b/hw/usb/core.c index 9a14a53852..0e02da7601 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -501,6 +501,7 @@ void usb_packet_set_state(USBPacket *p, USBPacketState state) void usb_packet_setup(USBPacket *p, int pid, USBEndpoint *ep) { assert(!usb_packet_is_inflight(p)); + assert(p->iov.iov != NULL); p->pid = pid; p->ep = ep; p->result = 0; diff --git a/hw/usb/desc.c b/hw/usb/desc.c index 3c77368cb0..e8a3c6af3d 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -1,3 +1,5 @@ +#include <ctype.h> + #include "hw/usb.h" #include "hw/usb/desc.h" #include "trace.h" @@ -412,6 +414,36 @@ void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str) s->str = g_strdup(str); } +/* + * This function creates a serial number for a usb device. + * The serial number should: + * (a) Be unique within the virtual machine. + * (b) Be constant, so you don't get a new one each + * time the guest is started. + * So we are using the physical location to generate a serial number + * from it. It has three pieces: First a fixed, device-specific + * prefix. Second the device path of the host controller (which is + * the pci address in most cases). Third the physical port path. + * Results in serial numbers like this: "314159-0000:00:1d.7-3". + */ +void usb_desc_create_serial(USBDevice *dev) +{ + DeviceState *hcd = dev->qdev.parent_bus->parent; + const USBDesc *desc = usb_device_get_usb_desc(dev); + int index = desc->id.iSerialNumber; + char serial[64]; + int dst; + + assert(index != 0 && desc->str[index] != NULL); + dst = snprintf(serial, sizeof(serial), "%s", desc->str[index]); + if (hcd && hcd->parent_bus && hcd->parent_bus->info->get_dev_path) { + char *path = hcd->parent_bus->info->get_dev_path(hcd); + dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", path); + } + dst += snprintf(serial+dst, sizeof(serial)-dst, "-%s", dev->port->path); + usb_desc_set_string(dev, index, serial); +} + const char *usb_desc_get_string(USBDevice *dev, uint8_t index) { USBDescString *s; diff --git a/hw/usb/desc.h b/hw/usb/desc.h index d164e8f891..7cf5442945 100644 --- a/hw/usb/desc.h +++ b/hw/usb/desc.h @@ -171,6 +171,7 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len); void usb_desc_init(USBDevice *dev); void usb_desc_attach(USBDevice *dev); void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str); +void usb_desc_create_serial(USBDevice *dev); const char *usb_desc_get_string(USBDevice *dev, uint8_t index); int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len); int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len); diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 426b95c82b..79b75fb628 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -648,6 +648,7 @@ static int usb_audio_initfn(USBDevice *dev) { USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev); + usb_desc_create_serial(dev); usb_desc_init(dev); s->dev.opaque = s; AUD_register_card("usb-audio", &s->card); diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c index 195370c24a..6b74eff4ad 100644 --- a/hw/usb/dev-bluetooth.c +++ b/hw/usb/dev-bluetooth.c @@ -494,6 +494,7 @@ static void usb_bt_handle_destroy(USBDevice *dev) static int usb_bt_initfn(USBDevice *dev) { + usb_desc_create_serial(dev); usb_desc_init(dev); return 0; } diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 9c9166551e..b5962da72a 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -520,6 +520,7 @@ static int usb_hub_initfn(USBDevice *dev) USBHubPort *port; int i; + usb_desc_create_serial(dev); usb_desc_init(dev); s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); for (i = 0; i < NUM_PORTS; i++) { diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index cff55f223e..b238a0973d 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1324,6 +1324,7 @@ static int usb_net_initfn(USBDevice *dev) { USBNetState *s = DO_UPCAST(USBNetState, dev, dev); + usb_desc_create_serial(dev); usb_desc_init(dev); s->rndis_state = RNDIS_UNINITIALIZED; diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 8dcac8bc88..56743ee020 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -479,6 +479,7 @@ static int usb_serial_initfn(USBDevice *dev) { USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev); + usb_desc_create_serial(dev); usb_desc_init(dev); if (!s->cs) { diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 8e66675d86..3b7604e8b1 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -1189,6 +1189,7 @@ static int ccid_initfn(USBDevice *dev) { USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev); + usb_desc_create_serial(dev); usb_desc_init(dev); qbus_create_inplace(&s->bus.qbus, &ccid_bus_info, &dev->qdev, NULL); s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP); diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index d865a5ef93..ae22fb1c97 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -268,7 +268,6 @@ static void usb_msd_request_cancelled(SCSIRequest *req) if (req == s->req) { scsi_req_unref(s->req); s->req = NULL; - s->packet = NULL; s->scsi_len = 0; } } @@ -330,6 +329,9 @@ static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p) { MSDState *s = DO_UPCAST(MSDState, dev, dev); + assert(s->packet == p); + s->packet = NULL; + if (s->req) { scsi_req_cancel(s->req); } @@ -544,6 +546,8 @@ static int usb_msd_initfn(USBDevice *dev) } if (s->serial) { usb_desc_set_string(dev, STR_SERIALNUMBER, s->serial); + } else { + usb_desc_create_serial(dev); } usb_desc_init(dev); diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c index c1cfd74403..3b51d458f4 100644 --- a/hw/usb/dev-wacom.c +++ b/hw/usb/dev-wacom.c @@ -339,6 +339,7 @@ static void usb_wacom_handle_destroy(USBDevice *dev) static int usb_wacom_initfn(USBDevice *dev) { USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev); + usb_desc_create_serial(dev); usb_desc_init(dev); s->changed = 1; return 0; diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 23631a47c9..4ff4d40a8c 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -133,7 +133,6 @@ #define NB_MAXINTRATE 8 // Max rate at which controller issues ints #define NB_PORTS 6 // Number of downstream ports #define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction -#define MAX_ITERATIONS 20 // Max number of QH before we break the loop #define MAX_QH 100 // Max allowable queue heads in a chain /* Internal periodic / asynchronous schedule state machine states @@ -665,6 +664,7 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async) q = g_malloc0(sizeof(*q)); q->ehci = ehci; + usb_packet_init(&q->packet); QTAILQ_INSERT_HEAD(head, q, next); trace_usb_ehci_queue_action(q, "alloc"); return q; @@ -1101,6 +1101,10 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) val &= USBINTR_MASK; break; + case FRINDEX: + val &= 0x00003ff8; /* frindex is 14bits and always a multiple of 8 */ + break; + case CONFIGFLAG: val &= 0x1; if (val) { @@ -1931,24 +1935,8 @@ static void ehci_advance_state(EHCIState *ehci, { EHCIQueue *q = NULL; int again; - int iter = 0; do { - if (ehci_get_state(ehci, async) == EST_FETCHQH) { - iter++; - /* if we are roaming a lot of QH without executing a qTD - * something is wrong with the linked list. TO-DO: why is - * this hack needed? - */ - assert(iter < MAX_ITERATIONS); -#if 0 - if (iter > MAX_ITERATIONS) { - DPRINTF("\n*** advance_state: bailing on MAX ITERATIONS***\n"); - ehci_set_state(ehci, async, EST_ACTIVE); - break; - } -#endif - } switch(ehci_get_state(ehci, async)) { case EST_WAITLISTHEAD: again = ehci_state_waitlisthead(ehci, async); @@ -1984,7 +1972,6 @@ static void ehci_advance_state(EHCIState *ehci, break; case EST_EXECUTE: - iter = 0; again = ehci_state_execute(q, async); break; diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 266d550b9c..9e211a0bb4 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -369,6 +369,7 @@ static void uhci_reset(void *opaque) } uhci_async_cancel_all(s); + uhci_update_irq(s); } static void uhci_pre_save(void *opaque) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 73b0c7f5e5..5cf1a64699 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -22,7 +22,6 @@ #include "qemu-timer.h" #include "hw/usb.h" #include "hw/pci.h" -#include "hw/qdev-addr.h" #include "hw/msi.h" //#define DEBUG_XHCI @@ -140,7 +139,7 @@ typedef struct XHCITRB { uint64_t parameter; uint32_t status; uint32_t control; - target_phys_addr_t addr; + dma_addr_t addr; bool ccs; } XHCITRB; @@ -291,8 +290,8 @@ typedef enum EPType { } EPType; typedef struct XHCIRing { - target_phys_addr_t base; - target_phys_addr_t dequeue; + dma_addr_t base; + dma_addr_t dequeue; bool ccs; } XHCIRing; @@ -345,7 +344,7 @@ typedef struct XHCIEPContext { unsigned int next_bg; XHCITransfer bg_transfers[BG_XFERS]; EPType type; - target_phys_addr_t pctx; + dma_addr_t pctx; unsigned int max_psize; bool has_bg; uint32_t state; @@ -353,7 +352,7 @@ typedef struct XHCIEPContext { typedef struct XHCISlot { bool enabled; - target_phys_addr_t ctx; + dma_addr_t ctx; unsigned int port; unsigned int devaddr; XHCIEPContext * eps[31]; @@ -402,7 +401,7 @@ struct XHCIState { uint32_t erdp_low; uint32_t erdp_high; - target_phys_addr_t er_start; + dma_addr_t er_start; uint32_t er_size; bool er_pcs; unsigned int er_ep_idx; @@ -479,22 +478,22 @@ static const char *trb_name(XHCITRB *trb) static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid); -static inline target_phys_addr_t xhci_addr64(uint32_t low, uint32_t high) +static inline dma_addr_t xhci_addr64(uint32_t low, uint32_t high) { -#if TARGET_PHYS_ADDR_BITS > 32 - return low | ((target_phys_addr_t)high << 32); -#else - return low; -#endif + if (sizeof(dma_addr_t) == 4) { + return low; + } else { + return low | (((dma_addr_t)high << 16) << 16); + } } -static inline target_phys_addr_t xhci_mask64(uint64_t addr) +static inline dma_addr_t xhci_mask64(uint64_t addr) { -#if TARGET_PHYS_ADDR_BITS > 32 - return addr; -#else - return addr & 0xffffffff; -#endif + if (sizeof(dma_addr_t) == 4) { + return addr & 0xffffffff; + } else { + return addr; + } } static void xhci_irq_update(XHCIState *xhci) @@ -502,7 +501,7 @@ static void xhci_irq_update(XHCIState *xhci) int level = 0; if (xhci->iman & IMAN_IP && xhci->iman & IMAN_IE && - xhci->usbcmd && USBCMD_INTE) { + xhci->usbcmd & USBCMD_INTE) { level = 1; } @@ -532,7 +531,7 @@ static void xhci_die(XHCIState *xhci) static void xhci_write_event(XHCIState *xhci, XHCIEvent *event) { XHCITRB ev_trb; - target_phys_addr_t addr; + dma_addr_t addr; ev_trb.parameter = cpu_to_le64(event->ptr); ev_trb.status = cpu_to_le32(event->length | (event->ccode << 24)); @@ -548,7 +547,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event) trb_name(&ev_trb)); addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx; - cpu_physical_memory_write(addr, (uint8_t *) &ev_trb, TRB_SIZE); + pci_dma_write(&xhci->pci_dev, addr, &ev_trb, TRB_SIZE); xhci->er_ep_idx++; if (xhci->er_ep_idx >= xhci->er_size) { @@ -559,7 +558,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event) static void xhci_events_update(XHCIState *xhci) { - target_phys_addr_t erdp; + dma_addr_t erdp; unsigned int dp_idx; bool do_irq = 0; @@ -570,8 +569,8 @@ static void xhci_events_update(XHCIState *xhci) erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high); if (erdp < xhci->er_start || erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) { - fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp); - fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n", + fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp); + fprintf(stderr, "xhci: ER at "DMA_ADDR_FMT" len %d\n", xhci->er_start, xhci->er_size); xhci_die(xhci); return; @@ -630,7 +629,7 @@ static void xhci_events_update(XHCIState *xhci) static void xhci_event(XHCIState *xhci, XHCIEvent *event) { - target_phys_addr_t erdp; + dma_addr_t erdp; unsigned int dp_idx; if (xhci->er_full) { @@ -649,8 +648,8 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event) erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high); if (erdp < xhci->er_start || erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) { - fprintf(stderr, "xhci: ERDP out of bounds: "TARGET_FMT_plx"\n", erdp); - fprintf(stderr, "xhci: ER at "TARGET_FMT_plx" len %d\n", + fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp); + fprintf(stderr, "xhci: ER at "DMA_ADDR_FMT" len %d\n", xhci->er_start, xhci->er_size); xhci_die(xhci); return; @@ -686,7 +685,7 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event) } static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring, - target_phys_addr_t base) + dma_addr_t base) { ring->base = base; ring->dequeue = base; @@ -694,18 +693,18 @@ static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring, } static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb, - target_phys_addr_t *addr) + dma_addr_t *addr) { while (1) { TRBType type; - cpu_physical_memory_read(ring->dequeue, (uint8_t *) trb, TRB_SIZE); + pci_dma_read(&xhci->pci_dev, ring->dequeue, trb, TRB_SIZE); trb->addr = ring->dequeue; trb->ccs = ring->ccs; le64_to_cpus(&trb->parameter); le32_to_cpus(&trb->status); le32_to_cpus(&trb->control); - DPRINTF("xhci: TRB fetched [" TARGET_FMT_plx "]: " + DPRINTF("xhci: TRB fetched [" DMA_ADDR_FMT "]: " "%016" PRIx64 " %08x %08x %s\n", ring->dequeue, trb->parameter, trb->status, trb->control, trb_name(trb)); @@ -735,19 +734,19 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring) { XHCITRB trb; int length = 0; - target_phys_addr_t dequeue = ring->dequeue; + dma_addr_t dequeue = ring->dequeue; bool ccs = ring->ccs; /* hack to bundle together the two/three TDs that make a setup transfer */ bool control_td_set = 0; while (1) { TRBType type; - cpu_physical_memory_read(dequeue, (uint8_t *) &trb, TRB_SIZE); + pci_dma_read(&xhci->pci_dev, dequeue, &trb, TRB_SIZE); le64_to_cpus(&trb.parameter); le32_to_cpus(&trb.status); le32_to_cpus(&trb.control); - DPRINTF("xhci: TRB peeked [" TARGET_FMT_plx "]: " + DPRINTF("xhci: TRB peeked [" DMA_ADDR_FMT "]: " "%016" PRIx64 " %08x %08x\n", dequeue, trb.parameter, trb.status, trb.control); @@ -790,8 +789,8 @@ static void xhci_er_reset(XHCIState *xhci) xhci_die(xhci); return; } - target_phys_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high); - cpu_physical_memory_read(erstba, (uint8_t *) &seg, sizeof(seg)); + dma_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high); + pci_dma_read(&xhci->pci_dev, erstba, &seg, sizeof(seg)); le32_to_cpus(&seg.addr_low); le32_to_cpus(&seg.addr_high); le32_to_cpus(&seg.size); @@ -807,7 +806,7 @@ static void xhci_er_reset(XHCIState *xhci) xhci->er_pcs = 1; xhci->er_full = 0; - DPRINTF("xhci: event ring:" TARGET_FMT_plx " [%d]\n", + DPRINTF("xhci: event ring:" DMA_ADDR_FMT " [%d]\n", xhci->er_start, xhci->er_size); } @@ -833,24 +832,24 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, return; } - cpu_physical_memory_read(epctx->pctx, (uint8_t *) ctx, sizeof(ctx)); + pci_dma_read(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx)); ctx[0] &= ~EP_STATE_MASK; ctx[0] |= state; ctx[2] = epctx->ring.dequeue | epctx->ring.ccs; ctx[3] = (epctx->ring.dequeue >> 16) >> 16; - DPRINTF("xhci: set epctx: " TARGET_FMT_plx " state=%d dequeue=%08x%08x\n", + DPRINTF("xhci: set epctx: " DMA_ADDR_FMT " state=%d dequeue=%08x%08x\n", epctx->pctx, state, ctx[3], ctx[2]); - cpu_physical_memory_write(epctx->pctx, (uint8_t *) ctx, sizeof(ctx)); + pci_dma_write(&xhci->pci_dev, epctx->pctx, ctx, sizeof(ctx)); epctx->state = state; } static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid, - unsigned int epid, target_phys_addr_t pctx, + unsigned int epid, dma_addr_t pctx, uint32_t *ctx) { XHCISlot *slot; XHCIEPContext *epctx; - target_phys_addr_t dequeue; + dma_addr_t dequeue; int i; assert(slotid >= 1 && slotid <= MAXSLOTS); @@ -1087,7 +1086,7 @@ static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid, { XHCISlot *slot; XHCIEPContext *epctx; - target_phys_addr_t dequeue; + dma_addr_t dequeue; assert(slotid >= 1 && slotid <= MAXSLOTS); @@ -1142,7 +1141,7 @@ static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data, for (i = 0; i < xfer->trb_count; i++) { XHCITRB *trb = &xfer->trbs[i]; - target_phys_addr_t addr; + dma_addr_t addr; unsigned int chunk = 0; switch (TRB_TYPE(*trb)) { @@ -1173,11 +1172,11 @@ static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data, memcpy(data, &idata, chunk); } else { DPRINTF("xhci_xfer_data: r/w(%d) %d bytes at " - TARGET_FMT_plx "\n", in_xfer, chunk, addr); + DMA_ADDR_FMT "\n", in_xfer, chunk, addr); if (in_xfer) { - cpu_physical_memory_write(addr, data, chunk); + pci_dma_write(&xhci->pci_dev, addr, data, chunk); } else { - cpu_physical_memory_read(addr, data, chunk); + pci_dma_read(&xhci->pci_dev, addr, data, chunk); } #ifdef DEBUG_DATA unsigned int count = chunk; @@ -1240,7 +1239,7 @@ static void xhci_stall_ep(XHCITransfer *xfer) epctx->ring.ccs = xfer->trbs[0].ccs; xhci_set_ep_state(xhci, epctx, EP_HALTED); DPRINTF("xhci: stalled slot %d ep %d\n", xfer->slotid, xfer->epid); - DPRINTF("xhci: will continue at "TARGET_FMT_plx"\n", epctx->ring.dequeue); + DPRINTF("xhci: will continue at "DMA_ADDR_FMT"\n", epctx->ring.dequeue); } static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, @@ -1802,7 +1801,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, { XHCISlot *slot; USBDevice *dev; - target_phys_addr_t ictx, octx, dcbaap; + dma_addr_t ictx, octx, dcbaap; uint64_t poctx; uint32_t ictl_ctx[2]; uint32_t slot_ctx[4]; @@ -1815,15 +1814,14 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci_address_slot(%d)\n", slotid); dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high); - cpu_physical_memory_read(dcbaap + 8*slotid, - (uint8_t *) &poctx, sizeof(poctx)); + pci_dma_read(&xhci->pci_dev, dcbaap + 8*slotid, &poctx, sizeof(poctx)); ictx = xhci_mask64(pictx); octx = xhci_mask64(le64_to_cpu(poctx)); - DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx); - DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx); + DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx); + DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx); - cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx)); + pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx)); if (ictl_ctx[0] != 0x0 || ictl_ctx[1] != 0x3) { fprintf(stderr, "xhci: invalid input context control %08x %08x\n", @@ -1831,8 +1829,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, return CC_TRB_ERROR; } - cpu_physical_memory_read(ictx+32, (uint8_t *) slot_ctx, sizeof(slot_ctx)); - cpu_physical_memory_read(ictx+64, (uint8_t *) ep0_ctx, sizeof(ep0_ctx)); + pci_dma_read(&xhci->pci_dev, ictx+32, slot_ctx, sizeof(slot_ctx)); + pci_dma_read(&xhci->pci_dev, ictx+64, ep0_ctx, sizeof(ep0_ctx)); DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); @@ -1881,8 +1879,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, 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]); - cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); - cpu_physical_memory_write(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx)); + pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); + pci_dma_write(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx)); return res; } @@ -1891,7 +1889,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, uint64_t pictx, bool dc) { - target_phys_addr_t ictx, octx; + dma_addr_t ictx, octx; uint32_t ictl_ctx[2]; uint32_t slot_ctx[4]; uint32_t islot_ctx[4]; @@ -1905,8 +1903,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, ictx = xhci_mask64(pictx); octx = xhci->slots[slotid-1].ctx; - DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx); - DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx); + DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx); + DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx); if (dc) { for (i = 2; i <= 31; i++) { @@ -1915,17 +1913,17 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, } } - cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); 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]); - cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); return CC_SUCCESS; } - cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx)); + pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx)); if ((ictl_ctx[0] & 0x3) != 0x0 || (ictl_ctx[1] & 0x3) != 0x1) { fprintf(stderr, "xhci: invalid input context control %08x %08x\n", @@ -1933,8 +1931,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, return CC_TRB_ERROR; } - cpu_physical_memory_read(ictx+32, (uint8_t *) islot_ctx, sizeof(islot_ctx)); - cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_read(&xhci->pci_dev, ictx+32, islot_ctx, sizeof(islot_ctx)); + pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); if (SLOT_STATE(slot_ctx[3]) < SLOT_ADDRESSED) { fprintf(stderr, "xhci: invalid slot state %08x\n", slot_ctx[3]); @@ -1946,8 +1944,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, xhci_disable_ep(xhci, slotid, i); } if (ictl_ctx[1] & (1<<i)) { - cpu_physical_memory_read(ictx+32+(32*i), - (uint8_t *) ep_ctx, sizeof(ep_ctx)); + pci_dma_read(&xhci->pci_dev, ictx+32+(32*i), ep_ctx, + sizeof(ep_ctx)); 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]); @@ -1959,8 +1957,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, 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]); - cpu_physical_memory_write(octx+(32*i), - (uint8_t *) ep_ctx, sizeof(ep_ctx)); + pci_dma_write(&xhci->pci_dev, octx+(32*i), ep_ctx, sizeof(ep_ctx)); } } @@ -1972,7 +1969,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); - cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); return CC_SUCCESS; } @@ -1981,7 +1978,7 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid, static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, uint64_t pictx) { - target_phys_addr_t ictx, octx; + dma_addr_t ictx, octx; uint32_t ictl_ctx[2]; uint32_t iep0_ctx[5]; uint32_t ep0_ctx[5]; @@ -1994,10 +1991,10 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, ictx = xhci_mask64(pictx); octx = xhci->slots[slotid-1].ctx; - DPRINTF("xhci: input context at "TARGET_FMT_plx"\n", ictx); - DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx); + DPRINTF("xhci: input context at "DMA_ADDR_FMT"\n", ictx); + DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx); - cpu_physical_memory_read(ictx, (uint8_t *) ictl_ctx, sizeof(ictl_ctx)); + pci_dma_read(&xhci->pci_dev, ictx, ictl_ctx, sizeof(ictl_ctx)); if (ictl_ctx[0] != 0x0 || ictl_ctx[1] & ~0x3) { fprintf(stderr, "xhci: invalid input context control %08x %08x\n", @@ -2006,13 +2003,12 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, } if (ictl_ctx[1] & 0x1) { - cpu_physical_memory_read(ictx+32, - (uint8_t *) islot_ctx, sizeof(islot_ctx)); + pci_dma_read(&xhci->pci_dev, ictx+32, islot_ctx, sizeof(islot_ctx)); DPRINTF("xhci: input slot context: %08x %08x %08x %08x\n", islot_ctx[0], islot_ctx[1], islot_ctx[2], islot_ctx[3]); - cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); slot_ctx[1] &= ~0xFFFF; /* max exit latency */ slot_ctx[1] |= islot_ctx[1] & 0xFFFF; @@ -2022,18 +2018,17 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n", slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]); - cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); } if (ictl_ctx[1] & 0x2) { - cpu_physical_memory_read(ictx+64, - (uint8_t *) iep0_ctx, sizeof(iep0_ctx)); + pci_dma_read(&xhci->pci_dev, ictx+64, iep0_ctx, sizeof(iep0_ctx)); 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]); - cpu_physical_memory_read(octx+32, (uint8_t *) ep0_ctx, sizeof(ep0_ctx)); + pci_dma_read(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx)); ep0_ctx[1] &= ~0xFFFF0000; /* max packet size*/ ep0_ctx[1] |= iep0_ctx[1] & 0xFFFF0000; @@ -2041,8 +2036,7 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, 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]); - cpu_physical_memory_write(octx+32, - (uint8_t *) ep0_ctx, sizeof(ep0_ctx)); + pci_dma_write(&xhci->pci_dev, octx+32, ep0_ctx, sizeof(ep0_ctx)); } return CC_SUCCESS; @@ -2051,7 +2045,7 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid, static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid) { uint32_t slot_ctx[4]; - target_phys_addr_t octx; + dma_addr_t octx; int i; assert(slotid >= 1 && slotid <= MAXSLOTS); @@ -2059,7 +2053,7 @@ static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid) octx = xhci->slots[slotid-1].ctx; - DPRINTF("xhci: output context at "TARGET_FMT_plx"\n", octx); + DPRINTF("xhci: output context at "DMA_ADDR_FMT"\n", octx); for (i = 2; i <= 31; i++) { if (xhci->slots[slotid-1].eps[i-1]) { @@ -2067,12 +2061,12 @@ static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid) } } - cpu_physical_memory_read(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_read(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); 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]); - cpu_physical_memory_write(octx, (uint8_t *) slot_ctx, sizeof(slot_ctx)); + pci_dma_write(&xhci->pci_dev, octx, slot_ctx, sizeof(slot_ctx)); return CC_SUCCESS; } @@ -2095,19 +2089,19 @@ static unsigned int xhci_get_slot(XHCIState *xhci, XHCIEvent *event, XHCITRB *tr static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx) { - target_phys_addr_t ctx; + dma_addr_t ctx; uint8_t bw_ctx[MAXPORTS+1]; DPRINTF("xhci_get_port_bandwidth()\n"); ctx = xhci_mask64(pctx); - DPRINTF("xhci: bandwidth context at "TARGET_FMT_plx"\n", ctx); + DPRINTF("xhci: bandwidth context at "DMA_ADDR_FMT"\n", ctx); /* TODO: actually implement real values here */ bw_ctx[0] = 0; memset(&bw_ctx[1], 80, MAXPORTS); /* 80% */ - cpu_physical_memory_write(ctx, bw_ctx, sizeof(bw_ctx)); + pci_dma_write(&xhci->pci_dev, ctx, bw_ctx, sizeof(bw_ctx)); return CC_SUCCESS; } @@ -2128,13 +2122,13 @@ static uint32_t xhci_nec_challenge(uint32_t hi, uint32_t lo) return ~val; } -static void xhci_via_challenge(uint64_t addr) +static void xhci_via_challenge(XHCIState *xhci, uint64_t addr) { uint32_t buf[8]; uint32_t obuf[8]; - target_phys_addr_t paddr = xhci_mask64(addr); + dma_addr_t paddr = xhci_mask64(addr); - cpu_physical_memory_read(paddr, (uint8_t *) &buf, 32); + pci_dma_read(&xhci->pci_dev, paddr, &buf, 32); memcpy(obuf, buf, sizeof(obuf)); @@ -2150,7 +2144,7 @@ static void xhci_via_challenge(uint64_t addr) obuf[7] = obuf[2] ^ obuf[3] ^ 0x65866593; } - cpu_physical_memory_write(paddr, (uint8_t *) &obuf, 32); + pci_dma_write(&xhci->pci_dev, paddr, &obuf, 32); } static void xhci_process_commands(XHCIState *xhci) @@ -2158,7 +2152,7 @@ static void xhci_process_commands(XHCIState *xhci) XHCITRB trb; TRBType type; XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS}; - target_phys_addr_t addr; + dma_addr_t addr; unsigned int i, slotid = 0; DPRINTF("xhci_process_commands()\n"); @@ -2247,7 +2241,7 @@ static void xhci_process_commands(XHCIState *xhci) event.ccode = xhci_get_port_bandwidth(xhci, trb.parameter); break; case CR_VENDOR_VIA_CHALLENGE_RESPONSE: - xhci_via_challenge(trb.parameter); + xhci_via_challenge(xhci, trb.parameter); break; case CR_VENDOR_NEC_FIRMWARE_REVISION: event.type = 48; /* NEC reply */ @@ -2537,7 +2531,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val) xhci_event(xhci, &event); DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low); } else { - target_phys_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val); + dma_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val); xhci_ring_init(xhci, &xhci->cmd_ring, base); } xhci->crcr_low &= ~(CRCR_CA | CRCR_CS); diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index 061a1b7825..048f8ffa8b 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -884,16 +884,16 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) } v = 0; - prem = p->iov.iov[v].iov_len; - pbuf = p->iov.iov[v].iov_base; + prem = 0; + pbuf = NULL; rem = p->iov.size; - while (rem) { - if (prem == 0) { - v++; + do { + if (prem == 0 && rem > 0) { assert(v < p->iov.niov); prem = p->iov.iov[v].iov_len; pbuf = p->iov.iov[v].iov_base; assert(prem <= rem); + v++; } aurb = async_alloc(s); aurb->packet = p; @@ -938,7 +938,7 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p) return USB_RET_STALL; } } - } + } while (rem > 0); return USB_RET_ASYNC; } diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 94ab4632ca..51c27b4051 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -39,6 +39,7 @@ #include "hw/usb.h" #define MAX_ENDPOINTS 32 +#define NO_INTERFACE_INFO 255 /* Valid interface_count always <= 32 */ #define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f)) #define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f)) @@ -276,7 +277,7 @@ static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id) return aurb; } } - ERROR("could not find async urb for packet_id %u\n", packet_id); + DPRINTF("could not find async urb for packet_id %u\n", packet_id); return NULL; } @@ -970,7 +971,7 @@ static void usbredir_handle_destroy(USBDevice *udev) static int usbredir_check_filter(USBRedirDevice *dev) { - if (dev->interface_info.interface_count == 0) { + if (dev->interface_info.interface_count == NO_INTERFACE_INFO) { ERROR("No interface info for device\n"); goto error; } @@ -1134,7 +1135,9 @@ static void usbredir_device_disconnect(void *priv) QTAILQ_INIT(&dev->endpoint[i].bufpq); } usb_ep_init(&dev->dev); - dev->interface_info.interface_count = 0; + dev->interface_info.interface_count = NO_INTERFACE_INFO; + dev->dev.addr = 0; + dev->dev.speed = 0; } static void usbredir_interface_info(void *priv, diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index e22940ecb2..ffbdfc2de1 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -528,6 +528,53 @@ static void set_config(VirtIODevice *vdev, const uint8_t *config_data) memcpy(&config, config_data, sizeof(config)); } +static void guest_reset(VirtIOSerial *vser) +{ + VirtIOSerialPort *port; + VirtIOSerialPortClass *vsc; + + QTAILQ_FOREACH(port, &vser->ports, next) { + vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port); + if (port->guest_connected) { + port->guest_connected = false; + + if (vsc->guest_close) + vsc->guest_close(port); + } + } +} + +static void set_status(VirtIODevice *vdev, uint8_t status) +{ + VirtIOSerial *vser; + VirtIOSerialPort *port; + + vser = DO_UPCAST(VirtIOSerial, vdev, vdev); + port = find_port_by_id(vser, 0); + + if (port && !use_multiport(port->vser) + && (status & VIRTIO_CONFIG_S_DRIVER_OK)) { + /* + * Non-multiport guests won't be able to tell us guest + * open/close status. Such guests can only have a port at id + * 0, so set guest_connected for such ports as soon as guest + * is up. + */ + port->guest_connected = true; + } + if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) { + guest_reset(vser); + } +} + +static void vser_reset(VirtIODevice *vdev) +{ + VirtIOSerial *vser; + + vser = DO_UPCAST(VirtIOSerial, vdev, vdev); + guest_reset(vser); +} + static void virtio_serial_save(QEMUFile *f, void *opaque) { VirtIOSerial *s = opaque; @@ -798,14 +845,6 @@ static int virtser_port_qdev_init(DeviceState *qdev) return ret; } - if (!use_multiport(port->vser)) { - /* - * Allow writes to guest in this case; we have no way of - * knowing if a guest port is connected. - */ - port->guest_connected = true; - } - port->elem.out_num = 0; QTAILQ_INSERT_TAIL(&port->vser->ports, port, next); @@ -905,6 +944,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf) vser->vdev.get_features = get_features; vser->vdev.get_config = get_config; vser->vdev.set_config = set_config; + vser->vdev.set_status = set_status; + vser->vdev.reset = vser_reset; vser->qdev = dev; diff --git a/hw/virtio.c b/hw/virtio.c index 314abf8a18..168abe4864 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -209,6 +209,10 @@ void virtio_queue_set_notification(VirtQueue *vq, int enable) } else { vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY); } + if (enable) { + /* Expose avail event/used flags before caller checks the avail idx. */ + smp_mb(); + } } int virtio_queue_ready(VirtQueue *vq) @@ -283,6 +287,11 @@ static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx) idx, vring_avail_idx(vq)); exit(1); } + /* On success, callers read a descriptor at vq->last_avail_idx. + * Make sure descriptor read does not bypass avail index read. */ + if (num_heads) { + smp_rmb(); + } return num_heads; } @@ -700,6 +709,8 @@ static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq) { uint16_t old, new; bool v; + /* We need to expose used array entries before checking used event. */ + smp_mb(); /* Always notify when queue is empty (when feature acknowledge) */ if (((vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) && !vq->inuse && vring_avail_idx(vq) == vq->last_avail_idx)) { |