mirror of
https://github.com/qemu/qemu.git
synced 2025-08-14 03:15:54 +00:00
xhci: trace: mmio reads+writes
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
64619739c4
commit
2d754a10e4
@ -23,6 +23,7 @@
|
|||||||
#include "hw/usb.h"
|
#include "hw/usb.h"
|
||||||
#include "hw/pci.h"
|
#include "hw/pci.h"
|
||||||
#include "hw/msi.h"
|
#include "hw/msi.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
//#define DEBUG_XHCI
|
//#define DEBUG_XHCI
|
||||||
//#define DEBUG_DATA
|
//#define DEBUG_DATA
|
||||||
@ -2301,7 +2302,7 @@ static void xhci_reset(DeviceState *dev)
|
|||||||
XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev.qdev, dev);
|
XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev.qdev, dev);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
DPRINTF("xhci: full reset\n");
|
trace_usb_xhci_reset();
|
||||||
if (!(xhci->usbsts & USBSTS_HCH)) {
|
if (!(xhci->usbsts & USBSTS_HCH)) {
|
||||||
fprintf(stderr, "xhci: reset while running!\n");
|
fprintf(stderr, "xhci: reset while running!\n");
|
||||||
}
|
}
|
||||||
@ -2342,77 +2343,98 @@ static void xhci_reset(DeviceState *dev)
|
|||||||
|
|
||||||
static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
|
static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
|
||||||
{
|
{
|
||||||
DPRINTF("xhci_cap_read(0x%x)\n", reg);
|
uint32_t ret;
|
||||||
|
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case 0x00: /* HCIVERSION, CAPLENGTH */
|
case 0x00: /* HCIVERSION, CAPLENGTH */
|
||||||
return 0x01000000 | LEN_CAP;
|
ret = 0x01000000 | LEN_CAP;
|
||||||
|
break;
|
||||||
case 0x04: /* HCSPARAMS 1 */
|
case 0x04: /* HCSPARAMS 1 */
|
||||||
return (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
|
ret = (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
|
||||||
|
break;
|
||||||
case 0x08: /* HCSPARAMS 2 */
|
case 0x08: /* HCSPARAMS 2 */
|
||||||
return 0x0000000f;
|
ret = 0x0000000f;
|
||||||
|
break;
|
||||||
case 0x0c: /* HCSPARAMS 3 */
|
case 0x0c: /* HCSPARAMS 3 */
|
||||||
return 0x00000000;
|
ret = 0x00000000;
|
||||||
|
break;
|
||||||
case 0x10: /* HCCPARAMS */
|
case 0x10: /* HCCPARAMS */
|
||||||
#if TARGET_PHYS_ADDR_BITS > 32
|
if (sizeof(dma_addr_t) == 4) {
|
||||||
return 0x00081001;
|
ret = 0x00081000;
|
||||||
#else
|
} else {
|
||||||
return 0x00081000;
|
ret = 0x00081001;
|
||||||
#endif
|
}
|
||||||
|
break;
|
||||||
case 0x14: /* DBOFF */
|
case 0x14: /* DBOFF */
|
||||||
return OFF_DOORBELL;
|
ret = OFF_DOORBELL;
|
||||||
|
break;
|
||||||
case 0x18: /* RTSOFF */
|
case 0x18: /* RTSOFF */
|
||||||
return OFF_RUNTIME;
|
ret = OFF_RUNTIME;
|
||||||
|
break;
|
||||||
|
|
||||||
/* extended capabilities */
|
/* extended capabilities */
|
||||||
case 0x20: /* Supported Protocol:00 */
|
case 0x20: /* Supported Protocol:00 */
|
||||||
#if USB3_PORTS > 0
|
ret = 0x02000402; /* USB 2.0 */
|
||||||
return 0x02000402; /* USB 2.0 */
|
break;
|
||||||
#else
|
|
||||||
return 0x02000002; /* USB 2.0 */
|
|
||||||
#endif
|
|
||||||
case 0x24: /* Supported Protocol:04 */
|
case 0x24: /* Supported Protocol:04 */
|
||||||
return 0x20425455; /* "USB " */
|
ret = 0x20425455; /* "USB " */
|
||||||
|
break;
|
||||||
case 0x28: /* Supported Protocol:08 */
|
case 0x28: /* Supported Protocol:08 */
|
||||||
return 0x00000001 | (USB2_PORTS<<8);
|
ret = 0x00000001 | (USB2_PORTS<<8);
|
||||||
|
break;
|
||||||
case 0x2c: /* Supported Protocol:0c */
|
case 0x2c: /* Supported Protocol:0c */
|
||||||
return 0x00000000; /* reserved */
|
ret = 0x00000000; /* reserved */
|
||||||
#if USB3_PORTS > 0
|
break;
|
||||||
case 0x30: /* Supported Protocol:00 */
|
case 0x30: /* Supported Protocol:00 */
|
||||||
return 0x03000002; /* USB 3.0 */
|
ret = 0x03000002; /* USB 3.0 */
|
||||||
|
break;
|
||||||
case 0x34: /* Supported Protocol:04 */
|
case 0x34: /* Supported Protocol:04 */
|
||||||
return 0x20425455; /* "USB " */
|
ret = 0x20425455; /* "USB " */
|
||||||
|
break;
|
||||||
case 0x38: /* Supported Protocol:08 */
|
case 0x38: /* Supported Protocol:08 */
|
||||||
return 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
|
ret = 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
|
||||||
|
break;
|
||||||
case 0x3c: /* Supported Protocol:0c */
|
case 0x3c: /* Supported Protocol:0c */
|
||||||
return 0x00000000; /* reserved */
|
ret = 0x00000000; /* reserved */
|
||||||
#endif
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", reg);
|
fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", reg);
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
trace_usb_xhci_cap_read(reg, ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg)
|
static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg)
|
||||||
{
|
{
|
||||||
uint32_t port = reg >> 4;
|
uint32_t port = reg >> 4;
|
||||||
|
uint32_t ret;
|
||||||
|
|
||||||
if (port >= MAXPORTS) {
|
if (port >= MAXPORTS) {
|
||||||
fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
|
fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
|
||||||
return 0;
|
ret = 0;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (reg & 0xf) {
|
switch (reg & 0xf) {
|
||||||
case 0x00: /* PORTSC */
|
case 0x00: /* PORTSC */
|
||||||
return xhci->ports[port].portsc;
|
ret = xhci->ports[port].portsc;
|
||||||
|
break;
|
||||||
case 0x04: /* PORTPMSC */
|
case 0x04: /* PORTPMSC */
|
||||||
case 0x08: /* PORTLI */
|
case 0x08: /* PORTLI */
|
||||||
return 0;
|
ret = 0;
|
||||||
|
break;
|
||||||
case 0x0c: /* reserved */
|
case 0x0c: /* reserved */
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "xhci_port_read (port %d): reg 0x%x unimplemented\n",
|
fprintf(stderr, "xhci_port_read (port %d): reg 0x%x unimplemented\n",
|
||||||
port, reg);
|
port, reg);
|
||||||
return 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
trace_usb_xhci_port_read(port, reg & 0x0f, ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
|
static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
|
||||||
@ -2420,6 +2442,8 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
|
|||||||
uint32_t port = reg >> 4;
|
uint32_t port = reg >> 4;
|
||||||
uint32_t portsc;
|
uint32_t portsc;
|
||||||
|
|
||||||
|
trace_usb_xhci_port_write(port, reg & 0x0f, val);
|
||||||
|
|
||||||
if (port >= MAXPORTS) {
|
if (port >= MAXPORTS) {
|
||||||
fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
|
fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
|
||||||
return;
|
return;
|
||||||
@ -2457,7 +2481,7 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
|
|||||||
|
|
||||||
static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
|
static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
|
||||||
{
|
{
|
||||||
DPRINTF("xhci_oper_read(0x%x)\n", reg);
|
uint32_t ret;
|
||||||
|
|
||||||
if (reg >= 0x400) {
|
if (reg >= 0x400) {
|
||||||
return xhci_port_read(xhci, reg - 0x400);
|
return xhci_port_read(xhci, reg - 0x400);
|
||||||
@ -2465,38 +2489,50 @@ static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
|
|||||||
|
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case 0x00: /* USBCMD */
|
case 0x00: /* USBCMD */
|
||||||
return xhci->usbcmd;
|
ret = xhci->usbcmd;
|
||||||
|
break;
|
||||||
case 0x04: /* USBSTS */
|
case 0x04: /* USBSTS */
|
||||||
return xhci->usbsts;
|
ret = xhci->usbsts;
|
||||||
|
break;
|
||||||
case 0x08: /* PAGESIZE */
|
case 0x08: /* PAGESIZE */
|
||||||
return 1; /* 4KiB */
|
ret = 1; /* 4KiB */
|
||||||
|
break;
|
||||||
case 0x14: /* DNCTRL */
|
case 0x14: /* DNCTRL */
|
||||||
return xhci->dnctrl;
|
ret = xhci->dnctrl;
|
||||||
|
break;
|
||||||
case 0x18: /* CRCR low */
|
case 0x18: /* CRCR low */
|
||||||
return xhci->crcr_low & ~0xe;
|
ret = xhci->crcr_low & ~0xe;
|
||||||
|
break;
|
||||||
case 0x1c: /* CRCR high */
|
case 0x1c: /* CRCR high */
|
||||||
return xhci->crcr_high;
|
ret = xhci->crcr_high;
|
||||||
|
break;
|
||||||
case 0x30: /* DCBAAP low */
|
case 0x30: /* DCBAAP low */
|
||||||
return xhci->dcbaap_low;
|
ret = xhci->dcbaap_low;
|
||||||
|
break;
|
||||||
case 0x34: /* DCBAAP high */
|
case 0x34: /* DCBAAP high */
|
||||||
return xhci->dcbaap_high;
|
ret = xhci->dcbaap_high;
|
||||||
|
break;
|
||||||
case 0x38: /* CONFIG */
|
case 0x38: /* CONFIG */
|
||||||
return xhci->config;
|
ret = xhci->config;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", reg);
|
fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", reg);
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
trace_usb_xhci_oper_read(reg, ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
|
static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
|
||||||
{
|
{
|
||||||
DPRINTF("xhci_oper_write(0x%x, 0x%08x)\n", reg, val);
|
|
||||||
|
|
||||||
if (reg >= 0x400) {
|
if (reg >= 0x400) {
|
||||||
xhci_port_write(xhci, reg - 0x400, val);
|
xhci_port_write(xhci, reg - 0x400, val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace_usb_xhci_oper_write(reg, val);
|
||||||
|
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case 0x00: /* USBCMD */
|
case 0x00: /* USBCMD */
|
||||||
if ((val & USBCMD_RS) && !(xhci->usbcmd & USBCMD_RS)) {
|
if ((val & USBCMD_RS) && !(xhci->usbcmd & USBCMD_RS)) {
|
||||||
@ -2552,35 +2588,46 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
|
|||||||
|
|
||||||
static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
|
static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
|
||||||
{
|
{
|
||||||
DPRINTF("xhci_runtime_read(0x%x)\n", reg);
|
uint32_t ret;
|
||||||
|
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case 0x00: /* MFINDEX */
|
case 0x00: /* MFINDEX */
|
||||||
fprintf(stderr, "xhci_runtime_read: MFINDEX not yet implemented\n");
|
fprintf(stderr, "xhci_runtime_read: MFINDEX not yet implemented\n");
|
||||||
return xhci->mfindex;
|
ret = xhci->mfindex;
|
||||||
|
break;
|
||||||
case 0x20: /* IMAN */
|
case 0x20: /* IMAN */
|
||||||
return xhci->iman;
|
ret = xhci->iman;
|
||||||
|
break;
|
||||||
case 0x24: /* IMOD */
|
case 0x24: /* IMOD */
|
||||||
return xhci->imod;
|
ret = xhci->imod;
|
||||||
|
break;
|
||||||
case 0x28: /* ERSTSZ */
|
case 0x28: /* ERSTSZ */
|
||||||
return xhci->erstsz;
|
ret = xhci->erstsz;
|
||||||
|
break;
|
||||||
case 0x30: /* ERSTBA low */
|
case 0x30: /* ERSTBA low */
|
||||||
return xhci->erstba_low;
|
ret = xhci->erstba_low;
|
||||||
|
break;
|
||||||
case 0x34: /* ERSTBA high */
|
case 0x34: /* ERSTBA high */
|
||||||
return xhci->erstba_high;
|
ret = xhci->erstba_high;
|
||||||
|
break;
|
||||||
case 0x38: /* ERDP low */
|
case 0x38: /* ERDP low */
|
||||||
return xhci->erdp_low;
|
ret = xhci->erdp_low;
|
||||||
|
break;
|
||||||
case 0x3c: /* ERDP high */
|
case 0x3c: /* ERDP high */
|
||||||
return xhci->erdp_high;
|
ret = xhci->erdp_high;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg);
|
fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg);
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
trace_usb_xhci_runtime_read(reg, ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
|
static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
|
||||||
{
|
{
|
||||||
DPRINTF("xhci_runtime_write(0x%x, 0x%08x)\n", reg, val);
|
trace_usb_xhci_runtime_read(reg, val);
|
||||||
|
|
||||||
switch (reg) {
|
switch (reg) {
|
||||||
case 0x20: /* IMAN */
|
case 0x20: /* IMAN */
|
||||||
@ -2623,14 +2670,14 @@ static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
|
|||||||
|
|
||||||
static uint32_t xhci_doorbell_read(XHCIState *xhci, uint32_t reg)
|
static uint32_t xhci_doorbell_read(XHCIState *xhci, uint32_t reg)
|
||||||
{
|
{
|
||||||
DPRINTF("xhci_doorbell_read(0x%x)\n", reg);
|
|
||||||
/* doorbells always read as 0 */
|
/* doorbells always read as 0 */
|
||||||
|
trace_usb_xhci_doorbell_read(reg, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xhci_doorbell_write(XHCIState *xhci, uint32_t reg, uint32_t val)
|
static void xhci_doorbell_write(XHCIState *xhci, uint32_t reg, uint32_t val)
|
||||||
{
|
{
|
||||||
DPRINTF("xhci_doorbell_write(0x%x, 0x%08x)\n", reg, val);
|
trace_usb_xhci_doorbell_write(reg, val);
|
||||||
|
|
||||||
if (!xhci_running(xhci)) {
|
if (!xhci_running(xhci)) {
|
||||||
fprintf(stderr, "xhci: wrote doorbell while xHC stopped or paused\n");
|
fprintf(stderr, "xhci: wrote doorbell while xHC stopped or paused\n");
|
||||||
|
12
trace-events
12
trace-events
@ -289,6 +289,18 @@ usb_uhci_td_nextqh(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
|
|||||||
usb_uhci_td_async(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
|
usb_uhci_td_async(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
|
||||||
usb_uhci_td_complete(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
|
usb_uhci_td_complete(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
|
||||||
|
|
||||||
|
# hw/usb/hcd-xhci.c
|
||||||
|
usb_xhci_reset(void) "=== RESET ==="
|
||||||
|
usb_xhci_cap_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
|
||||||
|
usb_xhci_oper_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
|
||||||
|
usb_xhci_port_read(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, ret 0x%08x"
|
||||||
|
usb_xhci_runtime_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
|
||||||
|
usb_xhci_doorbell_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
|
||||||
|
usb_xhci_oper_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
|
||||||
|
usb_xhci_port_write(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, val 0x%08x"
|
||||||
|
usb_xhci_runtime_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
|
||||||
|
usb_xhci_doorbell_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
|
||||||
|
|
||||||
# hw/usb/desc.c
|
# hw/usb/desc.c
|
||||||
usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
|
usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
|
||||||
usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d"
|
usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d"
|
||||||
|
Loading…
Reference in New Issue
Block a user