xhci: trace: mmio reads+writes

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
Gerd Hoffmann 2012-05-11 12:49:31 +02:00
parent 64619739c4
commit 2d754a10e4
2 changed files with 117 additions and 58 deletions

View file

@ -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");

View file

@ -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"