From 7748bcc0e7cef17dbf626f83cc03e56a17075330 Mon Sep 17 00:00:00 2001 From: Sven Anderson Date: Mon, 13 Jan 2025 20:26:32 +0100 Subject: [PATCH 24/26] xhci: configure TT for non-root-hubs --- grub-core/bus/usb/usbhub.c | 6 +++++ grub-core/bus/usb/xhci.c | 45 +++++++++++++++++++++++++++++++++----- include/grub/usb.h | 2 ++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c index e96505aa9..629b3ed53 100644 --- a/grub-core/bus/usb/usbhub.c +++ b/grub-core/bus/usb/usbhub.c @@ -818,3 +818,9 @@ grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data) return 0; } + +grub_usb_device_t +grub_usb_get_dev (int addr) +{ + return grub_usb_devs[addr]; +} diff --git a/grub-core/bus/usb/xhci.c b/grub-core/bus/usb/xhci.c index d13a7c39d..8ad2a10f9 100644 --- a/grub-core/bus/usb/xhci.c +++ b/grub-core/bus/usb/xhci.c @@ -623,13 +623,46 @@ grub_xhci_alloc_inctx(struct grub_xhci *x, int maxepid, break; } - /* Route is greater zero on devices that are connected to a non root hub */ - if (dev->route) - { - /* FIXME: Implement this code for non SuperSpeed hub devices */ + /* Set routing string */ + slot->ctx[0] |= dev->route; + + /* Set root hub port number */ + slot->ctx[1] |= (dev->root_port + 1) << 16; + + if (dev->split_hubaddr && (dev->speed == GRUB_USB_SPEED_LOW || + dev->speed == GRUB_USB_SPEED_FULL)) { + + grub_usb_device_t hubdev = grub_usb_get_dev(dev->split_hubaddr); + + if (!hubdev || hubdev->descdev.class != GRUB_USB_CLASS_HUB) { + grub_dprintf("xhci", "Invalid hub device at addr %d!\n", dev->split_hubaddr); + return NULL; + } + + struct grub_xhci_priv *hub_priv = hubdev->xhci_priv; + if (!hub_priv) { + grub_dprintf("xhci", "Hub has no xhci_priv!\n"); + return NULL; + } + + if (hubdev->speed == GRUB_USB_SPEED_HIGH) { + /* Direct connection to high-speed hub - set up TT */ + grub_dprintf("xhci", "Direct high-speed hub connection - configuring TT with " + "hub slot %d port %d\n", hub_priv->slotid, dev->split_hubport); + slot->ctx[2] |= hub_priv->slotid; + slot->ctx[2] |= dev->split_hubport << 8; } - slot->ctx[0] |= dev->route; - slot->ctx[1] |= (dev->root_port+1) << 16; + else { + /* Hub is not high-speed, inherit TT settings from parent */ + volatile struct grub_xhci_slotctx *hubslot; + grub_dprintf("xhci", "Non high-speed hub - inheriting TT settings from parent\n"); + hubslot = grub_dma_phys2virt(x->devs[hub_priv->slotid].ptr_low, x->devs_dma); + slot->ctx[2] = hubslot->ctx[2]; + } + } + + grub_dprintf("xhci", "Slot context: ctx[0]=0x%08x ctx[1]=0x%08x ctx[2]=0x%08x\n", + slot->ctx[0], slot->ctx[1], slot->ctx[2]); grub_arch_sync_dma_caches(in, size); diff --git a/include/grub/usb.h b/include/grub/usb.h index eb71fa1c7..df97a60cc 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -62,6 +62,8 @@ typedef int (*grub_usb_controller_iterate_hook_t) (grub_usb_controller_t dev, /* Call HOOK with each device, until HOOK returns non-zero. */ int grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data); +grub_usb_device_t grub_usb_get_dev (int addr); + grub_usb_err_t grub_usb_device_initialize (grub_usb_device_t dev); grub_usb_err_t grub_usb_get_descriptor (grub_usb_device_t dev, -- 2.39.5