summaryrefslogtreecommitdiff
path: root/config/grub/xhci/patches/0005-xhci
diff options
context:
space:
mode:
Diffstat (limited to 'config/grub/xhci/patches/0005-xhci')
-rw-r--r--config/grub/xhci/patches/0005-xhci/0001-grub-core-bus-usb-Parse-SuperSpeed-companion-descrip.patch245
-rw-r--r--config/grub/xhci/patches/0005-xhci/0002-usb-Add-enum-for-xHCI.patch29
-rw-r--r--config/grub/xhci/patches/0005-xhci/0003-usbtrans-Set-default-maximum-packet-size.patch33
-rw-r--r--config/grub/xhci/patches/0005-xhci/0004-grub-core-bus-usb-Add-function-pointer-for-attach-de.patch121
-rw-r--r--config/grub/xhci/patches/0005-xhci/0005-grub-core-bus-usb-usbhub-Add-new-private-fields-for-.patch77
-rw-r--r--config/grub/xhci/patches/0005-xhci/0006-grub-core-bus-usb-Add-xhci-support.patch2814
-rw-r--r--config/grub/xhci/patches/0005-xhci/0007-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch127
-rw-r--r--config/grub/xhci/patches/0005-xhci/0008-Fix-compilation-on-x86_64.patch90
8 files changed, 0 insertions, 3536 deletions
diff --git a/config/grub/xhci/patches/0005-xhci/0001-grub-core-bus-usb-Parse-SuperSpeed-companion-descrip.patch b/config/grub/xhci/patches/0005-xhci/0001-grub-core-bus-usb-Parse-SuperSpeed-companion-descrip.patch
deleted file mode 100644
index f533269f..00000000
--- a/config/grub/xhci/patches/0005-xhci/0001-grub-core-bus-usb-Parse-SuperSpeed-companion-descrip.patch
+++ /dev/null
@@ -1,245 +0,0 @@
-From 90c9011f2e0350a97e3df44b0fc6dd022e04c276 Mon Sep 17 00:00:00 2001
-From: Patrick Rudolph <patrick.rudolph@9elements.com>
-Date: Sun, 15 Nov 2020 19:00:27 +0100
-Subject: [PATCH 1/8] grub-core/bus/usb: Parse SuperSpeed companion descriptors
-
-Parse the SS_ENDPOINT_COMPANION descriptor, which is only present on USB 3.0
-capable devices and xHCI controllers. Make the descendp an array of pointers
-to the endpoint descriptor as it's no longer an continous array.
-
-Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
----
- grub-core/bus/usb/serial/common.c | 2 +-
- grub-core/bus/usb/usb.c | 44 +++++++++++++++++++------------
- grub-core/bus/usb/usbhub.c | 22 ++++++++++++----
- grub-core/commands/usbtest.c | 2 +-
- grub-core/disk/usbms.c | 2 +-
- grub-core/term/usb_keyboard.c | 2 +-
- include/grub/usb.h | 2 +-
- include/grub/usbdesc.h | 11 +++++++-
- 8 files changed, 59 insertions(+), 28 deletions(-)
-
-diff --git a/grub-core/bus/usb/serial/common.c b/grub-core/bus/usb/serial/common.c
-index e9c995a0a..fc847d66d 100644
---- a/grub-core/bus/usb/serial/common.c
-+++ b/grub-core/bus/usb/serial/common.c
-@@ -72,7 +72,7 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno,
- for (j = 0; j < interf->endpointcnt; j++)
- {
- struct grub_usb_desc_endp *endp;
-- endp = &usbdev->config[0].interf[interfno].descendp[j];
-+ endp = usbdev->config[0].interf[interfno].descendp[j];
-
- if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2
- && (in_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING
-diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c
-index 7bd49d201..e578af793 100644
---- a/grub-core/bus/usb/usb.c
-+++ b/grub-core/bus/usb/usb.c
-@@ -118,7 +118,7 @@ grub_usb_device_initialize (grub_usb_device_t dev)
- struct grub_usb_desc_device *descdev;
- struct grub_usb_desc_config config;
- grub_usb_err_t err;
-- int i;
-+ int i, j;
-
- /* First we have to read first 8 bytes only and determine
- * max. size of packet */
-@@ -152,6 +152,7 @@ grub_usb_device_initialize (grub_usb_device_t dev)
- int currif;
- char *data;
- struct grub_usb_desc *desc;
-+ struct grub_usb_desc_endp *endp;
-
- /* First just read the first 4 bytes of the configuration
- descriptor, after that it is known how many bytes really have
-@@ -201,24 +202,27 @@ grub_usb_device_initialize (grub_usb_device_t dev)
- = (struct grub_usb_desc_if *) &data[pos];
- pos += dev->config[i].interf[currif].descif->length;
-
-+ dev->config[i].interf[currif].descendp = grub_malloc (
-+ dev->config[i].interf[currif].descif->endpointcnt *
-+ sizeof(struct grub_usb_desc_endp));
-+
-+ j = 0;
- while (pos < config.totallen)
- {
- desc = (struct grub_usb_desc *)&data[pos];
-- if (desc->type == GRUB_USB_DESCRIPTOR_ENDPOINT)
-- break;
-- if (!desc->length)
-- {
-- err = GRUB_USB_ERR_BADDEVICE;
-- goto fail;
-- }
-- pos += desc->length;
-- }
--
-- /* Point to the first endpoint. */
-- dev->config[i].interf[currif].descendp
-- = (struct grub_usb_desc_endp *) &data[pos];
-- pos += (sizeof (struct grub_usb_desc_endp)
-- * dev->config[i].interf[currif].descif->endpointcnt);
-+ if (desc->type == GRUB_USB_DESCRIPTOR_ENDPOINT) {
-+ endp = (struct grub_usb_desc_endp *) &data[pos];
-+ dev->config[i].interf[currif].descendp[j++] = endp;
-+ pos += desc->length;
-+ } else {
-+ if (!desc->length)
-+ {
-+ err = GRUB_USB_ERR_BADDEVICE;
-+ goto fail;
-+ }
-+ pos += desc->length;
-+ }
-+ }
- }
- }
-
-@@ -226,8 +230,14 @@ grub_usb_device_initialize (grub_usb_device_t dev)
-
- fail:
-
-- for (i = 0; i < GRUB_USB_MAX_CONF; i++)
-+ for (i = 0; i < GRUB_USB_MAX_CONF; i++) {
-+ int currif;
-+
-+ for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
-+ grub_free (dev->config[i].interf[currif].descendp);
-+
- grub_free (dev->config[i].descconf);
-+ }
-
- return err;
- }
-diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c
-index f5608e330..2ae29cba1 100644
---- a/grub-core/bus/usb/usbhub.c
-+++ b/grub-core/bus/usb/usbhub.c
-@@ -82,8 +82,14 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller,
- if (i == GRUB_USBHUB_MAX_DEVICES)
- {
- grub_error (GRUB_ERR_IO, "can't assign address to USB device");
-- for (i = 0; i < GRUB_USB_MAX_CONF; i++)
-- grub_free (dev->config[i].descconf);
-+ for (i = 0; i < GRUB_USB_MAX_CONF; i++) {
-+ int currif;
-+
-+ for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
-+ grub_free (dev->config[i].interf[currif].descendp);
-+
-+ grub_free (dev->config[i].descconf);
-+ }
- grub_free (dev);
- return NULL;
- }
-@@ -96,8 +102,14 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller,
- i, 0, 0, NULL);
- if (err)
- {
-- for (i = 0; i < GRUB_USB_MAX_CONF; i++)
-- grub_free (dev->config[i].descconf);
-+ for (i = 0; i < GRUB_USB_MAX_CONF; i++) {
-+ int currif;
-+
-+ for (currif = 0; currif < dev->config[i].descconf->numif; currif++)
-+ grub_free (dev->config[i].interf[currif].descendp);
-+
-+ grub_free (dev->config[i].descconf);
-+ }
- grub_free (dev);
- return NULL;
- }
-@@ -176,7 +188,7 @@ grub_usb_add_hub (grub_usb_device_t dev)
- i++)
- {
- struct grub_usb_desc_endp *endp = NULL;
-- endp = &dev->config[0].interf[0].descendp[i];
-+ endp = dev->config[0].interf[0].descendp[i];
-
- if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp)
- == GRUB_USB_EP_INTERRUPT)
-diff --git a/grub-core/commands/usbtest.c b/grub-core/commands/usbtest.c
-index 2c6d93fe6..55a657635 100644
---- a/grub-core/commands/usbtest.c
-+++ b/grub-core/commands/usbtest.c
-@@ -185,7 +185,7 @@ usb_iterate (grub_usb_device_t dev, void *data __attribute__ ((unused)))
- for (j = 0; j < interf->endpointcnt; j++)
- {
- struct grub_usb_desc_endp *endp;
-- endp = &dev->config[0].interf[i].descendp[j];
-+ endp = dev->config[0].interf[i].descendp[j];
-
- grub_printf ("Endpoint #%d: %s, max packed size: %d, transfer type: %s, latency: %d\n",
- endp->endp_addr & 15,
-diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c
-index b81e3ad9d..b1512dc12 100644
---- a/grub-core/disk/usbms.c
-+++ b/grub-core/disk/usbms.c
-@@ -184,7 +184,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
- for (j = 0; j < interf->endpointcnt; j++)
- {
- struct grub_usb_desc_endp *endp;
-- endp = &usbdev->config[0].interf[interfno].descendp[j];
-+ endp = usbdev->config[0].interf[interfno].descendp[j];
-
- if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2)
- /* Bulk IN endpoint. */
-diff --git a/grub-core/term/usb_keyboard.c b/grub-core/term/usb_keyboard.c
-index 7322d8dff..d590979f5 100644
---- a/grub-core/term/usb_keyboard.c
-+++ b/grub-core/term/usb_keyboard.c
-@@ -175,7 +175,7 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno)
- for (j = 0; j < usbdev->config[configno].interf[interfno].descif->endpointcnt;
- j++)
- {
-- endp = &usbdev->config[configno].interf[interfno].descendp[j];
-+ endp = usbdev->config[configno].interf[interfno].descendp[j];
-
- if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp)
- == GRUB_USB_EP_INTERRUPT)
-diff --git a/include/grub/usb.h b/include/grub/usb.h
-index 0f346af12..688c11f6d 100644
---- a/include/grub/usb.h
-+++ b/include/grub/usb.h
-@@ -153,7 +153,7 @@ struct grub_usb_interface
- {
- struct grub_usb_desc_if *descif;
-
-- struct grub_usb_desc_endp *descendp;
-+ struct grub_usb_desc_endp **descendp;
-
- /* A driver is handling this interface. Do we need to support multiple drivers
- for single interface?
-diff --git a/include/grub/usbdesc.h b/include/grub/usbdesc.h
-index aac5ab05a..bb2ab2e27 100644
---- a/include/grub/usbdesc.h
-+++ b/include/grub/usbdesc.h
-@@ -29,7 +29,8 @@ typedef enum {
- GRUB_USB_DESCRIPTOR_INTERFACE,
- GRUB_USB_DESCRIPTOR_ENDPOINT,
- GRUB_USB_DESCRIPTOR_DEBUG = 10,
-- GRUB_USB_DESCRIPTOR_HUB = 0x29
-+ GRUB_USB_DESCRIPTOR_HUB = 0x29,
-+ GRUB_USB_DESCRIPTOR_SS_ENDPOINT_COMPANION = 0x30
- } grub_usb_descriptor_t;
-
- struct grub_usb_desc
-@@ -105,6 +106,14 @@ struct grub_usb_desc_endp
- grub_uint8_t interval;
- } GRUB_PACKED;
-
-+struct grub_usb_desc_ssep {
-+ grub_uint8_t length;
-+ grub_uint8_t type;
-+ grub_uint8_t maxburst;
-+ grub_uint8_t attrib;
-+ grub_uint16_t interval;
-+} GRUB_PACKED;
-+
- struct grub_usb_desc_str
- {
- grub_uint8_t length;
---
-2.39.2
-
diff --git a/config/grub/xhci/patches/0005-xhci/0002-usb-Add-enum-for-xHCI.patch b/config/grub/xhci/patches/0005-xhci/0002-usb-Add-enum-for-xHCI.patch
deleted file mode 100644
index d61da615..00000000
--- a/config/grub/xhci/patches/0005-xhci/0002-usb-Add-enum-for-xHCI.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From e111983ca5e2a52bfe2bdc5cd639b06bb2f7902d Mon Sep 17 00:00:00 2001
-From: Patrick Rudolph <patrick.rudolph@9elements.com>
-Date: Sun, 15 Nov 2020 19:47:06 +0100
-Subject: [PATCH 2/8] usb: Add enum for xHCI
-
-Will be used in future patches.
-
-Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
----
- include/grub/usb.h | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/include/grub/usb.h b/include/grub/usb.h
-index 688c11f6d..ea6ee8c2c 100644
---- a/include/grub/usb.h
-+++ b/include/grub/usb.h
-@@ -51,7 +51,8 @@ typedef enum
- GRUB_USB_SPEED_NONE,
- GRUB_USB_SPEED_LOW,
- GRUB_USB_SPEED_FULL,
-- GRUB_USB_SPEED_HIGH
-+ GRUB_USB_SPEED_HIGH,
-+ GRUB_USB_SPEED_SUPER
- } grub_usb_speed_t;
-
- typedef int (*grub_usb_iterate_hook_t) (grub_usb_device_t dev, void *data);
---
-2.39.2
-
diff --git a/config/grub/xhci/patches/0005-xhci/0003-usbtrans-Set-default-maximum-packet-size.patch b/config/grub/xhci/patches/0005-xhci/0003-usbtrans-Set-default-maximum-packet-size.patch
deleted file mode 100644
index 70e73ca2..00000000
--- a/config/grub/xhci/patches/0005-xhci/0003-usbtrans-Set-default-maximum-packet-size.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 3e25c83a1d1c6e149c7e9f0660ddadb2beca2476 Mon Sep 17 00:00:00 2001
-From: Patrick Rudolph <patrick.rudolph@9elements.com>
-Date: Sun, 15 Nov 2020 19:48:03 +0100
-Subject: [PATCH 3/8] usbtrans: Set default maximum packet size
-
-Set the maximum packet size to 512 for SuperSpeed devices.
-
-Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
----
- grub-core/bus/usb/usbtrans.c | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c
-index c5680b33a..c1080bb33 100644
---- a/grub-core/bus/usb/usbtrans.c
-+++ b/grub-core/bus/usb/usbtrans.c
-@@ -128,8 +128,12 @@ grub_usb_control_msg (grub_usb_device_t dev,
- setupdata_addr = grub_dma_get_phys (setupdata_chunk);
-
- /* Determine the maximum packet size. */
-- if (dev->descdev.maxsize0)
-+ if (dev->descdev.maxsize0 && dev->speed != GRUB_USB_SPEED_SUPER)
- max = dev->descdev.maxsize0;
-+ else if (dev->descdev.maxsize0 && dev->speed == GRUB_USB_SPEED_SUPER)
-+ max = 1UL << dev->descdev.maxsize0;
-+ else if (dev->speed == GRUB_USB_SPEED_SUPER)
-+ max = 512;
- else
- max = 64;
-
---
-2.39.2
-
diff --git a/config/grub/xhci/patches/0005-xhci/0004-grub-core-bus-usb-Add-function-pointer-for-attach-de.patch b/config/grub/xhci/patches/0005-xhci/0004-grub-core-bus-usb-Add-function-pointer-for-attach-de.patch
deleted file mode 100644
index a090e0ea..00000000
--- a/config/grub/xhci/patches/0005-xhci/0004-grub-core-bus-usb-Add-function-pointer-for-attach-de.patch
+++ /dev/null
@@ -1,121 +0,0 @@
-From 89701aba00caa81bb566ab10da0c89264393be30 Mon Sep 17 00:00:00 2001
-From: Patrick Rudolph <patrick.rudolph@9elements.com>
-Date: Sun, 15 Nov 2020 19:51:42 +0100
-Subject: [PATCH 4/8] grub-core/bus/usb: Add function pointer for attach/detach
- events
-
-The xHCI code needs to be called for attaching or detaching a device.
-Introduce two functions pointers and call it from the USB hub code.
-
-Will be used in future commits, currently this doesn't change any functionality.
-
-Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
----
- grub-core/bus/usb/ehci.c | 2 ++
- grub-core/bus/usb/ohci.c | 2 ++
- grub-core/bus/usb/uhci.c | 2 ++
- grub-core/bus/usb/usbhub.c | 19 +++++++++++++++++++
- include/grub/usb.h | 4 ++++
- 5 files changed, 29 insertions(+)
-
-diff --git a/grub-core/bus/usb/ehci.c b/grub-core/bus/usb/ehci.c
-index 9abebc6bd..953b851c0 100644
---- a/grub-core/bus/usb/ehci.c
-+++ b/grub-core/bus/usb/ehci.c
-@@ -1812,6 +1812,8 @@ static struct grub_usb_controller_dev usb_controller = {
- .hubports = grub_ehci_hubports,
- .portstatus = grub_ehci_portstatus,
- .detect_dev = grub_ehci_detect_dev,
-+ .attach_dev = NULL,
-+ .detach_dev = NULL,
- /* estimated max. count of TDs for one bulk transfer */
- .max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4
- };
-diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c
-index 5363a61f6..7a3f3e154 100644
---- a/grub-core/bus/usb/ohci.c
-+++ b/grub-core/bus/usb/ohci.c
-@@ -1440,6 +1440,8 @@ static struct grub_usb_controller_dev usb_controller =
- .hubports = grub_ohci_hubports,
- .portstatus = grub_ohci_portstatus,
- .detect_dev = grub_ohci_detect_dev,
-+ .attach_dev = NULL,
-+ .detach_dev = NULL,
- /* estimated max. count of TDs for one bulk transfer */
- .max_bulk_tds = GRUB_OHCI_TDS * 3 / 4
- };
-diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c
-index 0fdea4c1e..03c4605b2 100644
---- a/grub-core/bus/usb/uhci.c
-+++ b/grub-core/bus/usb/uhci.c
-@@ -845,6 +845,8 @@ static struct grub_usb_controller_dev usb_controller =
- .hubports = grub_uhci_hubports,
- .portstatus = grub_uhci_portstatus,
- .detect_dev = grub_uhci_detect_dev,
-+ .attach_dev = NULL,
-+ .detach_dev = NULL,
- /* estimated max. count of TDs for one bulk transfer */
- .max_bulk_tds = N_TD * 3 / 4
- };
-diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c
-index 2ae29cba1..8e963e84b 100644
---- a/grub-core/bus/usb/usbhub.c
-+++ b/grub-core/bus/usb/usbhub.c
-@@ -66,6 +66,15 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller,
- dev->split_hubport = split_hubport;
- dev->split_hubaddr = split_hubaddr;
-
-+ if (controller->dev->attach_dev) {
-+ err = controller->dev->attach_dev (controller, dev);
-+ if (err)
-+ {
-+ grub_free (dev);
-+ return NULL;
-+ }
-+ }
-+
- err = grub_usb_device_initialize (dev);
- if (err)
- {
-@@ -405,6 +414,8 @@ static void
- detach_device (grub_usb_device_t dev)
- {
- unsigned i;
-+ grub_usb_err_t err;
-+
- int k;
- if (!dev)
- return;
-@@ -425,6 +436,14 @@ detach_device (grub_usb_device_t dev)
- if (inter && inter->detach_hook)
- inter->detach_hook (dev, i, k);
- }
-+ if (dev->controller.dev->detach_dev) {
-+ err = dev->controller.dev->detach_dev (&dev->controller, dev);
-+ if (err)
-+ {
-+ // XXX
-+ }
-+ }
-+
- grub_usb_devs[dev->addr] = 0;
- }
-
-diff --git a/include/grub/usb.h b/include/grub/usb.h
-index ea6ee8c2c..4dd179db2 100644
---- a/include/grub/usb.h
-+++ b/include/grub/usb.h
-@@ -126,6 +126,10 @@ struct grub_usb_controller_dev
-
- grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port, int *changed);
-
-+ grub_usb_err_t (*attach_dev) (grub_usb_controller_t ctrl, grub_usb_device_t dev);
-+
-+ grub_usb_err_t (*detach_dev) (grub_usb_controller_t ctrl, grub_usb_device_t dev);
-+
- /* Per controller flag - port reset pending, don't do another reset */
- grub_uint64_t pending_reset;
-
---
-2.39.2
-
diff --git a/config/grub/xhci/patches/0005-xhci/0005-grub-core-bus-usb-usbhub-Add-new-private-fields-for-.patch b/config/grub/xhci/patches/0005-xhci/0005-grub-core-bus-usb-usbhub-Add-new-private-fields-for-.patch
deleted file mode 100644
index 7d69c3a6..00000000
--- a/config/grub/xhci/patches/0005-xhci/0005-grub-core-bus-usb-usbhub-Add-new-private-fields-for-.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-From 5e5d74a4531770258e21dedd45c33f1a9d3afa6b Mon Sep 17 00:00:00 2001
-From: Patrick Rudolph <patrick.rudolph@9elements.com>
-Date: Sun, 15 Nov 2020 19:54:40 +0100
-Subject: [PATCH 5/8] grub-core/bus/usb/usbhub: Add new private fields for xHCI
- controller
-
-Store the root port number, the route, consisting out of the port ID
-in each nibble, and a pointer to driver private data.
-
-Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
----
- grub-core/bus/usb/usbhub.c | 11 ++++++++---
- include/grub/usb.h | 5 +++++
- 2 files changed, 13 insertions(+), 3 deletions(-)
-
-diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c
-index 8e963e84b..b4b3a1a61 100644
---- a/grub-core/bus/usb/usbhub.c
-+++ b/grub-core/bus/usb/usbhub.c
-@@ -49,7 +49,9 @@ static grub_usb_controller_dev_t grub_usb_list;
- static grub_usb_device_t
- grub_usb_hub_add_dev (grub_usb_controller_t controller,
- grub_usb_speed_t speed,
-- int split_hubport, int split_hubaddr)
-+ int split_hubport, int split_hubaddr,
-+ int root_portno,
-+ grub_uint32_t route)
- {
- grub_usb_device_t dev;
- int i;
-@@ -65,6 +67,8 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller,
- dev->speed = speed;
- dev->split_hubport = split_hubport;
- dev->split_hubaddr = split_hubaddr;
-+ dev->root_port = root_portno;
-+ dev->route = route;
-
- if (controller->dev->attach_dev) {
- err = controller->dev->attach_dev (controller, dev);
-@@ -245,7 +249,7 @@ attach_root_port (struct grub_usb_hub *hub, int portno,
- and full/low speed device connected to OHCI/UHCI needs not
- transaction translation - e.g. hubport and hubaddr should be
- always none (zero) for any device connected to any root hub. */
-- dev = grub_usb_hub_add_dev (hub->controller, speed, 0, 0);
-+ dev = grub_usb_hub_add_dev (hub->controller, speed, 0, 0, portno, 0);
- hub->controller->dev->pending_reset = 0;
- npending--;
- if (! dev)
-@@ -676,7 +680,8 @@ poll_nonroot_hub (grub_usb_device_t dev)
-
- /* Add the device and assign a device address to it. */
- next_dev = grub_usb_hub_add_dev (&dev->controller, speed,
-- split_hubport, split_hubaddr);
-+ split_hubport, split_hubaddr, dev->root_port,
-+ dev->route << 4 | (i & 0xf));
- if (dev->controller.dev->pending_reset)
- {
- dev->controller.dev->pending_reset = 0;
-diff --git a/include/grub/usb.h b/include/grub/usb.h
-index 4dd179db2..609faf7d0 100644
---- a/include/grub/usb.h
-+++ b/include/grub/usb.h
-@@ -237,6 +237,11 @@ struct grub_usb_device
- int split_hubport;
-
- int split_hubaddr;
-+
-+ /* xHCI specific information */
-+ int root_port;
-+ grub_uint32_t route;
-+ void *xhci_priv;
- };
-
-
---
-2.39.2
-
diff --git a/config/grub/xhci/patches/0005-xhci/0006-grub-core-bus-usb-Add-xhci-support.patch b/config/grub/xhci/patches/0005-xhci/0006-grub-core-bus-usb-Add-xhci-support.patch
deleted file mode 100644
index 11df42d8..00000000
--- a/config/grub/xhci/patches/0005-xhci/0006-grub-core-bus-usb-Add-xhci-support.patch
+++ /dev/null
@@ -1,2814 +0,0 @@
-From fe3a0bce527e059e9121eb5ad2c3cc099f07a4bf Mon Sep 17 00:00:00 2001
-From: Patrick Rudolph <patrick.rudolph@9elements.com>
-Date: Sun, 15 Nov 2020 19:59:25 +0100
-Subject: [PATCH 6/8] grub-core/bus/usb: Add xhci support
-
-Add support for xHCI USB controllers.
-The code is based on seabios implementation, but has been heavily
-modified to match grubs internals.
-
-Changes done in version 2:
-* Code cleanup
-* Code style fixes
-* Don't leak memory buffers
-* Compile without warnings
-* Add more defines
-* Add more helper functions
-* Don't assume a 1:1 virtual to physical mapping
-* Flush cachelines after writing buffers
-* Don't use hardcoded page size
-* Proper scratchpad register setup
-* xHCI bios ownership handoff
-
-Changes done in version 3:
-* Fixed a race condition detecting events, which doesn't appear on
- qemu based xHCI controllers
-* Don't accidently disable USB3.0 devices after first command
-* Support arbitrary protocol speed IDs
-* Coding style cleanup
-
-Tested:
-* Qemu system x86_64
- * virtual USB HID keyboard (usb-kbd)
- * virtual USB HID mass storage (usb-storage)
-* init Supermicro X11SSH-F
- * iKVM HID keyboard
- * USB3 HID mass storage (controller root port)
- * USB HID keyboard
-
-TODO:
- * Test on more hardware
- * Test on USB3 hubs
- * Support for USB 3.1 and USB 3.2 controllers
-
-Tested on qemu using coreboot and grub as payload:
-
-qemu-system-x86_64 -M q35 -bios $firmware -device qemu-xhci,id=xhci -accel kvm -m 1024M \
- -device usb-storage,drive=thumbdrive,bus=xhci.0,port=3 \
- -drive if=none,format=raw,id=thumbdrive,file=ubuntu-20.04.1-desktop-amd64.iso \
- -device usb-kbd,bus=xhci.0
-
-Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
-Signed-off-by: sylv <sylv@sylv.io>
----
- Makefile.am | 2 +-
- grub-core/Makefile.core.def | 7 +
- grub-core/bus/usb/xhci-pci.c | 195 +++
- grub-core/bus/usb/xhci.c | 2496 ++++++++++++++++++++++++++++++++++
- include/grub/usb.h | 4 +
- 5 files changed, 2703 insertions(+), 1 deletion(-)
- create mode 100644 grub-core/bus/usb/xhci-pci.c
- create mode 100644 grub-core/bus/usb/xhci.c
-
-diff --git a/Makefile.am b/Makefile.am
-index 43635d5ff..65016f856 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -434,7 +434,7 @@ if COND_i386_coreboot
- FS_PAYLOAD_MODULES ?= $(shell cat grub-core/fs.lst)
- default_payload.elf: grub-mkstandalone grub-mkimage FORCE
- test -f $@ && rm $@ || true
-- pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata ehci uhci ohci usb_keyboard usbms part_msdos ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help syslinuxcfg xnu $(FS_PAYLOAD_MODULES) password_pbkdf2 $(EXTRA_PAYLOAD_MODULES)' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg
-+ pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata xhci ehci uhci ohci usb_keyboard usbms part_msdos ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help syslinuxcfg xnu $(FS_PAYLOAD_MODULES) password_pbkdf2 $(EXTRA_PAYLOAD_MODULES)' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg
- endif
-
- endif
-diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
-index fb6078a34..64c3806ab 100644
---- a/grub-core/Makefile.core.def
-+++ b/grub-core/Makefile.core.def
-@@ -667,6 +667,13 @@ module = {
- enable = arm_coreboot;
- };
-
-+module = {
-+ name = xhci;
-+ common = bus/usb/xhci.c;
-+ pci = bus/usb/xhci-pci.c;
-+ enable = pci;
-+};
-+
- module = {
- name = pci;
- common = bus/pci.c;
-diff --git a/grub-core/bus/usb/xhci-pci.c b/grub-core/bus/usb/xhci-pci.c
-new file mode 100644
-index 000000000..a5bd3c97d
---- /dev/null
-+++ b/grub-core/bus/usb/xhci-pci.c
-@@ -0,0 +1,195 @@
-+/* xhci.c - XHCI Support. */
-+/*
-+ * GRUB -- GRand Unified Bootloader
-+ * Copyright (C) 2020 9elements Cyber Security
-+ *
-+ * GRUB is free software: you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation, either version 3 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * GRUB is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#include <grub/pci.h>
-+#include <grub/cpu/pci.h>
-+#include <grub/cs5536.h>
-+#include <grub/misc.h>
-+#include <grub/mm.h>
-+#include <grub/time.h>
-+#include <grub/usb.h>
-+
-+#define GRUB_XHCI_PCI_SBRN_REG 0x60
-+#define GRUB_XHCI_ADDR_MEM_MASK (~0xff)
-+
-+/* USBLEGSUP bits and related OS OWNED byte offset */
-+enum
-+{
-+ GRUB_XHCI_BIOS_OWNED = (1 << 16),
-+ GRUB_XHCI_OS_OWNED = (1 << 24)
-+};
-+
-+/* PCI iteration function... */
-+static int
-+grub_xhci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
-+ void *data __attribute__ ((unused)))
-+{
-+ volatile grub_uint32_t *regs;
-+ grub_uint32_t base, base_h;
-+ grub_uint32_t eecp_offset;
-+ grub_uint32_t usblegsup = 0;
-+ grub_uint64_t maxtime;
-+ grub_uint32_t interf;
-+ grub_uint32_t subclass;
-+ grub_uint32_t class;
-+ grub_uint8_t release;
-+ grub_uint32_t class_code;
-+
-+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: begin\n");
-+
-+ if (pciid == GRUB_CS5536_PCIID)
-+ {
-+ grub_dprintf ("xhci", "CS5536 not supported\n");
-+ return 0;
-+ }
-+ else
-+ {
-+ grub_pci_address_t addr;
-+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
-+ class_code = grub_pci_read (addr) >> 8;
-+ interf = class_code & 0xFF;
-+ subclass = (class_code >> 8) & 0xFF;
-+ class = class_code >> 16;
-+
-+ /* If this is not an XHCI controller, just return. */
-+ if (class != 0x0c || subclass != 0x03 || interf != 0x30)
-+ return 0;
-+
-+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: class OK\n");
-+
-+ /* Check Serial Bus Release Number */
-+ addr = grub_pci_make_address (dev, GRUB_XHCI_PCI_SBRN_REG);
-+ release = grub_pci_read_byte (addr);
-+ if (release != 0x30)
-+ {
-+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: Wrong SBRN: %0x\n",
-+ release);
-+ return 0;
-+ }
-+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: bus rev. num. OK\n");
-+
-+ /* Determine XHCI XHCC registers base address. */
-+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
-+ base = grub_pci_read (addr);
-+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1);
-+ base_h = grub_pci_read (addr);
-+ /* Stop if registers are mapped above 4G - GRUB does not currently
-+ * work with registers mapped above 4G */
-+ if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32)
-+ && (base_h != 0))
-+ {
-+ grub_dprintf ("xhci",
-+ "XHCI grub_xhci_pci_iter: registers above 4G are not supported\n");
-+ return 0;
-+ }
-+ base &= GRUB_PCI_ADDR_MEM_MASK;
-+ if (!base)
-+ {
-+ grub_dprintf ("xhci",
-+ "XHCI: XHCI is not mapped\n");
-+ return 0;
-+ }
-+
-+ /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */
-+ addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
-+ grub_pci_write_word(addr,
-+ GRUB_PCI_COMMAND_MEM_ENABLED
-+ | GRUB_PCI_COMMAND_BUS_MASTER
-+ | grub_pci_read_word(addr));
-+
-+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: 32-bit XHCI OK\n");
-+ }
-+
-+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: iobase of XHCC: %08x\n",
-+ (base & GRUB_XHCI_ADDR_MEM_MASK));
-+
-+ regs = grub_pci_device_map_range (dev,
-+ (base & GRUB_XHCI_ADDR_MEM_MASK),
-+ 0x100);
-+
-+ /* Is there EECP ? */
-+ eecp_offset = (grub_le_to_cpu32 (regs[2]) >> 8) & 0xff;
-+
-+ /* Determine and change ownership. */
-+ /* EECP offset valid in HCCPARAMS */
-+ /* Ownership can be changed via EECP only */
-+ if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40)
-+ {
-+ grub_pci_address_t pciaddr_eecp;
-+ pciaddr_eecp = grub_pci_make_address (dev, eecp_offset);
-+
-+ usblegsup = grub_pci_read (pciaddr_eecp);
-+ if (usblegsup & GRUB_XHCI_BIOS_OWNED)
-+ {
-+ grub_boot_time ("Taking ownership of XHCI controller");
-+ grub_dprintf ("xhci",
-+ "XHCI grub_xhci_pci_iter: XHCI owned by: BIOS\n");
-+ /* Ownership change - set OS_OWNED bit */
-+ grub_pci_write (pciaddr_eecp, usblegsup | GRUB_XHCI_OS_OWNED);
-+ /* Ensure PCI register is written */
-+ grub_pci_read (pciaddr_eecp);
-+
-+ /* Wait for finish of ownership change, XHCI specification
-+ * doesn't say how long it can take... */
-+ maxtime = grub_get_time_ms () + 1000;
-+ while ((grub_pci_read (pciaddr_eecp) & GRUB_XHCI_BIOS_OWNED)
-+ && (grub_get_time_ms () < maxtime));
-+ if (grub_pci_read (pciaddr_eecp) & GRUB_XHCI_BIOS_OWNED)
-+ {
-+ grub_dprintf ("xhci",
-+ "XHCI grub_xhci_pci_iter: XHCI change ownership timeout");
-+ /* Change ownership in "hard way" - reset BIOS ownership */
-+ grub_pci_write (pciaddr_eecp, GRUB_XHCI_OS_OWNED);
-+ /* Ensure PCI register is written */
-+ grub_pci_read (pciaddr_eecp);
-+ }
-+ }
-+ else if (usblegsup & GRUB_XHCI_OS_OWNED)
-+ /* XXX: What to do in this case - nothing ? Can it happen ? */
-+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: XHCI owned by: OS\n");
-+ else
-+ {
-+ grub_dprintf ("xhci",
-+ "XHCI grub_Xhci_pci_iter: XHCI owned by: NONE\n");
-+ /* XXX: What to do in this case ? Can it happen ?
-+ * Is code below correct ? */
-+ /* Ownership change - set OS_OWNED bit */
-+ grub_pci_write (pciaddr_eecp, GRUB_XHCI_OS_OWNED);
-+ /* Ensure PCI register is written */
-+ grub_pci_read (pciaddr_eecp);
-+ }
-+
-+ /* Disable SMI, just to be sure. */
-+ pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4);
-+ grub_pci_write (pciaddr_eecp, 0);
-+ /* Ensure PCI register is written */
-+ grub_pci_read (pciaddr_eecp);
-+ }
-+
-+ grub_dprintf ("xhci", "inithw: XHCI grub_xhci_pci_iter: ownership OK\n");
-+
-+ grub_xhci_init_device (regs);
-+ return 0;
-+}
-+
-+void
-+grub_xhci_pci_scan (void)
-+{
-+ grub_pci_iterate (grub_xhci_pci_iter, NULL);
-+}
-diff --git a/grub-core/bus/usb/xhci.c b/grub-core/bus/usb/xhci.c
-new file mode 100644
-index 000000000..f4591ffb5
---- /dev/null
-+++ b/grub-core/bus/usb/xhci.c
-@@ -0,0 +1,2496 @@
-+/* xhci.c - XHCI Support. */
-+/*
-+ * GRUB -- GRand Unified Bootloader
-+ * Copyright (C) 2020 9elements Cyber Security
-+ *
-+ * GRUB is free software: you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation, either version 3 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * GRUB is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
-+ *
-+ * Big parts of this software are inspired by seabios XHCI implementation
-+ * Released under LGPLv3. Credits to:
-+ *
-+ * Copyright (C) 2013 Gerd Hoffmann <kraxel@redhat.com>
-+ * Copyright (C) 2014 Kevin O'Connor <kevin@koconnor.net>
-+ */
-+
-+#include <grub/dl.h>
-+#include <grub/err.h>
-+#include <grub/mm.h>
-+#include <grub/usb.h>
-+#include <grub/usbtrans.h>
-+#include <grub/misc.h>
-+#include <grub/time.h>
-+#include <grub/loader.h>
-+#include <grub/disk.h>
-+#include <grub/dma.h>
-+#include <grub/cache.h>
-+#include <grub/i386/cpuid.h>
-+
-+GRUB_MOD_LICENSE ("GPLv3+");
-+
-+/* This simple GRUB implementation of XHCI driver */
-+/* Based on the specification
-+ * "eXtensible Host Controller Interface for Universal Serial Bus" Revision 1.2
-+ */
-+
-+
-+#define xhci_get_field(data, field) \
-+ (((data) >> field##_SHIFT) & field##_MASK)
-+#define XHCI_PORTSC_PLS_MASK 0xf
-+#define XHCI_PORTSC_PLS_SHIFT 5
-+#define XHCI_PORTSC_SPEED_MASK 0xf
-+#define XHCI_PORTSC_SPEED_SHIFT 10
-+
-+enum
-+{
-+ XHCI_USB_FULLSPEED = 1,
-+ XHCI_USB_LOWSPEED,
-+ XHCI_USB_HIGHSPEED,
-+ XHCI_USB_SUPERSPEED
-+};
-+
-+/* Chapter 5.3 Host Controller Capability Registers */
-+struct grub_xhci_caps {
-+ grub_uint8_t caplength;
-+ grub_uint8_t reserved_01;
-+ grub_uint16_t hciversion;
-+ grub_uint32_t hcsparams1;
-+ grub_uint32_t hcsparams2;
-+ grub_uint32_t hcsparams3;
-+ grub_uint32_t hccparams;
-+ grub_uint32_t dboff;
-+ grub_uint32_t rtsoff;
-+ grub_uint32_t hccparams2;
-+} GRUB_PACKED;
-+
-+/* extended capabilities */
-+struct grub_xhci_xcap {
-+ grub_uint32_t cap;
-+ grub_uint32_t data[];
-+} GRUB_PACKED;
-+
-+#define XHCI_CAP_LEGACY_SUPPORT 1
-+#define XHCI_CAP_SUPPORTED_PROTOCOL 2
-+
-+struct xhci_portmap {
-+ grub_uint8_t start;
-+ grub_uint8_t count;
-+} GRUB_PACKED;
-+
-+struct grub_xhci_op {
-+ grub_uint32_t usbcmd;
-+ grub_uint32_t usbsts;
-+ grub_uint32_t pagesize;
-+ grub_uint32_t reserved_01[2];
-+ grub_uint32_t dnctl;
-+ grub_uint32_t crcr_low;
-+ grub_uint32_t crcr_high;
-+ grub_uint32_t reserved_02[4];
-+ grub_uint32_t dcbaap_low;
-+ grub_uint32_t dcbaap_high;
-+ grub_uint32_t config;
-+} GRUB_PACKED;
-+
-+enum
-+{
-+ GRUB_XHCI_CMD_RS = (1<<0),
-+ GRUB_XHCI_CMD_HCRST = (1<<1),
-+ GRUB_XHCI_CMD_INTE = (1<<2),
-+ GRUB_XHCI_CMD_HSEE = (1<<3),
-+ GRUB_XHCI_CMD_LHCRST = (1<<7),
-+ GRUB_XHCI_CMD_CSS = (1<<8),
-+ GRUB_XHCI_CMD_CRS = (1<<9),
-+ GRUB_XHCI_CMD_EWE = (1<<10),
-+ GRUB_XHCI_CMD_EU3S = (1<<11)
-+};
-+
-+enum
-+{
-+ GRUB_XHCI_STS_HCH = (1<<0),
-+ GRUB_XHCI_STS_HSE = (1<<2),
-+ GRUB_XHCI_STS_EINT = (1<<3),
-+ GRUB_XHCI_STS_PCD = (1<<4),
-+ GRUB_XHCI_STS_SSS = (1<<8),
-+ GRUB_XHCI_STS_RSS = (1<<9),
-+ GRUB_XHCI_STS_SRE = (1<<10),
-+ GRUB_XHCI_STS_CNR = (1<<11),
-+ GRUB_XHCI_STS_HCE = (1<<12)
-+};
-+
-+
-+/* Port Registers Offset */
-+#define GRUB_XHCI_PR_OFFSET 0x400
-+/* Interrupter Registers Offset */
-+#define GRUB_XHCI_IR_OFFSET 0x20
-+
-+/* Port Status and Control registers offsets */
-+
-+/* Chapter 6 Data Structures */
-+#define ALIGN_SPBA 64
-+#define ALIGN_DCBAA 64
-+#define ALIGN_CMD_RING_SEG 64
-+#define ALIGN_EVT_RING_SEG 64
-+#define ALIGN_EVT_RING_TABLE 64
-+#define ALIGN_TRB 16
-+#define ALIGN_INCTX 64
-+#define ALIGN_SLOTCTX 32
-+
-+#define BOUNDARY_RING 0x10000
-+
-+enum
-+{
-+ GRUB_XHCI_PORTSC_CCS = (1<<0),
-+ GRUB_XHCI_PORTSC_PED = (1<<1),
-+ GRUB_XHCI_PORTSC_OCA = (1<<3),
-+ GRUB_XHCI_PORTSC_PR = (1<<4),
-+ GRUB_XHCI_PORTSC_PP = (1<<9),
-+ GRUB_XHCI_PORTSC_SPEED_FULL = (1<<10),
-+ GRUB_XHCI_PORTSC_SPEED_LOW = (2<<10),
-+ GRUB_XHCI_PORTSC_SPEED_HIGH = (3<<10),
-+ GRUB_XHCI_PORTSC_SPEED_SUPER = (4<<10),
-+ GRUB_XHCI_PORTSC_LWS = (1<<16),
-+ GRUB_XHCI_PORTSC_CSC = (1<<17),
-+ GRUB_XHCI_PORTSC_PEC = (1<<18),
-+ GRUB_XHCI_PORTSC_WRC = (1<<19),
-+ GRUB_XHCI_PORTSC_OCC = (1<<20),
-+ GRUB_XHCI_PORTSC_PRC = (1<<21),
-+ GRUB_XHCI_PORTSC_PLC = (1<<22),
-+ GRUB_XHCI_PORTSC_CEC = (1<<23),
-+ GRUB_XHCI_PORTSC_CAS = (1<<24),
-+ GRUB_XHCI_PORTSC_WCE = (1<<25),
-+ GRUB_XHCI_PORTSC_WDE = (1<<26),
-+ GRUB_XHCI_PORTSC_WOE = (1<<27),
-+ GRUB_XHCI_PORTSC_DR = (1<<30),
-+ GRUB_XHCI_PORTSC_WPR = (1<<31)
-+};
-+
-+/* XHCI memory data structs */
-+#define GRUB_XHCI_MAX_ENDPOINTS 32
-+
-+#define GRUB_XHCI_RING_ITEMS 128
-+#define GRUB_XHCI_RING_SIZE (GRUB_XHCI_RING_ITEMS*sizeof(struct grub_xhci_trb))
-+/*
-+ * xhci_ring structs are allocated with XHCI_RING_SIZE alignment,
-+ * then we can get it from a trb pointer (provided by evt ring).
-+ */
-+#define XHCI_RING(_trb) \
-+ ((struct grub_xhci_ring*)((grub_uint32_t)(_trb) & ~(GRUB_XHCI_RING_SIZE-1)))
-+
-+/* slot context */
-+struct grub_xhci_slotctx {
-+ grub_uint32_t ctx[4];
-+ grub_uint32_t reserved_01[4];
-+} GRUB_PACKED;
-+
-+/* endpoint context */
-+struct grub_xhci_epctx {
-+ grub_uint32_t ctx[2];
-+ grub_uint32_t deq_low;
-+ grub_uint32_t deq_high;
-+ grub_uint32_t length;
-+ grub_uint32_t reserved_01[3];
-+} GRUB_PACKED;
-+
-+/* device context array element */
-+struct grub_xhci_devlist {
-+ grub_uint32_t ptr_low;
-+ grub_uint32_t ptr_high;
-+} GRUB_PACKED;
-+
-+/* input context */
-+struct grub_xhci_inctx {
-+ grub_uint32_t del;
-+ grub_uint32_t add;
-+ grub_uint32_t reserved_01[6];
-+} GRUB_PACKED;
-+
-+/* transfer block (ring element) */
-+struct grub_xhci_trb {
-+ grub_uint32_t ptr_low;
-+ grub_uint32_t ptr_high;
-+ grub_uint32_t status;
-+ grub_uint32_t control;
-+} GRUB_PACKED;
-+
-+#define TRB_C (1<<0)
-+#define TRB_TYPE_SHIFT 10
-+#define TRB_TYPE_MASK 0x3f
-+#define TRB_TYPE(t) (((t) >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK)
-+
-+#define TRB_EV_ED (1<<2)
-+
-+#define TRB_TR_ENT (1<<1)
-+#define TRB_TR_ISP (1<<2)
-+#define TRB_TR_NS (1<<3)
-+#define TRB_TR_CH (1<<4)
-+#define TRB_TR_IOC (1<<5)
-+#define TRB_TR_IDT (1<<6)
-+#define TRB_TR_TBC_SHIFT 7
-+#define TRB_TR_TBC_MASK 0x3
-+#define TRB_TR_BEI (1<<9)
-+#define TRB_TR_TLBPC_SHIFT 16
-+#define TRB_TR_TLBPC_MASK 0xf
-+#define TRB_TR_FRAMEID_SHIFT 20
-+#define TRB_TR_FRAMEID_MASK 0x7ff
-+#define TRB_TR_SIA (1<<31)
-+
-+#define TRB_TR_DIR (1<<16)
-+
-+#define TRB_CR_SLOTID_SHIFT 24
-+#define TRB_CR_SLOTID_MASK 0xff
-+#define TRB_CR_EPID_SHIFT 16
-+#define TRB_CR_EPID_MASK 0x1f
-+
-+#define TRB_CR_BSR (1<<9)
-+#define TRB_CR_DC (1<<9)
-+
-+#define TRB_LK_TC (1<<1)
-+
-+#define TRB_INTR_SHIFT 22
-+#define TRB_INTR_MASK 0x3ff
-+#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK)
-+
-+typedef enum TRBType {
-+ TRB_RESERVED = 0,
-+ TR_NORMAL,
-+ TR_SETUP,
-+ TR_DATA,
-+ TR_STATUS,
-+ TR_ISOCH,
-+ TR_LINK,
-+ TR_EVDATA,
-+ TR_NOOP,
-+ CR_ENABLE_SLOT,
-+ CR_DISABLE_SLOT,
-+ CR_ADDRESS_DEVICE,
-+ CR_CONFIGURE_ENDPOINT,
-+ CR_EVALUATE_CONTEXT,
-+ CR_RESET_ENDPOINT,
-+ CR_STOP_ENDPOINT,
-+ CR_SET_TR_DEQUEUE,
-+ CR_RESET_DEVICE,
-+ CR_FORCE_EVENT,
-+ CR_NEGOTIATE_BW,
-+ CR_SET_LATENCY_TOLERANCE,
-+ CR_GET_PORT_BANDWIDTH,
-+ CR_FORCE_HEADER,
-+ CR_NOOP,
-+ ER_TRANSFER = 32,
-+ ER_COMMAND_COMPLETE,
-+ ER_PORT_STATUS_CHANGE,
-+ ER_BANDWIDTH_REQUEST,
-+ ER_DOORBELL,
-+ ER_HOST_CONTROLLER,
-+ ER_DEVICE_NOTIFICATION,
-+ ER_MFINDEX_WRAP,
-+} TRBType;
-+
-+typedef enum TRBCCode {
-+ CC_INVALID = 0,
-+ CC_SUCCESS,
-+ CC_DATA_BUFFER_ERROR,
-+ CC_BABBLE_DETECTED,
-+ CC_USB_TRANSACTION_ERROR,
-+ CC_TRB_ERROR,
-+ CC_STALL_ERROR,
-+ CC_RESOURCE_ERROR,
-+ CC_BANDWIDTH_ERROR,
-+ CC_NO_SLOTS_ERROR,
-+ CC_INVALID_STREAM_TYPE_ERROR,
-+ CC_SLOT_NOT_ENABLED_ERROR,
-+ CC_EP_NOT_ENABLED_ERROR,
-+ CC_SHORT_PACKET,
-+ CC_RING_UNDERRUN,
-+ CC_RING_OVERRUN,
-+ CC_VF_ER_FULL,
-+ CC_PARAMETER_ERROR,
-+ CC_BANDWIDTH_OVERRUN,
-+ CC_CONTEXT_STATE_ERROR,
-+ CC_NO_PING_RESPONSE_ERROR,
-+ CC_EVENT_RING_FULL_ERROR,
-+ CC_INCOMPATIBLE_DEVICE_ERROR,
-+ CC_MISSED_SERVICE_ERROR,
-+ CC_COMMAND_RING_STOPPED,
-+ CC_COMMAND_ABORTED,
-+ CC_STOPPED,
-+ CC_STOPPED_LENGTH_INVALID,
-+ CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29,
-+ CC_ISOCH_BUFFER_OVERRUN = 31,
-+ CC_EVENT_LOST_ERROR,
-+ CC_UNDEFINED_ERROR,
-+ CC_INVALID_STREAM_ID_ERROR,
-+ CC_SECONDARY_BANDWIDTH_ERROR,
-+ CC_SPLIT_TRANSACTION_ERROR
-+} TRBCCode;
-+
-+enum {
-+ PLS_U0 = 0,
-+ PLS_U1 = 1,
-+ PLS_U2 = 2,
-+ PLS_U3 = 3,
-+ PLS_DISABLED = 4,
-+ PLS_RX_DETECT = 5,
-+ PLS_INACTIVE = 6,
-+ PLS_POLLING = 7,
-+ PLS_RECOVERY = 8,
-+ PLS_HOT_RESET = 9,
-+ PLS_COMPILANCE_MODE = 10,
-+ PLS_TEST_MODE = 11,
-+ PLS_RESUME = 15,
-+};
-+
-+/* event ring segment */
-+struct grub_xhci_er_seg {
-+ grub_uint32_t ptr_low;
-+ grub_uint32_t ptr_high;
-+ grub_uint32_t size;
-+ grub_uint32_t reserved_01;
-+} GRUB_PACKED;
-+
-+struct grub_xhci_ring {
-+ struct grub_xhci_trb ring[GRUB_XHCI_RING_ITEMS];
-+ struct grub_xhci_trb evt;
-+ grub_uint32_t eidx;
-+ grub_uint32_t nidx;
-+ grub_uint32_t cs;
-+};
-+
-+/* port registers */
-+struct grub_xhci_pr {
-+ grub_uint32_t portsc;
-+ grub_uint32_t portpmsc;
-+ grub_uint32_t portli;
-+ grub_uint32_t reserved_01;
-+} GRUB_PACKED;
-+
-+/* doorbell registers */
-+struct grub_xhci_db {
-+ grub_uint32_t doorbell;
-+} GRUB_PACKED;
-+
-+/* runtime registers */
-+struct grub_xhci_rts {
-+ grub_uint32_t mfindex;
-+} GRUB_PACKED;
-+
-+/* interrupter registers */
-+struct grub_xhci_ir {
-+ grub_uint32_t iman;
-+ grub_uint32_t imod;
-+ grub_uint32_t erstsz;
-+ grub_uint32_t reserved_01;
-+ grub_uint32_t erstba_low;
-+ grub_uint32_t erstba_high;
-+ grub_uint32_t erdp_low;
-+ grub_uint32_t erdp_high;
-+} GRUB_PACKED;
-+
-+struct grub_xhci_psid {
-+ grub_uint8_t id;
-+ grub_uint8_t psie;
-+ grub_uint16_t psim;
-+ grub_uint64_t bitrate;
-+ grub_usb_speed_t grub_usb_speed;
-+};
-+
-+struct grub_xhci_psids {
-+ grub_uint8_t major;
-+ grub_uint8_t minor;
-+ struct grub_xhci_psid psids[16];
-+};
-+
-+struct grub_xhci
-+{
-+ grub_uint8_t shutdown; /* 1 if preparing shutdown of controller */
-+ /* xhci registers */
-+ volatile struct grub_xhci_caps *caps; /* Capability registers */
-+ volatile struct grub_xhci_op *op; /* Operational registers */
-+ volatile struct grub_xhci_pr *pr; /* Port Registers */
-+ volatile struct grub_xhci_db *db; /* doorbell */
-+ volatile struct grub_xhci_ir *ir; /* Interrupt Registers */
-+ /* devinfo */
-+ grub_uint32_t xcap;
-+ grub_uint32_t ports;
-+ grub_uint32_t slots;
-+ grub_uint8_t flag64;
-+ grub_uint16_t spb;
-+ grub_uint32_t pagesize;
-+ struct xhci_portmap usb2;
-+ struct xhci_portmap usb3;
-+ struct grub_xhci_psids *psids;
-+ /* xhci data structures */
-+ struct grub_pci_dma_chunk *devs_dma;
-+ volatile struct grub_xhci_devlist *devs;
-+ struct grub_pci_dma_chunk *cmds_dma;
-+ volatile struct grub_xhci_ring *cmds;
-+ struct grub_pci_dma_chunk *evts_dma;
-+ volatile struct grub_xhci_ring *evts;
-+ struct grub_pci_dma_chunk *eseg_dma;
-+ volatile struct grub_xhci_er_seg *eseg;
-+ struct grub_pci_dma_chunk *spba_dma;
-+ struct grub_pci_dma_chunk *spad_dma;
-+
-+ struct grub_xhci *next;
-+};
-+
-+struct grub_xhci_priv {
-+ grub_uint8_t slotid;
-+ grub_uint32_t max_packet;
-+ struct grub_pci_dma_chunk *enpoint_trbs_dma[32];
-+ volatile struct grub_xhci_ring *enpoint_trbs[32];
-+ struct grub_pci_dma_chunk *slotctx_dma;
-+};
-+
-+struct grub_xhci_port {
-+ grub_uint32_t portsc;
-+ grub_uint32_t portpmsc;
-+ grub_uint32_t portli;
-+ grub_uint32_t reserved_01;
-+};
-+
-+struct grub_xhci_transfer_controller_data {
-+ grub_uint32_t transfer_size;
-+};
-+
-+static struct grub_xhci *xhci;
-+
-+/****************************************************************
-+ * general access functions
-+ ****************************************************************/
-+
-+static inline void
-+grub_xhci_write32(volatile void *addr, grub_uint32_t val) {
-+ *(volatile grub_uint32_t *)addr = val;
-+}
-+static inline void
-+grub_xhci_write16(volatile void *addr, grub_uint16_t val) {
-+ *(volatile grub_uint16_t *)addr = val;
-+}
-+static inline void
-+grub_xhci_write8(void *addr, grub_uint8_t val) {
-+ *(volatile grub_uint8_t *)addr = val;
-+}
-+
-+static inline grub_uint32_t
-+grub_xhci_read32(volatile void *addr) {
-+ return grub_le_to_cpu32 (*((volatile grub_uint32_t *)addr));
-+}
-+
-+static inline grub_uint16_t
-+grub_xhci_read16(volatile void *addr) {
-+ return grub_le_to_cpu16 (*((volatile grub_uint32_t *)addr));
-+}
-+static inline grub_uint8_t
-+grub_xhci_read8(volatile void *addr) {
-+ return (*((volatile grub_uint32_t *)addr));
-+}
-+
-+static inline grub_uint32_t
-+grub_xhci_port_read (struct grub_xhci *x, grub_uint32_t port)
-+{
-+ return grub_xhci_read32(&x->pr[port].portsc);
-+}
-+
-+static inline void
-+grub_xhci_port_write (struct grub_xhci *x, grub_uint32_t port,
-+ grub_uint32_t and_mask, grub_uint32_t or_mask)
-+{
-+ grub_uint32_t reg = grub_xhci_port_read(x, port);
-+ reg &= and_mask;
-+ reg |= or_mask;
-+
-+ grub_xhci_write32(&x->pr[port].portsc, reg);
-+}
-+
-+/****************************************************************
-+ * xhci status and support functions
-+ ****************************************************************/
-+
-+static grub_uint32_t xhci_get_pagesize(struct grub_xhci *x)
-+{
-+ /* Chapter 5.4.3 Page Size Register (PAGESIZE) */
-+ for (grub_uint8_t i = 0; i < 16; i++)
-+ {
-+ if (grub_xhci_read32(&x->op->pagesize) & (1 << i))
-+ return 1 << (12 + i);
-+ }
-+ return 0;
-+}
-+
-+static grub_uint8_t xhci_is_halted(struct grub_xhci *x)
-+{
-+ return !!(grub_xhci_read32(&x->op->usbsts) & 1);
-+}
-+
-+/* Just for debugging */
-+static void xhci_check_status(struct grub_xhci *x)
-+{
-+ grub_uint32_t reg;
-+
-+ reg = grub_xhci_read32(&x->op->usbsts);
-+ if (reg & 1)
-+ grub_dprintf("xhci", "%s: xHCI halted\n", __func__);
-+ if (reg & 2)
-+ grub_dprintf("xhci", "%s: Host system error detected\n", __func__);
-+ if (reg & (1 << 12))
-+ grub_dprintf("xhci", "%s: Internal error detected\n", __func__);
-+ reg = grub_xhci_read32(&x->op->crcr_low);
-+ if (reg & (1 << 3))
-+ grub_dprintf("xhci", "%s: Command ring running\n", __func__);
-+}
-+
-+/* xhci_memalign_dma32 allocates DMA memory satisfying alignment and boundary
-+ * requirements without wasting to much memory */
-+static struct grub_pci_dma_chunk *
-+xhci_memalign_dma32(grub_size_t align,
-+ grub_size_t size,
-+ grub_size_t boundary)
-+{
-+ struct grub_pci_dma_chunk *tmp;
-+ const grub_uint32_t mask = boundary - 1;
-+ grub_uint32_t start, end;
-+
-+ /* Allocate some memory and check if it doesn't cross boundary */
-+ tmp = grub_memalign_dma32(align, size);
-+ start = grub_dma_get_phys(tmp);
-+ end = start + size - 1;
-+ if ((start & mask) == (end & mask))
-+ return tmp;
-+ /* Buffer isn't usable, allocate bigger one */
-+ grub_dma_free(tmp);
-+
-+ return grub_memalign_dma32(boundary, size);
-+}
-+
-+/****************************************************************
-+ * helper functions for in context DMA buffer
-+ ****************************************************************/
-+
-+static int
-+grub_xhci_inctx_size(struct grub_xhci *x)
-+{
-+ const grub_uint8_t cnt = GRUB_XHCI_MAX_ENDPOINTS + 1;
-+ return (sizeof(struct grub_xhci_inctx) * cnt) << x->flag64;
-+}
-+
-+static void
-+grub_xhci_inctx_sync_dma_caches(struct grub_xhci *x, struct grub_pci_dma_chunk *inctx)
-+{
-+ grub_arch_sync_dma_caches(inctx, grub_xhci_inctx_size(x));
-+}
-+
-+static struct grub_pci_dma_chunk *
-+grub_xhci_alloc_inctx(struct grub_xhci *x, int maxepid,
-+ struct grub_usb_device *dev)
-+{
-+ int size = grub_xhci_inctx_size(x);
-+ struct grub_pci_dma_chunk *dma = xhci_memalign_dma32(ALIGN_INCTX, size,
-+ x->pagesize);
-+ if (!dma)
-+ return NULL;
-+
-+ volatile struct grub_xhci_inctx *in = grub_dma_get_virt(dma);
-+ grub_memset((void *)in, 0, size);
-+
-+ struct grub_xhci_slotctx *slot = (void*)&in[1 << x->flag64];
-+ slot->ctx[0] |= maxepid << 27; /* context entries */
-+ grub_dprintf("xhci", "%s: speed=%d root_port=%d\n", __func__, dev->speed, dev->root_port);
-+ switch (dev->speed) {
-+ case GRUB_USB_SPEED_FULL:
-+ slot->ctx[0] |= XHCI_USB_FULLSPEED << 20;
-+ break;
-+ case GRUB_USB_SPEED_HIGH:
-+ slot->ctx[0] |= XHCI_USB_HIGHSPEED << 20;
-+ break;
-+ case GRUB_USB_SPEED_LOW:
-+ slot->ctx[0] |= XHCI_USB_LOWSPEED << 20;
-+ break;
-+ case GRUB_USB_SPEED_SUPER:
-+ slot->ctx[0] |= XHCI_USB_SUPERSPEED << 20;
-+ break;
-+ case GRUB_USB_SPEED_NONE:
-+ slot->ctx[0] |= 0 << 20;
-+ 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 */
-+ }
-+ slot->ctx[0] |= dev->route;
-+ slot->ctx[1] |= (dev->root_port+1) << 16;
-+
-+ grub_arch_sync_dma_caches(in, size);
-+
-+ return dma;
-+}
-+
-+/****************************************************************
-+ * xHCI event processing
-+ ****************************************************************/
-+
-+/* Dequeue events on the XHCI event ring generated by the hardware */
-+static void xhci_process_events(struct grub_xhci *x)
-+{
-+ volatile struct grub_xhci_ring *evts = x->evts;
-+ /* XXX invalidate caches */
-+
-+ for (;;) {
-+ /* check for event */
-+ grub_uint32_t nidx = grub_xhci_read32(&evts->nidx);
-+ grub_uint32_t cs = grub_xhci_read32(&evts->cs);
-+ volatile struct grub_xhci_trb *etrb = evts->ring + nidx;
-+ grub_uint32_t control = grub_xhci_read32(&etrb->control);
-+ if ((control & TRB_C) != (cs ? 1 : 0))
-+ return;
-+
-+ /* process event */
-+ grub_uint32_t evt_type = TRB_TYPE(control);
-+ grub_uint32_t evt_cc = (grub_xhci_read32(&etrb->status) >> 24) & 0xff;
-+
-+ switch (evt_type)
-+ {
-+ case ER_TRANSFER:
-+ case ER_COMMAND_COMPLETE:
-+ {
-+ struct grub_xhci_trb *rtrb = (void*)grub_xhci_read32(&etrb->ptr_low);
-+ struct grub_xhci_ring *ring = XHCI_RING(rtrb);
-+ volatile struct grub_xhci_trb *evt = &ring->evt;
-+ grub_uint32_t eidx = rtrb - ring->ring + 1;
-+ grub_dprintf("xhci", "%s: ring %p [trb %p, evt %p, type %d, eidx %d, cc %d]\n",
-+ __func__, ring, rtrb, evt, evt_type, eidx, evt_cc);
-+ *evt = *etrb;
-+ grub_xhci_write32(&ring->eidx, eidx);
-+ break;
-+ }
-+ case ER_PORT_STATUS_CHANGE:
-+ {
-+ /* Nothing to do here. grub_xhci_detect_dev will handle it */
-+ break;
-+ }
-+ default:
-+ {
-+ grub_dprintf("xhci", "%s: unknown event, type %d, cc %d\n",
-+ __func__, evt_type, evt_cc);
-+ break;
-+ }
-+ }
-+
-+ /* move ring index, notify xhci */
-+ nidx++;
-+ if (nidx == GRUB_XHCI_RING_ITEMS)
-+ {
-+ nidx = 0;
-+ cs = cs ? 0 : 1;
-+ grub_xhci_write32(&evts->cs, cs);
-+ }
-+ grub_xhci_write32(&evts->nidx, nidx);
-+ volatile struct grub_xhci_ir *ir = x->ir;
-+ grub_uint32_t erdp = (grub_uint32_t)(evts->ring + nidx);
-+ grub_xhci_write32(&ir->erdp_low, erdp);
-+ grub_xhci_write32(&ir->erdp_high, 0);
-+ }
-+}
-+
-+/****************************************************************
-+ * TRB handling
-+ ****************************************************************/
-+
-+/* Signal the hardware to process events on a TRB ring */
-+static void xhci_doorbell(struct grub_xhci *x, grub_uint32_t slotid, grub_uint32_t value)
-+{
-+ xhci_check_status(x);
-+ grub_dprintf("xhci", "%s: slotid %d, epid %d\n", __func__, slotid, value);
-+ grub_xhci_write32(&x->db[slotid].doorbell, value);
-+}
-+
-+/* Check if a ring has any pending TRBs */
-+static int xhci_ring_busy(volatile struct grub_xhci_ring *ring)
-+{
-+ grub_uint32_t eidx = grub_xhci_read32(&ring->eidx);
-+ grub_uint32_t nidx = grub_xhci_read32(&ring->nidx);
-+
-+ return (eidx != nidx);
-+}
-+
-+/* Returns free space in ring */
-+static int xhci_ring_free_space(volatile struct grub_xhci_ring *ring)
-+{
-+ grub_uint32_t eidx = grub_xhci_read32(&ring->eidx);
-+ grub_uint32_t nidx = grub_xhci_read32(&ring->nidx);
-+
-+ /* nidx is never 0, so reduce ring buffer size by one */
-+ return (eidx > nidx) ? eidx-nidx
-+ : (ARRAY_SIZE(ring->ring) - 1) - nidx + eidx;
-+}
-+
-+/* Check if a ring is full */
-+static int xhci_ring_full(volatile struct grub_xhci_ring *ring)
-+{
-+ /* Might need to insert one link TRB */
-+ return xhci_ring_free_space(ring) <= 1;
-+}
-+
-+/* Check if a ring is almost full */
-+static int xhci_ring_almost_full(volatile struct grub_xhci_ring *ring)
-+{
-+ /* Might need to insert one link TRB */
-+ return xhci_ring_free_space(ring) <= 2;
-+}
-+
-+/* Wait for a ring to empty (all TRBs processed by hardware) */
-+static int xhci_event_wait(struct grub_xhci *x,
-+ volatile struct grub_xhci_ring *ring,
-+ grub_uint32_t timeout)
-+{
-+ grub_uint32_t end = grub_get_time_ms () + timeout;
-+
-+ for (;;)
-+ {
-+ xhci_check_status(x);
-+ xhci_process_events(x);
-+ if (!xhci_ring_busy(ring))
-+ {
-+ grub_uint32_t status = ring->evt.status;
-+ return (status >> 24) & 0xff;
-+ }
-+ if (grub_get_time_ms () > end)
-+ {
-+ xhci_check_status(x);
-+ grub_dprintf("xhci", "%s: Timeout waiting for event\n", __func__);
-+ return -1;
-+ }
-+ }
-+}
-+
-+/* Add a TRB to the given ring, either regular or inline */
-+static void xhci_trb_fill(volatile struct grub_xhci_ring *ring,
-+ grub_uint64_t ptr, grub_uint32_t xferlen,
-+ grub_uint32_t flags)
-+{
-+ volatile struct grub_xhci_trb *dst = &ring->ring[ring->nidx];
-+ dst->ptr_low = ptr & 0xffffffff;
-+ dst->ptr_high = ptr >> 32;
-+ dst->status = xferlen;
-+ dst->control = flags | (ring->cs ? TRB_C : 0);
-+
-+ grub_arch_sync_dma_caches(dst, sizeof(ring->ring[0]));
-+}
-+
-+/*
-+ * Queue a TRB onto a ring.
-+ *
-+ * The caller must pass a pointer to the data in physical address-space or the
-+ * data itself (but no more than 8 bytes) in data_or_addr. Inline data must have
-+ * the flag TRB_TR_IDT set.
-+ */
-+static void xhci_trb_queue(volatile struct grub_xhci_ring *ring,
-+ grub_uint64_t data_or_addr,
-+ grub_uint32_t xferlen, grub_uint32_t flags)
-+{
-+ grub_dprintf("xhci", "%s: ring %p data %llx len %d flags 0x%x remain 0x%x\n", __func__,
-+ ring, data_or_addr, xferlen & 0x1ffff, flags, xferlen >> 17);
-+
-+ if (xhci_ring_full(ring))
-+ {
-+ grub_dprintf("xhci", "%s: ERROR: ring %p is full, discarding TRB\n",
-+ __func__, ring);
-+ return;
-+ }
-+
-+ if (ring->nidx >= ARRAY_SIZE(ring->ring) - 1)
-+ {
-+ /* Reset to command buffer pointer to the first element */
-+ xhci_trb_fill(ring, (grub_addr_t)ring->ring, 0, (TR_LINK << 10) | TRB_LK_TC);
-+ ring->nidx = 0;
-+ ring->cs ^= 1;
-+ grub_dprintf("xhci", "%s: ring %p [linked]\n", __func__, ring);
-+ }
-+
-+ xhci_trb_fill(ring, data_or_addr, xferlen, flags);
-+ ring->nidx++;
-+ grub_dprintf("xhci", "%s: ring %p [nidx %d, len %d]\n",
-+ __func__, ring, ring->nidx, xferlen);
-+}
-+
-+/*
-+ * Queue a TRB onto a ring and flush it if necessary.
-+ *
-+ * The caller must pass a pointer to the data in physical address-space or the
-+ * data itself (but no more than 8 bytes) in data_or_addr. Inline data must have
-+ * the flag TRB_TR_IDT set.
-+ */
-+static int xhci_trb_queue_and_flush(struct grub_xhci *x,
-+ grub_uint32_t slotid,
-+ grub_uint32_t epid,
-+ volatile struct grub_xhci_ring *ring,
-+ grub_uint64_t data_or_addr,
-+ grub_uint32_t xferlen, grub_uint32_t flags)
-+{
-+ grub_uint8_t submit = 0;
-+ if (xhci_ring_almost_full(ring))
-+ {
-+ grub_dprintf("xhci", "%s: almost full e %d n %d\n", __func__, ring->eidx, ring->nidx);
-+ flags |= TRB_TR_IOC;
-+ submit = 1;
-+ }
-+ /* Note: xhci_trb_queue might queue on or two elements, if the end of the TRB
-+ * has been reached. The caller must account for that when filling the TRB. */
-+ xhci_trb_queue(ring, data_or_addr, xferlen, flags);
-+ /* Submit if less no free slot is remaining, we might need an additional
-+ * one on the next call to this function. */
-+ if (submit)
-+ {
-+ xhci_doorbell(x, slotid, epid);
-+ int rc = xhci_event_wait(x, ring, 1000);
-+ grub_dprintf("xhci", "%s: xhci_event_wait = %d\n", __func__, rc);
-+ return rc;
-+ }
-+ return 0;
-+}
-+
-+/****************************************************************
-+ * xHCI command functions
-+ ****************************************************************/
-+
-+/* Submit a command to the xHCI command TRB */
-+static int xhci_cmd_submit(struct grub_xhci *x,
-+ struct grub_pci_dma_chunk *inctx_dma,
-+ grub_uint32_t flags)
-+{
-+ volatile struct grub_xhci_inctx *inctx;
-+ /* Don't submit if halted, it will fail */
-+ if (xhci_is_halted(x))
-+ return -1;
-+
-+ if (inctx_dma)
-+ {
-+ grub_xhci_inctx_sync_dma_caches(x, inctx_dma);
-+
-+ inctx = grub_dma_get_virt(inctx_dma);
-+
-+ struct grub_xhci_slotctx *slot = (void*)&inctx[1 << x->flag64];
-+ grub_uint32_t port = ((slot->ctx[1] >> 16) & 0xff) - 1;
-+ grub_uint32_t portsc = grub_xhci_port_read(x, port);
-+ if (!(portsc & GRUB_XHCI_PORTSC_CCS))
-+ {
-+ grub_dprintf("xhci", "%s: root port %d no longer connected\n",
-+ __func__, port);
-+ return -1;
-+ }
-+ xhci_trb_queue(x->cmds, grub_dma_get_phys(inctx_dma), 0, flags);
-+ }
-+ else
-+ {
-+ xhci_trb_queue(x->cmds, 0, 0, flags);
-+ }
-+
-+ xhci_doorbell(x, 0, 0);
-+ int rc = xhci_event_wait(x, x->cmds, 1000);
-+ grub_dprintf("xhci", "%s: xhci_event_wait = %d\n", __func__, rc);
-+
-+ return rc;
-+}
-+
-+static int xhci_cmd_enable_slot(struct grub_xhci *x)
-+{
-+ grub_uint32_t flags = 0;
-+ flags |= (CR_ENABLE_SLOT << 10);
-+
-+ grub_dprintf("xhci", "%s:\n", __func__);
-+ int cc = xhci_cmd_submit(x, NULL, flags);
-+ if (cc != CC_SUCCESS)
-+ return -1;
-+ grub_dprintf("xhci", "%s: %p\n", __func__, &x->cmds->evt.control);
-+ grub_dprintf("xhci", "%s: %x\n", __func__, grub_xhci_read32(&x->cmds->evt.control));
-+
-+ return (grub_xhci_read32(&x->cmds->evt.control) >> 24) & 0xff;
-+}
-+
-+static int xhci_cmd_disable_slot(struct grub_xhci *x, grub_uint32_t slotid)
-+{
-+ grub_uint32_t flags = 0;
-+ flags |= (CR_DISABLE_SLOT << 10);
-+ flags |= (slotid << 24);
-+
-+ grub_dprintf("xhci", "%s: slotid %d\n", __func__, slotid);
-+ return xhci_cmd_submit(x, NULL, flags);
-+}
-+
-+static int xhci_cmd_stop_endpoint(struct grub_xhci *x, grub_uint32_t slotid
-+ , grub_uint32_t epid
-+ , grub_uint32_t suspend)
-+{
-+ grub_uint32_t flags = 0;
-+ flags |= (CR_STOP_ENDPOINT << 10);
-+ flags |= (epid << 16);
-+ flags |= (suspend << 23) ;
-+ flags |= (slotid << 24);
-+
-+ return xhci_cmd_submit(x, NULL, flags);
-+}
-+
-+static int xhci_cmd_reset_endpoint(struct grub_xhci *x, grub_uint32_t slotid
-+ , grub_uint32_t epid
-+ , grub_uint32_t preserve)
-+{
-+ grub_uint32_t flags = 0;
-+ flags |= (preserve << 9);
-+ flags |= (CR_RESET_ENDPOINT << 10);
-+ flags |= (epid << 16);
-+ flags |= (slotid << 24);
-+
-+ return xhci_cmd_submit(x, NULL, flags);
-+}
-+
-+static int xhci_cmd_set_dequeue_pointer(struct grub_xhci *x, grub_uint32_t slotid
-+ , grub_uint32_t epid
-+ , grub_addr_t tr_deque_pointer)
-+{
-+ grub_uint32_t flags = 0;
-+ flags |= (CR_SET_TR_DEQUEUE << 10);
-+ flags |= (epid << 16);
-+ flags |= (slotid << 24);
-+
-+ xhci_trb_queue(x->cmds, tr_deque_pointer, 0, flags);
-+
-+ xhci_doorbell(x, 0, 0);
-+ int rc = xhci_event_wait(x, x->cmds, 1000);
-+ grub_dprintf("xhci", "%s: xhci_event_wait = %d\n", __func__, rc);
-+
-+ return rc;
-+}
-+
-+static int xhci_cmd_address_device(struct grub_xhci *x, grub_uint32_t slotid,
-+ struct grub_pci_dma_chunk *inctx_dma)
-+{
-+ grub_uint32_t flags = 0;
-+ flags |= (CR_ADDRESS_DEVICE << 10);
-+ flags |= (slotid << 24);
-+
-+ grub_dprintf("xhci", "%s: slotid %d\n", __func__, slotid);
-+ return xhci_cmd_submit(x, inctx_dma, flags);
-+}
-+
-+static int xhci_cmd_configure_endpoint(struct grub_xhci *x, grub_uint32_t slotid,
-+ struct grub_pci_dma_chunk *inctx_dma)
-+{
-+ grub_uint32_t flags = 0;
-+ flags |= (CR_CONFIGURE_ENDPOINT << 10);
-+ flags |= (slotid << 24);
-+
-+ grub_dprintf("xhci", "%s: slotid %d\n", __func__, slotid);
-+ return xhci_cmd_submit(x, inctx_dma, flags);
-+}
-+
-+static int xhci_cmd_evaluate_context(struct grub_xhci *x, grub_uint32_t slotid,
-+ struct grub_pci_dma_chunk *inctx_dma)
-+{
-+ grub_uint32_t flags = 0;
-+ flags |= (CR_EVALUATE_CONTEXT << 10);
-+ flags |= (slotid << 24);
-+
-+ grub_dprintf("xhci", "%s: slotid %d\n", __func__, slotid);
-+ return xhci_cmd_submit(x, inctx_dma, flags);
-+}
-+
-+/****************************************************************
-+ * xHCI host controller initialization
-+ ****************************************************************/
-+
-+static grub_usb_err_t
-+grub_xhci_reset (struct grub_xhci *x)
-+{
-+ grub_uint32_t reg;
-+ grub_uint32_t end;
-+
-+ reg = grub_xhci_read32(&x->op->usbcmd);
-+ if (reg & GRUB_XHCI_CMD_RS)
-+ {
-+ reg &= ~GRUB_XHCI_CMD_RS;
-+ grub_xhci_write32(&x->op->usbcmd, reg);
-+
-+ end = grub_get_time_ms () + 32;
-+ while (grub_xhci_read32(&x->op->usbcmd) & GRUB_XHCI_STS_HCH)
-+ {
-+ if (grub_get_time_ms () > end)
-+ return GRUB_USB_ERR_TIMEOUT;
-+
-+ grub_millisleep(1);
-+ }
-+ }
-+
-+ grub_dprintf("xhci", "grub_xhci_reset: resetting HC\n");
-+ grub_xhci_write32(&x->op->usbcmd, GRUB_XHCI_CMD_HCRST);
-+
-+ /* Wait for device to complete reset and be enabled */
-+ end = grub_get_time_ms () + 100;
-+ while (grub_xhci_read32(&x->op->usbcmd) & GRUB_XHCI_CMD_HCRST)
-+ {
-+ if (grub_get_time_ms () > end)
-+ return GRUB_USB_ERR_TIMEOUT;
-+
-+ grub_millisleep(1);
-+ }
-+
-+ /* Wait for device to complete reset and be enabled */
-+ end = grub_get_time_ms () + 100;
-+ while (grub_xhci_read32(&x->op->usbsts) & GRUB_XHCI_STS_CNR)
-+ {
-+ if (grub_get_time_ms () > end)
-+ return GRUB_USB_ERR_TIMEOUT;
-+
-+ grub_millisleep(1);
-+ }
-+
-+ grub_xhci_write32(&x->op->config, x->slots);
-+ grub_xhci_write32(&x->op->dcbaap_low, grub_dma_get_phys(x->devs_dma));
-+ grub_xhci_write32(&x->op->dcbaap_high, 0);
-+ grub_xhci_write32(&x->op->crcr_low, grub_dma_get_phys(x->cmds_dma)| 1);
-+ grub_xhci_write32(&x->op->crcr_high, 0);
-+ x->cmds->cs = 1;
-+
-+ grub_arch_sync_dma_caches(x->cmds, sizeof(*x->cmds));
-+
-+ x->eseg->ptr_low = grub_dma_get_phys(x->evts_dma);
-+ x->eseg->ptr_high = 0;
-+ x->eseg->size = GRUB_XHCI_RING_ITEMS;
-+
-+ grub_arch_sync_dma_caches(x->eseg, sizeof(*x->eseg));
-+
-+ grub_xhci_write32(&x->ir->erstsz, 1);
-+ grub_xhci_write32(&x->ir->erdp_low, grub_dma_get_phys(x->evts_dma));
-+ grub_xhci_write32(&x->ir->erdp_high, 0);
-+ grub_xhci_write32(&x->ir->erstba_low, grub_dma_get_phys(x->eseg_dma));
-+ grub_xhci_write32(&x->ir->erstba_high, 0);
-+ x->evts->cs = 1;
-+
-+ grub_arch_sync_dma_caches(x->evts, sizeof(*x->eseg));
-+
-+ xhci_check_status(x);
-+
-+ grub_dprintf ("xhci", "XHCI OP COMMAND: %08x\n",
-+ grub_xhci_read32 (&x->op->usbcmd));
-+ grub_dprintf ("xhci", "XHCI OP STATUS: %08x\n",
-+ grub_xhci_read32 (&x->op->usbsts));
-+ grub_dprintf ("xhci", "XHCI OP PAGESIZE: %08x\n",
-+ grub_xhci_read32 (&x->op->pagesize));
-+ grub_dprintf ("xhci", "XHCI OP DNCTRL: %08x\n",
-+ grub_xhci_read32 (&x->op->dnctl));
-+ grub_dprintf ("xhci", "XHCI OP CRCR_LOW: %08x\n",
-+ grub_xhci_read32 (&x->op->crcr_low));
-+ grub_dprintf ("xhci", "XHCI OP CRCR_HIGH: %08x\n",
-+ grub_xhci_read32 (&x->op->crcr_high));
-+ grub_dprintf ("xhci", "XHCI OP DCBAAP_LOW: %08x\n",
-+ grub_xhci_read32 (&x->op->dcbaap_low));
-+ grub_dprintf ("xhci", "XHCI OP DCBAAP_HIGH: %08x\n",
-+ grub_xhci_read32 (&x->op->dcbaap_high));
-+ grub_dprintf ("xhci", "XHCI OP CONFIG: %08x\n",
-+ grub_xhci_read32 (&x->op->config));
-+ grub_dprintf ("xhci", "XHCI IR ERSTSZ: %08x\n",
-+ grub_xhci_read32 (&x->ir->erstsz));
-+ grub_dprintf ("xhci", "XHCI IR ERDP: %08x\n",
-+ grub_xhci_read32 (&x->ir->erdp_low));
-+ grub_dprintf ("xhci", "XHCI IR ERSTBA: %08x\n",
-+ grub_xhci_read32 (&x->ir->erstba_low));
-+
-+ xhci_check_status(x);
-+
-+ return GRUB_USB_ERR_NONE;
-+}
-+
-+static grub_usb_err_t
-+grub_xhci_request_legacy_handoff(volatile struct grub_xhci_xcap *xcap)
-+{
-+ grub_uint32_t end;
-+
-+ end = grub_get_time_ms () + 10;
-+ for (;;)
-+ {
-+ grub_uint32_t cap = grub_xhci_read32(&xcap->cap);
-+ if (cap & (1 << 16))
-+ grub_xhci_write32(&xcap->cap, cap | (1 << 24));
-+ else
-+ break;
-+
-+ if (grub_get_time_ms () > end)
-+ {
-+ grub_dprintf ("xhci","ERROR: %s TIMEOUT\n", __func__);
-+ return GRUB_USB_ERR_TIMEOUT;
-+ }
-+ grub_millisleep(1);
-+ }
-+ return GRUB_USB_ERR_NONE;
-+}
-+
-+static void
-+grub_xhci_fill_default_speed_mapping(struct grub_xhci_psids *ids)
-+{
-+ /* Chapter 7.2.2.1.1 "Default USB Speed ID Mapping" */
-+ ids->psids[0].id = 1;
-+ ids->psids[0].psie = 2;
-+ ids->psids[0].psim = 12;
-+ ids->psids[1].id = 2;
-+ ids->psids[1].psie = 1;
-+ ids->psids[1].psim = 1500;
-+ ids->psids[2].id = 3;
-+ ids->psids[2].psie = 2;
-+ ids->psids[2].psim = 480;
-+ ids->psids[3].id = 4;
-+ ids->psids[3].psie = 3;
-+ ids->psids[3].psim = 5;
-+ ids->psids[4].id = 5;
-+ ids->psids[4].psie = 3;
-+ ids->psids[4].psim = 10;
-+ ids->psids[5].id = 6;
-+ ids->psids[5].psie = 3;
-+ ids->psids[5].psim = 10;
-+ ids->psids[6].id = 7;
-+ ids->psids[6].psie = 3;
-+ ids->psids[6].psim = 20;
-+}
-+
-+static void
-+grub_xhci_calc_speed_mapping(struct grub_xhci_psids *ids)
-+{
-+ const grub_uint64_t mult[4] = {1ULL, 1000ULL, 1000000ULL, 1000000000ULL};
-+
-+ for (grub_uint8_t i = 0; i < 16; i++)
-+ {
-+ if (ids->psids[i].id == 0)
-+ continue;
-+ ids->psids[i].bitrate = mult[ids->psids[i].psie & 3] * (grub_uint64_t)ids->psids[i].psim;
-+ if (ids->psids[i].bitrate < 12000000ULL)
-+ ids->psids[i].grub_usb_speed = GRUB_USB_SPEED_LOW;
-+ else if (ids->psids[i].bitrate < 480000000ULL)
-+ ids->psids[i].grub_usb_speed = GRUB_USB_SPEED_FULL;
-+ else if (ids->psids[i].bitrate > 1200000000ULL)
-+ ids->psids[i].grub_usb_speed = GRUB_USB_SPEED_SUPER;
-+ else
-+ ids->psids[i].grub_usb_speed = GRUB_USB_SPEED_HIGH;
-+ }
-+}
-+
-+
-+/* PCI iteration function... */
-+void
-+grub_xhci_init_device (volatile void *regs)
-+{
-+ struct grub_xhci *x;
-+ grub_uint32_t hcs1, hcc, reg;
-+
-+ /* Allocate memory for the controller and fill basic values. */
-+ x = grub_zalloc (sizeof (*x));
-+ if (!x)
-+ {
-+ grub_dprintf("xhci", "Failed to allocate memory\n");
-+ return;
-+ }
-+ x->caps = (volatile struct grub_xhci_caps *) regs;
-+ x->op = (volatile struct grub_xhci_op *) (((grub_uint8_t *)regs) +
-+ grub_xhci_read8(&x->caps->caplength));
-+ x->pr = (volatile struct grub_xhci_pr *) (((grub_uint8_t *)x->op) +
-+ GRUB_XHCI_PR_OFFSET);
-+ x->db = (volatile struct grub_xhci_db *) (((grub_uint8_t *)regs) +
-+ grub_xhci_read32(&x->caps->dboff));
-+ x->ir = (volatile struct grub_xhci_ir *) (((grub_uint8_t *)regs) +
-+ grub_xhci_read32(&x->caps->rtsoff) + GRUB_XHCI_IR_OFFSET);
-+
-+ grub_dprintf ("xhci", "XHCI init: CAPLENGTH: 0x%02x\n",
-+ grub_xhci_read8 (&x->caps->caplength));
-+ grub_dprintf ("xhci", "XHCI init: HCIVERSION: 0x%04x\n",
-+ grub_xhci_read16 (&x->caps->hciversion));
-+ grub_dprintf ("xhci", "XHCI init: HCSPARAMS1: 0x%08x\n",
-+ grub_xhci_read32 (&x->caps->hcsparams1));
-+ grub_dprintf ("xhci", "XHCI init: HCSPARAMS2: 0x%08x\n",
-+ grub_xhci_read32 (&x->caps->hcsparams2));
-+ grub_dprintf ("xhci", "XHCI init: HCSPARAMS3: 0x%08x\n",
-+ grub_xhci_read32 (&x->caps->hcsparams3));
-+ grub_dprintf ("xhci", "XHCI init: HCCPARAMS: 0x%08x\n",
-+ grub_xhci_read32 (&x->caps->hcsparams3));
-+ grub_dprintf ("xhci", "XHCI init: DBOFF: 0x%08x\n",
-+ grub_xhci_read32 (&x->caps->dboff));
-+ grub_dprintf ("xhci", "XHCI init: RTOFF: 0x%08x\n",
-+ grub_xhci_read32 (&x->caps->rtsoff));
-+
-+ hcs1 = grub_xhci_read32(&x->caps->hcsparams1);
-+ hcc = grub_xhci_read32(&x->caps->hccparams);
-+ x->ports = (grub_uint32_t) ((hcs1 >> 24) & 0xff);
-+ x->slots = (grub_uint32_t) (hcs1 & 0xff);
-+ x->xcap = (grub_uint32_t) ((hcc >> 16) & 0xffff) * sizeof(grub_uint32_t);
-+ x->flag64 = (grub_uint8_t) ((hcc & 0x04) ? 1 : 0);
-+ grub_dprintf("xhci", "XHCI init: %d ports, %d slots, %d byte contexts\n"
-+ , x->ports, x->slots, x->flag64 ? 64 : 32);
-+
-+ x->psids = grub_zalloc (sizeof (struct grub_xhci_psids) * x->ports);
-+ if (x->xcap)
-+ {
-+ grub_uint32_t off;
-+ volatile grub_uint8_t *addr = (grub_uint8_t *) x->caps + x->xcap;
-+ do
-+ {
-+ volatile struct grub_xhci_xcap *xcap = (void *)addr;
-+ grub_uint32_t ports, name, cap = grub_xhci_read32(&xcap->cap);
-+ switch (cap & 0xff) {
-+ case XHCI_CAP_LEGACY_SUPPORT:
-+ {
-+ if (grub_xhci_request_legacy_handoff(xcap) != GRUB_USB_ERR_NONE)
-+ {
-+ grub_dprintf("xhci", "XHCI init: Failed to get xHCI ownership\n");
-+ goto fail;
-+ }
-+ break;
-+ }
-+ case XHCI_CAP_SUPPORTED_PROTOCOL:
-+ {
-+ name = grub_xhci_read32(&xcap->data[0]);
-+ ports = grub_xhci_read32(&xcap->data[1]);
-+ const grub_uint8_t major = (cap >> 24) & 0xff;
-+ const grub_uint8_t minor = (cap >> 16) & 0xff;
-+ const grub_uint8_t psic = (ports >> 28) & 0xf;
-+ const grub_uint8_t count = (ports >> 8) & 0xff;
-+ const grub_uint8_t start = (ports >> 0) & 0xff;
-+ grub_dprintf("xhci", "XHCI init: protocol %c%c%c%c %x.%02x"
-+ ", %d ports (offset %d), def %x, psic %d\n"
-+ , (name >> 0) & 0xff
-+ , (name >> 8) & 0xff
-+ , (name >> 16) & 0xff
-+ , (name >> 24) & 0xff
-+ , major, minor
-+ , count, start
-+ , ports >> 16
-+ , psic);
-+ if (name == 0x20425355 /* "USB " */)
-+ {
-+ if (major == 2)
-+ {
-+ x->usb2.start = start;
-+ x->usb2.count = count;
-+ }
-+ else if (major == 3)
-+ {
-+ x->usb3.start = start;
-+ x->usb3.count = count;
-+ }
-+
-+ for (grub_uint32_t p = start - 1; p < start + count - 1UL; p++)
-+ {
-+ x->psids[p].major = major;
-+ x->psids[p].minor = minor;
-+ grub_xhci_fill_default_speed_mapping(&x->psids[p]);
-+ for (grub_uint8_t i = 0; i < psic; i++)
-+ {
-+ grub_uint32_t psid = grub_xhci_read32(&xcap->data[3 + i]);
-+ x->psids[p].psids[i].id = (psid >> 0) & 0xf;
-+ x->psids[p].psids[i].psie = (psid >> 4) & 0x3;
-+ x->psids[p].psids[i].psim = (psid >> 16) & 0xfffff;
-+ }
-+ grub_xhci_calc_speed_mapping(&x->psids[p]);
-+ }
-+ }
-+
-+ break;
-+ }
-+ default:
-+ {
-+ grub_dprintf("xhci", "XHCI extcap 0x%x @ %p\n", cap & 0xff, addr);
-+ break;
-+ }
-+ }
-+ off = (cap >> 8) & 0xff;
-+ addr += off << 2;
-+ }
-+ while (off > 0);
-+ }
-+
-+ x->pagesize = xhci_get_pagesize(x);
-+ grub_dprintf("xhci", "XHCI init: Minimum supported page size 0x%x\n",
-+ x->pagesize);
-+
-+ /* Chapter 6.1 Device Context Base Address Array */
-+ x->devs_dma = xhci_memalign_dma32(ALIGN_DCBAA,
-+ sizeof(*x->devs) * (x->slots + 1),
-+ x->pagesize);
-+ if (!x->devs_dma)
-+ goto fail;
-+ x->devs = grub_dma_get_virt(x->devs_dma);
-+ grub_memset((void *)x->devs, 0, sizeof(*x->devs) * (x->slots + 1));
-+ grub_arch_sync_dma_caches(x->devs, sizeof(*x->devs) * (x->slots + 1));
-+ grub_dprintf ("xhci", "XHCI init: device memory %p (%x)\n",
-+ grub_dma_get_virt(x->devs_dma),
-+ grub_dma_get_phys(x->devs_dma));
-+
-+ /* Chapter 6.5 Event Ring Segment Table */
-+ x->eseg_dma = xhci_memalign_dma32(ALIGN_EVT_RING_TABLE, sizeof(*x->eseg), 0);
-+ if (!x->eseg_dma)
-+ goto fail;
-+ x->eseg = grub_dma_get_virt(x->eseg_dma);
-+ grub_memset((void *)x->eseg, 0, sizeof(*x->eseg));
-+ grub_arch_sync_dma_caches(x->eseg, sizeof(*x->eseg));
-+ grub_dprintf ("xhci", "XHCI init: event ring table memory %p (%x)\n",
-+ grub_dma_get_virt(x->eseg_dma),
-+ grub_dma_get_phys(x->eseg_dma));
-+
-+ x->cmds_dma = xhci_memalign_dma32(ALIGN_CMD_RING_SEG, sizeof(*x->cmds),
-+ BOUNDARY_RING);
-+ if (!x->cmds_dma)
-+ goto fail;
-+ x->cmds = grub_dma_get_virt(x->cmds_dma);
-+ grub_memset((void *)x->cmds, 0, sizeof(*x->cmds));
-+ grub_arch_sync_dma_caches(x->cmds, sizeof(*x->cmds));
-+ grub_dprintf ("xhci", "XHCI init: command ring memory %p (%x)\n",
-+ grub_dma_get_virt(x->cmds_dma),
-+ grub_dma_get_phys(x->cmds_dma));
-+
-+ x->evts_dma = xhci_memalign_dma32(ALIGN_EVT_RING_SEG, sizeof(*x->evts),
-+ BOUNDARY_RING);
-+ if (!x->evts_dma)
-+ goto fail;
-+ x->evts = grub_dma_get_virt(x->evts_dma);
-+ grub_memset((void *)x->evts, 0, sizeof(*x->evts));
-+ grub_arch_sync_dma_caches(x->evts, sizeof(*x->evts));
-+ grub_dprintf ("xhci", "XHCI init: event ring memory %p (%x)\n",
-+ grub_dma_get_virt(x->evts_dma),
-+ grub_dma_get_phys(x->evts_dma));
-+
-+ /* Chapter 4.20 Scratchpad Buffers */
-+ reg = grub_xhci_read32(&x->caps->hcsparams2);
-+ x->spb = (reg >> 21 & 0x1f) << 5 | reg >> 27;
-+ if (x->spb)
-+ {
-+ volatile grub_uint64_t *spba;
-+ grub_dprintf("xhci", "XHCI init: set up %d scratch pad buffers\n",
-+ x->spb);
-+ x->spba_dma = xhci_memalign_dma32(ALIGN_SPBA, sizeof(*spba) * x->spb,
-+ x->pagesize);
-+ if (!x->spba_dma)
-+ goto fail;
-+
-+ x->spad_dma = xhci_memalign_dma32(x->pagesize, x->pagesize * x->spb,
-+ x->pagesize);
-+ if (!x->spad_dma)
-+ {
-+ grub_dma_free(x->spba_dma);
-+ goto fail;
-+ }
-+
-+ spba = grub_dma_get_virt(x->spba_dma);
-+ for (grub_uint32_t i = 0; i < x->spb; i++)
-+ spba[i] = (grub_addr_t)grub_dma_get_phys(x->spad_dma) + (i * x->pagesize);
-+ grub_arch_sync_dma_caches(x->spba_dma, sizeof(*spba) * x->spb);
-+
-+ x->devs[0].ptr_low = grub_dma_get_phys(x->spba_dma);
-+ x->devs[0].ptr_high = 0;
-+ grub_arch_sync_dma_caches(x->devs_dma, sizeof(x->devs[0]));
-+ grub_dprintf ("xhci", "XHCI init: Allocated %d scratch buffers of size 0x%x\n",
-+ x->spb, x->pagesize);
-+ }
-+
-+ grub_xhci_reset(x);
-+
-+ /* Set the running bit */
-+ reg = grub_xhci_read32 (&x->op->usbcmd);
-+ reg |= GRUB_XHCI_CMD_RS;
-+ grub_xhci_write32 (&x->op->usbcmd, reg);
-+
-+
-+ /* Link to xhci now that initialisation is successful. */
-+ x->next = xhci;
-+ xhci = x;
-+
-+ return;
-+
-+fail:
-+ grub_dprintf ("xhci", "XHCI grub_xhci_pci_iter: FAILED!\n");
-+ if (x)
-+ {
-+ if (x->devs_dma)
-+ grub_dma_free (x->devs_dma);
-+ if (x->eseg_dma)
-+ grub_dma_free (x->eseg_dma);
-+ if (x->cmds_dma)
-+ grub_dma_free (x->cmds_dma);
-+ if (x->evts_dma)
-+ grub_dma_free (x->evts_dma);
-+ if (x->spad_dma)
-+ grub_dma_free (x->spad_dma);
-+ if (x->spba_dma)
-+ grub_dma_free (x->spba_dma);
-+ }
-+ grub_free (x);
-+
-+ return;
-+}
-+
-+static int
-+grub_xhci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data)
-+{
-+ struct grub_xhci *x;
-+ struct grub_usb_controller dev;
-+
-+ for (x = xhci; x; x = x->next)
-+ {
-+ dev.data = x;
-+ if (hook (&dev, hook_data))
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+/****************************************************************
-+ * xHCI maintainance functions
-+ ****************************************************************/
-+
-+static grub_usb_err_t
-+grub_xhci_update_hub_portcount (struct grub_xhci *x,
-+ grub_usb_transfer_t transfer,
-+ grub_uint32_t slotid)
-+{
-+ struct grub_pci_dma_chunk *in_dma;
-+ volatile struct grub_xhci_slotctx *hdslot;
-+ grub_uint32_t epid = 0;
-+
-+ if (!transfer || !transfer->dev || !transfer->dev->nports)
-+ return GRUB_USB_ERR_NONE;
-+
-+ hdslot = grub_dma_phys2virt(x->devs[slotid].ptr_low, x->devs_dma);
-+ if ((hdslot->ctx[3] >> 27) == 3)
-+ /* Already configured */
-+ return 0;
-+
-+ grub_dprintf("xhci", "%s: updating hub config to %d ports\n", __func__,
-+ transfer->dev->nports);
-+
-+ xhci_check_status(x);
-+
-+ /* Allocate input context and initialize endpoint info. */
-+ in_dma = grub_xhci_alloc_inctx(x, epid, transfer->dev);
-+ if (!in_dma)
-+ return GRUB_USB_ERR_INTERNAL;
-+ volatile struct grub_xhci_inctx *in = grub_dma_get_virt(in_dma);
-+
-+ in->add = (1 << epid);
-+
-+ struct grub_xhci_epctx *ep = (void*)&in[(epid+1) << x->flag64];
-+ ep->ctx[0] |= 1 << 26;
-+ ep->ctx[1] |= transfer->dev->nports << 24;
-+
-+ int cc = xhci_cmd_configure_endpoint(x, slotid, in_dma);
-+ grub_dma_free(in_dma);
-+
-+ if (cc != CC_SUCCESS)
-+ {
-+ grub_dprintf("xhci", "%s: reconf ctl endpoint: failed (cc %d)\n",
-+ __func__, cc);
-+ return GRUB_USB_ERR_BADDEVICE;
-+ }
-+
-+ return GRUB_USB_ERR_NONE;
-+}
-+
-+static grub_usb_err_t
-+grub_xhci_update_max_paket_size (struct grub_xhci *x,
-+ grub_usb_transfer_t transfer,
-+ grub_uint32_t slotid,
-+ grub_uint32_t max_packet)
-+{
-+ struct grub_pci_dma_chunk *in_dma;
-+ grub_uint32_t epid = 1;
-+
-+ if (!transfer || !transfer->dev || !max_packet)
-+ return GRUB_USB_ERR_NONE;
-+
-+ grub_dprintf("xhci", "%s: updating max packet size to 0x%x\n", __func__,
-+ max_packet);
-+
-+ xhci_check_status(x);
-+
-+ /* Allocate input context and initialize endpoint info. */
-+ in_dma = grub_xhci_alloc_inctx(x, epid, transfer->dev);
-+ if (!in_dma)
-+ return GRUB_USB_ERR_INTERNAL;
-+ volatile struct grub_xhci_inctx *in = grub_dma_get_virt(in_dma);
-+ in->add = (1 << epid);
-+
-+ struct grub_xhci_epctx *ep = (void*)&in[(epid+1) << x->flag64];
-+ ep->ctx[1] |= max_packet << 16;
-+
-+ int cc = xhci_cmd_evaluate_context(x, slotid, in_dma);
-+ grub_dma_free(in_dma);
-+
-+ if (cc != CC_SUCCESS)
-+ {
-+ grub_dprintf("xhci", "%s: reconf ctl endpoint: failed (cc %d)\n",
-+ __func__, cc);
-+ return GRUB_USB_ERR_BADDEVICE;
-+ }
-+
-+ return GRUB_USB_ERR_NONE;
-+}
-+
-+/****************************************************************
-+ * xHCI endpoint enablement functions
-+ ****************************************************************/
-+
-+static grub_usb_err_t
-+grub_xhci_prepare_endpoint (struct grub_xhci *x,
-+ struct grub_usb_device *dev,
-+ grub_uint8_t endpoint,
-+ grub_transfer_type_t dir,
-+ grub_transaction_type_t type,
-+ grub_uint32_t maxpaket,
-+ struct grub_xhci_priv *priv)
-+{
-+ grub_uint32_t epid;
-+ struct grub_pci_dma_chunk *reqs_dma;
-+ struct grub_pci_dma_chunk *in_dma;
-+ volatile struct grub_xhci_ring *reqs;
-+ volatile struct grub_xhci_slotctx *slotctx;
-+
-+ if (!x || !priv)
-+ return GRUB_USB_ERR_INTERNAL;
-+
-+ xhci_check_status(x);
-+
-+ if (endpoint == 0)
-+ {
-+ epid = 1;
-+ }
-+ else
-+ {
-+ epid = (endpoint & 0x0f) * 2;
-+ epid += (dir == GRUB_USB_TRANSFER_TYPE_IN) ? 1 : 0;
-+ }
-+ grub_dprintf("xhci", "%s: epid %d\n", __func__, epid);
-+
-+ /* Test if already prepared */
-+ if (priv->slotid > 0 && priv->enpoint_trbs[epid] != NULL)
-+ return GRUB_USB_ERR_NONE;
-+
-+ /* Allocate DMA buffer as endpoint cmd TRB */
-+ reqs_dma = xhci_memalign_dma32(ALIGN_TRB, sizeof(*reqs),
-+ BOUNDARY_RING);
-+ if (!reqs_dma)
-+ return GRUB_USB_ERR_INTERNAL;
-+ reqs = grub_dma_get_virt(reqs_dma);
-+ grub_memset((void *)reqs, 0, sizeof(*reqs));
-+ reqs->cs = 1;
-+
-+ grub_arch_sync_dma_caches(reqs, sizeof(*reqs));
-+
-+ /* Allocate input context and initialize endpoint info. */
-+ in_dma = grub_xhci_alloc_inctx(x, epid, dev);
-+ if (!in_dma)
-+ {
-+ grub_dma_free(reqs_dma);
-+ return GRUB_USB_ERR_INTERNAL;
-+ }
-+ volatile struct grub_xhci_inctx *in = grub_dma_get_virt(in_dma);
-+ in->add = 0x01 | (1 << epid);
-+
-+ struct grub_xhci_epctx *ep = (void*)&in[(epid+1) << x->flag64];
-+ switch (type)
-+ {
-+ case GRUB_USB_TRANSACTION_TYPE_CONTROL:
-+ ep->ctx[1] |= 0 << 3;
-+ break;
-+ case GRUB_USB_TRANSACTION_TYPE_BULK:
-+ ep->ctx[1] |= 2 << 3;
-+ break;
-+ }
-+ if (dir == GRUB_USB_TRANSFER_TYPE_IN
-+ || type== GRUB_USB_TRANSACTION_TYPE_CONTROL)
-+ ep->ctx[1] |= 1 << 5;
-+ ep->ctx[1] |= maxpaket << 16;
-+ ep->deq_low = grub_dma_get_phys(reqs_dma);
-+ ep->deq_low |= 1; /* dcs */
-+ ep->length = maxpaket;
-+
-+ grub_dprintf("xhci", "%s: ring %p, epid %d, max %d\n", __func__,
-+ reqs, epid, maxpaket);
-+ if (epid == 1 || priv->slotid == 0) {
-+ /* Enable slot. */
-+ int slotid = xhci_cmd_enable_slot(x);
-+ if (slotid < 0)
-+ {
-+ grub_dprintf("xhci", "%s: enable slot: failed\n", __func__);
-+ grub_dma_free(reqs_dma);
-+ grub_dma_free(in_dma);
-+ return GRUB_USB_ERR_BADDEVICE;
-+ }
-+ grub_dprintf("xhci", "%s: get slot %d assigned\n", __func__, slotid);
-+
-+ grub_uint32_t size = (sizeof(struct grub_xhci_slotctx) * GRUB_XHCI_MAX_ENDPOINTS) << x->flag64;
-+
-+ /* Allocate memory for the device specific slot context */
-+ priv->slotctx_dma = xhci_memalign_dma32(ALIGN_SLOTCTX, size,
-+ x->pagesize);
-+ if (!priv->slotctx_dma)
-+ {
-+ grub_dprintf("xhci", "%s: grub_memalign_dma32 failed\n", __func__);
-+ grub_dma_free(reqs_dma);
-+ grub_dma_free(in_dma);
-+ return GRUB_USB_ERR_INTERNAL;
-+ }
-+ slotctx = grub_dma_get_virt(priv->slotctx_dma);
-+
-+ grub_dprintf("xhci", "%s: enable slot: got slotid %d\n", __func__, slotid);
-+ grub_memset((void *)slotctx, 0, size);
-+ grub_arch_sync_dma_caches(slotctx, size);
-+
-+ x->devs[slotid].ptr_low = grub_dma_get_phys(priv->slotctx_dma);
-+ x->devs[slotid].ptr_high = 0;
-+ grub_arch_sync_dma_caches(&x->devs[slotid], sizeof(x->devs[0]));
-+
-+ /* Send set_address command. */
-+ int cc = xhci_cmd_address_device(x, slotid, in_dma);
-+ if (cc != CC_SUCCESS)
-+ {
-+ grub_dprintf("xhci","%s: address device: failed (cc %d)\n", __func__, cc);
-+ cc = xhci_cmd_disable_slot(x, slotid);
-+ if (cc != CC_SUCCESS) {
-+ grub_dprintf("xhci", "%s: disable failed (cc %d)\n", __func__, cc);
-+ } else {
-+ x->devs[slotid].ptr_low = 0;
-+ x->devs[slotid].ptr_high = 0;
-+ grub_arch_sync_dma_caches(&x->devs[slotid], sizeof(x->devs[0]));
-+ }
-+ grub_dma_free(priv->slotctx_dma);
-+ grub_dma_free(reqs_dma);
-+ grub_dma_free(in_dma);
-+ return GRUB_USB_ERR_BADDEVICE;
-+ }
-+ priv->enpoint_trbs[epid] = reqs;
-+ priv->enpoint_trbs_dma[epid] = reqs_dma;
-+ priv->slotid = slotid;
-+ priv->max_packet = 0;
-+ }
-+ if (epid != 1)
-+ {
-+ /* Send configure command. */
-+ int cc = xhci_cmd_configure_endpoint(x, priv->slotid, in_dma);
-+ if (cc != CC_SUCCESS)
-+ {
-+ grub_dprintf("xhci", "%s: configure endpoint: failed (cc %d)\n",
-+ __func__, cc);
-+ grub_dma_free(reqs_dma);
-+ grub_dma_free(in_dma);
-+ return GRUB_USB_ERR_BADDEVICE;
-+ }
-+ priv->enpoint_trbs[epid] = reqs;
-+ priv->enpoint_trbs_dma[epid] = reqs_dma;
-+ }
-+
-+ grub_dprintf("xhci", "%s: done\n", __func__);
-+ grub_dma_free(in_dma);
-+
-+ return GRUB_USB_ERR_NONE;
-+}
-+
-+
-+/****************************************************************
-+ * xHCI transfer helper functions
-+ ****************************************************************/
-+
-+static grub_usb_err_t
-+grub_xhci_usb_to_grub_err (unsigned char status)
-+{
-+ if (status != CC_SUCCESS)
-+ grub_dprintf("xhci", "%s: xfer failed (cc %d)\n", __func__, status);
-+ else
-+ grub_dprintf("xhci", "%s: xfer done (cc %d)\n", __func__, status);
-+
-+ if (status == CC_BABBLE_DETECTED)
-+ return GRUB_USB_ERR_BABBLE;
-+ else if (status == CC_DATA_BUFFER_ERROR)
-+ return GRUB_USB_ERR_DATA;
-+ else if (status == CC_STALL_ERROR)
-+ return GRUB_USB_ERR_STALL;
-+ else if (status != CC_SUCCESS)
-+ return GRUB_USB_ERR_NAK;
-+
-+ return GRUB_USB_ERR_NONE;
-+}
-+
-+static int
-+grub_xhci_transfer_is_zlp(grub_usb_transfer_t transfer, int idx)
-+{
-+ if (idx >= transfer->transcnt)
-+ return 0;
-+
-+ grub_usb_transaction_t tr = &transfer->transactions[idx];
-+
-+ return (tr->size == 0) &&
-+ ((tr->pid == GRUB_USB_TRANSFER_TYPE_OUT) ||
-+ (tr->pid == GRUB_USB_TRANSFER_TYPE_IN));
-+}
-+
-+static int
-+grub_xhci_transfer_is_last(grub_usb_transfer_t transfer, int idx)
-+{
-+ return (idx + 1) == transfer->transcnt;
-+}
-+
-+static int
-+grub_xhci_transfer_is_data(grub_usb_transfer_t transfer, int idx)
-+{
-+ grub_usb_transaction_t tr;
-+
-+ if (idx >= transfer->transcnt)
-+ return 0;
-+
-+ tr = &transfer->transactions[idx];
-+ if (tr->size == 0 ||
-+ (tr->pid == GRUB_USB_TRANSFER_TYPE_SETUP))
-+ return 0;
-+
-+ /* If there's are no DATA pakets before it's a DATA paket */
-+ for (int i = idx - 1; i >= 0; i--)
-+ {
-+ tr = &transfer->transactions[i];
-+ if (tr->size > 0 &&
-+ ((tr->pid == GRUB_USB_TRANSFER_TYPE_OUT) ||
-+ (tr->pid == GRUB_USB_TRANSFER_TYPE_IN)))
-+ return 0;
-+ }
-+ return 1;
-+}
-+
-+static int
-+grub_xhci_transfer_is_in(grub_usb_transfer_t transfer, int idx)
-+{
-+ grub_usb_transaction_t tr;
-+
-+ if (idx >= transfer->transcnt)
-+ return 0;
-+
-+ tr = &transfer->transactions[idx];
-+
-+ return tr->pid == GRUB_USB_TRANSFER_TYPE_IN;
-+}
-+
-+static int
-+grub_xhci_transfer_is_normal(grub_usb_transfer_t transfer, int idx)
-+{
-+ grub_usb_transaction_t tr;
-+
-+ if (idx >= transfer->transcnt)
-+ return 0;
-+
-+ tr = &transfer->transactions[idx];
-+ if (tr->size == 0 ||
-+ (tr->pid == GRUB_USB_TRANSFER_TYPE_SETUP))
-+ return 0;
-+
-+ /* If there's at least one DATA paket before it's a normal */
-+ for (int i = idx - 1; i >= 0; i--)
-+ {
-+ tr = &transfer->transactions[i];
-+ if (tr->size > 0 &&
-+ ((tr->pid == GRUB_USB_TRANSFER_TYPE_OUT) ||
-+ (tr->pid == GRUB_USB_TRANSFER_TYPE_IN)))
-+ return 1;
-+
-+ }
-+ return 0;
-+}
-+
-+static int
-+grub_xhci_transfer_next_is_normal(grub_usb_transfer_t transfer, int idx)
-+{
-+ return grub_xhci_transfer_is_normal(transfer, idx + 1);
-+}
-+
-+static int
-+grub_xhci_transfer_next_is_in(grub_usb_transfer_t transfer, int idx)
-+{
-+ return grub_xhci_transfer_is_in(transfer, idx + 1);
-+}
-+
-+static grub_uint8_t grub_xhci_epid_from_transfer(grub_usb_transfer_t transfer)
-+{
-+ grub_uint8_t epid;
-+
-+ if (transfer->endpoint == 0) {
-+ epid = 1;
-+ } else {
-+ epid = (transfer->endpoint & 0x0f) * 2;
-+ epid += (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN) ? 1 : 0;
-+ }
-+ return epid;
-+}
-+
-+/****************************************************************
-+ * xHCI transfer functions
-+ ****************************************************************/
-+
-+static grub_usb_err_t
-+grub_xhci_setup_transfer (grub_usb_controller_t dev,
-+ grub_usb_transfer_t transfer)
-+{
-+ struct grub_xhci_transfer_controller_data *cdata;
-+ struct grub_xhci *x = (struct grub_xhci *) dev->data;
-+ grub_uint8_t epid;
-+ grub_usb_err_t err;
-+ volatile struct grub_xhci_ring *reqs;
-+ int rc;
-+ struct grub_xhci_priv *priv;
-+
-+ xhci_check_status(x);
-+
-+ if (!dev || !transfer || !transfer->dev || !transfer->dev->xhci_priv)
-+ return GRUB_USB_ERR_INTERNAL;
-+
-+ priv = transfer->dev->xhci_priv;
-+ err = grub_xhci_prepare_endpoint(x, transfer->dev,
-+ transfer->endpoint,
-+ transfer->dir,
-+ transfer->type,
-+ transfer->max,
-+ priv);
-+
-+ if (err != GRUB_USB_ERR_NONE)
-+ return err;
-+
-+ epid = grub_xhci_epid_from_transfer(transfer);
-+
-+ /* Update the max packet size once descdev.maxsize0 is valid */
-+ if (epid == 1 &&
-+ (priv->max_packet == 0) &&
-+ (transfer->dev->descdev.maxsize0 > 0))
-+ {
-+ if (transfer->dev->speed == GRUB_USB_SPEED_SUPER)
-+ priv->max_packet = 1UL << transfer->dev->descdev.maxsize0;
-+ else
-+ priv->max_packet = transfer->dev->descdev.maxsize0;
-+ err = grub_xhci_update_max_paket_size(x, transfer, priv->slotid, priv->max_packet);
-+ if (err != GRUB_USB_ERR_NONE)
-+ {
-+ grub_dprintf("xhci", "%s: Updating max paket size failed\n", __func__);
-+ return err;
-+ }
-+ }
-+ if (epid == 1 &&
-+ transfer->dev->descdev.class == 9 &&
-+ transfer->dev->nports > 0)
-+ {
-+ err = grub_xhci_update_hub_portcount(x, transfer, priv->slotid);
-+ if (err != GRUB_USB_ERR_NONE)
-+ {
-+ grub_dprintf("xhci", "%s: Updating max paket size failed\n", __func__);
-+ return err;
-+ }
-+ }
-+
-+ /* Allocate private data for the transfer */
-+ cdata = grub_zalloc(sizeof(*cdata));
-+ if (!cdata)
-+ return GRUB_USB_ERR_INTERNAL;
-+
-+ reqs = priv->enpoint_trbs[epid];
-+
-+ transfer->controller_data = cdata;
-+
-+ /* Now queue the transfer onto the TRB */
-+ if (transfer->type == GRUB_USB_TRANSACTION_TYPE_CONTROL)
-+ {
-+ volatile struct grub_usb_packet_setup *setupdata;
-+ setupdata = (void *)transfer->transactions[0].data;
-+ grub_dprintf("xhci", "%s: CONTROLL TRANS req %d\n", __func__, setupdata->request);
-+ grub_dprintf("xhci", "%s: CONTROLL TRANS length %d\n", __func__, setupdata->length);
-+
-+ if (setupdata && setupdata->request == GRUB_USB_REQ_SET_ADDRESS)
-+ return GRUB_USB_ERR_NONE;
-+
-+ if (transfer->transcnt < 2)
-+ return GRUB_USB_ERR_INTERNAL;
-+
-+ for (int i = 0; i < transfer->transcnt; i++)
-+ {
-+ grub_uint32_t flags = 0;
-+ grub_uint64_t inline_data;
-+ grub_usb_transaction_t tr = &transfer->transactions[i];
-+
-+ switch (tr->pid)
-+ {
-+ case GRUB_USB_TRANSFER_TYPE_SETUP:
-+ {
-+ grub_dprintf("xhci", "%s: SETUP PKG\n", __func__);
-+ grub_dprintf("xhci", "%s: transfer->size %d\n", __func__, transfer->size);
-+ grub_dprintf("xhci", "%s: tr->size %d SETUP PKG\n", __func__, tr->size);
-+
-+ flags |= (TR_SETUP << 10);
-+ flags |= TRB_TR_IDT;
-+
-+ if (transfer->size > 0)
-+ {
-+ if (grub_xhci_transfer_next_is_in(transfer, i))
-+ flags |= (3 << 16); /* TRT IN */
-+ else
-+ flags |= (2 << 16); /* TRT OUT */
-+ }
-+ break;
-+ }
-+ case GRUB_USB_TRANSFER_TYPE_OUT:
-+ {
-+ grub_dprintf("xhci", "%s: OUT PKG\n", __func__);
-+ cdata->transfer_size += tr->size;
-+ break;
-+ }
-+ case GRUB_USB_TRANSFER_TYPE_IN:
-+ {
-+ grub_dprintf("xhci", "%s: IN PKG\n", __func__);
-+ cdata->transfer_size += tr->size;
-+ flags |= TRB_TR_DIR;
-+ break;
-+ }
-+ }
-+
-+ if (grub_xhci_transfer_is_normal(transfer, i))
-+ flags |= (TR_NORMAL << 10);
-+ else if (grub_xhci_transfer_is_data(transfer, i))
-+ flags |= (TR_DATA << 10);
-+ else if (grub_xhci_transfer_is_zlp(transfer, i))
-+ flags |= (TR_STATUS << 10);
-+
-+ if (grub_xhci_transfer_next_is_normal(transfer, i))
-+ flags |= TRB_TR_CH;
-+
-+ if (grub_xhci_transfer_is_last(transfer, i))
-+ flags |= TRB_TR_IOC;
-+
-+ /* Assume the ring has enough free space for all TRBs */
-+ if (flags & TRB_TR_IDT && tr->size <= (int)sizeof(inline_data))
-+ {
-+ grub_memcpy(&inline_data, (void *)tr->data, tr->size);
-+ xhci_trb_queue(reqs, inline_data, tr->size, flags);
-+ }
-+ else
-+ {
-+ xhci_trb_queue(reqs, tr->data, tr->size, flags);
-+ }
-+ }
-+ }
-+ else if (transfer->type == GRUB_USB_TRANSACTION_TYPE_BULK)
-+ {
-+ for (int i = 0; i < transfer->transcnt; i++)
-+ {
-+ grub_uint32_t flags = (TR_NORMAL << 10);
-+ grub_usb_transaction_t tr = &transfer->transactions[i];
-+ switch (tr->pid)
-+ {
-+ case GRUB_USB_TRANSFER_TYPE_OUT:
-+ {
-+ grub_dprintf("xhci", "%s: OUT PKG\n", __func__);
-+ cdata->transfer_size += tr->size;
-+ break;
-+ }
-+ case GRUB_USB_TRANSFER_TYPE_IN:
-+ {
-+ grub_dprintf("xhci", "%s: IN PKG\n", __func__);
-+ cdata->transfer_size += tr->size;
-+ flags |= TRB_TR_DIR;
-+ break;
-+ }
-+ case GRUB_USB_TRANSFER_TYPE_SETUP:
-+ break;
-+ }
-+ if (grub_xhci_transfer_is_last(transfer, i))
-+ flags |= TRB_TR_IOC;
-+
-+ /* The ring might be to small, submit while adding new entries */
-+ rc = xhci_trb_queue_and_flush(x, priv->slotid, epid,
-+ reqs, tr->data, tr->size, flags);
-+ if (rc < 0)
-+ return GRUB_USB_ERR_TIMEOUT;
-+ else if (rc > 1)
-+ return grub_xhci_usb_to_grub_err(rc);
-+
-+ }
-+ }
-+ xhci_doorbell(x, priv->slotid, epid);
-+
-+ return GRUB_USB_ERR_NONE;
-+}
-+
-+static grub_usb_err_t
-+grub_xhci_check_transfer (grub_usb_controller_t dev,
-+ grub_usb_transfer_t transfer, grub_size_t * actual)
-+{
-+ grub_uint32_t status;
-+ grub_uint32_t remaining;
-+ grub_uint8_t epid;
-+ volatile struct grub_xhci_ring *reqs;
-+ grub_usb_err_t err;
-+ int rc;
-+
-+ if (!dev->data || !transfer->controller_data || !transfer->dev ||
-+ !transfer->dev->xhci_priv)
-+ return GRUB_USB_ERR_INTERNAL;
-+
-+
-+ struct grub_xhci_priv *priv = transfer->dev->xhci_priv;
-+ struct grub_xhci *x = (struct grub_xhci *) dev->data;
-+ struct grub_xhci_transfer_controller_data *cdata =
-+ transfer->controller_data;
-+
-+ xhci_check_status(x);
-+ xhci_process_events(x);
-+
-+ epid = grub_xhci_epid_from_transfer(transfer);
-+
-+ reqs = priv->enpoint_trbs[epid];
-+
-+ /* XXX: invalidate caches */
-+
-+ /* Get current status from event ring buffer */
-+ status = (reqs->evt.status>> 24) & 0xff;
-+ remaining = reqs->evt.status & 0xffffff;
-+
-+ if (status != CC_STOPPED_LENGTH_INVALID)
-+ *actual = cdata->transfer_size - remaining;
-+ else
-+ *actual = 0;
-+
-+ if (xhci_ring_busy(reqs))
-+ return GRUB_USB_ERR_WAIT;
-+
-+ grub_free(cdata);
-+
-+ grub_dprintf("xhci", "%s: xfer done\n", __func__);
-+
-+ err = grub_xhci_usb_to_grub_err(status);
-+ if (err != GRUB_USB_ERR_NONE)
-+ {
-+ if (status == CC_STALL_ERROR)
-+ {
-+ /* Clear the stall by resetting the endpoint */
-+ rc = xhci_cmd_reset_endpoint(x, priv->slotid, epid, 1);
-+
-+ if (rc < 0)
-+ return GRUB_USB_ERR_TIMEOUT;
-+
-+ return GRUB_USB_ERR_STALL;
-+ }
-+ else if (remaining > 0)
-+ {
-+ return GRUB_USB_ERR_DATA;
-+ }
-+ }
-+
-+ return err;
-+}
-+
-+static grub_usb_err_t
-+grub_xhci_cancel_transfer (grub_usb_controller_t dev,
-+ grub_usb_transfer_t transfer)
-+{
-+ grub_uint8_t epid;
-+ volatile struct grub_xhci_ring *reqs;
-+ struct grub_pci_dma_chunk *enpoint_trbs_dma;
-+ grub_addr_t deque_pointer;
-+ int rc;
-+
-+ if (!dev->data || !transfer->controller_data || !transfer->dev ||
-+ !transfer->dev->xhci_priv)
-+ return GRUB_USB_ERR_INTERNAL;
-+
-+ struct grub_xhci *x = (struct grub_xhci *) dev->data;
-+ struct grub_xhci_transfer_controller_data *cdata =
-+ transfer->controller_data;
-+ struct grub_xhci_priv *priv = transfer->dev->xhci_priv;
-+
-+ epid = grub_xhci_epid_from_transfer(transfer);
-+
-+ enpoint_trbs_dma = priv->enpoint_trbs_dma[epid];
-+ reqs = priv->enpoint_trbs[epid];
-+
-+ /* Abort current command */
-+ rc = xhci_cmd_stop_endpoint(x, priv->slotid, epid, 0);
-+ if (rc < 0)
-+ return GRUB_USB_ERR_TIMEOUT;
-+
-+ /* Reset state */
-+ reqs->nidx = 0;
-+ reqs->eidx = 0;
-+ reqs->cs = 1;
-+
-+ grub_arch_sync_dma_caches(reqs, sizeof(*reqs));
-+
-+ /* Reset the dequeue pointer to the begging of the TRB */
-+ deque_pointer = grub_dma_get_phys(enpoint_trbs_dma);
-+ rc = xhci_cmd_set_dequeue_pointer(x, priv->slotid, epid, deque_pointer| 1 );
-+ if (rc < 0)
-+ return GRUB_USB_ERR_TIMEOUT;
-+
-+ reqs->evt.ptr_low = 0;
-+ reqs->evt.ptr_high = 0;
-+ reqs->evt.control = 0;
-+ reqs->evt.status = 0;
-+
-+ grub_arch_sync_dma_caches(reqs, sizeof(*reqs));
-+
-+ /* Restart ring buffer processing */
-+ xhci_doorbell(x, priv->slotid, epid);
-+
-+ grub_free (cdata);
-+
-+ return GRUB_USB_ERR_NONE;
-+}
-+
-+/****************************************************************
-+ * xHCI port status functions
-+ ****************************************************************/
-+
-+static int
-+grub_xhci_hubports (grub_usb_controller_t dev)
-+{
-+ struct grub_xhci *x = (struct grub_xhci *) dev->data;
-+ grub_uint32_t portinfo;
-+
-+ portinfo = x->ports;
-+ grub_dprintf ("xhci", "root hub ports=%d\n", portinfo);
-+ return portinfo;
-+}
-+
-+static grub_usb_err_t
-+grub_xhci_portstatus (grub_usb_controller_t dev,
-+ unsigned int port, unsigned int enable)
-+{
-+ struct grub_xhci *x = (struct grub_xhci *) dev->data;
-+ grub_uint32_t portsc, pls;
-+ grub_uint32_t end;
-+
-+ portsc = grub_xhci_port_read(x, port);
-+ pls = xhci_get_field(portsc, XHCI_PORTSC_PLS);
-+
-+ grub_dprintf("xhci", "grub_xhci_portstatus port #%d: 0x%08x,%s%s pls %d enable %d\n",
-+ port, portsc,
-+ (portsc & GRUB_XHCI_PORTSC_PP) ? " powered," : "",
-+ (portsc & GRUB_XHCI_PORTSC_PED) ? " enabled," : "",
-+ pls, enable);
-+ xhci_check_status(x);
-+
-+ if ((enable && (portsc & GRUB_XHCI_PORTSC_PED)) ||
-+ (!enable && !(portsc & GRUB_XHCI_PORTSC_PED)))
-+ return GRUB_USB_ERR_NONE;
-+
-+ if (!enable)
-+ {
-+ /* Disable port */
-+ grub_xhci_port_write(x, port, ~0, GRUB_XHCI_PORTSC_PED);
-+ return GRUB_USB_ERR_NONE;
-+ }
-+
-+ grub_dprintf ("xhci", "portstatus: XHCI STATUS: %08x\n",
-+ grub_xhci_read32(&x->op->usbsts));
-+ grub_dprintf ("xhci",
-+ "portstatus: begin, iobase=%p, port=%d, status=0x%08x\n",
-+ x->caps, port, portsc);
-+
-+ switch (pls)
-+ {
-+ case PLS_U0:
-+ /* A USB3 port - controller automatically performs reset */
-+ break;
-+ case PLS_POLLING:
-+ /* A USB2 port - perform device reset */
-+ grub_xhci_port_write(x, port, ~GRUB_XHCI_PORTSC_PED, GRUB_XHCI_PORTSC_PR);
-+ break;
-+ default:
-+ return GRUB_USB_ERR_NONE;
-+ }
-+
-+ /* Wait for device to complete reset and be enabled */
-+ end = grub_get_time_ms () + 100;
-+ for (;;)
-+ {
-+ portsc = grub_xhci_port_read(x, port);
-+ if (!(portsc & GRUB_XHCI_PORTSC_CCS))
-+ {
-+ /* Device disconnected during reset */
-+ grub_dprintf ("xhci","ERROR: %s device disconnected\n", __func__);
-+ return GRUB_USB_ERR_BADDEVICE;
-+ }
-+ if (portsc & GRUB_XHCI_PORTSC_PED)
-+ /* Reset complete */
-+ break;
-+ if (grub_get_time_ms () > end)
-+ {
-+ grub_dprintf ("xhci","ERROR: %s TIMEOUT\n", __func__);
-+ return GRUB_USB_ERR_TIMEOUT;
-+ }
-+ }
-+ xhci_check_status(x);
-+
-+ return GRUB_USB_ERR_NONE;
-+}
-+
-+/****************************************************************
-+ * xHCI detect device functions
-+ ****************************************************************/
-+
-+static grub_usb_speed_t
-+grub_xhci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
-+{
-+ struct grub_xhci *x = (struct grub_xhci *) dev->data;
-+ grub_uint32_t portsc, speed;
-+
-+ *changed = 0;
-+ grub_dprintf("xhci", "%s: dev=%p USB%d_%d port %d\n", __func__, dev,
-+ x->psids[port-1].major, x->psids[port-1].minor, port);
-+
-+ /* On shutdown advertise all ports as disconnected. This will trigger
-+ * a gracefull detatch. */
-+ if (x->shutdown)
-+ {
-+ *changed = 1;
-+ return GRUB_USB_SPEED_NONE;
-+ }
-+
-+ /* Don't advertise new devices, connecting will fail if halted */
-+ if (xhci_is_halted(x))
-+ return GRUB_USB_SPEED_NONE;
-+
-+ portsc = grub_xhci_port_read(x, port);
-+ speed = xhci_get_field(portsc, XHCI_PORTSC_SPEED);
-+ grub_uint8_t pls = xhci_get_field(portsc, XHCI_PORTSC_PLS);
-+
-+ grub_dprintf("xhci", "grub_xhci_portstatus port #%d: 0x%08x,%s%s pls %d\n",
-+ port, portsc,
-+ (portsc & GRUB_XHCI_PORTSC_PP) ? " powered," : "",
-+ (portsc & GRUB_XHCI_PORTSC_PED) ? " enabled," : "",
-+ pls);
-+
-+ /* Connect Status Change bit - it detects change of connection */
-+ if (portsc & GRUB_XHCI_PORTSC_CSC)
-+ {
-+ *changed = 1;
-+
-+ grub_xhci_port_write(x, port, ~GRUB_XHCI_PORTSC_PED, GRUB_XHCI_PORTSC_CSC);
-+ }
-+
-+ if (!(portsc & GRUB_XHCI_PORTSC_CCS))
-+ return GRUB_USB_SPEED_NONE;
-+
-+ for (grub_uint8_t i = 0; i < 16 && x->psids[port-1].psids[i].id > 0; i++)
-+ {
-+ if (x->psids[port-1].psids[i].id == speed)
-+ {
-+ grub_dprintf("xhci", "%s: grub_usb_speed = %d\n", __func__,
-+ x->psids[port-1].psids[i].grub_usb_speed );
-+ return x->psids[port-1].psids[i].grub_usb_speed;
-+ }
-+ }
-+
-+ return GRUB_USB_SPEED_NONE;
-+}
-+
-+/****************************************************************
-+ * xHCI attach/detach functions
-+ ****************************************************************/
-+
-+static grub_usb_err_t
-+grub_xhci_attach_dev (grub_usb_controller_t ctrl, grub_usb_device_t dev)
-+{
-+ struct grub_xhci *x = (struct grub_xhci *) ctrl->data;
-+ grub_usb_err_t err;
-+ grub_uint32_t max;
-+
-+ grub_dprintf("xhci", "%s: dev=%p\n", __func__, dev);
-+
-+ if (!dev || !x)
-+ return GRUB_USB_ERR_INTERNAL;
-+
-+ dev->xhci_priv = grub_zalloc (sizeof (struct grub_xhci_priv));
-+ if (!dev->xhci_priv)
-+ return GRUB_USB_ERR_INTERNAL;
-+
-+
-+ switch (dev->speed)
-+ {
-+ case GRUB_USB_SPEED_LOW:
-+ {
-+ max = 8;
-+ break;
-+ }
-+ case GRUB_USB_SPEED_FULL:
-+ case GRUB_USB_SPEED_HIGH:
-+ {
-+ max = 64;
-+ break;
-+ }
-+ case GRUB_USB_SPEED_SUPER:
-+ {
-+ max = 512;
-+ break;
-+ }
-+ default:
-+ case GRUB_USB_SPEED_NONE:
-+ {
-+ max = 0;
-+ }
-+ }
-+
-+ /* Assign a slot, assign an address and configure endpoint 0 */
-+ err = grub_xhci_prepare_endpoint(x, dev,
-+ 0,
-+ 0,
-+ GRUB_USB_TRANSACTION_TYPE_CONTROL,
-+ max,
-+ dev->xhci_priv);
-+
-+ return err;
-+}
-+
-+static grub_usb_err_t
-+grub_xhci_detach_dev (grub_usb_controller_t ctrl, grub_usb_device_t dev)
-+{
-+ struct grub_xhci *x = (struct grub_xhci *) ctrl->data;
-+ struct grub_xhci_priv *priv;
-+ int cc = CC_SUCCESS;
-+
-+ grub_dprintf("xhci", "%s: dev=%p\n", __func__, dev);
-+
-+ if (!dev)
-+ return GRUB_USB_ERR_INTERNAL;
-+
-+ if (dev->xhci_priv)
-+ {
-+ priv = dev->xhci_priv;
-+ /* Stop endpoints and free ring buffer */
-+ for (int i = 0; i < GRUB_XHCI_MAX_ENDPOINTS; i++)
-+ {
-+ if (priv->enpoint_trbs[i] != NULL)
-+ {
-+ cc = xhci_cmd_stop_endpoint(x, priv->slotid, i, 1);
-+ if (cc != CC_SUCCESS)
-+ grub_dprintf("xhci", "Failed to disable EP%d on slot %d\n", i,
-+ priv->slotid);
-+
-+ grub_dprintf("xhci", "grub_dma_free[%d]\n", i);
-+
-+ grub_dma_free(priv->enpoint_trbs_dma[i]);
-+ priv->enpoint_trbs[i] = NULL;
-+ priv->enpoint_trbs_dma[i] = NULL;
-+ }
-+ }
-+
-+ cc = xhci_cmd_disable_slot(x, priv->slotid);
-+ if (cc == CC_SUCCESS)
-+ {
-+ if (priv->slotctx_dma)
-+ grub_dma_free(priv->slotctx_dma);
-+ x->devs[priv->slotid].ptr_low = 0;
-+ x->devs[priv->slotid].ptr_high = 0;
-+ grub_arch_sync_dma_caches(&x->devs[priv->slotid], sizeof(x->devs[0]));
-+ }
-+ else
-+ grub_dprintf("xhci", "Failed to disable slot %d\n", priv->slotid);
-+
-+ grub_free(dev->xhci_priv);
-+ }
-+
-+ dev->xhci_priv = NULL;
-+
-+ if (cc != CC_SUCCESS)
-+ return GRUB_USB_ERR_BADDEVICE;
-+ return GRUB_USB_ERR_NONE;
-+}
-+
-+/****************************************************************
-+ * xHCI terminate functions
-+ ****************************************************************/
-+
-+static void
-+grub_xhci_halt(struct grub_xhci *x)
-+{
-+ grub_uint32_t reg;
-+
-+ /* Halt the command ring */
-+ reg = grub_xhci_read32(&x->op->crcr_low);
-+ grub_xhci_write32(&x->op->crcr_low, reg | 4);
-+
-+ int rc = xhci_event_wait(x, x->cmds, 100);
-+ grub_dprintf("xhci", "%s: xhci_event_wait = %d\n", __func__, rc);
-+ if (rc < 0)
-+ return;
-+
-+ /* Stop the controller */
-+ reg = grub_xhci_read32(&x->op->usbcmd);
-+ if (reg & GRUB_XHCI_CMD_RS)
-+ {
-+ reg &= ~GRUB_XHCI_CMD_RS;
-+ grub_xhci_write32(&x->op->usbcmd, reg);
-+ }
-+
-+ return;
-+}
-+
-+static grub_err_t
-+grub_xhci_fini_hw (int noreturn __attribute__ ((unused)))
-+{
-+ struct grub_xhci *x;
-+
-+ /* We should disable all XHCI HW to prevent any DMA access etc. */
-+ for (x = xhci; x; x = x->next)
-+ {
-+ x->shutdown = 1;
-+
-+ /* Gracefully detach active devices */
-+ grub_usb_poll_devices(0);
-+
-+ /* Check if xHCI is halted and halt it if not */
-+ grub_xhci_halt (x);
-+
-+ /* Reset xHCI */
-+ if (grub_xhci_reset (x) != GRUB_USB_ERR_NONE)
-+ return GRUB_ERR_BAD_DEVICE;
-+ }
-+
-+ return GRUB_ERR_NONE;
-+}
-+
-+static struct grub_usb_controller_dev usb_controller = {
-+ .name = "xhci",
-+ .iterate = grub_xhci_iterate,
-+ .setup_transfer = grub_xhci_setup_transfer,
-+ .check_transfer = grub_xhci_check_transfer,
-+ .cancel_transfer = grub_xhci_cancel_transfer,
-+ .hubports = grub_xhci_hubports,
-+ .portstatus = grub_xhci_portstatus,
-+ .detect_dev = grub_xhci_detect_dev,
-+ .attach_dev = grub_xhci_attach_dev,
-+ .detach_dev = grub_xhci_detach_dev,
-+ /* estimated max. count of TDs for one bulk transfer */
-+ .max_bulk_tds = GRUB_XHCI_RING_ITEMS - 3
-+};
-+
-+GRUB_MOD_INIT (xhci)
-+{
-+ grub_stop_disk_firmware ();
-+
-+ grub_boot_time ("Initing XHCI hardware");
-+ grub_xhci_pci_scan ();
-+ grub_boot_time ("Registering XHCI driver");
-+ grub_usb_controller_dev_register (&usb_controller);
-+ grub_boot_time ("XHCI driver registered");
-+}
-+
-+GRUB_MOD_FINI (xhci)
-+{
-+ grub_xhci_fini_hw (0);
-+ grub_usb_controller_dev_unregister (&usb_controller);
-+}
-diff --git a/include/grub/usb.h b/include/grub/usb.h
-index 609faf7d0..eb71fa1c7 100644
---- a/include/grub/usb.h
-+++ b/include/grub/usb.h
-@@ -338,6 +338,10 @@ grub_usb_cancel_transfer (grub_usb_transfer_t trans);
- void
- grub_ehci_init_device (volatile void *regs);
- void
-+grub_xhci_init_device (volatile void *regs);
-+void
- grub_ehci_pci_scan (void);
-+void
-+grub_xhci_pci_scan (void);
-
- #endif /* GRUB_USB_H */
---
-2.39.2
-
diff --git a/config/grub/xhci/patches/0005-xhci/0007-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch b/config/grub/xhci/patches/0005-xhci/0007-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch
deleted file mode 100644
index a37bbd6b..00000000
--- a/config/grub/xhci/patches/0005-xhci/0007-grub-core-bus-usb-usbhub-Add-xHCI-non-root-hub-suppo.patch
+++ /dev/null
@@ -1,127 +0,0 @@
-From 2a2c64f6ea62337c1263a70f6ca9a9bade66b78b Mon Sep 17 00:00:00 2001
-From: Patrick Rudolph <patrick.rudolph@9elements.com>
-Date: Thu, 3 Dec 2020 13:44:55 +0100
-Subject: [PATCH 7/8] grub-core/bus/usb/usbhub: Add xHCI non root hub support
-
-Tested on Intel PCH C246, the USB3 hub can be configured by grub.
-
-Issues:
-* USB3 devices connected behind that hub are sometimes not detected.
-
-Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
----
- grub-core/bus/usb/usbhub.c | 38 +++++++++++++++++++++++++++++++++-----
- include/grub/usbdesc.h | 1 +
- include/grub/usbtrans.h | 4 ++++
- 3 files changed, 38 insertions(+), 5 deletions(-)
-
-diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c
-index b4b3a1a61..e96505aa9 100644
---- a/grub-core/bus/usb/usbhub.c
-+++ b/grub-core/bus/usb/usbhub.c
-@@ -148,19 +148,32 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller,
- return dev;
- }
-
--
-+static grub_usb_err_t
-+grub_usb_set_hub_depth(grub_usb_device_t dev, grub_uint8_t depth)
-+{
-+ return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
-+ | GRUB_USB_REQTYPE_CLASS
-+ | GRUB_USB_REQTYPE_TARGET_DEV),
-+ GRUB_USB_HUB_REQ_SET_HUB_DEPTH, depth,
-+ 0, 0, NULL);
-+}
-+
- static grub_usb_err_t
- grub_usb_add_hub (grub_usb_device_t dev)
- {
- struct grub_usb_usb_hubdesc hubdesc;
- grub_usb_err_t err;
-+ grub_uint16_t req;
- int i;
-
-+ req = (dev->speed == GRUB_USB_SPEED_SUPER) ? GRUB_USB_DESCRIPTOR_SS_HUB :
-+ GRUB_USB_DESCRIPTOR_HUB;
-+
- err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
- | GRUB_USB_REQTYPE_CLASS
- | GRUB_USB_REQTYPE_TARGET_DEV),
-- GRUB_USB_REQ_GET_DESCRIPTOR,
-- (GRUB_USB_DESCRIPTOR_HUB << 8) | 0,
-+ GRUB_USB_REQ_GET_DESCRIPTOR,
-+ (req << 8) | 0,
- 0, sizeof (hubdesc), (char *) &hubdesc);
- if (err)
- return err;
-@@ -183,6 +196,19 @@ grub_usb_add_hub (grub_usb_device_t dev)
- return GRUB_USB_ERR_INTERNAL;
- }
-
-+ if (dev->speed == GRUB_USB_SPEED_SUPER)
-+ {
-+ grub_uint8_t depth;
-+ grub_uint32_t route;
-+ /* Depth maximum value is 5, but root hubs doesn't count */
-+ for (depth = 0, route = dev->route; (route & 0xf) > 0; route >>= 4)
-+ depth++;
-+
-+ err = grub_usb_set_hub_depth(dev, depth);
-+ if (err)
-+ return err;
-+ }
-+
- /* Power on all Hub ports. */
- for (i = 1; i <= hubdesc.portcnt; i++)
- {
-@@ -637,7 +663,9 @@ poll_nonroot_hub (grub_usb_device_t dev)
- int split_hubaddr = 0;
-
- /* Determine the device speed. */
-- if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED)
-+ if (dev->speed == GRUB_USB_SPEED_SUPER)
-+ speed = GRUB_USB_SPEED_SUPER;
-+ else if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED)
- speed = GRUB_USB_SPEED_LOW;
- else
- {
-@@ -651,7 +679,7 @@ poll_nonroot_hub (grub_usb_device_t dev)
- grub_millisleep (10);
-
- /* Find correct values for SPLIT hubport and hubaddr */
-- if (speed == GRUB_USB_SPEED_HIGH)
-+ if (speed == GRUB_USB_SPEED_HIGH || speed == GRUB_USB_SPEED_SUPER)
- {
- /* HIGH speed device needs not transaction translation */
- split_hubport = 0;
-diff --git a/include/grub/usbdesc.h b/include/grub/usbdesc.h
-index bb2ab2e27..1697aa465 100644
---- a/include/grub/usbdesc.h
-+++ b/include/grub/usbdesc.h
-@@ -30,6 +30,7 @@ typedef enum {
- GRUB_USB_DESCRIPTOR_ENDPOINT,
- GRUB_USB_DESCRIPTOR_DEBUG = 10,
- GRUB_USB_DESCRIPTOR_HUB = 0x29,
-+ GRUB_USB_DESCRIPTOR_SS_HUB = 0x2a,
- GRUB_USB_DESCRIPTOR_SS_ENDPOINT_COMPANION = 0x30
- } grub_usb_descriptor_t;
-
-diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h
-index 039ebed65..d6c3f71dc 100644
---- a/include/grub/usbtrans.h
-+++ b/include/grub/usbtrans.h
-@@ -110,6 +110,10 @@ enum
- GRUB_USB_REQ_SET_INTERFACE = 0x0B,
- GRUB_USB_REQ_SYNC_FRAME = 0x0C
- };
-+enum
-+ {
-+ GRUB_USB_HUB_REQ_SET_HUB_DEPTH = 0x0C,
-+ };
-
- #define GRUB_USB_FEATURE_ENDP_HALT 0x00
- #define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x01
---
-2.39.2
-
diff --git a/config/grub/xhci/patches/0005-xhci/0008-Fix-compilation-on-x86_64.patch b/config/grub/xhci/patches/0005-xhci/0008-Fix-compilation-on-x86_64.patch
deleted file mode 100644
index af79c3d0..00000000
--- a/config/grub/xhci/patches/0005-xhci/0008-Fix-compilation-on-x86_64.patch
+++ /dev/null
@@ -1,90 +0,0 @@
-From 871d768f8c5c960cb0d9761a9028b16882e1a7d3 Mon Sep 17 00:00:00 2001
-From: Patrick Rudolph <patrick.rudolph@9elements.com>
-Date: Wed, 24 Feb 2021 08:25:41 +0100
-Subject: [PATCH 8/8] Fix compilation on x86_64
-
-Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
----
- grub-core/bus/usb/xhci.c | 24 ++++++++++++++++--------
- 1 file changed, 16 insertions(+), 8 deletions(-)
-
-diff --git a/grub-core/bus/usb/xhci.c b/grub-core/bus/usb/xhci.c
-index f4591ffb5..3495bb919 100644
---- a/grub-core/bus/usb/xhci.c
-+++ b/grub-core/bus/usb/xhci.c
-@@ -184,7 +184,7 @@ enum
- * then we can get it from a trb pointer (provided by evt ring).
- */
- #define XHCI_RING(_trb) \
-- ((struct grub_xhci_ring*)((grub_uint32_t)(_trb) & ~(GRUB_XHCI_RING_SIZE-1)))
-+ ((struct grub_xhci_ring*)((grub_addr_t)(_trb) & ~(GRUB_XHCI_RING_SIZE-1)))
-
- /* slot context */
- struct grub_xhci_slotctx {
-@@ -495,6 +495,14 @@ grub_xhci_read8(volatile void *addr) {
- return (*((volatile grub_uint32_t *)addr));
- }
-
-+static inline void *
-+grub_xhci_read_etrb_ptr(volatile struct grub_xhci_trb *trb) {
-+ grub_uint64_t tmp;
-+ tmp = (grub_uint64_t)grub_xhci_read32(&trb->ptr_low);
-+ tmp |= ((grub_uint64_t)grub_xhci_read32(&trb->ptr_high)) << 32;
-+ return (void *)(grub_addr_t)tmp;
-+}
-+
- static inline grub_uint32_t
- grub_xhci_port_read (struct grub_xhci *x, grub_uint32_t port)
- {
-@@ -664,7 +672,7 @@ static void xhci_process_events(struct grub_xhci *x)
- case ER_TRANSFER:
- case ER_COMMAND_COMPLETE:
- {
-- struct grub_xhci_trb *rtrb = (void*)grub_xhci_read32(&etrb->ptr_low);
-+ struct grub_xhci_trb *rtrb = grub_xhci_read_etrb_ptr(etrb);
- struct grub_xhci_ring *ring = XHCI_RING(rtrb);
- volatile struct grub_xhci_trb *evt = &ring->evt;
- grub_uint32_t eidx = rtrb - ring->ring + 1;
-@@ -697,9 +705,9 @@ static void xhci_process_events(struct grub_xhci *x)
- }
- grub_xhci_write32(&evts->nidx, nidx);
- volatile struct grub_xhci_ir *ir = x->ir;
-- grub_uint32_t erdp = (grub_uint32_t)(evts->ring + nidx);
-- grub_xhci_write32(&ir->erdp_low, erdp);
-- grub_xhci_write32(&ir->erdp_high, 0);
-+ grub_uint64_t erdp = (grub_addr_t)(void *)(&evts->ring[nidx]);
-+ grub_xhci_write32(&ir->erdp_low, erdp & 0xffffffff);
-+ grub_xhci_write32(&ir->erdp_high, erdp >> 32);
- }
- }
-
-@@ -800,7 +808,7 @@ static void xhci_trb_queue(volatile struct grub_xhci_ring *ring,
- grub_uint32_t xferlen, grub_uint32_t flags)
- {
- grub_dprintf("xhci", "%s: ring %p data %llx len %d flags 0x%x remain 0x%x\n", __func__,
-- ring, data_or_addr, xferlen & 0x1ffff, flags, xferlen >> 17);
-+ ring, (unsigned long long)data_or_addr, xferlen & 0x1ffff, flags, xferlen >> 17);
-
- if (xhci_ring_full(ring))
- {
-@@ -1907,7 +1915,7 @@ grub_xhci_setup_transfer (grub_usb_controller_t dev,
- if (transfer->type == GRUB_USB_TRANSACTION_TYPE_CONTROL)
- {
- volatile struct grub_usb_packet_setup *setupdata;
-- setupdata = (void *)transfer->transactions[0].data;
-+ setupdata = (void *)(grub_addr_t)transfer->transactions[0].data;
- grub_dprintf("xhci", "%s: CONTROLL TRANS req %d\n", __func__, setupdata->request);
- grub_dprintf("xhci", "%s: CONTROLL TRANS length %d\n", __func__, setupdata->length);
-
-@@ -1974,7 +1982,7 @@ grub_xhci_setup_transfer (grub_usb_controller_t dev,
- /* Assume the ring has enough free space for all TRBs */
- if (flags & TRB_TR_IDT && tr->size <= (int)sizeof(inline_data))
- {
-- grub_memcpy(&inline_data, (void *)tr->data, tr->size);
-+ grub_memcpy(&inline_data, (void *)(grub_addr_t)tr->data, tr->size);
- xhci_trb_queue(reqs, inline_data, tr->size, flags);
- }
- else
---
-2.39.2
-