Revision ccaf87a0 hw/usb/hcd-xhci.c
b/hw/usb/hcd-xhci.c | ||
---|---|---|
363 | 363 |
typedef struct XHCISlot { |
364 | 364 |
bool enabled; |
365 | 365 |
dma_addr_t ctx; |
366 |
unsigned int port;
|
|
366 |
USBPort *uport;
|
|
367 | 367 |
unsigned int devaddr; |
368 | 368 |
XHCIEPContext * eps[31]; |
369 | 369 |
} XHCISlot; |
... | ... | |
1230 | 1230 |
ep |= 0x80; |
1231 | 1231 |
} |
1232 | 1232 |
|
1233 |
dev = xhci->ports[xhci->slots[slotid-1].port-1].uport->dev;
|
|
1233 |
dev = xhci->slots[slotid-1].uport->dev;
|
|
1234 | 1234 |
if (!dev) { |
1235 | 1235 |
return CC_USB_TRANSACTION_ERROR; |
1236 | 1236 |
} |
... | ... | |
1412 | 1412 |
static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, |
1413 | 1413 |
XHCIEPContext *epctx); |
1414 | 1414 |
|
1415 |
static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr) |
|
1416 |
{ |
|
1417 |
if (!(port->portsc & PORTSC_PED)) { |
|
1418 |
return NULL; |
|
1419 |
} |
|
1420 |
return usb_find_device(port->uport, addr); |
|
1421 |
} |
|
1422 |
|
|
1423 | 1415 |
static int xhci_setup_packet(XHCITransfer *xfer) |
1424 | 1416 |
{ |
1425 | 1417 |
XHCIState *xhci = xfer->xhci; |
1426 |
XHCIPort *port; |
|
1427 | 1418 |
USBDevice *dev; |
1428 | 1419 |
USBEndpoint *ep; |
1429 | 1420 |
int dir; |
... | ... | |
1434 | 1425 |
ep = xfer->packet.ep; |
1435 | 1426 |
dev = ep->dev; |
1436 | 1427 |
} else { |
1437 |
port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1]; |
|
1438 |
dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr); |
|
1439 |
if (!dev) { |
|
1440 |
fprintf(stderr, "xhci: slot %d port %d has no device\n", |
|
1441 |
xfer->slotid, xhci->slots[xfer->slotid-1].port); |
|
1428 |
if (!xhci->slots[xfer->slotid-1].uport) { |
|
1429 |
fprintf(stderr, "xhci: slot %d has no device\n", |
|
1430 |
xfer->slotid); |
|
1442 | 1431 |
return -1; |
1443 | 1432 |
} |
1433 |
dev = xhci->slots[xfer->slotid-1].uport->dev; |
|
1444 | 1434 |
ep = usb_ep_get(dev, dir, xfer->epid >> 1); |
1445 | 1435 |
} |
1446 | 1436 |
|
... | ... | |
1772 | 1762 |
trace_usb_xhci_slot_enable(slotid); |
1773 | 1763 |
assert(slotid >= 1 && slotid <= MAXSLOTS); |
1774 | 1764 |
xhci->slots[slotid-1].enabled = 1; |
1775 |
xhci->slots[slotid-1].port = 0;
|
|
1765 |
xhci->slots[slotid-1].uport = NULL;
|
|
1776 | 1766 |
memset(xhci->slots[slotid-1].eps, 0, sizeof(XHCIEPContext*)*31); |
1777 | 1767 |
|
1778 | 1768 |
return CC_SUCCESS; |
... | ... | |
1795 | 1785 |
return CC_SUCCESS; |
1796 | 1786 |
} |
1797 | 1787 |
|
1788 |
static USBPort *xhci_lookup_uport(XHCIState *xhci, uint32_t *slot_ctx) |
|
1789 |
{ |
|
1790 |
USBPort *uport; |
|
1791 |
char path[32]; |
|
1792 |
int i, pos, port; |
|
1793 |
|
|
1794 |
port = (slot_ctx[1]>>16) & 0xFF; |
|
1795 |
port = xhci->ports[port-1].uport->index+1; |
|
1796 |
pos = snprintf(path, sizeof(path), "%d", port); |
|
1797 |
for (i = 0; i < 5; i++) { |
|
1798 |
port = (slot_ctx[0] >> 4*i) & 0x0f; |
|
1799 |
if (!port) { |
|
1800 |
break; |
|
1801 |
} |
|
1802 |
pos += snprintf(path + pos, sizeof(path) - pos, ".%d", port); |
|
1803 |
} |
|
1804 |
|
|
1805 |
QTAILQ_FOREACH(uport, &xhci->bus.used, next) { |
|
1806 |
if (strcmp(uport->path, path) == 0) { |
|
1807 |
return uport; |
|
1808 |
} |
|
1809 |
} |
|
1810 |
return NULL; |
|
1811 |
} |
|
1812 |
|
|
1798 | 1813 |
static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, |
1799 | 1814 |
uint64_t pictx, bool bsr) |
1800 | 1815 |
{ |
1801 | 1816 |
XHCISlot *slot; |
1817 |
USBPort *uport; |
|
1802 | 1818 |
USBDevice *dev; |
1803 | 1819 |
dma_addr_t ictx, octx, dcbaap; |
1804 | 1820 |
uint64_t poctx; |
1805 | 1821 |
uint32_t ictl_ctx[2]; |
1806 | 1822 |
uint32_t slot_ctx[4]; |
1807 | 1823 |
uint32_t ep0_ctx[5]; |
1808 |
unsigned int port; |
|
1809 | 1824 |
int i; |
1810 | 1825 |
TRBCCode res; |
1811 | 1826 |
|
... | ... | |
1837 | 1852 |
DPRINTF("xhci: input ep0 context: %08x %08x %08x %08x %08x\n", |
1838 | 1853 |
ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]); |
1839 | 1854 |
|
1840 |
port = (slot_ctx[1]>>16) & 0xFF; |
|
1841 |
dev = xhci->ports[port-1].uport->dev; |
|
1842 |
|
|
1843 |
if (port < 1 || port > xhci->numports) { |
|
1844 |
fprintf(stderr, "xhci: bad port %d\n", port); |
|
1855 |
uport = xhci_lookup_uport(xhci, slot_ctx); |
|
1856 |
if (uport == NULL) { |
|
1857 |
fprintf(stderr, "xhci: port not found\n"); |
|
1845 | 1858 |
return CC_TRB_ERROR; |
1846 |
} else if (!dev) { |
|
1847 |
fprintf(stderr, "xhci: port %d not connected\n", port); |
|
1859 |
} |
|
1860 |
|
|
1861 |
dev = uport->dev; |
|
1862 |
if (!dev) { |
|
1863 |
fprintf(stderr, "xhci: port %s not connected\n", uport->path); |
|
1848 | 1864 |
return CC_USB_TRANSACTION_ERROR; |
1849 | 1865 |
} |
1850 | 1866 |
|
1851 | 1867 |
for (i = 0; i < MAXSLOTS; i++) { |
1852 |
if (xhci->slots[i].port == port) {
|
|
1853 |
fprintf(stderr, "xhci: port %d already assigned to slot %d\n",
|
|
1854 |
port, i+1);
|
|
1868 |
if (xhci->slots[i].uport == uport) {
|
|
1869 |
fprintf(stderr, "xhci: port %s already assigned to slot %d\n",
|
|
1870 |
uport->path, i+1);
|
|
1855 | 1871 |
return CC_TRB_ERROR; |
1856 | 1872 |
} |
1857 | 1873 |
} |
1858 | 1874 |
|
1859 | 1875 |
slot = &xhci->slots[slotid-1]; |
1860 |
slot->port = port;
|
|
1876 |
slot->uport = uport;
|
|
1861 | 1877 |
slot->ctx = octx; |
1862 | 1878 |
|
1863 | 1879 |
if (bsr) { |
... | ... | |
2821 | 2837 |
xhci_kick_ep(xfer->xhci, xfer->slotid, xfer->epid); |
2822 | 2838 |
} |
2823 | 2839 |
|
2824 |
static void xhci_child_detach(USBPort *port, USBDevice *child) |
|
2840 |
static void xhci_child_detach(USBPort *uport, USBDevice *child)
|
|
2825 | 2841 |
{ |
2826 |
FIXME(); |
|
2842 |
USBBus *bus = usb_bus_from_device(child); |
|
2843 |
XHCIState *xhci = container_of(bus, XHCIState, bus); |
|
2844 |
int i; |
|
2845 |
|
|
2846 |
for (i = 0; i < MAXSLOTS; i++) { |
|
2847 |
if (xhci->slots[i].uport == uport) { |
|
2848 |
xhci->slots[i].uport = NULL; |
|
2849 |
} |
|
2850 |
} |
|
2827 | 2851 |
} |
2828 | 2852 |
|
2829 | 2853 |
static USBPortOps xhci_port_ops = { |
Also available in: Unified diff