aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2017-07-18 13:15:42 +0200
committerGerd Hoffmann <kraxel@redhat.com>2017-07-25 13:02:11 +0200
commitb404a5f417cbe5593f89c79954569b0e245fb80c (patch)
tree90aa94701c34df55f41069415afbe6df035e7074
parentca9dcc2edd72a33bacf11870b8476d5a9e02205e (diff)
downloadseabios-b404a5f417cbe5593f89c79954569b0e245fb80c.zip
seabios-b404a5f417cbe5593f89c79954569b0e245fb80c.tar.gz
seabios-b404a5f417cbe5593f89c79954569b0e245fb80c.tar.bz2
usb-xhci: use hub portmap
xhci controllers have two virtual ports per (usb3 capable) physical port, one for usb2 and one for usb3 devices. Add a hub portmap callback to map the virtual ports to physical ports. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r--src/hw/usb-xhci.c45
1 files changed, 41 insertions, 4 deletions
diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c
index 69954b9..50b3b86 100644
--- a/src/hw/usb-xhci.c
+++ b/src/hw/usb-xhci.c
@@ -226,6 +226,11 @@ struct xhci_ring {
struct mutex_s lock;
};
+struct xhci_portmap {
+ u8 start;
+ u8 count;
+};
+
struct usb_xhci_s {
struct usb_s usb;
@@ -234,6 +239,8 @@ struct usb_xhci_s {
u32 ports;
u32 slots;
u8 context64;
+ struct xhci_portmap usb2;
+ struct xhci_portmap usb3;
/* xhci registers */
struct xhci_caps *caps;
@@ -374,6 +381,23 @@ xhci_hub_reset(struct usbhub_s *hub, u32 port)
return rc;
}
+static int
+xhci_hub_portmap(struct usbhub_s *hub, u32 vport)
+{
+ struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb);
+ u32 pport = vport + 1;
+
+ if (vport + 1 >= xhci->usb3.start &&
+ vport + 1 < xhci->usb3.start + xhci->usb3.count)
+ pport = vport + 2 - xhci->usb3.start;
+
+ if (vport + 1 >= xhci->usb2.start &&
+ vport + 1 < xhci->usb2.start + xhci->usb2.count)
+ pport = vport + 2 - xhci->usb2.start;
+
+ return pport;
+}
+
static void
xhci_hub_disconnect(struct usbhub_s *hub, u32 port)
{
@@ -383,6 +407,7 @@ xhci_hub_disconnect(struct usbhub_s *hub, u32 port)
static struct usbhub_op_s xhci_hub_ops = {
.detect = xhci_hub_detect,
.reset = xhci_hub_reset,
+ .portmap = xhci_hub_portmap,
.disconnect = xhci_hub_disconnect,
};
@@ -553,17 +578,29 @@ xhci_controller_setup(struct pci_device *pci)
case 0x02:
name = readl(&xcap->data[0]);
ports = readl(&xcap->data[1]);
+ u8 major = (cap >> 24) & 0xff;
+ u8 minor = (cap >> 16) & 0xff;
+ u8 count = (ports >> 8) & 0xff;
+ u8 start = (ports >> 0) & 0xff;
dprintf(1, "XHCI protocol %c%c%c%c %x.%02x"
", %d ports (offset %d), def %x\n"
, (name >> 0) & 0xff
, (name >> 8) & 0xff
, (name >> 16) & 0xff
, (name >> 24) & 0xff
- , (cap >> 24) & 0xff
- , (cap >> 16) & 0xff
- , (ports >> 8) & 0xff
- , (ports >> 0) & 0xff
+ , major, minor
+ , count, start
, ports >> 16);
+ if (name == 0x20425355 /* "USB " */) {
+ if (major == 2) {
+ xhci->usb2.start = start;
+ xhci->usb2.count = count;
+ }
+ if (major == 3) {
+ xhci->usb3.start = start;
+ xhci->usb3.count = count;
+ }
+ }
break;
default:
dprintf(1, "XHCI extcap 0x%x @ %p\n", cap & 0xff, addr);